From 3c8928c8e4bf1096634413a0f18f76a3dee5f788 Mon Sep 17 00:00:00 2001 From: "Manikandan, Ramalingam Kandaswamy" Date: Tue, 28 Feb 2017 16:01:30 -0800 Subject: [PATCH] Date: Olson-timezone-support (real 'z', 'v', 'V') --- doc/api/date/date-formatter.md | 8 +- src/date.js | 4 +- src/date/format-properties.js | 148 +++++++++++++- src/date/format.js | 33 +++ src/magicDate.js | 120 +++++++++++ test/unit.js | 1 + test/unit/date/format-properties.js | 60 +++++- test/unit/date/format.js | 137 +++++++++++-- test/unit/date/magicDate.js | 305 ++++++++++++++++++++++++++++ 9 files changed, 781 insertions(+), 35 deletions(-) create mode 100644 src/magicDate.js create mode 100644 test/unit/date/magicDate.js diff --git a/doc/api/date/date-formatter.md b/doc/api/date/date-formatter.md index 76013cfbd..6d3054c6f 100644 --- a/doc/api/date/date-formatter.md +++ b/doc/api/date/date-formatter.md @@ -106,12 +106,12 @@ are: `full`, `long`, `medium`, and `short`. | `{ date: "full" }` | `"Monday, November 1, 2010"` | | `{ time: "short" }` | `"5:55 PM"` | | `{ time: "medium" }` | `"5:55:00 PM"` | -| `{ time: "long" }` | `"5:55:00 PM GMT-2"` | -| `{ time: "full" }` | `"5:55:00 PM GMT-02:00"` | +| `{ time: "long" }` | `"5:55:00 PM PST"` | +| `{ time: "full" }` | `"5:55:00 PM Pacific Standard Time"` | | `{ datetime: "short" }` | `"11/1/10, 5:55 PM"` | | `{ datetime: "medium" }` | `"Nov 1, 2010, 5:55:00 PM"` | -| `{ datetime: "long" }` | `"November 1, 2010 at 5:55:00 PM GMT-2"` | -| `{ datetime: "full" }` | `"Monday, November 1, 2010 at 5:55:00 PM GMT-02:00"` | +| `{ datetime: "long" }` | `"November 1, 2010 at 5:55:00 PM PST"` | +| `{ datetime: "full" }` | `"Monday, November 1, 2010 at 5:55:00 PM Pacific Standard Time"` | For comparison, follow the same formatter `{ datetime: "short" }` on different locales. diff --git a/src/date.js b/src/date.js index 98500c9fa..539ba2e9c 100644 --- a/src/date.js +++ b/src/date.js @@ -51,7 +51,7 @@ function validateRequiredCldr( path, value ) { */ Globalize.dateFormatter = Globalize.prototype.dateFormatter = function( options ) { - var args, cldr, numberFormatters, pad, pattern, properties, returnFn; + var args, cldr, numberFormatters, pad, pattern, properties, returnFn, timeZone; validateParameterTypePlainObject( options, "options" ); @@ -64,7 +64,7 @@ Globalize.prototype.dateFormatter = function( options ) { cldr.on( "get", validateRequiredCldr ); pattern = dateExpandPattern( options, cldr ); - properties = dateFormatProperties( pattern, cldr ); + properties = dateFormatProperties( pattern, cldr, timeZone ); cldr.off( "get", validateRequiredCldr ); // Create needed number formatters. diff --git a/src/date/format-properties.js b/src/date/format-properties.js index 6c42a9db5..b38395764 100644 --- a/src/date/format-properties.js +++ b/src/date/format-properties.js @@ -3,9 +3,10 @@ define([ "./pattern-re", "../common/create-error/unsupported-feature", "../number/symbol", - "../util/string/pad" + "../util/string/pad", + "../common/format-message" ], function( dateFirstDayOfWeek, datePatternRe, createErrorUnsupportedFeature, numberSymbol, - stringPad ) { + stringPad, formatMessage ) { /** * properties( pattern, cldr ) @@ -19,13 +20,28 @@ define([ * * TODO Support other calendar types. */ -return function( pattern, cldr ) { +return function( pattern, cldr, timeZone ) { var properties = { numberFormatters: {}, pattern: pattern, timeSeparator: numberSymbol( "timeSeparator", cldr ) }, - widths = [ "abbreviated", "wide", "narrow" ]; + widths = [ "abbreviated", "wide", "narrow" ], + metaZone, + exemplarCity; + + if ( timeZone ) { + + // The latest metazone data of the metazone array. + //TODO expand to support the historic metazones based on the given date. + metaZone = cldr.supplemental([ + "metaZones/metazoneInfo/timezone", timeZone, 0, + "usesMetazone/_mzone" + ]), + exemplarCity = cldr.main([ + "dates/timeZoneNames/zone", timeZone, "exemplarCity" + ]); + } function setNumberFormatterPattern( pad ) { properties.numberFormatters[ pad ] = stringPad( "", pad ); @@ -34,7 +50,10 @@ return function( pattern, cldr ) { pattern.replace( datePatternRe, function( current ) { var formatNumber, chr = current.charAt( 0 ), - length = current.length; + length = current.length, + standardTzName, + daylightTzName, + genericTzName; if ( chr === "j" ) { @@ -49,6 +68,62 @@ return function( pattern, cldr ) { length = 4; } + // z...zzz: fallback to "O" + // zzzz: fallback to "OOOO" + // http://unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns + if ( chr === "z" ) { + if ( metaZone ) { + + //z...zzz: "{shortRegion}", eg. "PST" or "PDT". + //zzzz: "{regionName} {Standard Time}" or "{regionName} {Daylight Time}", + //eg. "Pacific Standard Time" or "Pacific Daylight Time". + standardTzName = cldr.main([ + "dates/timeZoneNames/metazone", + metaZone, + length < 4 ? "short" : "long", + "standard" + ]); + daylightTzName = cldr.main([ + "dates/timeZoneNames/metazone", + metaZone, + length < 4 ? "short" : "long", + "daylight" + ]); + } + + //fall through "O" format + if ( !metaZone || !standardTzName ) { + chr = "O"; + if ( length < 4 ) { + length = 1; + } + } + } + + // v: fallback to "VVVV" + // vvvv: fallback to "VVVV" + // http://unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns + if ( chr === "v" ) { + if ( metaZone ) { + + //v...vvv: "{shortRegion}", eg. "PT". + //vvvv: "{regionName} {Time}" or "{regionName} {Time}", + //eg. "Pacific Time" + genericTzName = cldr.main([ + "dates/timeZoneNames/metazone", + metaZone, + length === 1 ? "short" : "long", + "generic" + ]); + } + + //fall through "V" format + if ( !metaZone || !genericTzName ) { + chr = "V"; + length = 4; + } + } + switch ( chr ) { // Era @@ -208,6 +283,63 @@ return function( pattern, cldr ) { // Zone case "z": + properties.standardTzName = standardTzName; + properties.daylightTzName = daylightTzName; + break; + case "v": + if ( length !== 1 && length !== 4 ) { + throw createErrorUnsupportedFeature({ + feature: "timezone pattern `" + pattern + "`" + }); + } + properties.genericTzName = genericTzName; + break; + case "V": + + if ( length === 1 ) { + throw createErrorUnsupportedFeature({ + feature: "timezone pattern `" + pattern + "`" + }); + } + + //fall through "{0} {Time}"" + //for VVVV format + if ( timeZone ) { + var TzName; + + if ( length === 2 ) { + TzName = timeZone; + } + + if ( exemplarCity ) { + if ( length === 3 ) { + TzName = exemplarCity; + } else if ( length === 4 ) { + TzName = formatMessage( + cldr.main( + "dates/timeZoneNames/regionFormat" + ), + [ exemplarCity ] + ); + } + } else if ( !exemplarCity && length === 4 ) { + var unKnownExemplarCity = cldr.main([ + "dates/timeZoneNames/zone/Etc/Unknown/exemplarCity" + ]); + TzName = formatMessage( + cldr.main( + "dates/timeZoneNames/regionFormat" + ), + [ unKnownExemplarCity ] + ); + } + if ( TzName ) { + properties.TzName = TzName; + break; + } + } + + /* falls through */ case "O": // O: "{gmtFormat}+H;{gmtFormat}-H" or "{gmtZeroFormat}", eg. "GMT-8" or "GMT". @@ -223,12 +355,6 @@ return function( pattern, cldr ) { setNumberFormatterPattern( 1 ); setNumberFormatterPattern( 2 ); break; - - case "v": - case "V": - throw createErrorUnsupportedFeature({ - feature: "timezone pattern `" + chr + "`" - }); } if ( formatNumber ) { diff --git a/src/date/format.js b/src/date/format.js index 0bb4834d3..2caaf2b29 100644 --- a/src/date/format.js +++ b/src/date/format.js @@ -207,6 +207,39 @@ return function( date, numberFormatters, properties ) { // Zone case "z": + + // z...zzz: "{shortRegion}", eg. "PST" or "PDT". + // zzzz: "{regionName} {Standard Time}" or "{regionName} {Daylight Time}", + // eg. "Pacific Standard Time" or "Pacific Daylight Time". + // TODO: date.isDST() FIXME + if ( date.isDST && properties.standardTzName ) { + ret = date.isDST() && properties.daylightTzName ? + properties.daylightTzName : properties.standardTzName; + break; + } + + /* falls through */ + case "v": + + //v...vvv: "{shortRegion}", eg. "PT". + //vvvv: "{regionName} {Time}", + //eg. "Pacific Time" + if ( properties.genericTzName ) { + ret = properties.genericTzName; + break; + } + + /* falls through */ + case "V": + + //VVVV: "{explarCity} {Time}", + //eg. "Los Angeles Time" + if ( properties.TzName ) { + ret = properties.TzName; + break; + } + + /* falls through */ case "O": // O: "{gmtFormat}+H;{gmtFormat}-H" or "{gmtZeroFormat}", eg. "GMT-8" or "GMT". diff --git a/src/magicDate.js b/src/magicDate.js new file mode 100644 index 000000000..b2856e7b8 --- /dev/null +++ b/src/magicDate.js @@ -0,0 +1,120 @@ + +define( function() { +var MagicDate = function( date, timeZonedata ) { + this.date = new Date( date.getTime() ); + this.timeZoneData = timeZonedata; + this.date = new Date( this.date.getTime() - this.getDaylightAdjustment() * 60 * 1000 ); +}; + +MagicDate.prototype.getFullYear = function() { + return this.date.getUTCFullYear(); +}; + +MagicDate.prototype.getMonth = function() { + return this.date.getUTCMonth(); +}; + +MagicDate.prototype.getDate = function() { + return this.date.getUTCDate(); +}; + +MagicDate.prototype.getMinutes = function() { + return this.date.getUTCMinutes(); +}; + +MagicDate.prototype.getSeconds = function() { + return this.date.getUTCSeconds(); +}; + +MagicDate.prototype.getHours = function() { + return this.date.getUTCHours(); +}; + +MagicDate.prototype.getMinutes = function() { + return this.date.getUTCMinutes(); +}; + +MagicDate.prototype.getSeconds = function() { + return this.date.getUTCSeconds(); +}; + +MagicDate.prototype.getMilliseconds = function() { + return this.date.getUTCMilliseconds(); +}; + +MagicDate.prototype.getTime = function() { + return this.date.getTime() + this.getDaylightAdjustment() * 60 * 60 * 1000; +}; + +MagicDate.prototype.setFullYear = function( year ) { + return this.date.setUTCFullYear( year ); +}; + +MagicDate.prototype.setMonth = function( month ) { + return this.date.setUTCMonth( month ); +}; + +MagicDate.prototype.setDate = function( date ) { + return this.date.setUTCDate( date ); +}; + +MagicDate.prototype.setMinutes = function( minutes ) { + return this.date.setUTCMinutes( minutes ); +}; + +MagicDate.prototype.setSeconds = function( seconds ) { + return this.date.setUTCSeconds( seconds ); +}; + +MagicDate.prototype.setHours = function( hour ) { + return this.date.setUTCHours( hour ); +}; + +MagicDate.prototype.setMinutes = function( minutes ) { + return this.date.setUTCMinutes( minutes ); +}; + +MagicDate.prototype.setSeconds = function( seconds ) { + return this.date.setUTCSeconds( seconds ); +}; + +MagicDate.prototype.setMilliseconds = function( milliseconds ) { + return this.date.setUTCMilliseconds( milliseconds ); +}; + +MagicDate.prototype.setTime = function( time ) { + return this.date.setTime( time ); +}; + +MagicDate.prototype.isDST = function() { + return this.getDaylightAdjustment() > 0; +}; + +MagicDate.prototype.getStdOffset = function() { + var stdOffset = -1; + if ( this.timeZoneData.offsets > 1 ) { + stdOffset *= Math.max( + this.timeZoneData.offsets[ this.timeZoneData.offsets.length - 1 ], + this.timeZoneData.offsets[ this.timeZoneData.offsets.length - 2 ] + ); + } else { + stdOffset *= this.timeZoneData.offsets[ this.timeZoneData.offsets.length - 1 ]; + } + return stdOffset; +}; + +MagicDate.prototype.getOffset = function() { + return this.getStdOffset() - this.getDaylightAdjustment(); +}; + +MagicDate.prototype.getDaylightAdjustment = function() { + var index = 0; + while ( index < this.timeZoneData.untils.length - 1 && + this.date.getTime() >= this.timeZoneData.untils[ index ] ) { + index++; + } + return index === 0 ? 0 : this.timeZoneData.offsets[ index ]; +}; + +return MagicDate; +}); diff --git a/test/unit.js b/test/unit.js index c9dd9174f..e5977a9ed 100644 --- a/test/unit.js +++ b/test/unit.js @@ -19,6 +19,7 @@ require([ "./unit/date/format-properties", "./unit/date/parse-properties", "./unit/date/tokenizer-properties", + "./unit/date/magicDate", "./unit/date/format", "./unit/date/tokenizer", diff --git a/test/unit/date/format-properties.js b/test/unit/date/format-properties.js index 76db3487d..862cb1f6c 100644 --- a/test/unit/date/format-properties.js +++ b/test/unit/date/format-properties.js @@ -5,10 +5,11 @@ define([ "json!cldr-data/supplemental/likelySubtags.json", "json!cldr-data/supplemental/timeData.json", "json!cldr-data/supplemental/weekData.json", + "json!cldr-data/supplemental/metaZones.json", "cldr/event", "cldr/supplemental" -], function( Cldr, properties, enCaGregorian, likelySubtags, timeData, weekData ) { +], function( Cldr, properties, enCaGregorian, likelySubtags, timeData, weekData, metaZones ) { var cldr; @@ -16,7 +17,8 @@ Cldr.load( enCaGregorian, likelySubtags, timeData, - weekData + weekData, + metaZones ); cldr = new Cldr( "en" ); @@ -117,4 +119,58 @@ QUnit.test( "should return dayPeriods property for period (a)", function( assert assert.ok( "dayPeriods" in properties( "a", cldr ) ); }); +/** + * Zone + */ + +QUnit.test( "should return standardTzName and daylightTzName properties for zone (z|zz|zzz|zzzz|zzzzz)", + function( assert ) { + [ "z", "zz", "zzz", "zzzz", "zzzzz" ].forEach(function( pattern ) { + var timeZone = "America/Los_Angeles", + length = pattern.length; + assert.ok( "standardTzName" in properties( pattern, cldr, timeZone ) ); + assert.ok( "daylightTzName" in properties( pattern, cldr, timeZone ) ); + + if ( length < 4 ) { + assert.equal( "PST", properties( pattern, cldr, timeZone ).standardTzName ); + assert.equal( "PDT", properties( pattern, cldr, timeZone ).daylightTzName ); + } else { + assert.equal( "Pacific Standard Time", properties( pattern, cldr, timeZone ).standardTzName ); + assert.equal( "Pacific Daylight Time", properties( pattern, cldr, timeZone ).daylightTzName ); + } + }); +}); + +QUnit.test( "should return standardTzName and daylightTzName properties for zone (v|vvvv)", + function( assert ) { + [ "v", "vvvv" ].forEach(function( pattern ) { + var timeZone = "America/Los_Angeles", + length = pattern.length; + assert.ok( "genericTzName" in properties( pattern, cldr, timeZone ) ); + + if ( length === 1 ) { + assert.equal( "PT", properties( pattern, cldr, timeZone ).genericTzName ); + } else if ( length === 4 ) { + assert.equal( "Pacific Time", properties( pattern, cldr, timeZone ).genericTzName ); + } + }); +}); + +QUnit.test( "should return standardTzName and daylightTzName properties for zone (VV|VVV|VVVV)", + function( assert ) { + [ "VV", "VVV", "VVVV" ].forEach(function( pattern ) { + var timeZone = "America/Los_Angeles", + length = pattern.length; + assert.ok( "TzName" in properties( pattern, cldr, timeZone ) ); + + if ( length === 2 ) { + assert.equal( "America/Los_Angeles", properties( pattern, cldr, timeZone ).TzName ); + } else if ( length === 3 ) { + assert.equal( "Los Angeles", properties( pattern, cldr, timeZone ).TzName ); + } else if ( length === 4 ) { + assert.equal( "Los Angeles Time", properties( pattern, cldr, timeZone ).TzName ); + } + }); +}); + }); diff --git a/test/unit/date/format.js b/test/unit/date/format.js index 9c586a693..6c597f7c6 100644 --- a/test/unit/date/format.js +++ b/test/unit/date/format.js @@ -13,12 +13,13 @@ define([ "json!cldr-data/supplemental/likelySubtags.json", "json!cldr-data/supplemental/timeData.json", "json!cldr-data/supplemental/weekData.json", + "json!cldr-data/supplemental/metaZones.json", "cldr/event", "cldr/supplemental" ], function( Cldr, format, formatProperties, stringPad, deCaGregorian, enCaGregorian, enTimeZoneNames, enGbCaGregorian, enInCaGregorian, ptCaGregorian, ruCaGregorian, likelySubtags, - timeData, weekData ) { + timeData, weekData, metaZones ) { var cldr, year0 = new Date( -62167190400000 ), @@ -52,15 +53,44 @@ Cldr.load( ptCaGregorian, ruCaGregorian, timeData, - weekData + weekData, + metaZones ); cldr = new Cldr( "en" ); +//test exemplerCity when metaZones not found for a given timeZone +//zzzz: "{regionName} {Standard Time}" or "{regionName} {Daylight Time}" +//z...zzz: fall back to "O" format +//vvvv: "{regionName} {Time}" +//v...vvv: fall back to "O" format + +Cldr.load({ + "main": { + "en": { + "dates": { + "timeZoneNames": { + "zone": { + "Foo":{ + "Bar":{ + "exemplarCity": "Foo City" + } + } + } + } + } + } + } +}); + QUnit.assert.dateFormat = function( date, pattern, cldr, expected ) { + this.dateFormatWithTimezone( date, pattern, undefined, cldr, expected ); +}; + +QUnit.assert.dateFormatWithTimezone = function( date, pattern, timeZone, cldr, expected ) { var pad, numberFormatters = [], - properties = formatProperties( pattern, cldr ); + properties = formatProperties( pattern, cldr, timeZone ); // Create simple number formatters for this test purposes. for ( pad in properties.numberFormatters ) { @@ -443,25 +473,100 @@ QUnit.test( "should format various milliseconds (A+)", function( assert ) { /** * Zone */ - QUnit.test( "should format timezone (z)", function( assert ) { var date = new FakeDate( 0 ); - assert.dateFormat( date, "z", cldr, "GMT" ); - assert.dateFormat( date, "zz", cldr, "GMT" ); - assert.dateFormat( date, "zzz", cldr, "GMT" ); - assert.dateFormat( date, "zzzz", cldr, "GMT" ); + + //Test for country with Daylight Savings and Standard time + //eg. Pacific Standard Time and Pacific Daylight Time + date.isDST = function(){ + return false; + }; + assert.dateFormatWithTimezone( date, "z", "America/Los_Angeles", cldr, "PST" ); + assert.dateFormatWithTimezone( date, "zz", "America/Los_Angeles", cldr, "PST" ); + assert.dateFormatWithTimezone( date, "zzz", "America/Los_Angeles", cldr, "PST" ); + assert.dateFormatWithTimezone( date, "zzzz", "America/Los_Angeles", cldr, "Pacific Standard Time" ); + + date.isDST = function(){ + return true; + }; + assert.dateFormatWithTimezone( date, "z", "America/Los_Angeles", cldr, "PDT" ); + assert.dateFormatWithTimezone( date, "zz", "America/Los_Angeles", cldr, "PDT" ); + assert.dateFormatWithTimezone( date, "zzz", "America/Los_Angeles", cldr, "PDT" ); + assert.dateFormatWithTimezone( date, "zzzz", "America/Los_Angeles", cldr, "Pacific Daylight Time" ); + + + //Test for country with only standard time + //eg. long: Indian Standard Time + //This test also covers the case where timezone name is undefined + //like short timezone name for Asia/Calcutta and should fall through 'O' format + date.isDST = function(){ + return false; + }; + assert.dateFormatWithTimezone( date, "z", "Asia/Calcutta", cldr, "GMT" ); + assert.dateFormatWithTimezone( date, "zz", "Asia/Calcutta", cldr, "GMT" ); + assert.dateFormatWithTimezone( date, "zzz", "Asia/Calcutta", cldr, "GMT" ); + assert.dateFormatWithTimezone( date, "zzzz", "Asia/Calcutta", cldr, "India Standard Time" ); + + date.isDST = function(){ + return true; + }; + assert.dateFormatWithTimezone( date, "z", "Asia/Calcutta", cldr, "GMT" ); + assert.dateFormatWithTimezone( date, "zz", "Asia/Calcutta", cldr, "GMT" ); + assert.dateFormatWithTimezone( date, "zzz", "Asia/Calcutta", cldr, "GMT" ); + assert.dateFormatWithTimezone( date, "zzzz", "Asia/Calcutta", cldr, "India Standard Time" ); + + //fall through to 'O' format + //using "America/Argentina/Buenos_Aires" (https://en.wikipedia.org/wiki/America/Argentina/Buenos_Aires) + //which is deprecated in CLDR json and thus no metaZones data + date = new FakeDate( 0 ); + assert.dateFormatWithTimezone( date, "z", "America/Argentina/Buenos_Aires", cldr, "GMT" ); + assert.dateFormatWithTimezone( date, "zz", "America/Argentina/Buenos_Aires", cldr, "GMT" ); + assert.dateFormatWithTimezone( date, "zzz", "America/Argentina/Buenos_Aires", cldr, "GMT" ); + assert.dateFormatWithTimezone( date, "zzzz", "America/Argentina/Buenos_Aires", cldr, "GMT" ); +}); + +QUnit.test( "should format timezone (v)", function( assert ) { + var date = new FakeDate( 0 ); + assert.dateFormatWithTimezone( date, "v", "America/Los_Angeles", cldr, "PT" ); + assert.dateFormatWithTimezone( date, "vvvv", "America/Los_Angeles", cldr, "Pacific Time" ); + + //fall through 'VVVV' format + assert.dateFormatWithTimezone( date, "v", "Foo/Bar", cldr, "Foo City Time" ); + assert.dateFormatWithTimezone( date, "vvvv", "Foo/Bar", cldr, "Foo City Time" ); + + //fall through to 'VVVV' format with "Unknown" exemplarCity + //using "America/Argentina/Buenos_Aires" (https://en.wikipedia.org/wiki/America/Argentina/Buenos_Aires) + //which is deprecated in CLDR json and thus no metaZones data + date = new FakeDate( 0 ); + assert.dateFormatWithTimezone( date, "v", "America/Argentina/Buenos_Aires", cldr, "Unknown City Time" ); + assert.dateFormatWithTimezone( date, "vvvv", "America/Argentina/Buenos_Aires", cldr, "Unknown City Time" ); +}); + +QUnit.test( "should format timezone (V)", function( assert ) { + var date = new FakeDate( 0 ); + assert.dateFormatWithTimezone( date, "VV", "America/Los_Angeles", cldr, "America/Los_Angeles" ); + assert.dateFormatWithTimezone( date, "VVV", "America/Los_Angeles", cldr, "Los Angeles" ); + assert.dateFormatWithTimezone( date, "VVVV", "America/Los_Angeles", cldr, "Los Angeles Time" ); +}); + +QUnit.test( "should format timezone (O)", function( assert ) { + var date = new FakeDate( 0 ); + assert.dateFormat( date, "O", cldr, "GMT" ); + assert.dateFormat( date, "OO", cldr, "GMT" ); + assert.dateFormat( date, "OOO", cldr, "GMT" ); + assert.dateFormat( date, "OOOO", cldr, "GMT" ); date = new FakeDate( -3 ); - assert.dateFormat( date, "z", cldr, "GMT-3" ); - assert.dateFormat( date, "zz", cldr, "GMT-3" ); - assert.dateFormat( date, "zzz", cldr, "GMT-3" ); - assert.dateFormat( date, "zzzz", cldr, "GMT-03:00" ); + assert.dateFormat( date, "O", cldr, "GMT-3" ); + assert.dateFormat( date, "OO", cldr, "GMT-3" ); + assert.dateFormat( date, "OOO", cldr, "GMT-3" ); + assert.dateFormat( date, "OOOO", cldr, "GMT-03:00" ); date = new FakeDate( 11 ); - assert.dateFormat( date, "z", cldr, "GMT+11" ); - assert.dateFormat( date, "zz", cldr, "GMT+11" ); - assert.dateFormat( date, "zzz", cldr, "GMT+11" ); - assert.dateFormat( date, "zzzz", cldr, "GMT+11:00" ); + assert.dateFormat( date, "O", cldr, "GMT+11" ); + assert.dateFormat( date, "OO", cldr, "GMT+11" ); + assert.dateFormat( date, "OOO", cldr, "GMT+11" ); + assert.dateFormat( date, "OOOO", cldr, "GMT+11:00" ); }); QUnit.test( "should format timezone (Z)", function( assert ) { diff --git a/test/unit/date/magicDate.js b/test/unit/date/magicDate.js new file mode 100644 index 000000000..245597f2d --- /dev/null +++ b/test/unit/date/magicDate.js @@ -0,0 +1,305 @@ +define([ + "src/magicDate" +], function( MagicDate ) { + +var date = new Date(Date.UTC(2017, 1, 19, 2)), + date1 = new Date(Date.UTC(2017, 1, 19, 1)); + +QUnit.assert.magicDate = function( date, tzdata, expected ) { + var magicDate = new MagicDate( date, tzdata ); + this.equal( magicDate.getDate(), expected.Date ); + this.equal( magicDate.getMonth(), expected.Month ); + this.equal( magicDate.getFullYear(), expected.Year ); + this.equal( magicDate.getHours(), expected.Hours ); + this.equal( magicDate.getMinutes(), expected.Minutes ); + this.equal( magicDate.getSeconds(), expected.Seconds ); +}; + +QUnit.test( "should test magic date with trasitions", function( assert ) { + var TzData_Sao_Paulo = { + "name": "America/Sao_Paulo", + "untils": [ + -1767214412000, + -1206957600000, + -1191362400000, + -1175374800000, + -1159826400000, + -633819600000, + -622069200000, + -602283600000, + -591832800000, + -570747600000, + -560210400000, + -539125200000, + -531352800000, + -195426000000, + -184197600000, + -155163600000, + -150069600000, + -128898000000, + -121125600000, + -99954000000, + -89589600000, + -68418000000, + -57967200000, + 499748400000, + 511236000000, + 530593200000, + 540266400000, + 562129200000, + 571197600000, + 592974000000, + 602042400000, + 624423600000, + 634701600000, + 656478000000, + 666756000000, + 687927600000, + 697600800000, + 719982000000, + 728445600000, + 750826800000, + 761709600000, + 782276400000, + 793159200000, + 813726000000, + 824004000000, + 844570800000, + 856058400000, + 876106800000, + 888717600000, + 908074800000, + 919562400000, + 938919600000, + 951616800000, + 970974000000, + 982461600000, + 1003028400000, + 1013911200000, + 1036292400000, + 1045360800000, + 1066532400000, + 1076810400000, + 1099364400000, + 1108864800000, + 1129431600000, + 1140314400000, + 1162695600000, + 1172368800000, + 1192330800000, + 1203213600000, + 1224385200000, + 1234663200000, + 1255834800000, + 1266717600000, + 1287284400000, + 1298167200000, + 1318734000000, + 1330221600000, + 1350788400000, + 1361066400000, + 1382238000000, + 1392516000000, + 1413687600000, + 1424570400000, + 1445137200000, + 1456020000000, + 1476586800000, + 1487469600000, + 1508036400000, + 1518919200000, + 1540090800000, + 1550368800000, + 1571540400000, + 1581818400000, + 1602990000000, + 1613872800000, + 1634439600000, + 1645322400000, + 1665889200000, + 1677376800000, + 1697338800000, + 1708221600000, + 1729393200000, + 1739671200000, + 1760842800000, + 1771725600000, + 1792292400000, + 1803175200000, + 1823742000000, + 1834624800000, + 1855191600000, + 1866074400000, + 1887246000000, + 1897524000000, + 1918695600000, + 1928973600000, + 1950145200000, + 1960423200000, + 1981594800000, + 1992477600000, + 2013044400000, + 2024532000000, + 2044494000000, + 2055376800000, + 2076548400000, + 2086826400000, + 2107998000000, + 2118880800000, + 2139447600000, + null + ], + "offsets": [ + 186.4667, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120, + 180, + 120 + ], + "population": 20365000 + }; + var expectedDate = { + Date: 18, + Month: 1, + Year: 2017, + Hours: 23, + Minutes: 0, + Seconds:0 + }; + assert.magicDate( date, TzData_Sao_Paulo, expectedDate ); + expectedDate = { + Date: 18, + Month: 1, + Year: 2017, + Hours: 23, + Minutes: 0, + Seconds:0 + }; + assert.magicDate( date1, TzData_Sao_Paulo, expectedDate ); +}); + +});