java.time
Инфраструктура java.time в Java 8 и более поздних версиях заменяет старые классы java.util.Date/.Calendar. Старые классы оказались проблематичными, запутанными и ошибочными. Избегайте их.
Фреймворк java.time создан на основе чрезвычайно успешной библиотеки Joda-Time , определенной JSR 310 , расширенной проектом ThreeTen-Extra и объяснено в Tutorial .
Instant
Класс Instant
представляет момент на временной шкале в UTC .
Фреймворк java.time имеет разрешение наносекунд или 9 цифр доли секунды. Миллисекунды - это всего лишь 3 цифры доли секунды. Поскольку разрешение в миллисекундах является обычным явлением, java.time включает удобный заводской метод.
long millisecondsSinceEpoch = 1446959825213L;
Instant instant = Instant.ofEpochMilli ( millisecondsSinceEpoch );
миллисекунды С момента появления: 1446959825213 мгновенно: 2015-11-08T05: 17: 05.213Z
ZonedDateTime
Чтобы учесть текущую неделю и текущий месяц, нам нужно применить определенный часовой пояс.
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneId );
В zoneId: Америка / Монреаль: 2015-11-08T00: 17: 05.213-05: 00 [Америка / Монреаль]
Half-Open
В работе с датой и временем мы обычно используем подход Half-Open для определения промежутка времени. Начало включительно , а окончание эксклюзив . Вместо того, чтобы пытаться определить последнюю долю секунды в конце недели (или месяца), мы получаем первый момент после недели (или месяца). Таким образом, неделя начинается с первого момента понедельника и поднимается до , но не включает первый момент после понедельника.
Давайте первый день недели и последний. Среда java.time включает в себя инструмент для этого, метод with
и перечисление ChronoField
.
По умолчанию java.time использует стандарт ISO 8601 . Таким образом, понедельник - первый день недели (1), а воскресенье - последнее (7).
ZonedDateTime firstOfWeek = zdt.with ( ChronoField.DAY_OF_WEEK , 1 ); // ISO 8601, Monday is first day of week.
ZonedDateTime firstOfNextWeek = firstOfWeek.plusWeeks ( 1 );
Эта неделя начинается с: 2015-11-02T00: 17: 05.213-05: 00 [Америка / Монреаль] до 2015-11-09T00: 17: 05.213-05: 00 [Америка / Монреаль]
Oops! Посмотрите на время суток на эти значения. Мы хотим первый момент дня. Первый момент дня не всегда 00:00:00.000
из-за перехода на летнее время (DST) или других аномалий. Поэтому мы должны позволить java.time внести коррективы от нашего имени. Для этого мы должны пройти класс LocalDate
.
ZonedDateTime firstOfWeek = zdt.with ( ChronoField.DAY_OF_WEEK , 1 ); // ISO 8601, Monday is first day of week.
firstOfWeek = firstOfWeek.toLocalDate ().atStartOfDay ( zoneId );
ZonedDateTime firstOfNextWeek = firstOfWeek.plusWeeks ( 1 );
Эта неделя начинается с: 2015-11-02T00: 00-05: 00 [Америка / Монреаль] до 2015-11-09T00: 00-05: 00 [Америка / Монреаль]
И то же самое за месяц.
ZonedDateTime firstOfMonth = zdt.with ( ChronoField.DAY_OF_MONTH , 1 );
firstOfMonth = firstOfMonth.toLocalDate ().atStartOfDay ( zoneId );
ZonedDateTime firstOfNextMonth = firstOfMonth.plusMonths ( 1 );
Этот месяц начинается с: 2015-11-01T00: 00-04: 00 [Америка / Монреаль] до 2015-12-01T00: 00-05: 00 [Америка / Монреаль]
YearMonth
Другой способ проверить, находятся ли пары моментов в одном месяце, - это проверить одно и то же значение YearMonth
.
Например, предполагая, что thisZdt
и thatZdt
являются ZonedDateTime
объектами:
boolean inSameMonth = YearMonth.from( thisZdt ).equals( YearMonth.from( thatZdt ) ) ;
миллисекунды
Я настоятельно рекомендую не делать вашу работу с датой и временем в миллисекундах с эпохи. Это действительно способ, которым классы даты и времени работают внутренне, но у нас есть причины по причине. Обработка отсчетов из эпохи неуклюжа, так как значения не понятны людям, поэтому отладка и ведение журнала трудны и подвержены ошибкам. И, как мы уже видели, могут быть разные разрешения; старые классы Java и библиотека Joda-Time используют миллисекунды, в то время как базы данных, такие как Postgres, используют микросекунды, а теперь java.time использует наносекунды.
Будете ли вы обрабатывать текст как биты, или вы позволите таким деталям, как String
, StringBuffer
и StringBuilder
обрабатывать такие детали?
Но если вы настаиваете, из ZonedDateTime
получите Instant
, и из этого получите отсчет миллисекунд от эпохи. Но имейте в виду, этот вызов может означать потерю данных . Любые микросекунды или наносекунды, которые могут быть у вас в ZonedDateTime
/ Instant
, будут усечены (потеряны).
long millis = firstOfWeek.toInstant().toEpochMilli(); // Possible data loss.
О java.time
Платформа java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date
, Calendar
и & SimpleDateFormat
.
Чтобы узнать больше, см. Oracle Tutorial . И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310 .
Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на java.time классы.
Вы можете обмениваться java.time объектами напрямую с вашей базой данных. Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.*
классах.
Где получить классы java.time?