Разница между датой предоставления (дата UTC) и текущей датой в днях с использованием Java 8 - PullRequest
1 голос
/ 19 июня 2019

В мой метод будет введено String, содержащее дату в UTC.Мне нужно сравнить дату ввода с текущей датой и временем и проверить разницу между двумя датами.Результат должен быть в днях.

Я попробовал следующее безуспешно.

String dateString = "2019-06-18T16:23:41.575 UTC";
final DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS 'UTC'").withZone(ZoneId.of("UTC"));
OffsetDateTime parsedDate  = OffsetDateTime.parse(dateString, formatter1);
System.out.println("======================:"+parsedDate.format(formatter1));


OffsetDateTime currentUTC = OffsetDateTime.now(ZoneOffset.UTC);
System.out.println("Until (with crono): " + parsedDate.until(currentUTC, ChronoUnit.DAYS));

Мне нужен результат в int (т. Е. В количестве дней).

Строка OffsetDateTime parsedDate = OffsetDateTime.parse(dateString, formatter1); вызывает исключение со следующей трассировкой стека:

Exception in thread "main" java.time.format.DateTimeParseException: Text '2019-06-18T16:23:41.575 UTC' could not be parsed: Unable to obtain OffsetDateTime from TemporalAccessor: {InstantSeconds=1560875021},ISO,UTC resolved to 2019-06-18T16:23:41.575 of type java.time.format.Parsed
    at java.base/java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1959)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1894)
    at java.base/java.time.OffsetDateTime.parse(OffsetDateTime.java:402)
    at thiagarajanramanathan.misc.App.main(App.java:86)
Caused by: java.time.DateTimeException: Unable to obtain OffsetDateTime from TemporalAccessor: {InstantSeconds=1560875021},ISO,UTC resolved to 2019-06-18T16:23:41.575 of type java.time.format.Parsed
    at java.base/java.time.OffsetDateTime.from(OffsetDateTime.java:370)
    at java.base/java.time.format.Parsed.query(Parsed.java:235)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1890)
    ... 3 more
Caused by: java.time.DateTimeException: Unable to obtain ZoneOffset from TemporalAccessor: {InstantSeconds=1560875021},ISO,UTC resolved to 2019-06-18T16:23:41.575 of type java.time.format.Parsed
    at java.base/java.time.ZoneOffset.from(ZoneOffset.java:348)
    at java.base/java.time.OffsetDateTime.from(OffsetDateTime.java:359)
    ... 5 more

Ответы [ 3 ]

2 голосов
/ 19 июня 2019

Как видно из этой темы: Невозможно получить OffsetDateTime из TemporalAccessor
Я изменил следующие строки:

//OffsetDateTime parsedDate  = OffsetDateTime.parse(dateString, formatter1);
ZonedDateTime parsedDate = ZonedDateTime.parse(dateString, formatter1);

Когда ваш код запускается с этой модификацией, я могу получить следующие результаты

для «2019-06-18T16: 23: 41,575 UTC»:

======================:2019-06-17T16:23:41.575 UTC
Until (with crono): 0

Так как меньше 24 часов, возвращается 0

для «2019-06-17T16: 23: 41,575 UTC»:

======================:2019-06-17T16:23:41.575 UTC
Until (with crono): 1

Точно так же, поскольку прошло более 24 часов, но менее 2 дней, возвращается 1.

Я думаю, это то, что вы хотите. Пожалуйста, попробуйте и дайте мне знать, если это работает для вас.

1 голос
/ 19 июня 2019

Разница между часовым поясом и смещением

У вас уже есть два хороших ответа. Вы затрагиваете интересную и немного хитрую часть java.time, поэтому я хотел бы также внести свой вклад. Мой ключевой момент заключается в том, что часовой пояс и смещение UTC не совпадают . Чтобы получить OffsetDateTime вам нужно смещение. Вы предоставляете часовой пояс посредством звонка .withZone(ZoneId.of("UTC")) на устройстве форматирования, но это вам не поможет. Да, мы с вами знаем, что UTC является базой всех смещений и поэтому само определяет смещение 0. Но Java не обнаружила этого в вашем коде.

Признаюсь, я с удивлением обнаружил, что следующего простого изменения было достаточно, чтобы ваш код работал на Java 9: ​​

    final DateTimeFormatter formatter1
            = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS 'UTC'")
                    .withZone(ZoneOffset.UTC);

Однако на Java 8 я получаю то же исключение, что и раньше. Вывод, который я получил на Java 9.0.4, был:

======================:2019-06-18T16:23:41.575 UTC
Until (with crono): 0

Единственное изменение заключается в том, что теперь я передаю ZoneOffset, а не ZoneId объект withZone (это возможно, поскольку ZoneOffset является подклассом ZoneId).

Форматер, который работает и в Java 8, - это тот, в котором мы предоставляем смещение по умолчанию. Для этого нам нужно DateTimeFormatterBuilder:

    final DateTimeFormatter formatter1 = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
            .appendLiteral(" UTC")
            .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
            .toFormatter();

Еще одним и, возможно, более простым вариантом будет сначала выполнить синтаксический анализ LocalDateTime (который не требует ни смещения, ни часового пояса), а затем преобразовать в OffsetDateTime, вызвав .atOffset(ZoneOffset.UTC).

1 голос
/ 19 июня 2019

Синтаксический

Я бы упростил анализ, если ваш вклад соответствовал стандарту ISO 8601.

String input = "2019-06-18T16:23:41.575 UTC".replace( " UTC", "Z" ) ;
Instant instant = Instant.parse( input ) ;

Дней как 24-часовой кусок

Если ваше определение прошедших дней составляет 24-часовой отрезок времени, используйте Duration.

Duration d = Duration.between( instant , Instant.now() ;
long days = d.toDays() ;

Дни по календарю

Если вы хотите, чтобы количество дней прошло, как показано в календаре, то есть даты, а не 24-часовые отрезки времени, вы должны указать часовой пояс.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;

Извлечь даты.

LocalDate start = zdt.toLocalDate() ;
LocalDate stop = now.toLocalDate() ;
long days = ChronoUnit.DAYS.between( start , stop ) ;
...