Как правильно преобразовать новую дату (0L) в LocalDate (1970-01-01)? - PullRequest
0 голосов
/ 17 сентября 2018

Рассмотрим код:

import org.junit.Test;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;

import static org.assertj.core.api.Assertions.assertThat;

/**
 * @author nsheremet
 */
public class MyTest {
    private static final Date CREATED_ON = new Date(0L);

    @Test
    public void someTest() {
        LocalDate actualDate = CREATED_ON.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDate();
        assertThat(actualDate).isEqualTo(LocalDate.of(1970, 01, 01));
    }
}

На моей машине это работает хорошо, но на других я получил исключение:

[ERROR] Failures: 
[ERROR] MyTest.someTest:23 expected: <19[70-01-0]1> but was:<19[69-12-3]>1 

Почему это происходит?Использование UTC вместо ZoneId.systemDefault() является corrent?

Ответы [ 3 ]

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

Почему это происходит? Использование UTC вместо ZoneId.systemDefault() исправить?

Да. EPOCH для java.util.Date равно 1 января 1970 г. 00: 00: 00.000 UTC , но ZoneId.systemDefault() извлечет то, что текущий компьютер настроен для использования в качестве часового пояса пользователя. Крайне маловероятно, что будет UTC.

Так что вам нужно использовать часовой пояс UTC, а не что-либо еще.

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

tl; др

Instant
.ofEpochMilli( 0L ) 
.atOffset( 
    ZoneOffset.UTC
)
.toLocalDate()
.toString()

1970-01-01

java.util.Date

java.util.Date представляет момент в UTC,дата с временем суток.

Ваш код:

new Date(0L)

… произвел объект, представляющий первый момент 1970 года в UTC, 1970-01-01T00: 00: 00Z.

Часовой пояс

В тот же момент, попросив кого-нибудь по телефону в Индии сообщить вам время дня, которое они видят на часах, вы получите ответ «5:30».AM».Часовой пояс Asia/Kolkata в тот момент использовал смещение на пять с половиной часов впереди UTC.

Если вы позвоните кому-нибудь из Монреаля в Квебеке, вы получите ответ «7 вечера… даты 1969-12-31».Часовой пояс America/Montreal на эту дату использовал смещение в пять часов после UTC.Быть на часах позади полуночи в UTC означает быть в день позади, тоже в последний день 1969 года, а не в первый день 1970 года. То же самое для зоны America/New_York и большей части восточного побережья Северной Америки.

Итак, вы должны понимать, что в любой данный момент дата меняется по всему земному шару, дата меняется в зависимости от зоны.Когда в Японии наступает новый день, например, в Бразилии это «вчера».

java.time

Класс Date ужасен и никогда не должен использоваться .Наряду с Calendar это теперь наследие, вытесненное годами назад классами java.time .В частности, Date заменяется на Instant, оба класса представляют момент в UTC.

Instant instant = Instant.ofEpochMilli( 0L ) ;

instant.toString (): 1970-01-01T00: 00Z

Настройте время настенных часов, используемое людьми определенного региона,часовой пояс.Примените ZoneId, чтобы получить ZonedDateTime объект.

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

Извлечение части, содержащей только дату, без времени суток и без зоны.

LocalDate ld = zdt.toLocalDate() ;

ld.toString (): 1969-12-31

Если вы хотите остаться в UTC, примените ZoneOffset константу ZoneOffset.UTCвместо ZoneId.И получите OffsetDateTime, а не ZonedDateTime.

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;

Извлечение значения только для даты, a LocalDate.

LocalDate ld = odt.toLocalDate() ;

ld.toString (): 1970-01-01

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

Возможная проблема заключается в том, что обе ваши машины находятся в разных часовых поясах.Проверьте ZoneId на обеих машинах (если они одинаковые).

Может быть, вы хотите установить определенный ZoneId, чтобы результаты всегда были одинаковыми?

...