OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // ECMAScript 402 API implementation. | 5 // ECMAScript 402 API implementation. |
6 | 6 |
7 /** | 7 /** |
8 * Intl object is a single object that has some named properties, | 8 * Intl object is a single object that has some named properties, |
9 * all of which are constructors. | 9 * all of which are constructors. |
10 */ | 10 */ |
11 (function(global, utils) { | 11 (function(global, utils) { |
12 | 12 |
13 "use strict"; | 13 "use strict"; |
14 | 14 |
15 %CheckIsBootstrapping(); | 15 %CheckIsBootstrapping(); |
16 | 16 |
17 // ------------------------------------------------------------------- | 17 // ------------------------------------------------------------------- |
18 // Imports | 18 // Imports |
19 | 19 |
20 var ArrayIndexOf; | 20 var ArrayIndexOf; |
21 var ArrayJoin; | 21 var ArrayJoin; |
22 var ArrayPush; | 22 var ArrayPush; |
23 var InstallFunctions = utils.InstallFunctions; | |
24 var InstallGetter = utils.InstallGetter; | |
25 var IsFinite; | |
26 var IsNaN; | |
27 var GlobalBoolean = global.Boolean; | 23 var GlobalBoolean = global.Boolean; |
28 var GlobalDate = global.Date; | 24 var GlobalDate = global.Date; |
29 var GlobalNumber = global.Number; | 25 var GlobalNumber = global.Number; |
30 var GlobalRegExp = global.RegExp; | 26 var GlobalRegExp = global.RegExp; |
31 var GlobalString = global.String; | 27 var GlobalString = global.String; |
| 28 var InstallFunctions = utils.InstallFunctions; |
| 29 var InstallGetter = utils.InstallGetter; |
| 30 var InternalPackedArray = utils.InternalPackedArray; |
| 31 var InternalRegExpMatch; |
| 32 var InternalRegExpReplace |
| 33 var IsFinite; |
| 34 var IsNaN; |
32 var MakeError; | 35 var MakeError; |
33 var MakeRangeError; | 36 var MakeRangeError; |
34 var MakeTypeError; | 37 var MakeTypeError; |
35 var ObjectDefineProperties = utils.ImportNow("ObjectDefineProperties"); | 38 var ObjectDefineProperties = utils.ImportNow("ObjectDefineProperties"); |
36 var ObjectDefineProperty = utils.ImportNow("ObjectDefineProperty"); | 39 var ObjectDefineProperty = utils.ImportNow("ObjectDefineProperty"); |
37 var ObjectHasOwnProperty = utils.ImportNow("ObjectHasOwnProperty"); | 40 var ObjectHasOwnProperty = utils.ImportNow("ObjectHasOwnProperty"); |
38 var OverrideFunction = utils.OverrideFunction; | 41 var OverrideFunction = utils.OverrideFunction; |
39 var patternSymbol = utils.ImportNow("intl_pattern_symbol"); | 42 var patternSymbol = utils.ImportNow("intl_pattern_symbol"); |
40 var RegExpTest; | |
41 var resolvedSymbol = utils.ImportNow("intl_resolved_symbol"); | 43 var resolvedSymbol = utils.ImportNow("intl_resolved_symbol"); |
42 var SetFunctionName = utils.SetFunctionName; | 44 var SetFunctionName = utils.SetFunctionName; |
43 var StringIndexOf; | 45 var StringIndexOf; |
44 var StringLastIndexOf; | 46 var StringLastIndexOf; |
45 var StringMatch; | |
46 var StringReplace; | |
47 var StringSplit; | 47 var StringSplit; |
48 var StringSubstr; | 48 var StringSubstr; |
49 var StringSubstring; | 49 var StringSubstring; |
50 | 50 |
51 utils.Import(function(from) { | 51 utils.Import(function(from) { |
52 ArrayIndexOf = from.ArrayIndexOf; | 52 ArrayIndexOf = from.ArrayIndexOf; |
53 ArrayJoin = from.ArrayJoin; | 53 ArrayJoin = from.ArrayJoin; |
54 ArrayPush = from.ArrayPush; | 54 ArrayPush = from.ArrayPush; |
55 IsFinite = from.IsFinite; | 55 IsFinite = from.IsFinite; |
56 IsNaN = from.IsNaN; | 56 IsNaN = from.IsNaN; |
57 MakeError = from.MakeError; | 57 MakeError = from.MakeError; |
58 MakeRangeError = from.MakeRangeError; | 58 MakeRangeError = from.MakeRangeError; |
59 MakeTypeError = from.MakeTypeError; | 59 MakeTypeError = from.MakeTypeError; |
60 RegExpTest = from.RegExpTest; | 60 InternalRegExpMatch = from.InternalRegExpMatch; |
| 61 InternalRegExpReplace = from.InternalRegExpReplace; |
61 StringIndexOf = from.StringIndexOf; | 62 StringIndexOf = from.StringIndexOf; |
62 StringLastIndexOf = from.StringLastIndexOf; | 63 StringLastIndexOf = from.StringLastIndexOf; |
63 StringMatch = from.StringMatch; | |
64 StringReplace = from.StringReplace; | |
65 StringSplit = from.StringSplit; | 64 StringSplit = from.StringSplit; |
66 StringSubstr = from.StringSubstr; | 65 StringSubstr = from.StringSubstr; |
67 StringSubstring = from.StringSubstring; | 66 StringSubstring = from.StringSubstring; |
68 }); | 67 }); |
69 | 68 |
70 // Utilities for definitions | 69 // Utilities for definitions |
71 | 70 |
72 function InstallFunction(object, name, func) { | 71 function InstallFunction(object, name, func) { |
73 InstallFunctions(object, DONT_ENUM, [name, func]); | 72 InstallFunctions(object, DONT_ENUM, [name, func]); |
74 } | 73 } |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 } | 255 } |
257 return TIMEZONE_NAME_LOCATION_PART_RE; | 256 return TIMEZONE_NAME_LOCATION_PART_RE; |
258 } | 257 } |
259 | 258 |
260 | 259 |
261 /** | 260 /** |
262 * Returns an intersection of locales and service supported locales. | 261 * Returns an intersection of locales and service supported locales. |
263 * Parameter locales is treated as a priority list. | 262 * Parameter locales is treated as a priority list. |
264 */ | 263 */ |
265 function supportedLocalesOf(service, locales, options) { | 264 function supportedLocalesOf(service, locales, options) { |
266 if (IS_NULL(%_Call(StringMatch, service, GetServiceRE()))) { | 265 if (IS_NULL(InternalRegExpMatch(GetServiceRE(), service))) { |
267 throw MakeError(kWrongServiceType, service); | 266 throw MakeError(kWrongServiceType, service); |
268 } | 267 } |
269 | 268 |
270 // Provide defaults if matcher was not specified. | 269 // Provide defaults if matcher was not specified. |
271 if (IS_UNDEFINED(options)) { | 270 if (IS_UNDEFINED(options)) { |
272 options = {}; | 271 options = {}; |
273 } else { | 272 } else { |
274 options = TO_OBJECT(options); | 273 options = TO_OBJECT(options); |
275 } | 274 } |
276 | 275 |
(...skipping 27 matching lines...) Expand all Loading... |
304 | 303 |
305 /** | 304 /** |
306 * Returns the subset of the provided BCP 47 language priority list for which | 305 * Returns the subset of the provided BCP 47 language priority list for which |
307 * this service has a matching locale when using the BCP 47 Lookup algorithm. | 306 * this service has a matching locale when using the BCP 47 Lookup algorithm. |
308 * Locales appear in the same order in the returned list as in the input list. | 307 * Locales appear in the same order in the returned list as in the input list. |
309 */ | 308 */ |
310 function lookupSupportedLocalesOf(requestedLocales, availableLocales) { | 309 function lookupSupportedLocalesOf(requestedLocales, availableLocales) { |
311 var matchedLocales = []; | 310 var matchedLocales = []; |
312 for (var i = 0; i < requestedLocales.length; ++i) { | 311 for (var i = 0; i < requestedLocales.length; ++i) { |
313 // Remove -u- extension. | 312 // Remove -u- extension. |
314 var locale = %_Call(StringReplace, | 313 var locale = InternalRegExpReplace( |
315 requestedLocales[i], | 314 GetUnicodeExtensionRE(), requestedLocales[i], ''); |
316 GetUnicodeExtensionRE(), | |
317 ''); | |
318 do { | 315 do { |
319 if (!IS_UNDEFINED(availableLocales[locale])) { | 316 if (!IS_UNDEFINED(availableLocales[locale])) { |
320 // Push requested locale not the resolved one. | 317 // Push requested locale not the resolved one. |
321 %_Call(ArrayPush, matchedLocales, requestedLocales[i]); | 318 %_Call(ArrayPush, matchedLocales, requestedLocales[i]); |
322 break; | 319 break; |
323 } | 320 } |
324 // Truncate locale if possible, if not break. | 321 // Truncate locale if possible, if not break. |
325 var pos = %_Call(StringLastIndexOf, locale, '-'); | 322 var pos = %_Call(StringLastIndexOf, locale, '-'); |
326 if (pos === -1) { | 323 if (pos === -1) { |
327 break; | 324 break; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 | 410 |
414 return resolved; | 411 return resolved; |
415 } | 412 } |
416 | 413 |
417 | 414 |
418 /** | 415 /** |
419 * Returns best matched supported locale and extension info using basic | 416 * Returns best matched supported locale and extension info using basic |
420 * lookup algorithm. | 417 * lookup algorithm. |
421 */ | 418 */ |
422 function lookupMatcher(service, requestedLocales) { | 419 function lookupMatcher(service, requestedLocales) { |
423 if (IS_NULL(%_Call(StringMatch, service, GetServiceRE()))) { | 420 if (IS_NULL(InternalRegExpMatch(GetServiceRE(), service))) { |
424 throw MakeError(kWrongServiceType, service); | 421 throw MakeError(kWrongServiceType, service); |
425 } | 422 } |
426 | 423 |
427 // Cache these, they don't ever change per service. | 424 // Cache these, they don't ever change per service. |
428 if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) { | 425 if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) { |
429 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service); | 426 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service); |
430 } | 427 } |
431 | 428 |
432 for (var i = 0; i < requestedLocales.length; ++i) { | 429 for (var i = 0; i < requestedLocales.length; ++i) { |
433 // Remove all extensions. | 430 // Remove all extensions. |
434 var locale = %_Call(StringReplace, requestedLocales[i], | 431 var locale = InternalRegExpReplace( |
435 GetAnyExtensionRE(), ''); | 432 GetAnyExtensionRE(), requestedLocales[i], ''); |
436 do { | 433 do { |
437 if (!IS_UNDEFINED(AVAILABLE_LOCALES[service][locale])) { | 434 if (!IS_UNDEFINED(AVAILABLE_LOCALES[service][locale])) { |
438 // Return the resolved locale and extension. | 435 // Return the resolved locale and extension. |
439 var extensionMatch = | 436 var extensionMatch = InternalRegExpMatch( |
440 %_Call(StringMatch, requestedLocales[i], GetUnicodeExtensionRE()); | 437 GetUnicodeExtensionRE(), requestedLocales[i]); |
441 var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; | 438 var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; |
442 return {'locale': locale, 'extension': extension, 'position': i}; | 439 return {'locale': locale, 'extension': extension, 'position': i}; |
443 } | 440 } |
444 // Truncate locale if possible. | 441 // Truncate locale if possible. |
445 var pos = %_Call(StringLastIndexOf, locale, '-'); | 442 var pos = %_Call(StringLastIndexOf, locale, '-'); |
446 if (pos === -1) { | 443 if (pos === -1) { |
447 break; | 444 break; |
448 } | 445 } |
449 locale = %_Call(StringSubstring, locale, 0, pos); | 446 locale = %_Call(StringSubstring, locale, 0, pos); |
450 } while (true); | 447 } while (true); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 if (original === resolved) { | 601 if (original === resolved) { |
605 return original; | 602 return original; |
606 } | 603 } |
607 | 604 |
608 var locales = %GetLanguageTagVariants([original, resolved]); | 605 var locales = %GetLanguageTagVariants([original, resolved]); |
609 if (locales[0].maximized !== locales[1].maximized) { | 606 if (locales[0].maximized !== locales[1].maximized) { |
610 return resolved; | 607 return resolved; |
611 } | 608 } |
612 | 609 |
613 // Preserve extensions of resolved locale, but swap base tags with original. | 610 // Preserve extensions of resolved locale, but swap base tags with original. |
614 var resolvedBase = new GlobalRegExp('^' + locales[1].base); | 611 var resolvedBase = new GlobalRegExp('^' + locales[1].base, 'g'); |
615 return %_Call(StringReplace, resolved, resolvedBase, locales[0].base); | 612 return InternalRegExpReplace(resolvedBase, resolved, locales[0].base); |
616 } | 613 } |
617 | 614 |
618 | 615 |
619 /** | 616 /** |
620 * Returns an Object that contains all of supported locales for a given | 617 * Returns an Object that contains all of supported locales for a given |
621 * service. | 618 * service. |
622 * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ | 619 * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ |
623 * that is supported. This is required by the spec. | 620 * that is supported. This is required by the spec. |
624 */ | 621 */ |
625 function getAvailableLocalesOf(service) { | 622 function getAvailableLocalesOf(service) { |
626 var available = %AvailableLocalesOf(service); | 623 var available = %AvailableLocalesOf(service); |
627 | 624 |
628 for (var i in available) { | 625 for (var i in available) { |
629 if (HAS_OWN_PROPERTY(available, i)) { | 626 if (HAS_OWN_PROPERTY(available, i)) { |
630 var parts = | 627 var parts = InternalRegExpMatch( |
631 %_Call(StringMatch, i, /^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/); | 628 /^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/, i); |
632 if (parts !== null) { | 629 if (!IS_NULL(parts)) { |
633 // Build xx-ZZ. We don't care about the actual value, | 630 // Build xx-ZZ. We don't care about the actual value, |
634 // as long it's not undefined. | 631 // as long it's not undefined. |
635 available[parts[1] + '-' + parts[3]] = null; | 632 available[parts[1] + '-' + parts[3]] = null; |
636 } | 633 } |
637 } | 634 } |
638 } | 635 } |
639 | 636 |
640 return available; | 637 return available; |
641 } | 638 } |
642 | 639 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 %StringToLowerCase(%_Call(StringSubstr, word, 1)); | 689 %StringToLowerCase(%_Call(StringSubstr, word, 1)); |
693 } | 690 } |
694 | 691 |
695 /** | 692 /** |
696 * Returns titlecased location, bueNos_airES -> Buenos_Aires | 693 * Returns titlecased location, bueNos_airES -> Buenos_Aires |
697 * or ho_cHi_minH -> Ho_Chi_Minh. It is locale-agnostic and only | 694 * or ho_cHi_minH -> Ho_Chi_Minh. It is locale-agnostic and only |
698 * deals with ASCII only characters. | 695 * deals with ASCII only characters. |
699 * 'of', 'au' and 'es' are special-cased and lowercased. | 696 * 'of', 'au' and 'es' are special-cased and lowercased. |
700 */ | 697 */ |
701 function toTitleCaseTimezoneLocation(location) { | 698 function toTitleCaseTimezoneLocation(location) { |
702 var match = %_Call(StringMatch, location, GetTimezoneNameLocationPartRE()); | 699 var match = InternalRegExpMatch(GetTimezoneNameLocationPartRE(), location) |
703 if (IS_NULL(match)) throw MakeRangeError(kExpectedLocation, location); | 700 if (IS_NULL(match)) throw MakeRangeError(kExpectedLocation, location); |
704 | 701 |
705 var result = toTitleCaseWord(match[1]); | 702 var result = toTitleCaseWord(match[1]); |
706 if (!IS_UNDEFINED(match[2]) && 2 < match.length) { | 703 if (!IS_UNDEFINED(match[2]) && 2 < match.length) { |
707 // The first character is a separator, '_' or '-'. | 704 // The first character is a separator, '_' or '-'. |
708 // None of IANA zone names has both '_' and '-'. | 705 // None of IANA zone names has both '_' and '-'. |
709 var separator = %_Call(StringSubstring, match[2], 0, 1); | 706 var separator = %_Call(StringSubstring, match[2], 0, 1); |
710 var parts = %_Call(StringSplit, match[2], separator); | 707 var parts = %_Call(StringSplit, match[2], separator); |
711 for (var i = 1; i < parts.length; i++) { | 708 for (var i = 1; i < parts.length; i++) { |
712 var part = parts[i] | 709 var part = parts[i] |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 * Validates the language tag. Section 2.2.9 of the bcp47 spec | 786 * Validates the language tag. Section 2.2.9 of the bcp47 spec |
790 * defines a valid tag. | 787 * defines a valid tag. |
791 * | 788 * |
792 * ICU is too permissible and lets invalid tags, like | 789 * ICU is too permissible and lets invalid tags, like |
793 * hant-cmn-cn, through. | 790 * hant-cmn-cn, through. |
794 * | 791 * |
795 * Returns false if the language tag is invalid. | 792 * Returns false if the language tag is invalid. |
796 */ | 793 */ |
797 function isValidLanguageTag(locale) { | 794 function isValidLanguageTag(locale) { |
798 // Check if it's well-formed, including grandfadered tags. | 795 // Check if it's well-formed, including grandfadered tags. |
799 if (!%_Call(RegExpTest, GetLanguageTagRE(), locale)) { | 796 if (IS_NULL(InternalRegExpMatch(GetLanguageTagRE(), locale))) { |
800 return false; | 797 return false; |
801 } | 798 } |
802 | 799 |
803 // Just return if it's a x- form. It's all private. | 800 // Just return if it's a x- form. It's all private. |
804 if (%_Call(StringIndexOf, locale, 'x-') === 0) { | 801 if (%_Call(StringIndexOf, locale, 'x-') === 0) { |
805 return true; | 802 return true; |
806 } | 803 } |
807 | 804 |
808 // Check if there are any duplicate variants or singletons (extensions). | 805 // Check if there are any duplicate variants or singletons (extensions). |
809 | 806 |
810 // Remove private use section. | 807 // Remove private use section. |
811 locale = %_Call(StringSplit, locale, /-x-/)[0]; | 808 locale = %_Call(StringSplit, locale, '-x-')[0]; |
812 | 809 |
813 // Skip language since it can match variant regex, so we start from 1. | 810 // Skip language since it can match variant regex, so we start from 1. |
814 // We are matching i-klingon here, but that's ok, since i-klingon-klingon | 811 // We are matching i-klingon here, but that's ok, since i-klingon-klingon |
815 // is not valid and would fail LANGUAGE_TAG_RE test. | 812 // is not valid and would fail LANGUAGE_TAG_RE test. |
816 var variants = []; | 813 var variants = []; |
817 var extensions = []; | 814 var extensions = []; |
818 var parts = %_Call(StringSplit, locale, /-/); | 815 var parts = %_Call(StringSplit, locale, '-'); |
819 for (var i = 1; i < parts.length; i++) { | 816 for (var i = 1; i < parts.length; i++) { |
820 var value = parts[i]; | 817 var value = parts[i]; |
821 if (%_Call(RegExpTest, GetLanguageVariantRE(), value) && | 818 if (!IS_NULL(InternalRegExpMatch(GetLanguageVariantRE(), value)) && |
822 extensions.length === 0) { | 819 extensions.length === 0) { |
823 if (%_Call(ArrayIndexOf, variants, value) === -1) { | 820 if (%_Call(ArrayIndexOf, variants, value) === -1) { |
824 %_Call(ArrayPush, variants, value); | 821 %_Call(ArrayPush, variants, value); |
825 } else { | 822 } else { |
826 return false; | 823 return false; |
827 } | 824 } |
828 } | 825 } |
829 | 826 |
830 if (%_Call(RegExpTest, GetLanguageSingletonRE(), value)) { | 827 if (!IS_NULL(InternalRegExpMatch(GetLanguageSingletonRE(), value))) { |
831 if (%_Call(ArrayIndexOf, extensions, value) === -1) { | 828 if (%_Call(ArrayIndexOf, extensions, value) === -1) { |
832 %_Call(ArrayPush, extensions, value); | 829 %_Call(ArrayPush, extensions, value); |
833 } else { | 830 } else { |
834 return false; | 831 return false; |
835 } | 832 } |
836 } | 833 } |
837 } | 834 } |
838 | 835 |
839 return true; | 836 return true; |
840 } | 837 } |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1076 | 1073 |
1077 | 1074 |
1078 AddBoundMethod(Intl.Collator, 'compare', compare, 2); | 1075 AddBoundMethod(Intl.Collator, 'compare', compare, 2); |
1079 | 1076 |
1080 /** | 1077 /** |
1081 * Verifies that the input is a well-formed ISO 4217 currency code. | 1078 * Verifies that the input is a well-formed ISO 4217 currency code. |
1082 * Don't uppercase to test. It could convert invalid code into a valid one. | 1079 * Don't uppercase to test. It could convert invalid code into a valid one. |
1083 * For example \u00DFP (Eszett+P) becomes SSP. | 1080 * For example \u00DFP (Eszett+P) becomes SSP. |
1084 */ | 1081 */ |
1085 function isWellFormedCurrencyCode(currency) { | 1082 function isWellFormedCurrencyCode(currency) { |
1086 return typeof currency == "string" && | 1083 return typeof currency == "string" && currency.length == 3 && |
1087 currency.length == 3 && | 1084 IS_NULL(InternalRegExpMatch(/[^A-Za-z]/, currency)); |
1088 %_Call(StringMatch, currency, /[^A-Za-z]/) == null; | |
1089 } | 1085 } |
1090 | 1086 |
1091 | 1087 |
1092 /** | 1088 /** |
1093 * Returns the valid digit count for a property, or throws RangeError on | 1089 * Returns the valid digit count for a property, or throws RangeError on |
1094 * a value out of the range. | 1090 * a value out of the range. |
1095 */ | 1091 */ |
1096 function getNumberOption(options, property, min, max, fallback) { | 1092 function getNumberOption(options, property, min, max, fallback) { |
1097 var value = options[property]; | 1093 var value = options[property]; |
1098 if (!IS_UNDEFINED(value)) { | 1094 if (!IS_UNDEFINED(value)) { |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1408 return ''; | 1404 return ''; |
1409 } | 1405 } |
1410 } | 1406 } |
1411 | 1407 |
1412 | 1408 |
1413 /** | 1409 /** |
1414 * Returns object that matches LDML representation of the date. | 1410 * Returns object that matches LDML representation of the date. |
1415 */ | 1411 */ |
1416 function fromLDMLString(ldmlString) { | 1412 function fromLDMLString(ldmlString) { |
1417 // First remove '' quoted text, so we lose 'Uhr' strings. | 1413 // First remove '' quoted text, so we lose 'Uhr' strings. |
1418 ldmlString = %_Call(StringReplace, ldmlString, GetQuotedStringRE(), ''); | 1414 ldmlString = InternalRegExpReplace(GetQuotedStringRE(), ldmlString, ''); |
1419 | 1415 |
1420 var options = {}; | 1416 var options = {}; |
1421 var match = %_Call(StringMatch, ldmlString, /E{3,5}/g); | 1417 var match = InternalRegExpMatch(/E{3,5}/, ldmlString); |
1422 options = appendToDateTimeObject( | 1418 options = appendToDateTimeObject( |
1423 options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'}); | 1419 options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'}); |
1424 | 1420 |
1425 match = %_Call(StringMatch, ldmlString, /G{3,5}/g); | 1421 match = InternalRegExpMatch(/G{3,5}/, ldmlString); |
1426 options = appendToDateTimeObject( | 1422 options = appendToDateTimeObject( |
1427 options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'}); | 1423 options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'}); |
1428 | 1424 |
1429 match = %_Call(StringMatch, ldmlString, /y{1,2}/g); | 1425 match = InternalRegExpMatch(/y{1,2}/, ldmlString); |
1430 options = appendToDateTimeObject( | 1426 options = appendToDateTimeObject( |
1431 options, 'year', match, {y: 'numeric', yy: '2-digit'}); | 1427 options, 'year', match, {y: 'numeric', yy: '2-digit'}); |
1432 | 1428 |
1433 match = %_Call(StringMatch, ldmlString, /M{1,5}/g); | 1429 match = InternalRegExpMatch(/M{1,5}/, ldmlString); |
1434 options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit', | 1430 options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit', |
1435 M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'}); | 1431 M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'}); |
1436 | 1432 |
1437 // Sometimes we get L instead of M for month - standalone name. | 1433 // Sometimes we get L instead of M for month - standalone name. |
1438 match = %_Call(StringMatch, ldmlString, /L{1,5}/g); | 1434 match = InternalRegExpMatch(/L{1,5}/, ldmlString); |
1439 options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit', | 1435 options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit', |
1440 L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'}); | 1436 L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'}); |
1441 | 1437 |
1442 match = %_Call(StringMatch, ldmlString, /d{1,2}/g); | 1438 match = InternalRegExpMatch(/d{1,2}/, ldmlString); |
1443 options = appendToDateTimeObject( | 1439 options = appendToDateTimeObject( |
1444 options, 'day', match, {d: 'numeric', dd: '2-digit'}); | 1440 options, 'day', match, {d: 'numeric', dd: '2-digit'}); |
1445 | 1441 |
1446 match = %_Call(StringMatch, ldmlString, /h{1,2}/g); | 1442 match = InternalRegExpMatch(/h{1,2}/, ldmlString); |
1447 if (match !== null) { | 1443 if (match !== null) { |
1448 options['hour12'] = true; | 1444 options['hour12'] = true; |
1449 } | 1445 } |
1450 options = appendToDateTimeObject( | 1446 options = appendToDateTimeObject( |
1451 options, 'hour', match, {h: 'numeric', hh: '2-digit'}); | 1447 options, 'hour', match, {h: 'numeric', hh: '2-digit'}); |
1452 | 1448 |
1453 match = %_Call(StringMatch, ldmlString, /H{1,2}/g); | 1449 match = InternalRegExpMatch(/H{1,2}/, ldmlString); |
1454 if (match !== null) { | 1450 if (match !== null) { |
1455 options['hour12'] = false; | 1451 options['hour12'] = false; |
1456 } | 1452 } |
1457 options = appendToDateTimeObject( | 1453 options = appendToDateTimeObject( |
1458 options, 'hour', match, {H: 'numeric', HH: '2-digit'}); | 1454 options, 'hour', match, {H: 'numeric', HH: '2-digit'}); |
1459 | 1455 |
1460 match = %_Call(StringMatch, ldmlString, /m{1,2}/g); | 1456 match = InternalRegExpMatch(/m{1,2}/, ldmlString); |
1461 options = appendToDateTimeObject( | 1457 options = appendToDateTimeObject( |
1462 options, 'minute', match, {m: 'numeric', mm: '2-digit'}); | 1458 options, 'minute', match, {m: 'numeric', mm: '2-digit'}); |
1463 | 1459 |
1464 match = %_Call(StringMatch, ldmlString, /s{1,2}/g); | 1460 match = InternalRegExpMatch(/s{1,2}/, ldmlString); |
1465 options = appendToDateTimeObject( | 1461 options = appendToDateTimeObject( |
1466 options, 'second', match, {s: 'numeric', ss: '2-digit'}); | 1462 options, 'second', match, {s: 'numeric', ss: '2-digit'}); |
1467 | 1463 |
1468 match = %_Call(StringMatch, ldmlString, /z|zzzz/g); | 1464 match = InternalRegExpMatch(/z|zzzz/, ldmlString); |
1469 options = appendToDateTimeObject( | 1465 options = appendToDateTimeObject( |
1470 options, 'timeZoneName', match, {z: 'short', zzzz: 'long'}); | 1466 options, 'timeZoneName', match, {z: 'short', zzzz: 'long'}); |
1471 | 1467 |
1472 return options; | 1468 return options; |
1473 } | 1469 } |
1474 | 1470 |
1475 | 1471 |
1476 function appendToDateTimeObject(options, option, match, pairs) { | 1472 function appendToDateTimeObject(options, option, match, pairs) { |
1477 if (IS_NULL(match)) { | 1473 if (IS_NULL(match)) { |
1478 if (!HAS_OWN_PROPERTY(options, option)) { | 1474 if (!HAS_OWN_PROPERTY(options, option)) { |
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1785 var upperID = %StringToUpperCase(tzID); | 1781 var upperID = %StringToUpperCase(tzID); |
1786 if (upperID === 'UTC' || upperID === 'GMT' || | 1782 if (upperID === 'UTC' || upperID === 'GMT' || |
1787 upperID === 'ETC/UTC' || upperID === 'ETC/GMT') { | 1783 upperID === 'ETC/UTC' || upperID === 'ETC/GMT') { |
1788 return 'UTC'; | 1784 return 'UTC'; |
1789 } | 1785 } |
1790 | 1786 |
1791 // TODO(jshin): Add support for Etc/GMT[+-]([1-9]|1[0-2]) | 1787 // TODO(jshin): Add support for Etc/GMT[+-]([1-9]|1[0-2]) |
1792 | 1788 |
1793 // We expect only _, '-' and / beside ASCII letters. | 1789 // We expect only _, '-' and / beside ASCII letters. |
1794 // All inputs should conform to Area/Location(/Location)* from now on. | 1790 // All inputs should conform to Area/Location(/Location)* from now on. |
1795 var match = %_Call(StringMatch, tzID, GetTimezoneNameCheckRE()); | 1791 var match = InternalRegExpMatch(GetTimezoneNameCheckRE(), tzID); |
1796 if (IS_NULL(match)) throw MakeRangeError(kExpectedTimezoneID, tzID); | 1792 if (IS_NULL(match)) throw MakeRangeError(kExpectedTimezoneID, tzID); |
1797 | 1793 |
1798 var result = toTitleCaseTimezoneLocation(match[1]) + '/' + | 1794 var result = toTitleCaseTimezoneLocation(match[1]) + '/' + |
1799 toTitleCaseTimezoneLocation(match[2]); | 1795 toTitleCaseTimezoneLocation(match[2]); |
1800 | 1796 |
1801 if (!IS_UNDEFINED(match[3]) && 3 < match.length) { | 1797 if (!IS_UNDEFINED(match[3]) && 3 < match.length) { |
1802 var locations = %_Call(StringSplit, match[3], '/'); | 1798 var locations = %_Call(StringSplit, match[3], '/'); |
1803 // The 1st element is empty. Starts with i=1. | 1799 // The 1st element is empty. Starts with i=1. |
1804 for (var i = 1; i < locations.length; i++) { | 1800 for (var i = 1; i < locations.length; i++) { |
1805 result = result + '/' + toTitleCaseTimezoneLocation(locations[i]); | 1801 result = result + '/' + toTitleCaseTimezoneLocation(locations[i]); |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2136 } | 2132 } |
2137 | 2133 |
2138 var locales = arguments[0]; | 2134 var locales = arguments[0]; |
2139 var options = arguments[1]; | 2135 var options = arguments[1]; |
2140 return toLocaleDateTime( | 2136 return toLocaleDateTime( |
2141 this, locales, options, 'time', 'time', 'dateformattime'); | 2137 this, locales, options, 'time', 'time', 'dateformattime'); |
2142 } | 2138 } |
2143 ); | 2139 ); |
2144 | 2140 |
2145 }) | 2141 }) |
OLD | NEW |