tl; dr
- Вы игнорируете критическую проблему часового пояса.Вы невольно анализируете ввод как значение в UTC.
- Вы используете ужасные старые классы даты и времени, которые были вытеснены несколько лет назад.Вместо этого используйте java.time .
Пример кода:
LocalDateTime
.parse(
"2018-01-23 13:45".replace( " " , "T" ) // Comply with standard ISO 8601 format by replacing SPACE with `T`. Standard formats are used by default in java.time when parsing/generating strings.
) // Returns a `LocalDateTime` object. This is *not* a moment, is *not* a point on the timeline.
.atZone( // Apply a time zone to determine a moment, an actual point on the timeline.
ZoneId.of( "America/Montreal" )
) // Returns a `ZonedDateTime` object.
.toInstant() // Adjust from a time zone to UTC, if need be.
java.time
В современном подходе используется java.time классы.
Ваша входная строка почти в стандартном формате ISO 8601.Чтобы полностью соответствовать, замените этот ПРОБЕЛ в середине на T
.
String input = "2018-01-23 13:45".replace( " " , "T" ) ;
Разобрать как LocalDateTime
, потому что на вашем входе нет индикатора часового пояса или смещения от UTC.
LocalDateTime ldt = LocalDateTime.parse( input ) ;
A LocalDateTime
по определению не представляет момент, является не точкой на временной шкале.Он представляет потенциальных моментов в диапазоне около 26-27 часов (диапазон часовых поясов по всему миру).
Чтобы определить момент, назначьте часовой пояс (ZoneId
), чтобы получить объект ZonedDateTime
.
Укажите правильное имя часового пояса в формате continent/region
, например America/Montreal
, Africa/Casablanca
или Pacific/Auckland
.Никогда не используйте 3-4-буквенное сокращение, например EST
или IST
, поскольку они не истинных часовых поясов, не стандартизированы и даже не уникальны (!).
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
Если вы хотите увидеть тот же момент во время часового пояса UTC, извлеките Instant
.
Instant instant = zdt.toInstant() ; // Adjust from some time zone to UTC.
Избегайте java.util.Date
, где это возможно.Но если вам необходимо взаимодействовать со старым кодом, который еще не обновлен до java.time , вы можете конвертировать туда и обратно.Вызовите новые методы преобразования, добавленные к старым классам.
java.util.Date d = java.util.Date.from( instant ) ; // Going the other direction: `myJavaUtilDate.toInstant()`
О java.time
java.time Framework встроен в Java 8 и более поздние версии.Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date
, Calendar
, & SimpleDateFormat
.
Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на классы java.time .
Чтобы узнать больше, см. Oracle Tutorial .И поиск переполнения стека для многих примеров и объяснений.Спецификация: JSR 310 .
Вы можете обмениваться java.time объектами непосредственно с вашей базой данных.Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии.Нет необходимости в строках, нет необходимости в java.sql.*
классах.
Где получить классы java.time?
ThreeTen-Extra Проект расширяет java.time дополнительными классами.Этот проект является полигоном для возможных будущих дополнений к java.time.Здесь вы можете найти несколько полезных классов, таких как Interval
, YearWeek
, YearQuarter
и еще .