OffsetDateTime Сравнение строк с OffsetDateTime.now () в Java - PullRequest
0 голосов
/ 20 февраля 2019

Я очень новичок в использовании OffsetDateTime и пытаюсь сравнить строки OffsetDateTime с OffsetDateTime.now () в Java таким образом,

import java.time.OffsetDateTime;

public class OffsetDateTimeDemo {
   public static void main(String[] args) {

      OffsetDateTime one = OffsetDateTime.parse("2017-02-03T12:30:30+01:00");
      System.out.println("First ::" + OffsetDateTime.now().compareTo(one));

      OffsetDateTime date1 = OffsetDateTime.parse("2019-02-14T00:00:00");
      System.out.println("Second ::" +  OffsetDateTime.now().compareTo(date1));

      OffsetDateTime date3 = OffsetDateTime.parse("Mon Jun 18 00:00:00 IST 2012");
      System.out.println(" Third :: " +OffsetDateTime.now().compareTo(date3));


   }
}   

Но я получаю исключение java.time.format.DateTimeParseException ввсе 3 случая.

Однако, если я сравниваю 2 строки OffsetDateTime с методом CompareTo, он работает нормально.

Может кто-нибудь пролить мне свет на этот счет и любезно подсказать мне мою ошибку.

Заранее спасибо.

1 Ответ

0 голосов
/ 20 февраля 2019

Ваша 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?

  • Java SE 8 , Java SE 9 , Java SE 10, Java SE 11 и более поздних версий - часть стандартного Java API с связанной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и JavaSE 7
    • Большинство функций java.time перенесены в Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии пакетов Android для реализации java.time классы.
    • Для более ранних версий Android (<26) проект <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"> ThreeTenABP адаптируется ThreeTen-Backport (упомянуто выше).См. Как использовать ThreeTenABP… .

ThreeTen-Extra Проект расширяет java.time дополнительными классами.Этот проект является полигоном для возможных будущих дополнений к java.time.Здесь вы можете найти несколько полезных классов, таких как Interval, YearWeek, YearQuarter и more .

...