2

I am facing an issue in converting datetime in current timzone.

I am receiving this date string from server in a format "2015-10-09T08:00:00" which is Central Time but when I convert this date time using new Date(strDate) in GMT+5 its returning me below which is incorrect.

var dateObj = '2015-10-09T08:00:00';
new Date(dateObj); // return me below
Fri Oct 09 2015 13:00:00 GMT+0500 (PKT)

Another way I used is to convert by adding timezone offset and its returning me right result but defiantly failed when daylight saving activated.

dateObj2 = '2015-10-09T08:00:00'+'-06:00';
new Date(dateObj2)// return me below
Fri Oct 09 2015 19:00:00 GMT+0500 (PKT)

I appreciated if anyone help OR suggest me efficient way to handle to timezone conversion with daylight saving in JavaScript?

Thank you.

Muhammad Saifuddin
  • 1,284
  • 11
  • 29
  • if you are not against using a library: http://momentjs.com/timezone/ – Manube Nov 04 '15 at 14:19
  • @Manube Thanks for suggestion I'll try BTW any clue in plain javascript. – Muhammad Saifuddin Nov 04 '15 at 15:17
  • 1
    in plain js, it is tricky, I think, as your app would need to know about daylight saving according to timezone; all this is well thought out and taken care of by the momentjs timezone library – Manube Nov 04 '15 at 16:24

1 Answers1

1

Note that behavior of the code you wrote differs between the browsers:

new Date('2015-10-09T08:00:00').toString()

// "Fri Oct 09 2015 10:00:00 GMT+0200 (Romance Daylight Time)" // Chrome 46 on Windows 8.1
// "Fri Oct 09 2015 08:00:00 GMT+0200 (Romance Daylight Time)" // Firefox 41 on Windows 8.1
// "Fri Oct 09 2015 08:00:00 GMT+0200 (Romance Daylight Time)" // IE11 on Windows 8.1
// "Fri Oct 9 08:00:00 UTC+0200 2015" // IE10 emulation
// "Fri Oct 9 10:00:00 UTC+0200 2015" // IE9 emulation
// on IE8 it even returns NaN!

(my timezone is Paris)

So, Firefox and IE interpret the provided date as specified as if it were in local timezone of the user, whereas Chrome interprets it as UTC, and when printed, it gets converted to user's timezone.

Checking the MDN docs, this is due to differences in EcmaScript 5 and EcmaScript 6 (2015) specifications. It seems that Chrome follows ES5 spec while Firefox and IE11 follow ES6 spec.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse#ECMAScript_5_ISO-8601_format_support (emphasis mine)

The date time string may be in ISO 8601 format. For example, "2011-10-10" (just date) or "2011-10-10T14:48:00" (date and time) can be passed and parsed. The UTC time zone is used to interpret arguments in ISO 8601 format that do not contain time zone information (note that ECMAScript 2015 specifies that date time strings without a time zone are to be treated as local, not UTC).

Unfortunately Date object in JavaScript is famous for its quirks and cross-browser inconsistencies, particularly on ambiguous input.

I wrote here how you can leverage moment.js or native Intl API to make sure your date will not be converted to user's timezone (the secret is to use UTC manipulating methods).

In general it's best to always specify either both time and UTC offset, or just a UTC timestamp, to make sure your input is unambiguous.

Coming back to your example, you can use following code:

moment('2015-10-09T08:00:00-06:00')
 .utcOffset(+300).locale('en_gb').format("LLLL")
// "Friday, 9 October 2015 19:00" cross-browser

in which you say "this is date in UTC-0600, please convert and print it as UTC+0500 (+300 minutes)". Then you can pass in which locale you want it printed (i.e. language + culture specific settings, e.g. en_gb uses 24 hour clock while en_us 12-hour clock) and use multitude of date formats supported by moment.js.

Community
  • 1
  • 1
jakub.g
  • 38,512
  • 12
  • 92
  • 130
  • 2
    Actually, Chrome is still following ES5 spec, like IE9 did. ES6 clarifies that unspecified offset means *local*, to match ISO-8601. However, [this is being actively contested](https://github.com/tc39/ecma262/issues/87)! The [current compromise](https://github.com/tc39/ecma262/pull/138) is to have date-only still be in UTC, while date+time uses local (which is still insane IMHO), but Chrome has not adopted it yet. :( – Matt Johnson-Pint Nov 04 '15 at 21:11
  • @MattJohnson you're right, I wrote stuff the other way around :) Fixed. – jakub.g Nov 04 '15 at 21:15
  • 1
    Thanks. Good answer, and see also Chromium issues [543320](https://code.google.com/p/chromium/issues/detail?id=543320) and [539813](https://code.google.com/p/chromium/issues/detail?id=539813), and also [my blog post](http://codeofmatt.com/2015/06/17/javascript-date-parsing-changes-in-es6/). :) – Matt Johnson-Pint Nov 04 '15 at 21:17
  • One note - if the OP desires to emit the time according the local browser, not necessarily just Pakistani time, then I would omit `.utcOffset(+300)`. Other than that, looks great. – Matt Johnson-Pint Nov 04 '15 at 21:35
  • @jakub.g thank you for your input but defining offset in date "-06:00" not giving you dst time? – Muhammad Saifuddin Nov 05 '15 at 15:33
  • @Saifuddin can you be more precise in your question about the your DST issue because it's in fact not clear what is your exact issue? You mean, you are not sure what UTC offset is the input time, because it differs throughout the year depending on UTC rules? – jakub.g Nov 05 '15 at 15:46