UNPKG

todomvc

Version:

> Helping you select an MV\* framework

217 lines (169 loc) 5.39 kB
/* poly/date ES5-ish Date shims for older browsers. (c) copyright 2011-2013 Brian Cavalier and John Hann This module is part of the cujo.js family of libraries (http://cujojs.com/). Licensed under the MIT License at: http://www.opensource.org/licenses/mit-license.php */ (function (origDate) { define(['./lib/_base'], function (base) { var origProto, origParse, featureMap, maxDate, invalidDate, isoCompat, isoParseRx, ownProp, undef; origProto = origDate.prototype; origParse = origDate.parse; ownProp = Object.prototype.hasOwnProperty; maxDate = 8.64e15; invalidDate = NaN; // borrowed this from https://github.com/kriskowal/es5-shim isoCompat = function () { return origDate.parse('+275760-09-13T00:00:00.000Z') == maxDate; }; // can't even have spaces in iso date strings // in Chrome and FF, the colon in the timezone is optional, but IE, Opera, and Safari need it isoParseRx = /^([+\-]\d{6}|\d{4})(?:-(\d{2}))?(?:-(\d{2}))?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:.(\d{1,3}))?)?(?:Z|([+\-])(\d{2})(?::(\d{2}))?)?)?$/; featureMap = { 'date-now': 'now', 'date-tojson': 'toJSON', 'date-toisostring': 'toISOString' }; function has (feature) { var prop = featureMap[feature]; return prop in origDate || prop in origProto; } if (!has('date-now')) { origDate.now = function () { return +(new Date); }; } function isInvalidDate (date) { return !isFinite(date); } function fix2 (number) { // ensures number is formatted to at least two digits return (number < 10 ? '0' : '') + number; } function isoParse (str) { // parses simplified iso8601 dates, such as // yyyy-mm-ddThh:mm:ssZ // +yyyyyy-mm-ddThh:mm:ss-06:30 var result; // prepare for the worst result = invalidDate; // fast parse str.replace(isoParseRx, function (a, y, m, d, h, n, s, ms, tzs, tzh, tzm) { var adjust = 0; // Date.UTC handles years between 0 and 100 as 2-digit years, but // that's not what we want with iso dates. If we move forward // 400 years -- a full cycle in the Gregorian calendar -- then // subtract the 400 years (as milliseconds) afterwards, we can avoid // this problem. (learned of this trick from kriskowal/es5-shim.) if (y >= 0 && y < 100) { y = +y + 400; // convert to number adjust = -126227808e5; // 400 years } result = Date.UTC(y, (m || 1) - 1, d || 1, h || 0, n || 0, s || 0, ms || 0) + adjust; tzh = +(tzs + tzh); // convert to signed number tzm = +(tzs + tzm); // convert to signed number if (tzh || tzm) { result -= (tzh + tzm / 60) * 36e5; // check if time zone is out of bounds if (tzh > 23 || tzh < -23 || tzm > 59) result = invalidDate; // check if time zone pushed us over maximum date value if (result > maxDate) result = invalidDate; } return ''; // reduces memory used }); return result; } if (!has('date-toisostring')) { origProto.toISOString = function toIsoString () { if (isInvalidDate(this)) { throw new RangeError("toISOString called on invalid value"); } return [ this.getUTCFullYear(), '-', fix2(this.getUTCMonth() + 1), '-', fix2(this.getUTCDate()), 'T', fix2(this.getUTCHours()), ':', fix2(this.getUTCMinutes()), ':', fix2(this.getUTCSeconds()), '.', (this.getUTCMilliseconds()/1000).toFixed(3).slice(2), 'Z' ].join(''); }; } if (!has('date-tojson')) { origProto.toJSON = function toJSON (key) { // key arg is ignored by Date objects, but since this function // is generic, other Date-like objects could use the key arg. // spec says to throw a TypeError if toISOString is not callable // but that's what happens anyways, so no need for extra code. return this.toISOString(); }; } function checkIsoCompat () { // fix Date constructor var newDate = (function () { // Replacement Date constructor return function Date (y, m, d, h, mn, s, ms) { var len, result; // Date called as function, not constructor if (!(this instanceof newDate)) return origDate.apply(this, arguments); len = arguments.length; if (len === 0) { result = new origDate(); } else if (len === 1) { result = new origDate(base.isString(y) ? newDate.parse(y) : y); } else { result = new origDate(y, m, d == undef ? 1 : d, h || 0, mn || 0, s || 0, ms || 0); } result.constructor = newDate; return result; }; }()); if (!isoCompat()) { newDate.now = origDate.now; newDate.UTC = origDate.UTC; newDate.prototype = origProto; newDate.prototype.constructor = newDate; newDate.parse = function parse (str) { var result; // check for iso date result = isoParse('' + str); if (isInvalidDate(result)) { // try original parse() result = origParse(str); } return result; }; // Unfortunate. See cujojs/poly#11 // Copy any owned props that may have been previously added to // the Date constructor by 3rd party libs. copyPropsSafely(newDate, origDate); Date = newDate; } else if (Date != origDate) { Date = origDate; } } function copyPropsSafely(dst, src) { for (var p in src) { if (ownProp.call(src, p) && !ownProp.call(dst, p)) { dst[p] = src[p]; } } } checkIsoCompat(); return { setIsoCompatTest: function (testFunc) { isoCompat = testFunc; checkIsoCompat(); } }; }); }(Date));