Расчет продолжительности времени с Joda-Time
Я пытаюсь использовать Joda-Time для того, чтобы узнать продолжительность времени между двумя точками во времени, где каждая точка указана в своем местном часовом поясе.
Например:
DateTime ny = new DateTime(2011, 2, 2, 7, 0, 0, 0, DateTimeZone.forID("America/New_York"));
DateTime la = new DateTime(2011, 2, 3, 10, 15, 0, 0, DateTimeZone.forID("America/Los_Angeles"));
DateTime utc1 = ny.withZone(DateTimeZone.UTC);
DateTime utc2 = la.withZone(DateTimeZone.UTC);
Period period = new Period(utc1, utc2);
Теперь я хотел бы знать, принимает ли это во внимание дневную экономию и високосные годы... Кроме того, является ли использование "Периода" правильным способом Joda-Time для достижения этой цели? Спасибо;)
2 ответа
Предоставленный вами код будет работать и учитывать часовые пояса, но вам не нужно выполнять преобразование в UTC. Этот код проще и делает то же самое (используя Duration, а не Period):
DateTime ny = new DateTime(2011, 2, 2, 7, 0, 0, 0, DateTimeZone.forID("America/New_York"));
DateTime la = new DateTime(2011, 2, 3, 10, 15, 0, 0, DateTimeZone.forID("America/Los_Angeles"));
Duration duration = new Interval(ny, la).toDuration();
В зависимости от того, как вы его используете, приведенный выше код может не быть хорошей идеей.
Все конструкторы DateTime, которые принимают int для года / месяца / дня / часа и т. Д., Уязвимы к переходным периодам перехода на летнее время (DST), и в этом случае Joda-time выдает исключение. Так что, если час во время перехода является возможным вводом в вашем приложении, он потерпит неудачу:
DateTime ny = new DateTime(2011, 3, 13, 2, 0, 0, 0, DateTimeZone.forID("America/New_York"));
Exception in thread "main" java.lang.IllegalArgumentException: Illegal instant due to time zone offset transition: 2011-03-13T07:00:00.000
at org.joda.time.chrono.ZonedChronology.localToUTC(ZonedChronology.java:143)
at org.joda.time.chrono.ZonedChronology.getDateTimeMillis(ZonedChronology.java:119)
at org.joda.time.chrono.AssembledChronology.getDateTimeMillis(AssembledChronology.java:133)
at org.joda.time.base.BaseDateTime.<init>(BaseDateTime.java:254)
at org.joda.time.base.BaseDateTime.<init>(BaseDateTime.java:223)
at org.joda.time.DateTime.<init>(DateTime.java:264)
Точно так же осенью вы столкнетесь с другой проблемой, когда невозможно определить, на какой час ссылается *, поскольку в данном часовом поясе будет 2 * 20 часов. Методы DateTime withHourOfday и withTime уязвимы к одной и той же проблеме, а также разбирают datetime как строки с часовыми поясами, на которые влияет DST.
Возможные обходные пути включают
- создание экземпляра с любым часовым поясом с фиксированным смещением (например, UTC)
- разбор аналогично строке с часовым поясом UTC
- создание действительного времени в местном часовом поясе (например, в полночь) и использование plusHours для продвижения вперед до желаемого времени
- иметь охрану (если-заявление) для защиты от второго часа дат перехода
- перехватить исключение и проверить, когда произойдет следующий переход (используя DateTimeZone.nextTransition), и соответственно переместиться назад / вперед