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 7, 2017
1 parent 26f6b01 commit ab7566c
Show file tree
Hide file tree
Showing 12 changed files with 1,439 additions and 41 deletions.
8 changes: 7 additions & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,14 @@ module.exports = function( grunt ) {
.replace( rdefineEnd, "" ) /* 2 */
.replace( /define\(\[[^\]]+\]\)[\W\n]+$/, "" ); /* 3 */

// Type b (not as simple as a single return)
if ( [ "util/globalize-date" ].indexOf( id ) !== -1 ) {
contents = "var " + name[ 0 ].toUpperCase() +
name.slice( 1 ) + " = (function() {" +
contents + "}());";

// Type a (single return)
if ( ( /\// ).test( id ) ) {
} else if ( ( /\// ).test( id ) ) {
contents = contents
.replace( /\nreturn/, "\nvar " + name + " =" );
}
Expand Down
8 changes: 4 additions & 4 deletions doc/api/date/date-formatter.md
Original file line number Diff line number Diff line change
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
30 changes: 27 additions & 3 deletions src/date.js
Original file line number Diff line number Diff line change
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 @@ -62,9 +80,12 @@ Globalize.prototype.dateFormatter = function( options ) {

validateDefaultLocale( cldr );

timeZone = options.timeZone;
validateParameterTypeString( options.timeZone, "options.timeZone" );

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 Expand Up @@ -93,7 +114,7 @@ Globalize.prototype.dateFormatter = function( options ) {
*/
Globalize.dateParser =
Globalize.prototype.dateParser = function( options ) {
var args, cldr, numberParser, parseProperties, pattern, tokenizerProperties, returnFn;
var args, cldr, numberParser, parseProperties, pattern, tokenizerProperties, returnFn, timeZone;

validateParameterTypePlainObject( options, "options" );

Expand All @@ -104,6 +125,9 @@ Globalize.prototype.dateParser = function( options ) {

validateDefaultLocale( cldr );

timeZone = options.timeZone;
validateParameterTypeString( options.timeZone, "options.timeZone" );

cldr.on( "get", validateRequiredCldr );
pattern = dateExpandPattern( options, cldr );
tokenizerProperties = dateTokenizerProperties( pattern, cldr );
Expand Down
151 changes: 141 additions & 10 deletions src/date/format-properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ define([
"./first-day-of-week",
"./pattern-re",
"../common/create-error/unsupported-feature",
"../common/format-message",
"../number/symbol",
"../util/string/pad"
], function( dateFirstDayOfWeek, datePatternRe, createErrorUnsupportedFeature, numberSymbol,
stringPad ) {
], function( dateFirstDayOfWeek, datePatternRe, createErrorUnsupportedFeature, formatMessage,
numberSymbol, stringPad ) {

/**
* 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
43 changes: 41 additions & 2 deletions src/date/format.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ define([
"./start-of",
"./timezone-hour-format",
"./week-days",
"../util/remove-literal-quotes"
"../util/remove-literal-quotes",
"../util/globalize-date"
], function( dateDayOfWeek, dateDayOfYear, dateMillisecondsInDay, datePatternRe, dateStartOf,
dateTimezoneHourFormat, dateWeekDays, removeLiteralQuotes ) {
dateTimezoneHourFormat, dateWeekDays, removeLiteralQuotes, GlobalizeDate ) {

/**
* format( date, properties )
Expand All @@ -24,6 +25,11 @@ define([
return function( date, numberFormatters, properties ) {
var timeSeparator = properties.timeSeparator;

// create globalize date with given timezone data
if ( properties.timeZoneData ) {
date = new GlobalizeDate( date, properties.timeZoneData );
}

return properties.pattern.replace( datePatternRe, function( current ) {
var ret,
chr = current.charAt( 0 ),
Expand Down Expand Up @@ -207,6 +213,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
10 changes: 8 additions & 2 deletions src/date/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ define([
"./start-of",
"../common/create-error/unsupported-feature",
"../util/date/set-month",
"../util/out-of-range"
"../util/out-of-range",
"../util/globalize-date"
], function( dateIsLeapYear, dateLastDayOfMonth, datePatternRe, dateStartOf,
createErrorUnsupportedFeature, dateSetMonth, outOfRange ) {
createErrorUnsupportedFeature, dateSetMonth, outOfRange, GlobalizeDate ) {

/**
* parse( value, tokens, properties )
Expand All @@ -33,6 +34,11 @@ return function( value, tokens, properties ) {
truncateAt = [],
units = [ "year", "month", "day", "hour", "minute", "second", "milliseconds" ];

// create globalize date with given timezone data
if ( properties.timeZoneData ) {
date = new GlobalizeDate( date, properties.timeZoneData );
}

if ( !tokens.length ) {
return null;
}
Expand Down
Loading

0 comments on commit ab7566c

Please sign in to comment.