Skip to content

Commit

Permalink
Date: Olson-timezone-support (real 'z', 'v', 'V')
Browse files Browse the repository at this point in the history
  • Loading branch information
rajavelmani committed Mar 2, 2017
1 parent 26f6b01 commit 8fd175f
Show file tree
Hide file tree
Showing 9 changed files with 824 additions and 36 deletions.
8 changes: 4 additions & 4 deletions doc/api/date/date-formatter.md
Expand Up @@ -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.

Expand Down
22 changes: 20 additions & 2 deletions src/date.js
Expand Up @@ -34,6 +34,24 @@ function validateRequiredCldr( path, value ) {
});
}

/**
* .loadIANA( json )
*
* @json [JSON]
*
* Load IANA data.
*/
Globalize.loadIANA = function( json ) {
var customData = {
"globalize-iana": json
};

validateParameterPresence( json, "json" );
validateParameterTypePlainObject( json, "json" );

Cldr.load( customData );
};

/**
* .dateFormatter( options )
*
Expand All @@ -51,7 +69,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" );

Expand All @@ -64,7 +82,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.
Expand Down
151 changes: 141 additions & 10 deletions src/date/format-properties.js
Expand Up @@ -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 )
Expand All @@ -19,22 +20,46 @@ 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" ];

if ( timeZone ) {
var getTimeZoneData = function( timeZoneData ) {
if ( timeZoneData.name && timeZoneData.name === timeZone ) {
return true;
}
return false;
};
properties.timeZoneData = cldr.get( "globalize-iana/zones" ).filter( getTimeZoneData )[0];
}

function setNumberFormatterPattern( pad ) {
properties.numberFormatters[ pad ] = stringPad( "", pad );
}

pattern.replace( datePatternRe, function( current ) {
var formatNumber,
chr = current.charAt( 0 ),
length = current.length;
length = current.length,
metaZone,
standardTzName,
daylightTzName,
genericTzName;

if ( timeZone && ( chr === "v" || chr === "z" )) {

// 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"
]);
}

if ( chr === "j" ) {

Expand All @@ -49,6 +74,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
Expand Down Expand Up @@ -208,6 +289,62 @@ 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 + "`"
});
}

if ( timeZone ) {
var TimeZoneName;

if ( length === 2 ) {
TimeZoneName = timeZone;
}

var exemplarCity = cldr.main([
"dates/timeZoneNames/zone", timeZone, "exemplarCity"
]);

if ( length === 3 ) {
if ( !exemplarCity ) {
exemplarCity = cldr.main([
"dates/timeZoneNames/zone/Etc/Unknown/exemplarCity"
]);
}
TimeZoneName = exemplarCity;
}

if ( exemplarCity && length === 4 ) {
TimeZoneName = formatMessage(
cldr.main(
"dates/timeZoneNames/regionFormat"
),
[ exemplarCity ]
);
}
if ( TimeZoneName ) {
properties.TimeZoneName = TimeZoneName;
break;
}
}

/* falls through */
case "O":

// O: "{gmtFormat}+H;{gmtFormat}-H" or "{gmtZeroFormat}", eg. "GMT-8" or "GMT".
Expand All @@ -223,12 +360,6 @@ return function( pattern, cldr ) {
setNumberFormatterPattern( 1 );
setNumberFormatterPattern( 2 );
break;

case "v":
case "V":
throw createErrorUnsupportedFeature({
feature: "timezone pattern `" + chr + "`"
});
}

if ( formatNumber ) {
Expand Down
42 changes: 40 additions & 2 deletions src/date/format.js
Expand Up @@ -6,9 +6,10 @@ define([
"./start-of",
"./timezone-hour-format",
"./week-days",
"../util/remove-literal-quotes"
"../util/remove-literal-quotes",
"../magicDate"
], function( dateDayOfWeek, dateDayOfYear, dateMillisecondsInDay, datePatternRe, dateStartOf,
dateTimezoneHourFormat, dateWeekDays, removeLiteralQuotes ) {
dateTimezoneHourFormat, dateWeekDays, removeLiteralQuotes, MagicDate ) {

/**
* format( date, properties )
Expand All @@ -29,6 +30,10 @@ return function( date, numberFormatters, properties ) {
chr = current.charAt( 0 ),
length = current.length;

if ( properties.timeZoneData ) {
date = new MagicDate( date, properties.timeZoneData );
}

if ( chr === "j" ) {

// Locale preferred hHKk.
Expand Down Expand Up @@ -207,6 +212,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.TimeZoneName ) {
ret = properties.TimeZoneName;
break;
}

/* falls through */
case "O":

// O: "{gmtFormat}+H;{gmtFormat}-H" or "{gmtZeroFormat}", eg. "GMT-8" or "GMT".
Expand Down

0 comments on commit 8fd175f

Please sign in to comment.