Skip to content

Instantly share code, notes, and snippets.

@tdegrunt
Created December 1, 2011 21:42
Show Gist options
  • Save tdegrunt/1420103 to your computer and use it in GitHub Desktop.
Save tdegrunt/1420103 to your computer and use it in GitHub Desktop.
JavaScript and CoffeeScript polyfills for manipulating ISO 8601 date time strings
if isNaN Date.parse "2011-01-01T12:00:00-05:00"
Date.parse = ((parse) ->
# The date time string format as specified by ES 5.1 section 15.9.1.15.
pattern = ///^
(\d{4}) # Year
(?:-(\d{2}) # Optional month
(?:-(\d{2}) # Optional date
(?: # Optional time component
T(\d{2}) # Hours
:(\d{2}) # Minutes
(?:
:(\d{2}) # Optional seconds
(?:\.(\d{3}))? # Optional milliseconds
)?
(?: # Optional time zone offset component
Z| # UTC specifier
(?: # Offset specifier
([-+]) # Direction of offset
(\d{2}) # Hour offset
:(\d{2}) # Minute offset
)
)?
)?)?)?
$///
(value) ->
if match = pattern.exec value
[_, year, month, date, hours, minutes, seconds, milliseconds, direction, hourOffset, minuteOffset] = value
# Parse the specified UTC offset.
if direction
# Detect invalid hour and minute offset values.
return 0 / 0 if hourOffset > 23 or minuteOffset > 59
# Express the specified time zone offset in minutes. The offset is negative for time
# zones west of UTC, and positive for those east of UTC.
offset = (hourOffset * 60 + (+minuteOffset)) * 6e4 * (if direction is "+" then -1 else 1)
# Compute a new UTC date value.
result = Date.UTC year, (month or 1) - 1, date or 1, hours or 0, minutes or 0, seconds or 0, milliseconds or 0
# Apply the offset to the computed date.
result + offset
parse value
)(Date.parse)
if typeof Date::toISOString isnt "function"
Date::toISOString = ->
throw new RangeError if not isFinite @
result = [@getUTCFullYear(), @getUTCMonth() + 1, @getUTCDate(), @getUTCHours(), @getUTCMinutes(), @getUTCSeconds()]
# Months, dates, hours, minutes, and seconds should have two digits.
(result[index] = "0" + element) for element, index in result when element < 10
# Milliseconds should have three digits.
"#{result.slice(0, 3).join("-")}T#{result.slice(3).join(":")}.#{("000" + @getUTCMilliseconds()).slice(-3)}Z"
Date::toJSON = ->
if isFinite @ then @toISOString() else null
if (isNaN(Date.parse('2011-01-01T12:00:00-05:00'))) {
Date.parse = (function (parse) {
// The date time string format as specified by ES 5.1 section 15.9.1.15.
var pattern = /^(\d{4})(?:-(\d{2})(?:-(\d{2})(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:Z|(?:([-+])(\d{2}):(\d{2})))?)?)?)?$/;
return function (value) {
var match, direction, hourOffset, minuteOffset, offset = 0, result;
if ((match = pattern.exec(value))) {
// Parse the specified UTC offset.
if ((direction = match[8])) {
hourOffset = +match[9];
minuteOffset = +match[10];
// Detect invalid hour and minute offset values.
if (hourOffset > 23 || minuteOffset > 59) {
return 0 / 0;
}
// Express the specified time zone offset in minutes. The offset is negative for time
// zones west of UTC, and positive for those east of UTC.
offset = (hourOffset * 60 + minuteOffset) * 6e4 * (direction == '+' ? -1 : 1);
}
// Compute a new UTC date value using the provided year, month, date, hours, minutes,
// seconds, and milliseconds.
result = Date.UTC(match[1], (match[2] || 1) - 1, match[3] || 1, match[4] || 0, match[5] || 0, match[6] || 0, match[7] || 0);
// Apply the offset to the computed date.
return result + offset;
}
return parse(value);
};
}(Date.parse));
}
if (typeof Date.prototype.toString != 'function') {
Date.prototype.toString = function () {
var result, length, value;
if (!isFinite(this)) {
throw new RangeError;
}
// See ES 5.1 section 15.9.1.15 for the ISO 8601 date time string format.
result = [this.getUTCFullYear(), this.getUTCMonth() + 1, this.getUTCDate(), this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()];
length = result.length;
while (length--) {
value = result[length];
// Months, dates, hours, minutes, and seconds should have two digits.
if (value < 10) {
result[length] = '0' + value;
}
}
// Milliseconds should have three digits.
return result.slice(0, 3).join('-') + 'T' + result.slice(3).join(':') + '.' + ('000' + value.getUTCMilliseconds()).slice(-3) + 'Z';
};
Date.prototype.toJSON = function () {
return isFinite(this) ? this.toISOString() : null;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment