Skip to content

Instantly share code, notes, and snippets.

@spatialtime
Created May 21, 2020 19:31
Show Gist options
  • Save spatialtime/9501d7f6ce331a475f81fa2bb084b04d to your computer and use it in GitHub Desktop.
Save spatialtime/9501d7f6ce331a475f81fa2bb084b04d to your computer and use it in GitHub Desktop.
JavaScript code for parsing an ISO 8601 string to a JavaScript Date instance.
/*
* dateFromISODatetime creates a JavaScript date from a string that adheres to
* ECMAScript's specified syntax:
* Zulu/UTC time:
* YYYY-MM-DDTHH:mm:ss.sssZ
* Specified time zone offset:
* YYYY-MM-DDTHH:mm:ss.sss±HH:mm
* Local time (no time zone specification):
* YYYY-MM-DDTHH:mm:ss.sss
*/
let dateFromISODatetime = function (isoString) {
const DATE_REGEX = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}.\d{3})(Z|(?:(?:-|\+)\d{2}:\d{2}))?$/;
const MIN_YEAR =1;
const MAX_YEAR = 9999;
const MIN_MONTH = 1;
const MAX_MONTH = 12;
const MIN_DAY = 1;
const MIN_HOUR = 0;
const MAX_HOUR = 24;
const MIN_MINUTE = 0;
const MAX_MINUTE = 59;
const MIN_SECOND = 0;
const MAX_SECOND = 60;
const matches = isoString.match(DATE_REGEX);
if (matches === null) {
throw new SyntaxError("Invalid date attribute");
}
let year = parseInt(matches[1]);
if (year < MIN_YEAR || year > MAX_YEAR) {
throw new RangeError(`Year must be >= ${MIN_YEAR} and <= ${MAX_YEAR}`);
}
let month = parseInt(matches[2]);
if (month < MIN_MONTH || month > MAX_MONTH) {
throw new RangeError(`Month must be >= ${MIN_MONTH} and <= ${MAX_MONTH}`);
}
let dayCount = monthDayCount(month, year);
let day = parseInt(matches[3]);
if (day < MIN_DAY || day > dayCount) {
throw new RangeError(`Day must be >= ${MIN_DAY} and <= ${dayCount}`);
}
let hour = parseInt(matches[4]);
if (hour < MIN_HOUR || hour > MAX_HOUR) {
throw new RangeError(`Hour must be >= ${MIN_HOUR} and <= ${MAX_HOUR}`);
}
let minute = parseInt(matches[5]);
if (minute < MIN_MINUTE || minute > MAX_MINUTE) {
throw new RangeError(`Minutes must be >= ${MIN_MINUTE} and <= ${MAX_MINUTE}`);
}
let second = parseInt(matches[6]);
if (second < MIN_SECOND || second > MAX_SECOND) {
throw new RangeError(`Seconds must be >= ${MIN_SECOND} and <= ${MAX_SECOND}`);
}
return new Date(isoString);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment