Зачем получать разные localDate с тем же часовым поясом - PullRequest
0 голосов
/ 03 сентября 2018
java.sql.Date date = java.sql.Date.valueOf("1900-01-01");
org.joda.time.LocalDate localDate = new org.joda.time.LocalDate(date);

На основе приведенного выше кода я провел несколько тестов, как показано ниже:

  • Вопрос # 1, почему я получаю другой объект localDate с одинаковым часовым поясом?

Если я изменю местный часовой пояс на UTC+8 Singapore Timezone, получу 1899-12-31

Если я изменю местный часовой пояс на UTC+8 China Timezone, получим 1900-01-01

  • Вопрос № 2, почему я получаю одно и то же время с другим часовым поясом?

Если я изменю местный часовой пояс на UTC-8 America/Los_Angeles Timezone, получим 1900-01-01

Если я изменю местный часовой пояс на UTC+8 China Timezone, получим 1900-01-01

Может ли кто-нибудь помочь прояснить это? это немного запутано.

Ответы [ 2 ]

0 голосов
/ 03 сентября 2018

ТЛ; др

java.time.LocalDate
.of( 
    1900 , 
    Month.JANUARY , 
    1 
) ;

Избегайте устаревших классов даты и времени

Вы используете ужасный старый класс java.sql.Date, который был плохо спроектирован с ошибочными взломами. Среди его проблем - то, что он делает вид, что представляет значение только для даты, но на самом деле содержит время суток. Он даже держит часовой пояс глубоко внутри, хотя и без геттера или сеттера. Никогда не используйте этот класс. Замененный лет назад классом java.time.LocalDate.

Проект Joda-Time также вытесняется классами java.time . Проект находится в режиме обслуживания, получая обновления и исправления критических ошибок, но новые функции не работают. Проект рекомендует перейти на классы java.time . Миграция проста, так как они разделяют схожие концепции, оба возглавляемые одним и тем же человеком, Стивеном Коулборном.

java.time.LocalDate

Используйте java.time.LocalDate, если вы хотите использовать значение только для даты без времени суток и без часового пояса. Все ваши проблемы, поднятые в вашем Вопросе, исчезнут.

java.time.LocalDate ld = LocalDate.of( 1900 , Month.JANUARY , 1 ) ;  // Simply a year-month-day date, no problems, no issues, no confusion. 

ld.toString (): 1900-01-01

Также обратите внимание, что java.time использует нормальную нумерацию, где 2018 означает 2018 год, а 1-12 означает январь-декабрь. Это резко отличается от проблемных классов наследства.


О 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?

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти некоторые полезные классы, такие как Interval, YearWeek, YearQuarter и more .

0 голосов
/ 03 сентября 2018

В 1900 году смещение в Singpore равно UTC +6:55:25, поэтому, когда вы создаете дату 1900-01-01 в часовом поясе Сингапура, она должна быть 1899-12-31T17:04:35Z[UTC], как показано ниже:

java.time.ZonedDateTime localDateTime = ZonedDateTime.of(1900, 01, 01, 0,
            0, 0, 0, ZoneId.of("Singapore"));

System.out.println(localDateTime.withZoneSameInstant(ZoneId.of("UTC")));
// 1899-12-31T17:04:35Z[UTC]

Однако при использовании java.sql.Date используется неправильное смещение UTC +08:00:

TimeZone.setDefault(TimeZone.getTimeZone("Singapore"));
java.sql.Date date = java.sql.Date.valueOf("1900-01-01");

java.time.Instant instant = Instant.ofEpochMilli(date.getTime());
System.out.println(instant);   // 1899-12-31T16:00:00Z

и когда вы создаете org.joda.time.LocalDateTime с этим неправильным значением, Joda использует UTC +6:55:25 в качестве смещения, что приводит к дате 1899-12-31T16:00:00 + 6:55:25:

org.joda.time.LocalDateTime singaporeDateTime = new org.joda.time.LocalDateTime(date);
System.out.println(singaporeDateTime);  // 1899-12-31T22:55:25.000 

Вы можете использовать аналогичный подход для проверки результатов в Шанхае и Лос-Анджелесе, суть в том, чтобы избегать использования java.sql.Date и других устаревших классов, связанных с датой и временем. Вместо этого используйте java.time, если вы работаете с java8 или новее.

...