package/package.json000644 000765 000024 0000000722 12265203131013011 0ustar00000000 000000 { "name": "chrono", "author": "Konstantin Käfer", "description": "Format dates in JavaScript", "version": "1.0.5", "devDependencies": { "mocha": "~1.14" }, "repository": { "type": "git", "url": "git://github.com/kkaefer/chrono.js.git" }, "bugs": { "url": "https://github.com/kkaefer/chrono.js/issues" }, "scripts": { "test": "mocha -R spec -u exports" }, "main": "index" } package/LICENSE000644 000765 000024 0000002052 12265202056011533 0ustar00000000 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/index.js000644 000765 000024 0000000052 12265202056012171 0ustar00000000 000000 module.exports = require('./lib/chrono'); package/.travis.yml000644 000765 000024 0000000104 12265203204012627 0ustar00000000 000000 language: node_js node_js: - "0.11" - "0.10" - "0.8" - "0.6"package/Makefile000644 000765 000024 0000000127 12265202056012167 0ustar00000000 000000 test: @expresso -I lib test-cov: @expresso -I lib --coverage .PHONY: test test-cov package/README.markdown000644 000765 000024 0000005231 12265203453013233 0ustar00000000 000000 # chrono.js [![Build Status](https://travis-ci.org/kkaefer/chrono.js.png)](https://travis-ci.org/kkaefer/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 0000025153 12265202577013141 0ustar00000000 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, 'NZST': -720, 'NZDT': -780, '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', 'NZST'], '-765': ['CHAST'], '-780': ['PHOT', 'NZDT'], '-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.getFullYear() - self.getFullYear(), other.getMonth() - self.getMonth(), 0, // weeks other.getDate() - self.getDate(), other.getHours() - self.getHours(), other.getMinutes() - self.getMinutes(), other.getSeconds() - self.getSeconds() ]; 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': this.setTime(time); result += this.format('Y-m-d\\TH:i:sP', tz); break; case 'r': this.setTime(time); 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.setUTCDate(1); 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)) { 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 0000022357 12265203036014322 0ustar00000000 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'); assert.equal(d.format('c'), d.format('Y-m-d\\TH:i:sP')); assert.equal(d.format('r'), d.format('D, d M y H:i:s O')); }; 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 getUTCDaysOfMonth'] = function() { assert.equal(new Date('Jan 30 2012 00:00:00 GMT+0000').getUTCDaysOfMonth(), 31); assert.equal(new Date('Jan 30 2012').getUTCDaysOfMonth(), 31); assert.equal(new Date('Feb 02 2012 00:00:00 GMT+0000').getUTCDaysOfMonth(), 29); assert.equal(new Date('Feb 02 2012').getUTCDaysOfMonth(), 29); assert.deepEqual(new Date('Jan 30 2012 00:00:00 GMT+0000').interval(new Date('Feb 6, 2012 00:00:00 GMT+0000')), ['1 week']); assert.deepEqual(new Date('Jan 30 2012').interval(new Date('Feb 6, 2012')), ['1 week']); }; 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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(new Date('Feb 28 2004').interval(new Date('Feb 29 2004')), ['1 day']); assert.deepEqual(new Date('Feb 28 2004').interval(new Date('Mar 1 2004')), ['2 days']); assert.deepEqual(new Date('Feb 28 2004').interval(new Date('Feb 28 2005')), ['1 year']); assert.deepEqual(new Date('Feb 28 2004').interval(new Date('Mar 2 2004')), ['3 days']); assert.deepEqual(new Date('Feb 28 2003').interval(new Date('Mar 1 2005')), ['2 years', '1 day']); assert.deepEqual(new Date('Feb 28 2004').interval(new Date('Mar 1 2005')), ['1 year', '2 days']); assert.deepEqual(new Date('Feb 29 2004').interval(new Date('Mar 1 2005')), ['1 year', '1 day']); assert.deepEqual(new Date('Feb 28 2003').interval(new Date('Mar 1 2004')), ['1 year', '1 day']); }; exports['test time zone identifiers'] = function() { var d = new Date('May 31 2012 12:34:56 GMT+0200'); assert.equal(d.format('Y-m-d H:i:s O T', 'CEST'), '2012-05-31 12:34:56 +0200 CEST'); assert.equal(d.format('Y-m-d H:i:s O T', 'NZST'), '2012-05-31 22:34:56 +1200 NZST'); };