16

I have an javascript object with Date property which is being converted to JSON using JSON.stringify

I am on GMT+4 time zone (Russia/Moscow)

For example, 5 Jan 2012 converts to 2012-01-04T20:00:00.000Z

5 Jan 1975 converts to 1975-01-04T20:00:00.000Z

But in 1975 it was GMT+3 time zone, as daylight saving was canceled in Russia in 2011. So when it cames to server (java) it deserializes as:

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

1975-01-04T20:00:00.000Z becames 4 Jan 1975 23:00 - WRONG!

What is the recommended way to convert Date object to JSON in Javascript?

hvgotcodes
  • 118,147
  • 33
  • 203
  • 236
ike3
  • 1,760
  • 1
  • 17
  • 26
  • This might be useful. Maybe even a possible duplicate: http://stackoverflow.com/questions/4032967/json-date-to-java-date – Johan Jan 18 '12 at 13:46

6 Answers6

15

I prefer to stick to javascripts ISO 8601 date format, when parsing it correctly it'll will automatically handle timezone differences.

In java you can parse a javascript Stringified JSON date as follows:

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);

When turning it back into strings, you'll have something like this

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

For parsing JSON I use FlexJson, which you can configure like this.

//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);
Nils
  • 1,750
  • 14
  • 10
  • I am again your idea because transfering the long string like 'yyyy-MM-dd'T'HH:mm:ss.SSSXXX' is not so effective like just a number epoch. – anhquan Apr 08 '20 at 12:23
14

I would suggest passing the date/times around using their seconds since epoch notation, more specifically the number of seconds since the Unix Epoch (1 Jan 1970 00:00 GMT). If you're not familiar with this, there is an example converter here: http://www.epochconverter.com/

This has a few advantages:

  • It refers to the same moment in time independently of the time zone. This helps storing the time independently of time zone errors (although they would have to be input correctly in the first place, of course).
  • It's the only non-deprecated constructor (except constructor without params) in java.util.Date, see (getTime() too). (Note that this uses milliseconds.)
  • JavaScript can build date from it quite easily (e.g. new Date(1000 * 1326894706)). (Note that this uses milliseconds.)
  • If it matters, it's always going to be a bit smaller (in terms of data size in its JSON serialization) than any of "yyyy-MM-dd HH:mm:ss".
  • If you want the time zone to be rendered and associated with this number, you could always add an extra field to your representation. { "datetime": 1326894706, "tz": "GMT" } is still shorter than { "datetime": "18 Jan 2012 13:51:46 GMT" }.

Considering it's easy to get Date instances from this in Java and JavaScript, you can then use a DateFormatter to convert it to/from text in Java. For JavaScript, using a library such as Date Format will help you render it as appropriate on the page (for example with something like new Date(val * 1000).format("yyyy-mm-dd HH:MM")).

Bruno
  • 119,590
  • 31
  • 270
  • 376
  • I did some more research and found that epoch is treated differently in java and javascript (http://stackoverflow.com/questions/8913059/javascript-date-and-java-util-date-constructor-argument). If I cannot rely on getTime() method I have no idea how to use epoch time. – ike3 Jan 18 '12 at 16:19
  • They only behave differently in the way they tie the time zone to your location at the time. I thought your input were (correct) JS `Date` instances in the first place? How do you build them? Can you show an example of how you produced `5 Jan 1975` initially? – Bruno Jan 18 '12 at 16:45
  • I am getting Date from jQuery DatePicker $("date").datePicker("getTime") when 5 Jan 1975 is choosen in the calendar. Then it is serialized to JSON using JSON.stringify, which uses 4 hours difference independent on the year. But Java knows that before 2011 it was GMT+3 and deserializes it in the correct way so I get 1 hour difference for dates before 2011 – ike3 Jan 19 '12 at 02:47
  • Another advantage is an easy comparison - you don't need to deserialise to compare the dates. – Chanandler Bong Jan 20 '16 at 21:16
1

If you use the Spring Framework you can use the @JsonSerialize and @JsonDeserialize annotations. It will parse correctly your javascript Date.

Example:

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...
}
Brad Turek
  • 2,472
  • 3
  • 30
  • 56
Thibaut Mottet
  • 414
  • 4
  • 15
1

This thread is rather old. Nowadays, with java 8, you should use ZonedDateTime in your form dto. Using spring-mvc, Jackson will properly map a ISO format (ex: "2019-03-27T22:05:42.763Z") to a ZonedDateTime.

However the method Date.toISOString always set the timezone to utc, so your deserialized ZonedDateTime zone will always be set to UTC. It can be a issue if you need the zone on the server side. Let's say for example you need to send to a customer an email with a date he/she just submitted through a form: you want to use the same zone.

If you want to pass the timezone and comply to the ISO format, you should use a lib like moment.js to format dates in javascript. And then when serializing :

moment().format('YYYY:MM:DDTHH:mm:ssZ') // "2019:03:27T23:06:11+01:00"
Camille Vienot
  • 727
  • 8
  • 6
0

I personally would convert them to String in java using something like this:

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

And then the String is serialized. In the javascript side you, just parse that.

  • I think the issue is going *from* JavaScript *to* Java. – Pointy Jan 18 '12 at 13:58
  • Or the other way around: stringify in Javascript to parse in Java, as the author wants Javascript-> Java, if I read the question correctly. – Zlatko Jan 18 '12 at 14:00
  • Yes, I am thinking about writing custom Date serializer/deserializer for Spring MVC+Jackson. – ike3 Jan 18 '12 at 14:08
0

JSON does not have Date support, all parser/serializers use the toString or something like that. It is up to you to serialize/deserialize dates.
Since Javascript do not have a decent date formatter included, the simplest solution is to transform date to long. But if you want to be able to read what is going on, I recommend http://www.datejs.com/ and formatting dates as yyyy-MM-dd HH:mm:ss

Pablo Grisafi
  • 5,039
  • 1
  • 19
  • 29