Ваша compareTo
кодировка отвлекает.Ваше исключение касается разбора строковых входных данных в объекты.
Еще одна проблема: вы используете неправильные классы на втором и третьем входах.
Другая проблема: вы неявно полагаетесь на текущий часовой пояс JVM по умолчанию при вызове now()
.Плохая практика, так как любое программистское чтение не будет знать, предполагали ли вы значение по умолчанию или не знали о проблеме, как это делают многие программисты.Кроме того, текущее значение по умолчанию может быть изменено в любой момент во время выполнения любым кодом в любом потоке любого приложения в JVM.Поэтому лучше всегда явно указывать желаемую / ожидаемую зону или смещение.
OffsetDateTime.now(
ZoneOffset.UTC
)
Или, что еще лучше, используйте ZonedDateTime
, чтобы получить больше информации, чем OffsetDateTime
.
ZonedDateTime.now(
ZoneId.of( "Pacific/Auckland" )
)
Первый: OffsetDateTime
работает
Вашпервый ввод строки является правильным и успешно анализируется.
OffsetDateTime.parse( "2017-02-03T12:30:30+01:00" )
Полная строка кода:
OffsetDateTime odt = OffsetDateTime.parse( "2017-02-03T12:30:30+01:00" ) ;
См. этот код, запущенный в режиме реального времени на IdeOne.com .
odt.toString (): 2017-02-03T12: 30: 30 + 01: 00
Для сравнения извлеките Instant
,Это эффективно регулирует ваш момент от некоторого смещения до смещения нуля или самого UTC.Instant
всегда в UTC, по определению.
Instant instant = Instant.now() ; // Capture the current moment as seen in UTC.
boolean odtIsPast = odt.toInstant().isBefore( instant ) ;
Секунда: LocalDateTime
В вашем входе второй строки отсутствует индикатор offset-from-UTC или часовой пояс .Так что OffsetDateTime
- неправильный класс для использования.Вместо этого используйте LocalDateTime
, в котором отсутствует какое-либо понятие смещения или зоны.
Это означает, что LocalDateTime
не может представлять момент.Например, полдень 23 января этого года может означать полдень на Asia/Tokyo
, что будет на несколько часов раньше полудня на Europe/Paris
, или это может означать полдень на America/Montreal
, который будет на мгновение даже на несколько часов позже.Без контекста зоны или смещения LocalDateTime
не имеет реального значения.Так что сравнивать LocalDateTime
с текущим моментом бессмысленно .
LocalDateTime.parse( "2019-02-14T00:00:00" )
См. Этот код, запущенный в режиме реального времени на IdeOne.com .
ldt.toString (): 2019-02-14T00: 00
Сравнивать нельзя - нелогично, как обсуждалось выше.Вы должны назначить часовой пояс (или смещение), чтобы определить момент на временной шкале.Если вы знаете для определенного , эта дата и время предназначались для определенного часового пояса, присвойте ZoneId
, чтобы получить ZonedDateTime
.Затем извлеките Instant
для сравнения.
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ; // India time.
ZonedDateTime zdt = ldt.atZone( z ) ;
Instant instant = Instant.now() ; // Capture the current moment as seen in UTC.
boolean zdtIsPast = zdt.toInstant().isBefore( instant ) ; // Compare.
Кстати, я заметил, что время суток равно нулю.Если ваша цель состояла в том, чтобы представлять только дату, без какого-либо времени суток и без какой-либо зоны, используйте LocalDate
class.
Third: не беспокойтесь, неоднозначный ввод
Yourтретья строка ввода содержит индикатор часового пояса.Таким образом, он должен быть проанализирован как ZonedDateTime
.
К сожалению, вы выбрали ужасный формат строки для анализа.Никогда не используйте псевдозоны из 2-4 символов, такие как IST
.Они не стандартизированы.И они не уникальны!Ваше IST
может означать Стандартное время Ирландии или Стандартное время Индии или другие.
Укажите собственное имя часового пояса в формате Continent/Region
, например America/Montreal
, Africa/Casablanca
или Pacific/Auckland
.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
См. Этот код, запущенный в режиме реального времени на IdeOne.com .
zdt.toString (): 2019-02-20T22: 34: 26.833+01:00 [Африка / Тунис]
Вы можете попробовать , чтобы разобрать это.ZonedDateTime
сделает предположение о том, какая зона подразумевается под IST
.Но это будет всего лишь предположение, и поэтому оно ненадежно, учитывая изначально неоднозначный вклад.Лично я бы отказался это кодировать, отклонив эти входные данные обратно к их источнику.
Если вы настаиваете на этой ненадежной попытке анализа, см. правильный ответ на подобный вопрос , который вы недавно задавали.
Сообщите вашему источнику овсегда использовать стандартные форматы ISO 8601 для обмена значениями времени и даты в виде удобочитаемого текста.
*Классы 1140 * java.time по умолчанию используют эти форматы ISO 8601 при разборе / генерации строк.Класс ZonedDateTime
разумно расширяет стандарт, добавляя стандартное название часового пояса в квадратных скобках.
О 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 .