'use strict';
|
|
function padWithZeros(vNumber, width) {
|
var numAsString = vNumber.toString();
|
while (numAsString.length < width) {
|
numAsString = '0' + numAsString;
|
}
|
return numAsString;
|
}
|
|
function addZero(vNumber) {
|
return padWithZeros(vNumber, 2);
|
}
|
|
/**
|
* Formats the TimeOffset
|
* Thanks to http://www.svendtofte.com/code/date_format/
|
* @private
|
*/
|
function offset(timezoneOffset) {
|
var os = Math.abs(timezoneOffset);
|
var h = String(Math.floor(os / 60));
|
var m = String(os % 60);
|
if (h.length === 1) {
|
h = '0' + h;
|
}
|
if (m.length === 1) {
|
m = '0' + m;
|
}
|
return timezoneOffset < 0 ? '+' + h + m : '-' + h + m;
|
}
|
|
function datePart(date, displayUTC, part) {
|
return displayUTC ? date['getUTC' + part]() : date['get' + part]();
|
}
|
|
function asString(format, date) {
|
if (typeof format !== 'string') {
|
date = format;
|
format = module.exports.ISO8601_FORMAT;
|
}
|
if (!date) {
|
date = module.exports.now();
|
}
|
|
var displayUTC = format.indexOf('O') > -1;
|
|
var vDay = addZero(datePart(date, displayUTC, 'Date'));
|
var vMonth = addZero(datePart(date, displayUTC, 'Month') + 1);
|
var vYearLong = addZero(datePart(date, displayUTC, 'FullYear'));
|
var vYearShort = addZero(vYearLong.substring(2, 4));
|
var vYear = (format.indexOf('yyyy') > -1 ? vYearLong : vYearShort);
|
var vHour = addZero(datePart(date, displayUTC, 'Hours'));
|
var vMinute = addZero(datePart(date, displayUTC, 'Minutes'));
|
var vSecond = addZero(datePart(date, displayUTC, 'Seconds'));
|
var vMillisecond = padWithZeros(datePart(date, displayUTC, 'Milliseconds'), 3);
|
var vTimeZone = offset(date.getTimezoneOffset());
|
var formatted = format
|
.replace(/dd/g, vDay)
|
.replace(/MM/g, vMonth)
|
.replace(/y{1,4}/g, vYear)
|
.replace(/hh/g, vHour)
|
.replace(/mm/g, vMinute)
|
.replace(/ss/g, vSecond)
|
.replace(/SSS/g, vMillisecond)
|
.replace(/O/g, vTimeZone);
|
return formatted;
|
}
|
|
function extractDateParts(pattern, str) {
|
var matchers = [
|
{ pattern: /y{1,4}/, regexp: "\\d{1,4}", fn: function(date, value) { date.setFullYear(value); } },
|
{ pattern: /MM/, regexp: "\\d{1,2}", fn: function(date, value) { date.setMonth(value -1); } },
|
{ pattern: /dd/, regexp: "\\d{1,2}", fn: function(date, value) { date.setDate(value); } },
|
{ pattern: /hh/, regexp: "\\d{1,2}", fn: function(date, value) { date.setHours(value); } },
|
{ pattern: /mm/, regexp: "\\d\\d", fn: function(date, value) { date.setMinutes(value); } },
|
{ pattern: /ss/, regexp: "\\d\\d", fn: function(date, value) { date.setSeconds(value); } },
|
{ pattern: /SSS/, regexp: "\\d\\d\\d", fn: function(date, value) { date.setMilliseconds(value); } },
|
{ pattern: /O/, regexp: "[+-]\\d{3,4}|Z", fn: function(date, value) {
|
if (value === 'Z') {
|
value = 0;
|
}
|
var offset = Math.abs(value);
|
var minutes = (offset % 100) + (Math.floor(offset / 100) * 60);
|
date.setMinutes(date.getMinutes() + (value > 0 ? minutes : -minutes));
|
} }
|
];
|
|
var parsedPattern = matchers.reduce(function(p, m) {
|
if (m.pattern.test(p.regexp)) {
|
m.index = p.regexp.match(m.pattern).index;
|
p.regexp = p.regexp.replace(m.pattern, "(" + m.regexp + ")");
|
} else {
|
m.index = -1;
|
}
|
return p;
|
}, { regexp: pattern, index: [] });
|
|
var dateFns = matchers.filter(function(m) {
|
return m.index > -1;
|
});
|
dateFns.sort(function(a, b) { return a.index - b.index; });
|
|
var matcher = new RegExp(parsedPattern.regexp);
|
var matches = matcher.exec(str);
|
if (matches) {
|
var date = module.exports.now();
|
dateFns.forEach(function(f, i) {
|
f.fn(date, matches[i+1]);
|
});
|
return date;
|
}
|
|
throw new Error('String \'' + str + '\' could not be parsed as \'' + pattern + '\'');
|
}
|
|
function parse(pattern, str) {
|
if (!pattern) {
|
throw new Error('pattern must be supplied');
|
}
|
|
return extractDateParts(pattern, str);
|
}
|
|
/**
|
* Used for testing - replace this function with a fixed date.
|
*/
|
function now() {
|
return new Date();
|
}
|
|
module.exports = asString;
|
module.exports.asString = asString;
|
module.exports.parse = parse;
|
module.exports.now = now;
|
module.exports.ISO8601_FORMAT = 'yyyy-MM-ddThh:mm:ss.SSS';
|
module.exports.ISO8601_WITH_TZ_OFFSET_FORMAT = 'yyyy-MM-ddThh:mm:ss.SSSO';
|
module.exports.DATETIME_FORMAT = 'dd MM yyyy hh:mm:ss.SSS';
|
module.exports.ABSOLUTETIME_FORMAT = 'hh:mm:ss.SSS';
|