Skip to content

Commit a98f8e1

Browse files
committed
Add date formatter time zone support
1 parent bd1beee commit a98f8e1

File tree

7 files changed

+66
-11
lines changed

7 files changed

+66
-11
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ Use the command line interface as a convenience over using the API directly. It'
2929

3030
**`-c, --cldr CLDR_FILE`** Optional. All necessary CLDR data for given locale (JSON format).
3131

32+
**`-z, --tz TIME_ZONE_FILE`** Optional. All necessary time zone data (JSON format).
33+
3234
**`-m, --messages MESSAGES_FILE`** Optional. Translation messages for given locale (JSON format).
3335

3436
**`-o, --output DEST_FILE`** Destination JavaScript file, e.g., `app-en.js`.
@@ -139,6 +141,8 @@ globalize.formatNumber( ... );
139141

140142
    **cldr** optional. It's an *Object* with CLDR data (in the JSON format) or a *Function* taking one argument: locale, a *String*; returning an *Object* with the CLDR data for the passed locale. Defaults to the entire supplemental data plus the entire main data for the defaultLocale.
141143

144+
    **timeZoneData** optional. It's an *Object* with IANA time zone data (in the JSON format) or a *Function* returning an *Object* with the IANA time zone data. Defaults to the entire IANA time zone data from `[iana-tz-data](https://github.com/rxaviers/iana-tz-data)` package.
145+
142146
    **messages** optional. It's an *Object* with messages data (in the JSON format) or a *Function* taking one argument: locale, a *String*; returning an *Object* with the messages data for the passed locale. Defaults to `{}`.
143147

144148
    **template** optional. A function that replaces the default template. See [`.compile()`][] for more details.

bin/globalize-compiler.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ var nopt = require( "nopt" );
66
var path = require( "path" );
77
var pkg = require( "../package.json" );
88

9-
var bundle, cldr, extracts, extraOptions, input, locale, messages, opts, output, requiredOpts;
9+
var bundle, cldr, extracts, extraOptions, timeZoneData, input, locale, messages, opts, output, requiredOpts;
1010

1111
function help() {
1212
var out = [
@@ -41,6 +41,7 @@ opts = nopt( {
4141
v: "--version",
4242
l: "--locale",
4343
c: "--cldr",
44+
z: "--tz",
4445
m: "--messages",
4546
o: "--output"
4647
});
@@ -69,10 +70,12 @@ if ( opts.help || !requiredOpts || extraOptions.length ) {
6970
input = opts.argv.remain;
7071
locale = opts.locale;
7172
cldr = opts.cldr;
73+
timeZoneData = opts.tz;
7274
messages = opts.messages;
7375
output = opts.output;
7476

7577
cldr = cldr ? JSON.parse( fs.readFileSync( cldr ) ) : null;
78+
timeZoneData = timeZoneData ? JSON.parse( fs.readFileSync( timeZoneData ) ) : null;
7679
messages = messages ? JSON.parse( fs.readFileSync( messages ) ) : null;
7780

7881
extracts = input.map(function( input ) {
@@ -82,6 +85,7 @@ extracts = input.map(function( input ) {
8285
bundle = GlobalizeCompiler.compileExtracts({
8386
defaultLocale: locale,
8487
cldr: cldr,
88+
timeZoneData: timeZoneData,
8589
messages: messages,
8690
extracts: extracts
8791
});

lib/compile-extracts.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ function alwaysArray( itemOrArray ) {
55
}
66

77
function compileExtracts( attributes ) {
8-
var cldr, cldrObject, defaultLocale, extracts, formattersAndParsers, messages, messagesObject;
8+
var cldr, cldrObject, defaultLocale, extracts, formattersAndParsers, timeZoneData, timeZoneDataObject, messages, messagesObject;
99
var Globalize = require( "globalize" );
1010

1111
attributes = attributes || {};
@@ -48,12 +48,23 @@ function compileExtracts( attributes ) {
4848
};
4949
}
5050

51+
timeZoneData = attributes.timeZoneData || function() {
52+
return require( "iana-tz-data" );
53+
};
54+
if ( typeof timeZoneData === "object" ) {
55+
timeZoneDataObject = timeZoneData;
56+
timeZoneData = function() {
57+
return timeZoneDataObject;
58+
};
59+
}
60+
5161
// TODO
5262
//assert( defaultLocale )
5363
//assert( extracts )
5464

5565
Globalize.load( cldr( defaultLocale ) );
5666
Globalize.loadMessages( messages( defaultLocale ) );
67+
Globalize.loadTimeZone( timeZoneData() );
5768
Globalize.locale( defaultLocale );
5869
formattersAndParsers = alwaysArray( extracts ).reduce(function( sum, extract ) {
5970
[].push.apply( sum, extract( Globalize ) );

lib/compile.js

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
var COMPILED_ORDER, DEPENDENCIES, DEPENDENCIES_VARS, fnPlaceholder, fnPlaceholderRe,
2-
regexpPlaceholder, regexpPlaceholderRe, template, undefinedPlaceholder,
3-
undefinedPlaceholderRe,
1+
var COMPILED_ORDER, DEPENDENCIES, DEPENDENCIES_VARS, dataCache, fnPlaceholder, fnPlaceholderRe,
2+
regexpPlaceholder, regexpPlaceholderRe, template, undefinedPlaceholder, undefinedPlaceholderRe,
43
extend = require( "util" )._extend,
54
fs = require( "fs" );
65

@@ -97,6 +96,8 @@ DEPENDENCIES_VARS = {
9796
}
9897
};
9998

99+
dataCache = {};
100+
100101
template = fs.readFileSync( __dirname + "/compile.template" ).toString( "utf-8" );
101102

102103
function functionName( fn ) {
@@ -130,6 +131,9 @@ function stringifyIncludingFunctionsAndRegExpsAndUndefined( object ) {
130131
var fn = fns.shift();
131132
if ( "generatorString" in fn ) {
132133
return fn.generatorString();
134+
} else if ( "dataCacheKey" in fn ) {
135+
dataCache[ fn.dataCacheKey ] = fn();
136+
return "getCache(\"" + fn.dataCacheKey + "\")";
133137
} else {
134138
return fn.toString();
135139
}
@@ -181,10 +185,8 @@ function defaultTemplate( properties ) {
181185
* @param {options} object
182186
*/
183187
function compiler( formattersAndParsers, options ) {
184-
var dependencies,
185-
code,
186-
dependenciesVars,
187-
templateFn,
188+
var code, dependencies, dependenciesVars, templateFn,
189+
dataCacheCode = "",
188190
extractedFormattersAndParsers = [],
189191
formattersAndParsersKeys = [];
190192

@@ -225,6 +227,16 @@ function compiler( formattersAndParsers, options ) {
225227
return COMPILED_ORDER.indexOf( a ) - COMPILED_ORDER.indexOf( b );
226228
}).map( compile ).join( "\n" );
227229

230+
// Generate the optional dataCache.
231+
if ( Object.keys( dataCache ).length ) {
232+
dataCacheCode = "var dataCache = " + JSON.stringify( dataCache ) + ";\n" +
233+
"function getCache(key) {\n" +
234+
" return function() {\n" +
235+
" return dataCache[key];\n" +
236+
" };\n" +
237+
"}\n";
238+
}
239+
228240
// Generate dependency assignments and requirements.
229241
dependencies = Object.keys( extractedFormattersAndParsers.map( functionName ).reduce(function( sum, i ) {
230242
return extend( sum, DEPENDENCIES[ i ] );
@@ -243,7 +255,7 @@ function compiler( formattersAndParsers, options ) {
243255
return "var " + dependency + " = Globalize._" + dependency + ";";
244256
}).join( "\n" );
245257

246-
code = dependenciesVars + "\n\n" + code;
258+
code = dependenciesVars + "\n\n" + dataCacheCode + code;
247259

248260
/*
249261
// Generate exports.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@
3939
},
4040
"peerDependencies": {
4141
"cldr-data": ">=25",
42-
"globalize": ">=1.3.0-a <2.0.0"
42+
"globalize": ">=1.3.0-a <2.0.0",
43+
"iana-tz-data": ">=2017.0.0"
4344
},
4445
"devDependencies": {
4546
"babel": "^5.6.14",
@@ -48,6 +49,7 @@
4849
"eslint": "^3.19.0",
4950
"eslint-config-defaults": "^9.0.0",
5051
"globalize": ">=1.3.0-a <2.0.0",
52+
"iana-tz-data": ">=2017.0.0",
5153
"jshint": "2.6.x",
5254
"mocha": "2.1.0"
5355
}

test/functional/index.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ describe("The compiled `basic.js`", function() {
1616
expect(result).to.have.string("2017");
1717
});
1818

19+
it("should include formatDate with timeZone support", function() {
20+
var result = Globalize.formatDate(new Date("2017-04-15T12:00:00Z"), {datetime: "full", timeZone: "America/Sao_Paulo"});
21+
expect(result).to.equal("Saturday, April 15, 2017 at 9:00:00 AM Brasilia Standard Time");
22+
});
23+
1924
it("should include formatDateToParts", function() {
2025
var result = Globalize.formatDateToParts(new Date(2017, 3, 15), {datetime: "medium"});
2126
expect(result).to.include({type: "month", value: "Apr"});
@@ -58,4 +63,9 @@ describe("The compiled `basic.js`", function() {
5863
expect(result.getMonth()).to.equal(0);
5964
expect(result.getDate()).to.equal(2);
6065
});
66+
67+
it("should include parseDate with timeZone support", function() {
68+
var result = Globalize.parseDate("January 1, 2000 at 12:00:00 AM EST", {datetime: "long", timeZone: "America/New_York"});
69+
expect(result).to.deep.equal(new Date("2000-01-01T05:00:00Z"));
70+
});
6171
});

test/unit/fixtures/basic.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ console.log( dateFormatter( new Date() ) );
77

88
console.log( Globalize.formatDate( new Date(), { date: "medium" } ) );
99

10+
// Use Globalize to format dates in specific time zones.
11+
console.log( Globalize.formatDate( new Date(), {
12+
datetime: "full",
13+
timeZone: "America/Sao_Paulo"
14+
}));
15+
1016
// Use Globalize to format dates to parts.
1117
console.log( Globalize.formatDateToParts( new Date(), { datetime: "medium" } ) );
1218

@@ -37,3 +43,9 @@ console.log( Globalize.parseNumber( "12345.6789" ) );
3743

3844
// Use Globalize to parse a date.
3945
console.log( Globalize.parseDate( "1/2/1982" ) );
46+
47+
// Use Globalize to parse a date in specific time zones.
48+
console.log( Globalize.parseDate( "January 1, 2000 at 12:00:00 AM EST", {
49+
datetime: "long",
50+
timeZone: "America/New_York"
51+
}));

0 commit comments

Comments
 (0)