3

I am providing dates two to my script in this format: 2016-05-25 12:30:02. However, JavaScript is setting the each date to a different GMT offset. I formatted the dates to match the suggested answer here and added the function provided, but I got the same results as shown below so I reverted back to my original script shown below.

var response = JSON.parse(jsonResponse);
var lastExportedOrderData = response.lastExportedOrder;

/* currentDateTime = '2016-05-25 12:30:02'; */
var currentDateTime = new Date(response.scriptExecutionTime); 

/* lastOrderExportedAt = '2016-01-12 16:53:56'; */
var lastOrderExportedAt = new Date(lastExportedOrderData.exported_at); 

currentDateTime Results: 2016-05-25 12:30:02 -> Wed May 25 2016 12:30:02 GMT-0400 (EDT)

lastOrderExportedAt Results: 2016-01-12 16:53:56 > Tue Jan 12 2016 16:53:56 GMT-0500 (EST)

I don't really care about the timezone so long as the dates are in the same timezone.

Update

My dates are now being input using the ISO-8601 Standard format but my the problem remains. 2016-05-25T14:04:00-05:00 results as GMT-0400 where 2016-01-12T16:53:56-05:00 results as GMT -0500

Community
  • 1
  • 1
tylersDisplayName
  • 1,603
  • 4
  • 24
  • 42
  • Updated the post to clarify current state of the script. I meant that I tried the parseDate() suggestion but no longer have it implemented. I pasted an old version of the code to further confuse things. – tylersDisplayName May 25 '16 at 16:45
  • Questions on Stack Overflow are not meant to be moving targets. Once you have an answer, it's not okay to modify the question such that it invalidates significant portions of an answer. I've rolled back the edit. It didn't change the fundamental thing, which is that it's down to DST, but still... – T.J. Crowder May 25 '16 at 17:36
  • My post has been updated to reflect my current input, rather than overwriting my original content. You mentioned "..and as both dates have been parsed (in your example) as local time, they can reliably be compared". If I understand you correctly you are suggesting that the GMT offset will be disregarded when comparing the dates? I'd still like to understand why I am seeing two different offsets since, I think, I implemented your suggestion correctly. – tylersDisplayName May 25 '16 at 18:12
  • Fundamentally, `Date` instances are just really simple wrappers around a number. The number is the number of milliseconds since Jan 1st 1970 at midnight, GMT. The strings you see are just interpretations of that data. So yes, they can be compared reliably. – T.J. Crowder May 25 '16 at 23:39

2 Answers2

7

They're in the same timezone (U.S. Eastern). The difference is that the one in May is during Daylight Savings Time and thus is Eastern Daylight Time (EDT), and the one in January isn't, and thus is in Eastern Standard Time.

It's important to note that their underlying time values (e.g., as from dt.getTime()) are unaffected by timezone, and as both dates have been parsed (in your example) as local time, they can reliably be compared. You'd only run into an issue comparing them if one were parsed as local time and the other as UTC.


Side note: You're relying on new Date to parse those strings, which means you're relying on unspecified behavior that may vary from JavaScript engine to JavaScript engine. The only string format engines are required to support is a simplified version of ISO-8601, which those strings are not in. In particular, it's entirely possible that one browser's JavaScript engine will decide to parse them as though they were in UTC and another engine's browser will decide (as yours seems to have done) to parse them as local time.

You haven't said what timezone the strings are meant to be interpreted in, but if (for instance) they were meant to be UTC, you can fairly easily change them to be in ISO-8601 format by replacing the space between the date and time with a T, and adding a Z to the end:

str = str.replace(" ", "T") + "Z";

The resulting string, for instance "2016-05-25T12:30:02Z", is valid for new Date on any modern JavaScript engine (so, not IE8).

Alternately, if you know what timezone offset they should be interpreted in (say, GMT-05:00), you can replace the space with T and add a timezone offset to the end:

str = str.replace(" ", "T") + "-05:00";

That string (for instance, "2016-05-25T12:30:02-05:00") is also valid for new Date.

Alternately, get the parts of them:

var parts = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/.exec(str);

...and build the date/time yourself

// As local time
var dt = new Date(
    +parts[1],     // Year
    +parts[2] - 1, // Month (0 = January)
    +parts[3],     // Day
    +parts[4],     // Hour
    +parts[5],     // Minute
    +parts[6]      // Second
);

or

// As UTC
var dt = new Date(Date.UTC(
    +parts[1],     // Year
    +parts[2] - 1, // Month (0 = January)
    +parts[3],     // Day
    +parts[4],     // Hour
    +parts[5],     // Minute
    +parts[6]      // Second
));

The unary + on the above coerces from string to number. (It isn't strictly necessary, though, both new Date and Date.UTC do it for you.)

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    The US [*EDT and EST*](http://www.timeanddate.com/time/zones/edt) are different timezones for the same region. ;-) – RobG May 25 '16 at 21:28
  • @RobG: Yeah, fair enough. :-) ...From a certain point of view. Date/time stuff is weird. – T.J. Crowder May 25 '16 at 23:43
1

Just to add to TJ's answer, in implementations consistent with ES5 and later, the string 2016-05-25T14:04:00 will be parsed as a "local" time as it doesn't have a time zone offset. (In an ES2015-compliant browser. Sadly in the previous specification, they got that wrong and made it default to UTC, and currently Chrome implements the ES5 spec [UTC] but Firefox implements the ES2015 spec [local time].) But don't rely on that, parse the string per TJ's answer.

When creating a local time value, the host time zone settings are taking in to consideration. It seems that the host system is set for EST/EDT.

EDT starts at 02:00 on the second Sunday in March, so on 2016-01-12 US Eastern Standard Time (EST) applies which has an offset of -0500. For 2016-05-25, US Eastern Daylight Time (EDT) is used which has an offset of -0400.

Note that the actual time value of the Date created for 2016-05-25T12:30:02-0400 is for 2016-05-25T16:30:02Z (i.e. the equivalent UTC time). When displayed, the date's toString method is called which applies the host system offset for that time and date to adjust the displayed value to "local" time.

Date's use UTC internally so that they can be displayed in any time zone and still represent the same instant in time.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
RobG
  • 142,382
  • 31
  • 172
  • 209
  • If you meant `"2016-05-25T14:04:00"` (no `-05:00`), ES5 had a bug. :-) If implementations correctly implement ES5, that's parsed in UTC, because the ES5 spec [said](http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.15) *"The value of an absent time zone offset is “Z”."* This was at odds with ISO-8601 and it was corrected in the ES2015 spec, leading us to the bizarre situation we're in now: On current Chrome (v50), it's parsed as UTC (ES2015 spec). On current Firefox (v46.0.1), it's parsed as local time. ***ouch*** – T.J. Crowder May 26 '16 at 08:07
  • @T.J.Crowder—oops, fixed the first bit. The situation with parsing is a complete mess, new methods for parsing and formatting are required that take a format string as an argument. There are plenty of small libraries to copy from. The current strategy of relying on the *Intl* object only does half the job. But I'm not holding my breath… :-( – RobG May 26 '16 at 08:52
  • Couldn't agree more. Sadly, I [don't see any proposals](https://github.com/tc39/ecma262) and previous experience suggests that TC-39 is happy to leave that job to libraries. :-| (I took the liberty of updating the "local time" bit in the answer. BTW, I got my comment slightly wrong, it should have read *"...current Chrome (v50), it's parsed as UTC (ES5 spec)."*) – T.J. Crowder May 26 '16 at 09:00