Как я могу получить UT C Момент startDate и endDate сегодняшнего дня в указанном c часовом поясе («Европа / Париж») - PullRequest
1 голос
/ 12 апреля 2020

Я хочу получить время UT C (так как моя БД хранится в UT C) из Java (что также в UT C) определенного часового пояса, это то, что у меня есть до сих пор пробовал:

    public static Instant getStartOfTheDayDateTime(Instant instant, String zoneId) {

        ZonedDateTime zoned = instant.atZone(ZONE_ID_TO_ZONE_MAP.get(zoneId));
        ZoneId zone = ZoneId.of(zoneId);

        return zoned.toLocalDate().atStartOfDay(zone).toInstant();
//        ZonedDateTime startOfTheDay = zoned.withHour(0)
//                .withMinute(0)
//                .withSecond(0)
//                .withNano(0);
//
//        return startOfTheDay.toInstant();
    }

    public static Instant getEndOfTheDayDateTime(Instant instant, String zoneId) {
        ZonedDateTime zoned = instant.atZone(ZONE_ID_TO_ZONE_MAP.get(zoneId));
        ZonedDateTime endOfTheDay = zoned.withHour(0)
                .withMinute(0)
                .withSecond(0)
                .withNano(0)
                .plusDays(1);
        return endOfTheDay.toInstant();

    }

Каждая попытка показывает:

2020-04-10 22:00:00.0(Timestamp), 2020-04-11 22:00:00.0(Timestamp)
  • Это время начала / окончания дня UT C в Европе / зоне Парижа?
  • Я ожидал получить 2020-04-11 02:00:00.0(Timestamp), 2020-04-12 02:00:00.0(Timestamp)

Ответы [ 3 ]

3 голосов
/ 12 апреля 2020

Сейчас в Париже летнее время: UTC + 2. Париж опережает UT C на 2 часа

2 голосов
/ 12 апреля 2020

Спросите программно, есть ли момент в летнее время

Это время начала / окончания дня UT C в Европе / зоне Парижа?

Получить начало дня.

ZoneId z = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdtStartOfDay = instant.atZone( z ).toLocalDate().atStartOfDay( z ) ; 

Спросите, находится ли этот момент в DST для этой зоны.

ZoneRules rules = z.getRules();
boolean isDst = rules.isDaylightSavings( zdtStartOfDay.toInstant() );

Передайте объекты даты-времени, а не просто строки

public static Instant getStartOfTheDayDateTime(Instant instant, String zoneId)

Я предлагаю вам попросить вызывающего программиста передать действительный объект ZoneId, а не просто строку. Этот метод не должен проверять их строковые данные. Если разумно ожидать Instant, то также разумно ожидать ZoneId.

 public static Instant getStartOfTheDayDateTime(Instant instant, ZoneID zoneId )

Half-Open

public static Instant getEndOfTheDayDateTime(Instant instant, String zoneId) {

Попытка определить последний момент дня невозможна из-за бесконечно делимой последней секунды ,

Также такой подход к определению промежутка времени неудобен. Это затрудняет стыковку нескольких пролетов. Разные программные системы и протоколы различаются по разрешающей способности в течение последней доли секунды, используя миллисекунды, микросекунды, наносекунды или некоторые другие доли.

Обычная практика обработки даты и времени заключается в отслеживании промежутка времени с использованием Полуоткрытый подход. В Half-Open начало включительно , а окончание эксклюзивно .

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

ZoneId z = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdtStartOfDay = instant.atZone( z ).toLocalDate().atStartOfDay( z ) ; 
ZonedDateTime zdtStartOfNextDay = instant.atZone( z ).toLocalDate().plusDays( 1 ).atStartOfDay( z ) ;

Возможно, вы захотите разбить этот код на несколько строк, чтобы упростить чтение / отладку.

Instant instant = Instant.now() ;  // Or passed in. 
ZoneId z = ZoneId.of( "Europe/Paris" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
LocalDate ld = zdt.toLocalDate() ;
LocalDate ldNextDay = ld.plusDays( 1 ) ;
ZonedDateTime zdtStartOfNextDay = ldNextDay.atStartOfDay( z ) ;

См. Этот код, запущенный на IdeOne.com . Например:

System.out.println( instant ) ;             // 2020-04-13T00:15:25.235341Z
System.out.println( zdt ) ;                 // 2020-04-13T02:15:25.235341+02:00[Europe/Paris]
System.out.println( ld ) ;                  // 2020-04-13
System.out.println( ldNextDay ) ;           // 2020-04-14
System.out.println( zdtStartOfNextDay ) ;   // 2020-04-14T00:00+02:00[Europe/Paris]

ThreeTen-Extra Interval

Если вы выполняете такую ​​работу часто, то я предлагаю добавить ThreeTen-Extra библиотека для вашего проекта. Эта библиотека включает в себя класс Interval для отслеживания промежутка времени в виде пары Instant объектов.

Interval interval = Interval.of( zdtStartOfDay.toInstant() , zdtStartOfNextDay.toInstant() ) ;

Затем можно использовать несколько удобных методов сравнения. такие как abuts, contains, encloses, intersection, overlaps и union.

Timestamp

Никогда не используйте класс java.sql.Timestamp. Этот класс является частью ужасных классов даты и времени, которые поставлялись с самыми ранними версиями Java. Эти классы теперь унаследованы, полностью заменены современными java .time классами, определенными в JSR 310 и встроенными в Java 8 и более поздние.

Начиная с JDB C 4.2 мы можем обмениваться java .time объектами с базой данных. Используйте getObject и setObject и updateObject.

JDB C spe c, как ни странно, требует поддержки OffsetDateTime, но не более часто используемых Instant и ZonedDateTime. Ваш конкретный драйвер может поддерживать эти другие типы. Если нет, преобразуйте.

Извлечение из базы данных.

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Instant instant = odt.toInstant() ;

Отправка в базу данных.

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;
2 голосов
/ 12 апреля 2020

Это время начала / окончания дня UT C в Европе / зоне Парижа?

Да. Европа / Париж в летнее время. Полночь в Париже произошла в 22:00 UT C время.

Я ожидал, что 2020-04-11 02: 00: 00.0 (метка времени), 2020-04-12 02:00 : 00.0 (метка времени)

Это не правильно, 02:00 UT C было бы 04:00 по парижскому времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...