Javascript и Java Date JSON-сериализация

У меня есть объект javascript с свойством Дата, который преобразуется в JSON с помощью JSON.stringify

Я нахожусь в часовом поясе GMT ​​+ 4 (Россия/Москва)

Например, 5 Jan 2012 преобразуется в 2012-01-04T20:00:00.000Z

5 Jan 1975 преобразуется в 1975-01-04T20:00:00.000Z

Но в 1975 году это был часовой пояс GMT + 3, так как в 2011 году в России было отменено летнее время. Поэтому, когда он ссылается на сервер (java), он десериализуется как:

2012-01-04T20:00:00.000Z becames 5 Jan 2012 00:00 - ОК

1975-01-04T20:00:00.000Z becames 4 Jan 1975 23:00 - НЕПРАВИЛЬНО!

Каков рекомендуемый способ преобразования объекта Date в JSON в Javascript?

Ответы

Ответ 1

Я бы предложил пропустить дату/время, используя свои секунды с нотной записью эпохи, точнее количество секунд после эпохи Unix (1 января 1970 года 00:00 по Гринвичу). Если вы не знакомы с этим, здесь приведен пример конвертера: http://www.epochconverter.com/

Это имеет несколько преимуществ:

  • Это относится к одному и тому же моменту времени независимо от часового пояса. Это помогает сохранить время независимо от ошибок в часовых поясах (хотя, конечно, они должны быть правильно введены).
  • Это единственный неисчерпаемый конструктор (кроме конструктора без параметров) в java.util.Date, см. (getTime() тоже). (Обратите внимание, что это использует миллисекунды.)
  • JavaScript может легко строить дату из него (например, new Date(1000 * 1326894706)). (Обратите внимание, что это использует миллисекунды.)
  • Если это имеет значение, оно всегда будет немного меньше (с точки зрения размера данных в его сериализации JSON), чем любой из "yyyy-MM-dd HH:mm:ss".
  • Если вы хотите, чтобы часовой пояс отображался и ассоциировался с этим номером, вы всегда можете добавить дополнительное поле в свое представление. { "datetime": 1326894706, "tz": "GMT" } все еще короче { "datetime": "18 Jan 2012 13:51:46 GMT" }.

Учитывая, что легко получить экземпляры Date из этого в Java и JavaScript, вы можете использовать DateFormatter для преобразования его в/из текста в Java. Для JavaScript, используя библиотеку, такую ​​как Формат даты, вы сможете сделать ее соответствующим образом на странице (например, с чем-то вроде new Date(val * 1000).format("yyyy-mm-dd HH:MM")).

Ответ 2

Я предпочитаю придерживаться формата даты javascripts ISO 8601, при правильном анализе он автоматически будет обрабатывать разницу в часовом поясе.

В java вы можете проанализировать дату JScript с использованием Javascript следующим образом:

String iso8601Date = "2013-08-13T14:15:00.000Z";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
Date parsedDate = formatter.parse(iso8601Date);

Когда вы вернетесь в строки, у вас будет что-то вроде этого

//"2013-08-13T16:15:00.000+02:00"
String formattedDate = formatter.format(parsedDate);

Для разбора JSON я использую FlexJson, который вы можете настроить следующим образом.

//Serializing to JSON
DateTransformer dateTransformer = new DateTransformer("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
new JSONSerializer().transform(dateTransformer, Date.class).serialize(object);
//deserialize From JSON (replace object by java class)
JSONDeserializer<..Object..>().use(Date.class, dateTransformer).deserialize(json);

Ответ 3

Если вы используете Spring Framework, вы можете использовать аннотацию @JsonSerialize(using = CustomLocalDateSerializer.class) и @JsonDeserialize(using = ISO8601LocalDateDeserializer.class). Он правильно проанализирует ваш javascript Date.

Пример:

public class product {

    @NotNull
    private Long id;

    @NotNull
    private String name;

    @JsonSerialize(using = CustomLocalDateSerializer.class)
    @JsonDeserialize(using = ISO8601LocalDateDeserializer.class)
    private LocalDate date;

    // getter and setter...
}

Ответ 4

Я лично конвертировал бы их в String в java, используя что-то вроде этого:

String theDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);

И затем строка будет сериализована. На стороне javascript вы просто проанализируете это.

Ответ 5

JSON не поддерживает Date, все синтаксические анализаторы/сериализаторы используют toString или что-то в этом роде. Это зависит от вас, чтобы сериализовать/десериализовать даты.
Поскольку Javascript не имеет подходящего фидатера даты, самым простым решением является преобразование даты в длинную. Но если вы хотите прочитать, что происходит, я рекомендую http://www.datejs.com/ и даты форматирования как yyyy-MM-dd HH: mm: сс

Ответ 6

Эта тема довольно старая. В настоящее время, с Java 8, вы должны использовать ZonedDateTime в вашей форме dto. Используя spring-mvc, Джексон будет правильно отображать формат ISO (например: "2019-03-27T22:05:42.763Z") в ZonedDateTime.

Однако метод Date.toISOString всегда устанавливает часовой пояс на utc, поэтому ваша десериализованная зона ZonedDateTime всегда будет установлена на UTC. Это может быть проблемой, если вам нужна зона на стороне сервера. Допустим, например, что вам нужно отправить клиенту электронное письмо с датой, которую он/она только что отправил через форму: вы хотите использовать ту же зону.

Если вы хотите передать часовой пояс и соответствовать формату ISO, вы должны использовать lib, например, moment.js, чтобы форматировать даты в javascript. И тогда при сериализации:

moment().format('YYYY:MM:DDTHH:mm:ssZ') // "2019:03:27T23:06:11+01:00"