Спросите программно, есть ли момент в летнее время
Это время начала / окончания дня 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 ) ;