Чтобы определить «календарный» промежуток времени между двумя событиями, вам нужно Period
, как вы уже обнаружили. Однако это только касается местных дат и времени.
Чтобы определить «календарно-нейтральный» промежуток времени между двумя событиями, вы можете использовать Instant
и Duration
, но тогда вы не сможете отобразить количество оставшихся месяцев.
У обоих этих подходов есть недостатки, но в основном они лежат в основе того, как работает время. Если вы используете метод локального времени, то вы обнаружите, что количество времени будет прыгать назад или вперед на час, когда вы проходите переход на летнее время. Если вы используете мгновенный подход, вы ограничены днями/месяцами/часами/минутами и т. д., а не месяцами.
Одним из вариантов между ними было бы использование LocalDateTime
и Period
, но привязка события и текущего времени к UTC. Таким образом, никогда не будет разрыва, поскольку UTC фактически является неизменной базовой линией. Это также означает, что вы всегда будете отображать одно и то же количество «оставшегося времени», независимо от того, где в мире вы смотрите на счетчик (или размещаете код, в зависимости от того, что именно вы планировали сделать).
Если вам нужны дополнительные сведения о том, почему вы не можете получить Period
между двумя значениями ZonedDateTime
, я мог бы привести примеры, которые принципиально проблематичны. Суть в том, что календарная арифметика и часовые пояса плохо сочетаются друг с другом...
Просто чтобы дать реальный код, у меня было бы что-то вроде:
public sealed class EventCountdown
{
private readonly LocalDateTime eventTimeUtc;
private readonly IClock clock;
// It's probably most convenient to express the event time with the time zone
// in which it occurs. You could easily change this though.
public EventCountdown(ZonedDateTime zonedEventTime, IClock clock)
{
this.eventTimeUtc = zonedEventTime.WithZone(DateTimeZone.Utc).LocalDateTime;
this.clock = clock;
}
public Period GetPeriodRemaining()
{
return Period.Between(clock.Now.InUtc().LocalDateTime, eventTimeUtc);
}
}
Обратите внимание, что в Noda Time 2.0 свойство IClock.Now
заменяется на метод GetCurrentInstant
... но в этом случае вы, вероятно, использовали бы ZonedClock
в UTC и вызывали для него GetCurrentLocalDateTime
.
17.12.2014
OffsetDateTime
иZonedDateTime
, когда этот компромисс по существу удаляет смещение и часовой пояс (сравнивая только значения UTC). Нет ли решения, в котором разница в смещениях часового пояса UTC может быть применена к периоду (.Between)? 22.12.2014OffsetDateTime
— он идет прямо отZonedDateTime
кLocalDateTime
. 23.12.2014