ТЛ; др
Как я могу быть уверен, что время всегда будет подходящим?
- Включите индикатор часовой пояс или смещение от UTC со строкой ввода даты-времени.
- При обмене значениями даты и времени используются стандартные форматы ISO 8601 .
- Использовать только java.time классы в Java. Никогда не используйте
Date
, Timestamp
, Calendar
и т. Д.
- Совет. Перед отправкой (в общем случае) настройте значения из других зон в UTC.
Если это невозможно, то вот обходной путь. Предполагается, что вы знаете часовой пояс, предназначенный отправителем этих неверных данных.
LocalDateTime // Represent a date and time-of-day without the context of a time zone or offset-from-UTC. NOT a moment, NOT a point on the timeline. A meaningless value until you assign a zone/offset.
.parse(
"2018-12-31-12.30.50.000200" , // Avoid such custom formats. Use only ISO 8601 when exchanging date-time values textually.
DateTimeFormatter.ofPattern( "uuuu-MM-dd-HH.mm.ss.SSSSSS" ) // Define formatting pattern to match youre input.
) // Returns a `LocalDateTime` object.
.atZone( // Give meaning to the `LocalDateTime` object by applying a time zone.
ZoneId.of( "Africa/Tunis" ) // Always specify a time zone with `Continent/Region` name, never the 2-4 character pseudo-zones popularly seen in the media.
) // Returns a `ZonedDateTime` object.
.toInstant() // Adjust from a time zone to UTC by extracting an `Instant` object. Same moment, same point on the timeline, different wall-clock time.
См. код, запущенный в режиме реального времени на IdeOne.com .
Лучше всего избегать java.util.Date
класса. Но если вам необходимо взаимодействовать со старым кодом, который еще не обновлен до java.time , вы можете выполнить конвертацию. Вызовите новые методы, добавленные к старым классам, таким как Date.from( Instant )
.
Избегайте старых классов
Никогда не используйте java.sql.Timestamp
и java.util.Date
. Все классы даты и времени, связанные с самыми ранними версиями Java, теперь являются устаревшими, согласно принятию JSR 310. Используйте только современные java.time классы.
Неверный тип данных
Вы используете неправильный тип данных. Чтобы отслеживать момент определенной точки на временной шкале, у вас должен быть часовой пояс или смещение от UTC. Класс LocalDateTime
совершенно не подходит для использования здесь. В этом классе намеренно отсутствует какое-либо понятие зоны или смещения. Так что это противоположность того, что вы хотите.
Чтобы отслеживать момент, используйте Instant
, OffsetDateTime
или ZonedDateTime
.
Если классы java.time имеют методы с необязательным аргументом часового пояса (ZoneId
) или offset-from-UTC (ZoneOffset
), считайте этот аргумент обязательным. Всегда передавать зону / смещение. Тогда вам не нужно беспокоиться о том, как системный администратор устанавливает текущий часовой пояс JVM по умолчанию во время выполнения.
ZonedDateTime.now( // Capture the current moment as seen through the wall-clock time used by the people of a particular region (a time zone).
ZoneId.of( "Pacific/Auckland" )
)
Или используйте Instant
, который всегда по UTC, по определению.
Instant.now() // Capture the current moment in UTC.
Укажите правильное имя часового пояса в формате Continent/Region
, например America/Montreal
, Africa/Casablanca
или Pacific/Auckland
. Никогда не используйте 2-4 буквенные сокращения, такие как EST
или IST
, так как они не истинные часовые пояса, не стандартизированы и даже не уникальны (!).
ISO 8601
Ваш вопрос неясен, но, похоже, вы получаете входную строку для даты-времени в произвольном формате. Я предлагаю вам обучить людей, публикующих эти данные о стандарте ISO 8601 . Этот стандарт определяет практические форматы для обмена значениями даты и времени между системами в текстовом формате.
Классы java.time по умолчанию используют форматы ISO 8601 при разборе / генерации строк.
Обход
Если издатель данных отправляет вам такие значения, как 2018-12-31-12.30.50.000200
, чтобы сообщить момент, они потерпели неудачу. Дата и время суток без зоны или смещения бесполезны, как, например, указание суммы денег без указания валюты.
Знаете ли вы наверняка часовой пояс, который неявно предполагался отправителем этого ошибочного ввода данных? Если так, примените это, как неуклюжую меру остановки для их плохой практики.
Сначала проанализируйте ваш ввод как LocalDateTime
, учитывая, что в нем отсутствует индикатор зоны / смещения.
String input = "2018-12-31-12.30.50.000200" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd-HH.mm.ss.SSSSSS" ) ;
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;
Примените ZoneId
, чтобы получить объект ZonedDateTime
, таким образом, настраивая его таким образом, чтобы видеть момент через часы настенного времени, используемые людьми в этом конкретном регионе.
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = ldt.atZone( ldt ) ;
Обычно лучше всего работать с моментами в UTC , если у вас нет особых причин использовать часовой пояс (например, презентация для пользователя). Так что извлеките Instant
из вашего ZonedDateTime
.
Instant instant = zdt.toInstant() ;
Z
в конце строки, соответствующей ISO 8601, означает UTC и произносится как «Zulu».
См. Этот код, запущенный в режиме реального времени на IdeOne.com .
ввод: 2018-12-31-12.30.50.000200
ldt: 2018-12-31T12: 30: 50.000200
zdt: 2018-12-31T12: 30: 50.000200 + 09: 00 [Азия / Токио]
мгновенный: 2018-12-31T03: 30: 50.000200Z
О 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?
ThreeTen-Extra Проект расширяет java.time дополнительными классами.Этот проект является полигоном для возможных будущих дополнений к java.time.Здесь вы можете найти некоторые полезные классы, такие как Interval
, YearWeek
, YearQuarter
и more .