package/index.js000644 000765 000024 00000000052 11642367131 014672 0ustar00kkaeferstaff000000 000000 module.exports = require('./lib/chrono'); package/LICENSE000644 000765 000024 00000002052 11642367131 014234 0ustar00kkaeferstaff000000 000000 Copyright (c) 2010-2011 Konstantin Käfer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. package/Makefile000644 000765 000024 00000000127 11642367131 014670 0ustar00kkaeferstaff000000 000000 test: @expresso -I lib test-cov: @expresso -I lib --coverage .PHONY: test test-cov package/package.json000644 000765 000024 00000000526 11642367131 015521 0ustar00kkaeferstaff000000 000000 { "name": "chrono", "author": "Konstantin Käfer", "description": "Format dates in JavaScript", "version": "1.0.2", "repository": { "type": "git", "url": "git://github.com/kkaefer/chrono.js.git" }, "bugs": { "web": "https://github.com/kkaefer/chrono.js/issues" }, "main": "index" } package/README.markdown000644 000765 000024 00000005061 11642367131 015733 0ustar00kkaeferstaff000000 000000 # chrono.js ### Date.prototype.**format(format, [timezone])** Allows formatting of time in a `strftime` style, but with syntax taken from PHP's [`date`](http://php.net/date) function. It implements pretty much all of the tokens from PHP's [`date`](http://php.net/date) function, except for B (Swatch internet time) and e (Content/City timezone identifier). You can escape characters with a `\` (remember to encode the `\` in a string as well). All other characters will be printed as they appear in the format string. The optional `timezone` parameter specifies the time zone to be used. The values allowed are the same as for `Date.prototype.setTimezone()`. If no value is specified, the Date object's internal time zone will be used. The function returns a string with the tokens replaced with the Date object's information. Example: `new Date().format('d.m.Y H:i:s', 'CET');` returns `19.10.2010 15:48:20` (in CET, without regard to DST). ### Date.prototype.**isLeapYear()** Returns true if the Date object's UTC date is in a leap year. ### Date.prototype.**getUTCISOWeek()** Returns the ISO-8601 week number of the year, using the Date object's UTC date. ### Date.prototype.**getUTCISOFullYear()** Returns the ISO-8601 year, using the Date object's UTC date. This is generally the same as the Gregorian year, but may sometimes deviate at the beginning or end of the year. It is commonly used in conjunction with the ISO-8601 week number. ### Date.prototype.**getUTCDaysOfMonth()** Returns the number of days in the Date object's UTC date's month. ### Date.prototype.**getUTCDayOfYear()** Returns the day of the year of the Date object's UTC date. ### Date.prototype.**getTimezone()** Returns the deviation from UTC in minutes (using JavaScript's inverse offset). If no explicit time zone has been specified, it returns the system clock's time zone offset. ### Date.prototype.**getTimezoneName()** Returns the time zone acronym of the Date object's timezone. ### Date.prototype.**setTimezone(val)** Sets the Date object's timezone. Numbers are interpreted as deviation in minutes from UTC, with positive values west of UTC and negative values east thereof (this is JavaScript's way of specifying time zone offset and is the exact opposite of how timezone offsets normally work). Alternatively, you can specify a offset in RFC2822 notation, for example `'+0200'` for UTC + 2 hours. Common time zone shortcuts like `'PST'` also work. # TESTS Tests can be run with `make test` after installing [Expresso](http://github.com/visionmedia/expresso). `make test-cov` reports test coverage. package/lib/chrono.js000644 000765 000024 00000025322 11642367131 015630 0ustar00kkaeferstaff000000 000000 (function(){ // CommonJS exports. var data = (typeof exports !== 'undefined') ? exports : {}; data.tzToOffset = { 'ACDT': -630, 'ACST': -570, 'ACT': -480, 'ADT': +180, 'AEDT': -660, 'AEST': -600, 'AFT': -270, 'AKDT': +480, 'AKST': +540, 'AMST': -300, 'AMT': -240, 'ART': +180, 'AST': -240, // Arab Standard Time 'AWDT': -540, 'AWST': -480, 'AZOST': +60, 'AZT': -240, 'BDT': -480, 'BIOT': -360, 'BIT': +720, 'BOT': +240, 'BRT': +180, 'BST': -60, // British Summer Time 'BTT': -360, 'CAT': -120, 'CCT': -390, 'CDT': +300, 'CEDT': -120, 'CEST': -120, 'CET': -60, 'CHAST': -765, 'ChST': -600, 'CIST': +480, 'CKT': +600, 'CLST': +180, 'CLT': +240, 'COST': +240, 'COT': +300, 'CST': -480, 'CST': +360, 'CVT': +60, 'CXT': -420, 'DFT': -60, 'EAST': +360, 'EAT': -180, 'ECT': +240, 'ECT': +300, 'EDT': +240, 'EEDT': -180, 'EEST': -180, 'EET': -120, 'EST': +300, 'FJT': -720, 'FKST': +240, 'GALT': +360, 'GET': -240, 'GFT': +180, 'GILT': -720, 'GIT': +540, 'GMT': 0, 'GST': +120, 'GYT': +240, 'HADT': +540, 'HAST': +600, 'HKT': -480, 'HMT': -300, 'HST': +600, 'IRKT': -480, 'IRST': -210, 'IST': -120, 'IST': -330, 'IST': -60, 'JST': -540, 'KRAT': -420, 'KST': -540, 'LHST': -630, 'LINT': -840, 'MAGT': -660, 'MDT': +360, 'MIT': +570, 'MSD': -240, 'MSK': -180, 'MST': -390, 'MST': -480, 'MST': +420, 'MUT': -240, 'NDT': +150, 'NFT': -690, 'NPT': -345, 'NST': +210, 'NT': +210, 'OMST': -360, 'PDT': +420, 'PETT': -720, 'PHOT': -780, 'PKT': -300, 'PST': -480, 'PST': +480, 'RET': -240, 'SAMT': -240, 'SAST': -120, 'SBT': -660, 'SCT': -240, 'SLT': -330, 'SST': -480, 'SST': +660, 'TAHT': +600, 'THA': -420, 'UTC': 0, 'UYST': +120, 'UYT': +180, 'VET': +270, 'VLAT': -600, 'WAT': -60, 'WEDT': -60, 'WEST': -60, 'YAKT': -540, 'YEKT': -300 }; // While indices are strings here, numbers work fine too when retrieving. data.offsetToTz = { '720': ['BIT'], '660': ['SST'], '600': ['HST', 'CKT', 'HAST', 'TAHT'], '570': ['MIT'], '540': ['AKST', 'GIT', 'HADT'], '480': ['PST', 'AKDT', 'CIST'], '420': ['MST', 'PDT'], '360': ['CST', 'EAST', 'GALT', 'MDT'], '300': ['EST', 'CDT', 'COT', 'ECT'], '270': ['VET'], '240': ['ECT', 'AST', 'BOT', 'CLT', 'COST', 'EDT', 'FKST', 'GYT'], '210': ['NT', 'NST'], '180': ['BRT', 'ADT', 'ART', 'CLST', 'GFT', 'UYT'], '150': ['NDT'], '120': ['GST', 'UYST'], '60': ['AZOST', 'CVT'], '0': ['UTC', 'GMT'], '-60': ['CET', 'BST', 'DFT', 'IST', 'WAT', 'WEDT', 'WEST'], '-120': ['EET', 'CAT', 'CEDT', 'CEST', 'IST', 'SAST'], '-180': ['MSK', 'AST', 'AST', 'EAT', 'EEDT', 'EEST'], '-210': ['IRST'], '-240': ['AST', 'AMT', 'AZT', 'GET', 'MSD', 'MUT', 'RET', 'SAMT', 'SCT'], '-270': ['AFT'], '-300': ['AMST', 'HMT', 'PKT', 'YEKT'], '-330': ['IST', 'SLT'], '-345': ['NPT'], '-360': ['BIOT', 'BST', 'BTT', 'OMST'], '-390': ['CCT', 'MST'], '-420': ['CXT', 'KRAT', 'THA'], '-480': ['ACT', 'AWST', 'BDT', 'CST', 'HKT', 'IRKT', 'MST', 'PST', 'SST'], '-540': ['AWDT', 'JST', 'KST', 'YAKT'], '-570': ['ACST'], '-600': ['AEST', 'ChST', 'VLAT'], '-630': ['ACDT', 'LHST'], '-660': ['AEDT', 'MAGT', 'SBT'], '-690': ['NFT'], '-720': ['FJT', 'GILT', 'PETT'], '-765': ['CHAST'], '-780': ['PHOT'], '-840': ['LINT'] }; data.weekdays = [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ]; data.weekdaysShort = [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ]; data.months = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ]; data.monthsShort = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]; data.intervals = [ function(n) { return n !== 1 ? 'years' : 'year'; }, function(n) { return n !== 1 ? 'months' : 'month'; }, function(n) { return n !== 1 ? 'weeks' : 'week'; }, function(n) { return n !== 1 ? 'days' : 'day'; }, function(n) { return n !== 1 ? 'hours' : 'hour'; }, function(n) { return n !== 1 ? 'minutes' : 'minute'; }, function(n) { return n !== 1 ? 'seconds' : 'second'; } ]; data.intervalFormats = { 'ago': '% ago', 'in': 'in %' }; data.ordinals = function(number) { switch (number % 10) { case 1: return (number % 100 !== 11) ? 'st' : 'th'; case 2: return (number % 100 !== 12) ? 'nd' : 'th'; case 3: return (number % 100 !== 13) ? 'rd' : 'th'; default: return 'th'; } }; function pad2(i) { return i < 10 ? '0' + i : i; }; function pad2sign(i) { var sgn = i < 0 ? '-' : '+'; i = Math.abs(i); return sgn + (i < 10 ? '0' + i : i); }; function pad3(i) { return i < 10 ? '00' + i : i < 100 ? '0' + i : i; }; function pad4sign(i) { var sgn = i < 0 ? '-' : '+'; i = Math.abs(i); return sgn + (i < 10 ? '000' + i : i < 100 ? '00' + i : i < 1000 ? '0' + i : i); } Date.prototype.interval = function(other) { var self = this, inverse = self > other; if (inverse) { self = other; other = this; } var parts = [ other.getUTCFullYear() - self.getUTCFullYear(), other.getUTCMonth() - self.getUTCMonth(), 0, // weeks other.getUTCDate() - self.getUTCDate(), other.getUTCHours() - self.getUTCHours(), other.getUTCMinutes() - self.getUTCMinutes(), other.getUTCSeconds() - self.getUTCSeconds() ]; if (parts[6] < 0) { parts[5]--; parts[6] += 60; } if (parts[5] < 0) { parts[4]--; parts[5] += 60; } if (parts[4] < 0) { parts[3]--; parts[4] += 24; } if (parts[3] < 0) { parts[1]--; parts[3] += self.getUTCDaysOfMonth(); } if (parts[1] < 0) { parts[0]--; parts[1] += 12; } parts[2] = (parts[3] / 7) | 0; parts[3] -= parts[2] * 7; var fragments = []; for (var i = 0; i < parts.length; i++) { if (parts[i]) { fragments.push(parts[i] + ' ' + data.intervals[i](parts[i])); } } return fragments; }; Date.prototype.format = function(format, tz) { var time = this.getTime(); if (tz === undefined) { tz = this.getTimezone(); tzName = this.getTimezoneName(); } else { var tzData = parseTimezone(tz); tz = tzData[0]; var tzName = tzData[1]; } // Use correct timezone. this.setTime(time - tz * 60000); var result = ''; for (var i = 0; i < format.length; i++) { switch (format.charAt(i)) { // Day case 'd': result += pad2(this.getUTCDate()); break; case 'D': result += data.weekdaysShort[this.getUTCDay()]; break; case 'j': result += this.getUTCDate(); break; case 'l': result += data.weekdays[this.getUTCDay()]; break; case 'N': result += this.getUTCDay() || 7; break; case 'S': result += data.ordinals(this.getUTCDate()); break; case 'w': result += this.getUTCDay(); break; case 'z': result += this.getUTCDayOfYear(); break; // Week case 'W': result += pad2(this.getUTCISOWeek()); break; // Month case 'F': result += data.months[this.getUTCMonth()]; break; case 'm': result += pad2(this.getUTCMonth() + 1); break; case 'M': result += data.monthsShort[this.getUTCMonth()]; break; case 'n': result += this.getUTCMonth() + 1; break; case 't': result += this.getUTCDaysOfMonth(); break; // Year case 'L': result += this.isLeapYear() ? 1 : 0; break; case 'o': result += this.getUTCISOFullYear(); break; case 'Y': result += this.getUTCFullYear(); break; case 'y': result += pad2(this.getUTCFullYear() % 100); break; // Time case 'a': result += this.getUTCHours() >= 12 ? 'pm' : 'am'; break; case 'A': result += this.getUTCHours() >= 12 ? 'PM' : 'AM'; break; case 'g': result += this.getUTCHours() % 12 || 12; break; case 'G': result += this.getUTCHours(); break; case 'h': result += pad2(this.getUTCHours() % 12 || 12); break; case 'H': result += pad2(this.getUTCHours()); break; case 'i': result += pad2(this.getUTCMinutes()); break; case 's': result += pad2(this.getUTCSeconds()); break; case 'u': result += pad3(this.getUTCMilliseconds()); break; // Timezone case 'O': result += pad4sign((tz < 0 ? 1 : -1) * (Math.floor(Math.abs(tz) / 60) * 100 + Math.abs(tz) % 60)); break; case 'P': result += pad2sign((tz < 0 ? 1 : -1) * (Math.floor(Math.abs(tz) / 60))) + ':' + pad2(Math.abs(tz) % 60); break; case 'T': result += tzName; break; case 'Z': result += -tz * 60; break; // Full Date/Time case 'c': result += this.format('Y-m-d\\TH:i:sP', tz); break; case 'r': result += this.format('D, d M y H:i:s O', tz); break; case 'U': result += Math.floor(this.getTime() / 1000); break; case '\\': if (format.charAt(++i) !== undefined) result += format.charAt(i); break; default: result += format.charAt(i); break; } } this.setTime(time); return result; }; function parseTimezone(tz) { if (typeof tz === 'number') { return [tz, tz in data.offsetToTz ? data.offsetToTz[tz][0] : '']; } var number = parseInt(tz, 10); if (isNaN(number)) { return [data.tzToOffset[tz], tz]; } else { tz = (number < 0 ? 1 : -1) * (Math.floor(Math.abs(number) / 100) * 60 + Math.abs(number) % 100); return [tz, tz in data.offsetToTz ? data.offsetToTz[tz][0] : '']; } } Date.prototype.isLeapYear = function() { var y = this.getUTCFullYear(); return (y % 400 === 0) || (y % 4 === 0 && y % 100 !== 0); }; Date.prototype.getUTCISOWeek = function() { // Go to the week's thursday. var d = new Date(this); d.setUTCDate(d.getUTCDate() - (d.getUTCDay() || 7) + 4); return Math.ceil((d.getTime() - Date.UTC(d.getUTCFullYear(), 0)) / 86400000 / 7); }; Date.prototype.getUTCISOFullYear = function() { // Go to the week's thursday. var d = new Date(this); d.setUTCDate(d.getUTCDate() - (d.getUTCDay() || 7) + 4); return d.getUTCFullYear(); }; Date.prototype.getUTCDaysOfMonth = function() { var d = new Date(this); d.setUTCMonth(d.getUTCMonth() + 1); d.setUTCDate(0); return d.getUTCDate(); }; Date.prototype.getUTCDayOfYear = function() { return Math.floor((this.getTime() - Date.UTC(this.getUTCFullYear(), 0)) / 86400000); }; Date.prototype.getTimezone = function() { if (!('_tz' in this)) { var matches = new Date().toString().match(/([A-Z]{3,4}|NT|ChST)(?![-\+])/); if (matches && matches[1]) { this.setTimezone(matches[1]); } else { this.setTimezone(new Date().getTimezoneOffset()); } } return this._tz; }; Date.prototype.getTimezoneName = function() { this.getTimezone(); // Make sure the tz data is populated. return this._tzName; }; Date.prototype.setTimezone = function(val) { var tzData = parseTimezone(val); this._tz = tzData[0]; this._tzName = tzData[1]; }; })(); package/test/chrono.test.js000644 000765 000024 00000017554 11642367131 017027 0ustar00kkaeferstaff000000 000000 var assert = require('assert'); require('..'); exports['test general formatting'] = function() { var d = new Date('Apr 02 2010 08:47:07.049 GMT+0000'); assert.equal(d.format('y-m-d H:i:s', 0), '10-04-02 08:47:07'); assert.equal(d.format('D, jS F Y \\a\\t g a', 0), 'Fri, 2nd April 2010 at 8 am'); assert.equal(d.format('d D j l N S w z', 0), '02 Fri 2 Friday 5 nd 5 91'); assert.equal(d.format('F m M n t', 0), 'April 04 Apr 4 30'); assert.equal(d.format('L o Y y O P T Z', 0), '0 2010 2010 10 +0000 +00:00 UTC 0'); assert.equal(d.format('a A g G h H i s u', 0), 'am AM 8 8 08 08 47 07 049'); assert.equal(d.format('c r U', 0), '2010-04-02T08:47:07+00:00 Fri, 02 Apr 10 08:47:07 +0000 1270198027'); }; exports['test padding'] = function() { var d = new Date('Feb 04 2005 05:03:08 GMT+0000'); // Test padding. assert.equal(d.format('W d m y h H i s u O P', 0), '05 04 02 05 05 05 03 08 000 +0000 +00:00'); // Test non-padding. assert.equal(d.format('j z n g G', 0), '4 34 2 5 5'); }; exports['test am/pm'] = function() { assert.equal(new Date('May 15 2010 00:00:00 GMT+0000').format('a A g G h H', 0), 'am AM 12 0 12 00'); assert.equal(new Date('May 15 2010 14:00:00 GMT+0000').format('a A g G h H', 0), 'pm PM 2 14 02 14'); }; exports['test leap years'] = function() { assert.equal(new Date('Feb 01 1900 00:00:00 GMT+0000').format('L t', 0), '0 28'); assert.equal(new Date('Feb 01 1904 00:00:00 GMT+0000').format('L t', 0), '1 29'); assert.equal(new Date('Feb 01 2000 00:00:00 GMT+0000').format('L t', 0), '1 29'); assert.equal(new Date('Feb 01 2001 00:00:00 GMT+0000').format('L t', 0), '0 28'); }; exports['test english ordinals'] = function() { assert.equal(new Date('May 1 2010 00:00:00 GMT+0000').format('jS', 0), '1st'); assert.equal(new Date('May 2 2010 00:00:00 GMT+0000').format('jS', 0), '2nd'); assert.equal(new Date('May 3 2010 00:00:00 GMT+0000').format('jS', 0), '3rd'); assert.equal(new Date('May 4 2010 00:00:00 GMT+0000').format('jS', 0), '4th'); assert.equal(new Date('May 11 2010 00:00:00 GMT+0000').format('jS', 0), '11th'); assert.equal(new Date('May 21 2010 00:00:00 GMT+0000').format('jS', 0), '21st'); }; exports['test missing timezone parameter'] = function() { var date = new Date(); assert.equal(parseInt(date.format('G'), 10), date.getHours()); assert.equal(parseInt(date.format('i'), 10), date.getMinutes()); assert.equal(parseInt(date.format('j'), 10), date.getDate()); }; exports['test timezone tokens'] = function() { var d = new Date('Jul 18 2010 12:00:00 GMT+0000'); assert.equal(d.format('Y-m-d H:i:s O P Z', 285), '2010-07-18 07:15:00 -0445 -04:45 -17100'); assert.equal(d.format('Y-m-d H:i:s O P Z', '-0445'), '2010-07-18 07:15:00 -0445 -04:45 -17100'); assert.equal(d.format('Y-m-d H:i:s O P Z', 270), '2010-07-18 07:30:00 -0430 -04:30 -16200'); assert.equal(d.format('Y-m-d H:i:s O P Z', '-0430'), '2010-07-18 07:30:00 -0430 -04:30 -16200'); assert.equal(d.format('Y-m-d H:i:s O P Z', 'VET'), '2010-07-18 07:30:00 -0430 -04:30 -16200'); assert.equal(d.format('Y-m-d H:i:s O P Z', 60), '2010-07-18 11:00:00 -0100 -01:00 -3600'); assert.equal(d.format('Y-m-d H:i:s O P Z', '-0100'), '2010-07-18 11:00:00 -0100 -01:00 -3600'); assert.equal(d.format('Y-m-d H:i:s O P Z', 'CVT'), '2010-07-18 11:00:00 -0100 -01:00 -3600'); assert.equal(d.format('Y-m-d H:i:s O P Z', -60), '2010-07-18 13:00:00 +0100 +01:00 3600'); assert.equal(d.format('Y-m-d H:i:s O P Z', '+0100'), '2010-07-18 13:00:00 +0100 +01:00 3600'); assert.equal(d.format('Y-m-d H:i:s O P Z', 'CET'), '2010-07-18 13:00:00 +0100 +01:00 3600'); assert.equal(d.format('Y-m-d H:i:s O P Z', -345), '2010-07-18 17:45:00 +0545 +05:45 20700'); assert.equal(d.format('Y-m-d H:i:s O P Z', '+0545'), '2010-07-18 17:45:00 +0545 +05:45 20700'); assert.equal(d.format('Y-m-d H:i:s O P Z', 'NPT'), '2010-07-18 17:45:00 +0545 +05:45 20700'); }; exports['test timezones across day boundaries'] = function() { var d = new Date('Jan 1 2010 00:00:00 GMT+0000'); assert.equal(d.format('Y-m-d H:i:s O T', '+1200'), '2010-01-01 12:00:00 +1200 FJT'); assert.equal(d.format('Y-m-d H:i:s O T', 'CEST'), '2010-01-01 02:00:00 +0200 CEST'); assert.equal(d.format('Y-m-d H:i:s O T', 'EST'), '2009-12-31 19:00:00 -0500 EST'); assert.equal(d.format('Y-m-d H:i:s O T', 'EDT'), '2009-12-31 20:00:00 -0400 EDT'); assert.equal(d.format('Y-m-d H:i:s O T', 'PST'), '2009-12-31 16:00:00 -0800 PST'); assert.equal(d.format('Y-m-d H:i:s O T', 'PDT'), '2009-12-31 17:00:00 -0700 PDT'); assert.equal(d.format('Y-m-d H:i:s O T', '-0730'), '2009-12-31 16:30:00 -0730 '); assert.equal(d.format('Y-m-d H:i:s O T', '-0745'), '2009-12-31 16:15:00 -0745 '); assert.equal(d.format('Y-m-d H:i:s O T', 'NPT'), '2010-01-01 05:45:00 +0545 NPT'); d.setTimezone('EEST'); assert.equal(d.format('Y-m-d H:i:s O T'), '2010-01-01 03:00:00 +0300 EEST'); assert.equal(d.format('Y-m-d H:i:s O T', 'CEST'), '2010-01-01 02:00:00 +0200 CEST'); }; exports['test ISO week numbers'] = function() { assert.equal(new Date('Jan 01 2005 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2004-W53-6'); assert.equal(new Date('Jan 02 2005 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2004-W53-7'); assert.equal(new Date('Dec 31 2005 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2005-W52-6'); assert.equal(new Date('Jan 01 2007 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2007-W01-1'); assert.equal(new Date('Dec 30 2007 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2007-W52-7'); assert.equal(new Date('Dec 31 2007 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2008-W01-1'); assert.equal(new Date('Jan 01 2008 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2008-W01-2'); assert.equal(new Date('Dec 28 2008 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2008-W52-7'); assert.equal(new Date('Dec 29 2008 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2009-W01-1'); assert.equal(new Date('Dec 30 2008 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2009-W01-2'); assert.equal(new Date('Dec 31 2008 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2009-W01-3'); assert.equal(new Date('Jan 01 2009 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2009-W01-4'); assert.equal(new Date('Dec 27 2009 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2009-W52-7'); assert.equal(new Date('Dec 28 2009 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2009-W53-1'); assert.equal(new Date('Dec 29 2009 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2009-W53-2'); assert.equal(new Date('Dec 30 2009 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2009-W53-3'); assert.equal(new Date('Dec 31 2009 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2009-W53-4'); assert.equal(new Date('Jan 01 2010 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2009-W53-5'); assert.equal(new Date('Jan 02 2010 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2009-W53-6'); assert.equal(new Date('Jan 03 2010 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2009-W53-7'); assert.equal(new Date('Jan 04 2010 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2010-W01-1'); assert.equal(new Date('Jan 05 2010 12:00:00 GMT+0000').format('o-\\WW-N', 0), '2010-W01-2'); }; exports['test time intervals'] = function() { assert.eql(new Date('Dec 27 2009 11:34:20 UTC').interval(new Date('Dec 27 2010 12:18:23 UTC')), ['1 year', '44 minutes', '3 seconds']); assert.eql(new Date('Dec 31 2009 11:34:20 UTC').interval(new Date('Feb 10 2010 12:18:23 UTC')), ['1 month', '1 week', '3 days', '44 minutes', '3 seconds']); assert.eql(new Date('Dec 15 2010 11:34:20 UTC').interval(new Date('Nov 28 2010 12:18:23 UTC')), ['2 weeks', '2 days', '23 hours', '15 minutes', '57 seconds']); assert.eql(new Date('Feb 28 2004').interval(new Date('Feb 29 2004')), ['1 day']); assert.eql(new Date('Feb 28 2004').interval(new Date('Mar 1 2004')), ['2 days']); assert.eql(new Date('Feb 28 2004').interval(new Date('Feb 28 2005')), ['1 year']); assert.eql(new Date('Feb 28 2004').interval(new Date('Mar 1 2005')), ['1 year', '1 day']); };