Нет летнего времени в Иране в 1970 году
Часовой пояс для Ирана, Asia/Tehran
, имеет значение Летнее время (летнее время) летом 2018 года, но не сделал этого обратно в1970.
Летом 2018 года Иран опережает UTC на четыре с половиной часа, а не на три с половиной.Таким образом, изменение с 4:55 по UTC должно привести к 9:25 в летний день, а не к 8: 25.
System.out.println(
OffsetDateTime.of(
LocalDate.of( 2018 , Month.JUNE , 1 ) ,
LocalTime.parse( "04:55" ) ,
ZoneOffset.UTC
)
.atZoneSameInstant(
ZoneId.of( "Asia/Tehran" )
)
);
2018-06-01T09: 25 + 04: 30 [Азия /Тегеран]
Но я подозреваю, что ваш код по умолчанию использует ссылку эпохи дату первого момента 1970 года в UTC при разборе вашей строки, 1970-01-01T00: 00: 00Zпотому что вы злоупотребляете этим классом, пытаясь разобрать время суток без указания даты.
В 1970 году Иран не наблюдал переход на летнее время (DST).Таким образом, смещение было на три с половиной часа до UTC летом 1970 года по сравнению с четырьмя с половиной часами до UTC летом 2018 года.
System.out.println(
OffsetDateTime.of(
LocalDate.EPOCH ,
LocalTime.parse( "04:55" ) ,
ZoneOffset.UTC
)
.atZoneSameInstant(
ZoneId.of( "Asia/Tehran" )
)
);
1970-01-01T08: 25+03:30 [Азия / Тегеран]
Неправильные классы
Вы используете неправильные классы.
Вы хотите представить значение времени дня.Таким образом, вы должны использовать класс времени дня.Но вы используете урок «дата со временем», java.util.Date
.
Вы используете неприятные, плохо продуманные классы даты и времени, java.util.Date
& java.text.SimpleDateFormat
.Они были вытеснены несколько лет назад классами java.time .Избегайте старых классов полностью.Используйте только классы, найденные в java.time пакете .
Время дня
Анализ строки времени дня.
LocalTime.parse( "04:55" )
Получите текущее время суток.
LocalTime.now() // Capture the current time of day per the JVM’s current default time zone.
Лучше явно заявить о своем намерении использовать текущий часовой пояс JVM по умолчанию.
LocalTime.now(
ZoneId.systemDefault() // Capture the current time of day by explicitly asking for the JVM’s current default time zone.
)
Или укажите конкретный часовой пояс.
LocalTime.now(
ZoneId.of( "Asia/Kabul" ) // Capture the current time-of-day as seen in the wall-clock time used by the people of a particular region (a time zone).
)
9: 25
Получите текущее время в UTC.
LocalTime.now(
ZoneOffset.UTC
)
04: 55
LocalTime
Если у вас есть строка ввода, такая как «04:55», анализируйте как LocalTime
объект.Этот класс представляет время суток без даты и без часового пояса.
String input = "04:55" ;
LocalTime lt = LocalTime.parse( input ) ;
Терминология
Я пытаюсь преобразовать время UTC в местное время
Ваша фраза «местное время» имеет особое значение при обработке даты и времени.К сожалению, это значение является противоположным вашего намерения.Слово «местный», как видно из классов * java.time.Local… », означает любой населенный пункт или все населенных пунктов, а не какой-либо один конкретный населенный пункт.
ИтакLocalTime
объект не имеет реального значения, пока не будет прикреплен к дате и помещен в контекст часового пояса (или смещения от UTC).
Часовые пояса
Если время UTC - 04:55, часы моего телефона - 9: 25
Это означает, что текущий часовой пояс по умолчанию вашей JVM -используя смещение от UTC за четыре с половиной часа до UTC, +04:30
.Согласно этому списку часовых поясов как , управляемым IANA , в настоящее время используется только один часовой пояс, использующий это смещение: Asia/Kabul
.
Чтобы полностью представить текущий момент, вам нужны дата и время дня, а также зона / смещение.Чтобы зафиксировать текущий момент, используйте Instant
.Класс Instant
представляет момент на временной шкале в UTC с разрешением наносекунд (до девяти (9) цифр десятичной дроби).
Instant instant = Instant.now() ; // Capture the current moment in UTC.
Чтобы увидеть тот же момент в вашем часовом поясе, примените ZoneId
, чтобы получить ZonedDateTime
.
ZoneId zKabul = ZoneId.of( "Asia/Kabul" ) ;
ZonedDateTime zdt = instant.atZone( zKabul ) ;
Если вам действительно нужна только часть времени этого значения, извлеките LocalTime
.Это может быть полезно для рендеринга в пользовательском интерфейсе, но вряд ли полезно в вашей бизнес-логике.
LocalTime lt = zdt.toLocalTime() ; // Extract just the time-of-day as seen in the wall-clock time used by the people of this region (this time zone).
В качестве ярлыка вы можете вызвать LocalTime.now
:
LocalTime lt = LocalTime.now( zKabul ) ;
Иранское время
Позже вВ наших комментариях вы поясните, что предполагаемый часовой пояс составляет Asia/Tehran
, время в Иране .В настоящее время Иран соблюдает переход на летнее время (DST), что может стать причиной вашей путаницы.При стандартном смещении, если +03: 30 (за три с половиной часа до UTC), в период с 22 марта по 22 сентября смещение составляет +04: 30, еще на один час впереди по UTC.
Именно поэтому вы должны указать желаемый / ожидаемый часовой пояс.Для случайного использования вы можете использовать текущий часовой пояс JVM по умолчанию.Но знайте, что значение по умолчанию может измениться в любой момент во время выполнения.И по умолчанию может не соответствовать вашим намерениям.Для критического использования всегда подтверждайте пользователю предполагаемый часовой пояс.
Давайте создадим дату-время для 1 июня с вашим примером времени 4:55 в UTC.Мы можем использовать константу ZoneOffset.UTC
.При использовании просто смещения от UTC (смещение нуля в данном случае), используйте OffsetDateTime
. смещение от UTC - это просто количество часов и минут, ни больше, ни меньше.Напротив, часовой пояс - это история прошлых, настоящих и будущих изменений в смещении, используемом людьми определенного региона.
LocalTime lt = LocalTime.parse( "04:55" ) ;
LocalDate ld = LocalDate.of( 2018 , Month.JUNE , 1 ) ;
OffsetDateTime odt = OffsetDateTime.of( ld , lt , ZoneOffset.UTC ) ;
odt.toString (): 2018-06-01T04: 55Z
Настройтесь на зону Asia/Tehran
, применив ZoneId
, чтобы получитьZonedDateTime
.Тот же момент, та же точка на временной шкале, но другое время на настенных часах.
ZoneId zTehran = ZoneId.of( "Asia/Tehran" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( zTehran );
zdt.toString (): 2018-06-01T09: 25 + 04: 30 [Азия / Тегеран]
Обратите внимание, что время дня летом показывает 9 часов, а не 8.
Попробуйте использовать тот же код с январским месяцем, когда летнее время равно не в силе.
LocalTime lt = LocalTime.parse( "04:55" );
LocalDate ld = LocalDate.of( 2018 , Month.JANUARY , 1 );
OffsetDateTime odt = OffsetDateTime.of( ld , lt , ZoneOffset.UTC );
ZoneId zTehran = ZoneId.of( "Asia/Tehran" );
ZonedDateTime zdt = odt.atZoneSameInstant( zTehran );
zdt.toString (): 2018-01-01T08: 25 + 03: 30 [Азия / Тегеран]
Теперь мысм. час 8.
Имена зон
Укажите правильное имя часового пояса в формате continent/region
, например, America/Montreal
, Africa/Casablanca
или Pacific/Auckland
.Никогда не используйте 3-4-буквенное сокращение, такое как EST
или IST
, поскольку они не истинные часовые пояса, не стандартизированы и даже не уникальны (!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
Если вы хотите использовать текущий часовой пояс JVM по умолчанию, запросите его и передайте в качестве аргумента.Если опущено, текущее значение по умолчанию JVM применяется неявно.Лучше быть явным, поскольку значение по умолчанию может быть изменено в любой момент во время выполнения любым кодом в любом потоке любого приложения в JVM.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
О java.time
Фреймворк java.time встроен в Java 8 и более поздние версии.Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date
, Calendar
, & SimpleDateFormat
.
Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на классы java.time .
Чтобы узнать больше, см. Oracle Tutorial .И поиск переполнения стека для многих примеров и объяснений.Спецификация: JSR 310 .
Вы можете обмениваться java.time объектами непосредственно с вашей базой данных.Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии.Нет необходимости в строках, нет необходимости в java.sql.*
классах.
Где получить классы java.time?
- Java SE 8 , Java SE 9 , Java SE 10, а позже
- Встроенный.
- Часть стандартного Java API с встроенной реализацией.
- Java 9 добавляет некоторые незначительные функции и исправления.
- Java SE 6 и Java SE 7
- Android
- Более поздние версии Android связывают реализации классов java.time.
- Для более ранних версий Android (<26) проект <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"> ThreeTenABP адаптируется ThreeTen-Backport (упомянутое выше).См. Как использовать ThreeTenABP… .
ThreeTen-Extra Проект расширяет java.time дополнительными классами.Этот проект является полигоном для возможных будущих дополнений к java.time.Здесь вы можете найти несколько полезных классов, таких как Interval
, YearWeek
, YearQuarter
и more .