michaeldd
michaeldd

Reputation: 514

Working with UTC Dates in Javascript and MongoDB

I am having a problem correctly working with UTC-Dates and wondered if there is a common way of dealing with this.

Basically I have a javascript datepicker where I can select a date. For example:

 2014-10-15

When this gets converted to a string with JSON.stringify() I end up with:

 2014-10-14T22:00:00+0200

I am assuming that this is correct because the date gets converted to a UTC date.

When the date then arrives at my java (jersey) REST interface it looks like the following:

 2014-10-14T22:00:00.000Z

The date appears to be the same, but the +0200 is no longer there. Possibly causing the problem.

The next step is to save the date to my mongo database, which then stores the date like this:

 2014-10-14 20:00:00.000Z

Another 2 hours have been taken off and I am assuming that this is because the date is being converted to UTC "again".

The problem I have now is that if I reload the page, my input field now says:

2014-10-14

instead of 2014-10-15.

If I manually change the date in the database and add the 2 hours again to end up with "2014-10-14T22:00:00.000Z", the date is displayed correctly in the frontend again - the date is now correctly represented as local time because 2 hours on top of 2014-10-14T22:00:00.000Z makes 2014-10-15 again.

My question is:

Where do I need to make my change to prevent this from happening?

a) I only use local time in the frontend, so that mongodb then only converts to UTC. This does not sound very safe to me as I am sure this will cause problems when the client is being called from different time-zones.

b) I only work with UTC dates, but I then need to somehow tell mongodb that the date is already in UTC and therefore there is no need to convert it again.

Any help would be greatly appreciated.

Thanks, Michael

EDIT

I think I may be a step further now. I can tell the json deserializer what date-format can be expected. I have configured this to:

 new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")

If I test the date format manually I end up with

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
 System.out.println(sdf.parse("2014-10-14T22:00:00+0200"));

which produces

 Tue Oct 14 22:00:00 CEST 2014

So no wonder that mongodb (or the mongo-bson-driver) is converting the date to UTC again.

If I do this however:

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); // Removed the "Z"
 sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
 System.out.println(sdf.parse("2014-10-14T22:00:00+0200"));

it correctly comes up with:

 Wed Oct 15 00:00:00 CEST 2014

When the conversion is done from the mongodb driver, it will probably turn this into "2014-10-14T22:00:00+0200" again which is correct.

Not sure if this is the best way though ... would I run into problems if the client date is in yet another timezone? I suppose not because if it was "2014-10-15T06:00:00-0600" for example, it would probably turn that into the right date too ...

Can anyone confirm that this is the way to go?

Thanks!

Upvotes: 2

Views: 1747

Answers (1)

Wizard
Wizard

Reputation: 4431

Hope this information may give a help.

MongoDB database doesn't make the conversion. It simply assumes the received date is UTC time. And it's java driver who gets UTC time in milliseconds from date object. The following codes from BasicBSONEncoder.java of mongo-java-driver-2.12.3.jar.

protected void putDate( String name , Date d ){
    _put( DATE , name );
    _buf.writeLong( d.getTime() ); // d.getTime() Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
}

If you still have a question about it, you can new a Date Object in java code directly and save it to database to check whether any further conversion. (Pay attention to the time zone of your java application when compare)


Now, the point is: if you get 2014-10-14T22:00:00+0200, then the source should be 2014-10-15T00:00:00+0400, or 2014-10-15T02:00:00+0600, etc. That means different time zones have been used among invoking that javascript datepicker and JSON.stringify().

When you send string "2014-10-14T22:00:00+0200" to java application and parsed by SimpleDateFormat, please make sure the pattern is consistent with the data (use new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz"). Don't forget the last character z, else +0200 will be dropped and the remainder of string will be parsed based on the time zone of your java application time zone.)

When you use SimpleDateFormat to double check the output, you'd better create another new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz") to format the date object before pass it to System.out.print(), because it's easier to compare by time zone.

If possible, I suggest you send the UTC milliseconds to java application since it's easy to get and avoid various converting format issues.

Upvotes: 2

Related Questions