Date: Olson-timezone-support (real 'z', 'v', 'V')#687
Conversation
212e748 to
8e074bf
Compare
rxaviers
left a comment
There was a problem hiding this comment.
@rajavelmani, thanks for your PR. I left some comments above and updated the description with some TODOs. Thanks so far!!
| Globalize.dateFormatter = | ||
| Globalize.prototype.dateFormatter = function( options ) { | ||
| var args, cldr, numberFormatters, pad, pattern, properties, returnFn; | ||
| var args, cldr, numberFormatters, pad, pattern, properties, returnFn, tzId; |
There was a problem hiding this comment.
CLDR and IANA refers to them as timezone names. Let's rename tzId into timezoneName?
There was a problem hiding this comment.
i can use timeZone as timezoneName is locale dependent
| pattern = dateExpandPattern( options, cldr ); | ||
| properties = dateFormatProperties( pattern, cldr ); | ||
| cldr.off( "get", validateRequiredCldr ); | ||
| properties.tzId = tzId;//TODO validate |
There was a problem hiding this comment.
This variable is being declared and then set here (i.e., always undefined). I believe this was here as a placeholder to accept a potential options.timeZone value. Therefore, I think this can be safely removed for now.
| cldr = new Cldr( "en" ); | ||
|
|
||
| QUnit.assert.dateFormat = function( date, pattern, cldr, expected ) { | ||
| QUnit.assert.dateFormat = function( date, pattern, cldr, expected, tzId ) { |
There was a problem hiding this comment.
Nitpick comment, let's leave cldr, expected as the last arguments. We could place tzId (actually, timezoneName) after pattern.
There was a problem hiding this comment.
Just to confirm, I added the tzId to the end to avoid the changes to rest of the test cases. if your are ok to change all the test then, i can change all the tests.
There was a problem hiding this comment.
I have changed the order of the signature as you mentioned.
|
|
||
| //fall through to 'O' format | ||
| date = new FakeDate( 0 ); | ||
| assert.dateFormat(date, "z", cldr, "GMT", "Etc/GMT"); |
There was a problem hiding this comment.
Where that is unavailable, falls back to the short localized GMT format ("O").
http://www.unicode.org/reports/tr35/tr35-dates.html#dfst-zone
According to the above, I expect a test where it's used an unavailable metaZone, not "Etc/GMT" that actually exists and is equal to O format as a coincidence.
There was a problem hiding this comment.
i used "America/Argentina/Buenos_Aires" which is not supported in CLDR json yet
There was a problem hiding this comment.
Nice! Though, I'm wondering... Should we use an invalid stuff that will never be supported like "Foo/Bar"?
| ); | ||
| properties.regionFormatDaylight = cldr.main( | ||
| "dates/timeZoneNames/regionFormat-type-daylight" | ||
| ); |
There was a problem hiding this comment.
Missing break here, i.e., in the case where it's found.
| format = ( standardTzName ) ? standardTzName : | ||
| ( regionFormatStandard ) ? regionFormatStandard.replace( /\{0\}/, exemplarCity ) : | ||
| undefined; | ||
| } |
There was a problem hiding this comment.
It seems to me that at this runtime point we could have done more processing on these properties... I mean, standardTzName (or exemplarCity) could have been incorporated into regionFormatStandard, and daylightTzName (or exemplarCity) could have been incorporated into regionFormatDaylight.
There was a problem hiding this comment.
Other points:
- The parentheses on
( standardTzName ) ?is unnecessary; - Why the
undefinedcase?
There was a problem hiding this comment.
It seems to me that at this runtime point we could have done more processing on these properties... I mean, standardTzName (or exemplarCity) could have been incorporated into regionFormatStandard, and daylightTzName (or exemplarCity) could have been incorporated into regionFormatDaylight.
I have optimized the properties please take a look and let me know your thoughts
| "pattern": "h:mm:ss a", | ||
| "timeSeparator": ":" | ||
| "timeSeparator": ":", | ||
| "tzId": undefined |
There was a problem hiding this comment.
If it's undefined, let's simply not include it.
| assert.dateFormat( date, "OO", cldr, "GMT+11" ); | ||
| assert.dateFormat( date, "OOO", cldr, "GMT+11" ); | ||
| assert.dateFormat( date, "OOOO", cldr, "GMT+11:00" ); | ||
| }); |
There was a problem hiding this comment.
There's already a "should format timezone (O)" section above. Instead of duplicating it, let's simply incorporate the missing pieces there please.
| // z...zzz: "{shortRegion}", eg. "PST" or "PDT". | ||
| // zzzz: "{regionName} {Standard Time}" or "{regionName} {Daylight Time}", | ||
| // eg. "Pacific Standard Time" or "Pacific Daylight Time". | ||
| if ( properties.tzId ) { |
There was a problem hiding this comment.
Checking for properties.tzId isn't valid, because there's a case where properties.tzId is truthy and metaZone is unavailable and therefore the properties below are invalid (by looking at your code at date/format-properties.js). I think you should check for something else, e.g., one of the set properties.
There was a problem hiding this comment.
ok let me change this to check properties.standardTzName and properties.daylightTzName
| ); | ||
| if ( ret ) { | ||
| break; | ||
| } |
There was a problem hiding this comment.
Since the properties exist, this should always be truthy.
There was a problem hiding this comment.
Yes, this will not be required with check for properties.standardTzName and properties.daylightTzName
a0f3c96 to
be210ba
Compare
| length < 4 ? "short" : "long", | ||
| "daylight" | ||
| ]); | ||
| if ( !standardTzName && !daylightTzName ) { |
There was a problem hiding this comment.
What should happen for !standardTzName || !daylightTzName? It won't fall either in here or in the next if. Should we use examplarCity if !standardTzName || !daylightTzName. Probably, this would only happen in a corrupted CLDR data where there is one content, but not the other.
There was a problem hiding this comment.
this will help on the scenario like https://github.com/globalizejs/globalize/pull/687/files#diff-df6075946ae91cbb093f63c7597cd746R460 where the timezone id is valid not supported in CLDR.
There was a problem hiding this comment.
Note I'm referring to using || instead of && in here, so we also catch the additional case where part of the data exists.
| ]); | ||
| if ( !standardTzName && !daylightTzName ) { | ||
| var exemplarCity = cldr.main( | ||
| "dates/timeZoneNames/zone/", |
| standardTzName = cldr.main( | ||
| "dates/timeZoneNames/regionFormat-type-standard" | ||
| ) | ||
| .replace( /\{0\}/, exemplarCity ); |
There was a problem hiding this comment.
Instead of replacing {0} yourself, you can use src/common/format-message (example).
There was a problem hiding this comment.
FWIW, it's an internal utility to help in cases like that. Note, it's not ICU message format :)
There was a problem hiding this comment.
i just followed from the format.js. but, i can use the format-message as you suggested. Do i change the format.js code too?
| pattern: pattern, | ||
| timeSeparator: numberSymbol( "timeSeparator", cldr ) | ||
| timeSeparator: numberSymbol( "timeSeparator", cldr ), | ||
| timeZone: timeZone |
There was a problem hiding this comment.
Let's skip adding timeZone to the properties. We can add it later if required.
There was a problem hiding this comment.
If we don't add timeZone from option.timeZone to properties.timeZone we may not be able to test time zone implementation. Can you clarify why we need to skip timeZone from properties?
| assert.dateFormat(date, "zz", "America/Los_Angeles", cldr, "PST"); | ||
| assert.dateFormat(date, "zzz", "America/Los_Angeles", cldr, "PST"); | ||
| assert.dateFormat(date, "zzzz", "America/Los_Angeles", cldr, "Pacific Standard Time"); | ||
|
|
There was a problem hiding this comment.
We need to test the "exemplarCity" case.
5b0201e to
028ae5f
Compare
9599fe1 to
b46372b
Compare
z)801152a to
3c8928c
Compare
rxaviers
left a comment
There was a problem hiding this comment.
It's looking great!! I have left some comments for your consideration please.
| } | ||
|
|
||
| //fall through "{0} {Time}"" | ||
| //for VVVV format |
There was a problem hiding this comment.
nitpick: space after //, like // for ...
| //fall through "{0} {Time}"" | ||
| //for VVVV format | ||
| if ( timeZone ) { | ||
| var TzName; |
There was a problem hiding this comment.
nitpick: variable names should start with lowercase, i.e., tzName. Preferably using full words, like timezoneName.
| ]), | ||
| exemplarCity = cldr.main([ | ||
| "dates/timeZoneNames/zone", timeZone, "exemplarCity" | ||
| ]); |
There was a problem hiding this comment.
If timeZone is passed to format anything but VVVV this is unnecessary, so let's move this assignment below in the only place where it's used.
| metaZone = cldr.supplemental([ | ||
| "metaZones/metazoneInfo/timezone", timeZone, 0, | ||
| "usesMetazone/_mzone" | ||
| ]), |
There was a problem hiding this comment.
If timeZone is passed to format anything but z* or v* this is unnecessary, so (considering we move exemplarCity below away) let's update the if condition:
- if ( timeZone ) {
+ if ( timeZone && ( chr === "v" || chr === "z" ) ) {There was a problem hiding this comment.
ok let me move this condition into https://github.com/globalizejs/globalize/pull/687/files#diff-a8a17cd910e21f0b9d3e8ffe4fcea2a8R50 to access chr
| assert.equal( "Pacific Time", properties( pattern, cldr, timeZone ).genericTzName ); | ||
| } | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Let's add a test to assert vv and vvv throw.
There was a problem hiding this comment.
In here, or where it's possible to test this...
| } | ||
| }); | ||
| }); | ||
|
|
There was a problem hiding this comment.
Let's add a test to assert V throws.
| case "z": | ||
| properties.standardTzName = standardTzName; | ||
| properties.daylightTzName = daylightTzName; | ||
| break; |
There was a problem hiding this comment.
nitpick: let's add an empty line after break and before the next case.
| ), | ||
| [ unKnownExemplarCity ] | ||
| ); | ||
| } |
There was a problem hiding this comment.
Can we simplify the the above as:
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 ( length === 3 ) {
+ TzName = exemplarCity;
+ } else if ( length === 4 ) {
+ if ( !exemplarCity ) {
+ exemplarCity = cldr.main([
+ "dates/timeZoneNames/zone/Etc/Unknown/exemplarCity"
+ ]);
}
- } else if ( !exemplarCity && length === 4 ) {
- var unKnownExemplarCity = cldr.main([
- "dates/timeZoneNames/zone/Etc/Unknown/exemplarCity"
- ]);
TzName = formatMessage(
cldr.main(
"dates/timeZoneNames/regionFormat"
),
- [ unKnownExemplarCity ]
+ [ exemplarCity ]
);
}
if ( TzName ) {There was a problem hiding this comment.
| 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" ); |
There was a problem hiding this comment.
Can we include VVV and VVVV tests that use unkown city? It could re-use the above America/Argentina/Buenos_Aires, but it's good to have it explicitly tested here (in addition to the above fallback-test). Thanks
ef85e52 to
8fd175f
Compare
| * @json [JSON] | ||
| * | ||
| * Load IANA data. | ||
| */ |
There was a problem hiding this comment.
Pros:
- Letting users to load this data similarly to the way they do with CLDR is good. Therefore we don't embed such in the library.
Cons:
- Differently from CLDR, IANA doesn't provide with an official JSON binding. The one used here is non-official, it is using the JSON bindings from moment-timezone, and could be subject to changes. Ways to mitigate risks here could be 1) to get moment-timezone data put into a separate iana-json library; 2) check if IANA is interested in making it official? Ideas?
| validateDefaultLocale( cldr ); | ||
|
|
||
| timeZone = options.timeZone; | ||
| validateParameterTypeString( options.timeZone, "options.timeZone" ); |
There was a problem hiding this comment.
Now that we the additional option options.timeZone, we need to update the above options = options || { skeleton: "yMd" }. For example, dateFormatter({timeZone: "something"}) should also set the default skeleton: "yMd". This default doesn't need to be set if either one is used: skeleton, date, or datetime.
| "../number/symbol", | ||
| "../util/string/pad" | ||
| "../util/string/pad", | ||
| "../common/format-message" |
There was a problem hiding this comment.
nitpick: sort these filepaths alphabetically please, therefore common/format-message should be included after the common/.. one above.
| "zones": [ | ||
| { | ||
| "name": "America/Los_Angeles", | ||
| "abbrs": [ |
| 420, | ||
| 480 | ||
| ], | ||
| "population": 15058000 |
| }); | ||
|
|
||
| QUnit.test( "should format timezone (v)", function( assert ) { | ||
| try { |
There was a problem hiding this comment.
It seems like this was used for debug and was left?
|
Closed in favor of #701 |
#340
z,v,Vformat with timezone namesAdded by @rxaviers:
TODO:
options.timeZoneoptions.timeZoneoptions.timeZoneFollow up items: