Как работать с метками времени с дополнительными миллисекундами в Java дате - PullRequest
1 голос
/ 24 апреля 2020

У меня есть API-интерфейс REST javax.ws.rs, который принимает тело объекта с полем метки времени, сопоставленным с утилитой Date с JPA, но что-то отправляющее ему отправляет метку времени с дополнительными миллисекундами (может быть, предполагается, что это наносекунды? ) и это приводит к тому, что дата будет в будущем, когда я использую объект в своем методе обработчика запросов.

например, это пришло: "TimeStamp": "2020-04-24T16: 26: 11.9376071Z" ,

и он разрешается в объекте до 2020-04-24T19: 02: 27.

Если я использую Почтальон и отправляю точно такое же сообщение только с TimeStamp, уменьшенным до 2 миллисекунд он работает, как и ожидалось, и дата верна.

Итак, если я не могу изменить то, что отправляется, но хочу иметь возможность обрабатывать это, как я могу сократить миллисекунды, чтобы Дата разрешалась правильно?

1 Ответ

2 голосов
/ 24 апреля 2020

Такие строки анализируются в соответствии с шаблоном. Числа, следующие за «точкой», анализируются как миллисекунды, и даты разбора, очевидно, настраиваются в снисходительном режиме, что означает, что переполнение настраивается в верхних полях. Если вы анализируете 9376071 как миллисекунды, это 9376.071 секунда; это около 2 часов и измениться. Добавьте это к 16: 26: 11, и вы получите 19:02. Итак, вот что здесь не так.

Я не вижу достаточно деталей в механизме, который вы используете для передачи этой строки в значение типа java.util.Date - в различных средах вы можете явно указать шаблон , Тем не менее, «старый» API (тот, который java.util.Date принадлежит , не может проанализировать этот ввод - у него нет возможности правильно проанализировать этот свисающий пакет цифр. Да, действительно. Старый API ( java.text.SimpleDateFormat) на самом деле не может прочитать ISO8601 - печальное упущение, которое настоятельно рекомендует вам действительно, действительно прекратить использовать этот недееспособный старый устаревший материал. (ISO8601 действительно допускает любое количество цифр на дробном часть, и она допускает дробную часть в «самой низкой» записи на входе, поэтому полученная вами временная метка, хотя и несколько экзотичная c, соответствует ISO8601 spe c).

Но, хорошо news!

Новый API прекрасно справляется с этим!

import java.time.Instant;
import java.time.format.DateTimeFormatter;

class Test { public static void main(String[] args) {
    Instant parsed =  
        DateTimeFormatter.ISO_INSTANT.parse("2020-04-24T16:26:11.9376071Z", Instant::from);
    System.out.println(parsed);
}}

Я не совсем уверен, как вы можете сказать своей платформе прекратить использование плохого API, но как только вы справитесь чтобы сказать ему, чтобы он прекратил бить себя по лицу со старым, все снова будет хорошо.

Sidenote: j.u.Date - это действительно плохой тип для использования; это дата вообще не представляет , но мгновение во времени, и плохо при этом. В общем, я бы не использовал API с таким эпическим названием! Могу ли я предложить java.time.Instant вместо этого? Его имя соответствует тому, что оно представляет, и должно быть готово Другой работоспособный вариант - ZonedDateTime или LocalDateTime в зависимости от того, что он представляет).

...