Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to safely parse the Date HTTP header in javascript

If I use Date.parse(), am I "nearly guaranteed" to be able to parse what comes at my program?

In Mozilla's entry for Date.parse, they write:

Given a string representing a time, parse() returns the time value. It accepts the RFC2822 / IETF date syntax (RFC2822 Section 3.3), e.g. "Mon, 25 Dec 1995 13:30:00 GMT".

My own server returns Sun, 24 May 2015 05:37:13 GMT.

Trouble is, Wikipedia tells me that the Date header follows the RFC 7131. Now, RFC 7231 and while they seem to be saying the same thing (although 7231 is broader), I was wondering...

If I use Date.parse(), am I "nearly guaranteed" to be able to parse what comes at my program? I am happy to assume that the server isn't running in a time vacuum.

like image 653
Merc Avatar asked May 24 '15 06:05

Merc


1 Answers

TL;DR If you're getting back a new or old RFC 7231 compliant string, it will parse on most modern browsers since they all have very similar and insanely flexible parsing rules:

new Date('Sun, 24 May 2015 05:37:13 GMT')
new Date('2015 GMT 24 05:37:13 May')
// => Sun May 24 2015 01:37:13 GMT-0400 (EDT)

If you need a 100% guarantee across any compliant ECMAScript implementation, you'll need to use your application code to convert the timestamp to the ISO 8601 format: YYYY-MM-DDTHH:mm:ss.sssZ

Remember though the timezone may shift according to the user's location.


ECMAScript only specifies the following format for dates:

ECMAScript defines a string interchange format for date-times based upon a simplification of the ISO 8601 Extended Format. The format is as follows: YYYY-MM-DDTHH:mm:ss.sssZ

Source: http://es5.github.io/#x15.9.1.15

Regarding Date.parse:

If the String does not conform to that format the function may fall back to any implementation-specific heuristics or implementation-specific date formats.

Source: http://es5.github.io/#x15.9.4.2

With modern browser implementations, the following rules generally apply:

  • month/day/year, month-day-year for short dates
  • Months and days can be 1 or 2 digits
  • Years with only two digits must be >= 70
  • For spelled out dates, the year month and day can be in any order anywhere (you'll see what I mean by anywhere later): January 1 2000, 1 January 2000, 2000 1 January
  • Months may be abbreviated to three characters (I believe IE allows for two)
  • JavaScript will override invalid days of the week
  • Hours minutes and seconds are separated by colons: '10:20:30', '10:20', '10:' are valid
  • You can specify 'AM' and 'PM' anywhere, but if you're wrong or redundant you'll get NaN or an invalid date error
  • You can specify a timezone string (e.g. 'EST', 'EDT', 'GMT') anywhere

"Anywhere" truly means "anywhere": you can jumble the crap out of the components. The following insanity works, for example...

new Date('PM Jan EST 2015 1 10:00')
new Date('2015 1 10:00 Jan EST PM')
// => Thu Jan 01 2015 10:00:00 GMT-0500 (EST)

...which is why you're nearly guaranteed for those dates to parse.

Sources:

  • V8: https://github.com/v8/v8-git-mirror/blob/master/test/mjsunit/date-parse.js
  • Mozilla: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse
  • WebKit: https://github.com/WebKit/webkit/blob/master/LayoutTests/js/date-parse-test-expected.txt, https://github.com/WebKit/webkit/blob/master/Source/WTF/wtf/DateMath.cpp (what a namespace!)
  • MSDN: https://msdn.microsoft.com/library/k4w173wk%28v=vs.94%29.aspx
like image 50
fny Avatar answered Sep 23 '22 03:09

fny