UTC
Think, работа, и хранить данные в UTC, а не любой часовой пояс. Подумайте о UTC как One True Time, а все остальные часовые пояса - это просто варианты. Поэтому, кодируя, забудьте все о своем часовом поясе. Сделайте свою бизнес-логику, протоколирование, хранение данных и обмен данными в UTC. Я предлагаю, чтобы каждый программист держал на часах часы, установленные на UTC.
java.time
Современный способ является java.time классы.
Проект Joda-Time предоставил вдохновение для классов java.time, и проект теперь находится в режиме обслуживания с командой, предлагающей переход на классы java.time.
Рамка java.time встроена в Java 8 и более поздних версий. Эти классы вытесняют неприятные старые legacy классы времени, такие как java.util.Date
, .Calendar
, & java.text.SimpleDateFormat
.
Чтобы узнать больше, см. Oracle Tutorial. И поиск Stack Overflow для многих примеров и объяснений. Спецификация: JSR 310.
Где получить классы java.time?
- Java SE 8 и SE 9, а затем
- Встроенный.
- Часть стандартного Java API с объединенной реализацией.
- Java 9 добавляет некоторые незначительные функции и исправления.
- Java SE 6 и SE 7
- Большая часть функциональности java.time будет обратно портирован на Java 6 & 7 в ThreeTen-Backport.
- Android
- Проект ThreeTenABP адаптирует ThreeTen-Backport (как упоминалось выше) для Android специально.
- См. How to use….
Проект ThreeTen-Extra расширяет java.time с дополнительными классами. Этот проект является доказательством возможных будущих дополнений к java.time. Здесь вы можете найти полезные классы, такие как Interval
, YearWeek
, YearQuarter
и more.
ISO 8601
При сериализации значение даты и времени в текст, использовать стандарт ISO 8601.
Например, время в UTC: 2016-10-17T01:24:35Z
Адрес Z
Номер модели: Zulu
и означает UTC. Для других offset-from-UTC в конце появляется смещение часов и минут, например 2016-01-23T12:34:56+05:30
. Классы java.time расширяют этот стандартный формат, чтобы добавить имя часового пояса (если известно) в квадратных скобках, например 2016-01-23T12:34:56+05:30[Asia/Kolkata]
.
Стандарт имеет множество других удобных форматов, а также в том числе для durations, intervals, ordinals и year-week.
Database
Для хранения баз данных, использование типов даты и времени для значений даты и времени, например, SQL standard data types которые в первую очередь DATE
, TIME
и TIMESTAMP WITH TIME ZONE
.
Позвольте вашему JDBC driver сделать тяжелый подъем. Драйвер обрабатывает подробные сведения о посредничестве и адаптации между внутренними системами того, как Java обрабатывает данные и как ваша база данных обрабатывает данные на своей стороне. Но обязательно ознакомьтесь с примерами данных, чтобы узнать поведение вашего драйвера и вашей базы данных. Стандарт SQL очень мало описывает обработку с датой и временем, поэтому поведение сильно различается, что удивительно.
Если вы используете драйвер JDBC, совместимый с JDBC 4.2 и более поздними версиями, вы можете напрямую загружать и хранить типы java.time с помощью методов ResultSet::getObject
и PreparedStatement::setObject
.
Instant instant = myResultSet.getObject(…);
myPreparedStatement.setObject(… , instant);
Для старых драйверов вам необходимо вернуться к преобразованию типов java.sql. Ищите новые методы преобразования, добавленные в старые классы. Например, java.sql.Timestamp.toInstant()
.
Instant instant = myResultSet.getTimestamp(…).toInstant();
myPreparedStatement.setObject(… , java.sql.Timestamp.from(instant));
Используйте типы java.sql как можно короче. Они плохо обработаны, например, java.sql.Date
, маскируясь как значение только для даты, но на самом деле в качестве подкласса java.util.Date
оно действительно имеет время, установленное для 00:00:00
в UTC. И, о, вы должны игнорировать факт того, что наследование говорит класс doc. Уродливый беспорядок.
Пример кода
Получить текущий момент в UTC.
Instant instant = Instant.now();
Сохранение и извлечение, что Instant
объект/из базы данных показано выше.
Чтобы создать строку ISO 8601, просто вызовите toString
. Ява.во всех классах по умолчанию используются форматы ISO 8601 по умолчанию для синтаксического анализа и генерации строк их различных значений даты и времени.
String output = instant.toString();
Adjust в любой офсетной из-UTC с применением ZoneOffset
, чтобы получить OffsetDateTime
. Вызовите toString
для создания строки в формате ISO 8601.
ZoneOffset offset = ZoneOffset.ofHoursMinutes(5 , 30);
OffsetDateTime odt = instant.atOffset(offset);
Временной зона является смещением плюса набором правил для обработки аномалий, таких как Daylight Saving Time (DST). Когда вам нужно увидеть тот же самый момент через объектив своего региона wall-clock time, примените часовой пояс (ZoneId
), чтобы получить объект ZonedDateTime
.
Укажите proper time zone name в формате continent/region
. Никогда не используйте аббревиатуру 3-4 буквы, такую как EST
или IST
, поскольку они не являются настоящими часовыми поясами, а не стандартизированы и даже не уникальны (!).
ZoneId z = ZoneId.of("Asia/Kolkata");
ZonedDateTime zdt = instant.atZone(z);
Переход в другую сторону, вы можете извлечь Instant
из OffsetDateTime
или ZonedDateTime
по телефону toInstant
.
Instant instant = zdt.toInstant();
Форматирование
Для представления пользователю в виде строк в отличных от ISO 8601, search Stack Overflow для использования DateTimeFormatter
класса форматов.
Пока вы можете указать нестандартный формат, обычно лучше всего разрешить java.time автоматически локализовать. Чтобы локализовать, укажите:
FormatStyle
, чтобы определить, насколько длинной или сокращенной должна быть строка.
Locale
определить (а) человеческий язык для перевода имени дня, названия месяца и т. Д. И (b) культурных норм, решающих вопросы сокращения, капитализации, пунктуации и т. Д.
Пример:
Locale l = Locale.CANADA_FRENCH ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale(l);
String output = zdt.format(f);
Конверсия
Лучше всего, чтобы избежать типов даты и времени унаследованных всякий раз, когда это возможно. Но если вы работаете со старым кодом, который еще не обновлен для типов java.time, вы можете конвертировать в/из типов java.time. Подробнее см. В Вопросе, Convert java.util.Date to what “java.time” type?.
Использование объектов
Использование объектов, а не простые закодированных примитивов и простых строк. Например:
- Не использовать 1-7, чтобы представить день-неделю, используйте
DayOfWeek
перечисление таких как DayOfWeek.TUESDAY
.
- Вместо того чтобы проходить вокруг строки в качестве даты, пройдите около
LocalDate
объектов.
- Вместо того чтобы проходить пару целых чисел за год и месяц, пройдите около
YearMonth
объектов.
- Вместо 1-12 в течение месяца используйте гораздо более читаемый список
Month
, такой как Month.JANUARY
.
Использование таких объектов делает ваш код более самодокументированным, обеспечивает достоверные значения и предоставляет type-safety.
bla bla bla, joda time, bla bla bla ... –