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 ArrayJoin; | 20 var ArrayJoin; |
21 var ArrayPush; | 21 var ArrayPush; |
22 var GlobalDate = global.Date; | 22 var GlobalDate = global.Date; |
23 var GlobalNumber = global.Number; | 23 var GlobalNumber = global.Number; |
24 var GlobalRegExp = global.RegExp; | 24 var GlobalRegExp = global.RegExp; |
25 var GlobalString = global.String; | 25 var GlobalString = global.String; |
26 var InstallFunctions = utils.InstallFunctions; | 26 var InstallFunctions = utils.InstallFunctions; |
27 var InstallGetter = utils.InstallGetter; | 27 var InstallGetter = utils.InstallGetter; |
28 var InternalArray = utils.InternalArray; | 28 var InternalArray = utils.InternalArray; |
29 var InternalRegExpMatch; | |
30 var InternalRegExpReplace | |
31 var ObjectHasOwnProperty = utils.ImportNow("ObjectHasOwnProperty"); | 29 var ObjectHasOwnProperty = utils.ImportNow("ObjectHasOwnProperty"); |
32 var OverrideFunction = utils.OverrideFunction; | 30 var OverrideFunction = utils.OverrideFunction; |
33 var patternSymbol = utils.ImportNow("intl_pattern_symbol"); | 31 var patternSymbol = utils.ImportNow("intl_pattern_symbol"); |
34 var resolvedSymbol = utils.ImportNow("intl_resolved_symbol"); | 32 var resolvedSymbol = utils.ImportNow("intl_resolved_symbol"); |
35 var SetFunctionName = utils.SetFunctionName; | 33 var SetFunctionName = utils.SetFunctionName; |
36 var StringSubstr = GlobalString.prototype.substr; | 34 var StringSubstr = GlobalString.prototype.substr; |
37 var StringSubstring = GlobalString.prototype.substring; | 35 var StringSubstring = GlobalString.prototype.substring; |
38 | 36 |
39 utils.Import(function(from) { | 37 utils.Import(function(from) { |
40 ArrayJoin = from.ArrayJoin; | 38 ArrayJoin = from.ArrayJoin; |
41 ArrayPush = from.ArrayPush; | 39 ArrayPush = from.ArrayPush; |
42 InternalRegExpMatch = from.InternalRegExpMatch; | |
43 InternalRegExpReplace = from.InternalRegExpReplace; | |
44 }); | 40 }); |
45 | 41 |
46 // Utilities for definitions | 42 // Utilities for definitions |
47 | 43 |
48 function InstallFunction(object, name, func) { | 44 function InstallFunction(object, name, func) { |
49 InstallFunctions(object, DONT_ENUM, [name, func]); | 45 InstallFunctions(object, DONT_ENUM, [name, func]); |
50 } | 46 } |
51 | 47 |
52 | 48 |
53 function InstallConstructor(object, name, func) { | 49 function InstallConstructor(object, name, func) { |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 } | 238 } |
243 return TIMEZONE_NAME_LOCATION_PART_RE; | 239 return TIMEZONE_NAME_LOCATION_PART_RE; |
244 } | 240 } |
245 | 241 |
246 | 242 |
247 /** | 243 /** |
248 * Returns an intersection of locales and service supported locales. | 244 * Returns an intersection of locales and service supported locales. |
249 * Parameter locales is treated as a priority list. | 245 * Parameter locales is treated as a priority list. |
250 */ | 246 */ |
251 function supportedLocalesOf(service, locales, options) { | 247 function supportedLocalesOf(service, locales, options) { |
252 if (IS_NULL(InternalRegExpMatch(GetServiceRE(), service))) { | 248 if (IS_NULL(%regexp_internal_match(GetServiceRE(), service))) { |
253 throw %make_error(kWrongServiceType, service); | 249 throw %make_error(kWrongServiceType, service); |
254 } | 250 } |
255 | 251 |
256 // Provide defaults if matcher was not specified. | 252 // Provide defaults if matcher was not specified. |
257 if (IS_UNDEFINED(options)) { | 253 if (IS_UNDEFINED(options)) { |
258 options = {}; | 254 options = {}; |
259 } else { | 255 } else { |
260 options = TO_OBJECT(options); | 256 options = TO_OBJECT(options); |
261 } | 257 } |
262 | 258 |
(...skipping 27 matching lines...) Expand all Loading... |
290 | 286 |
291 /** | 287 /** |
292 * Returns the subset of the provided BCP 47 language priority list for which | 288 * Returns the subset of the provided BCP 47 language priority list for which |
293 * this service has a matching locale when using the BCP 47 Lookup algorithm. | 289 * this service has a matching locale when using the BCP 47 Lookup algorithm. |
294 * Locales appear in the same order in the returned list as in the input list. | 290 * Locales appear in the same order in the returned list as in the input list. |
295 */ | 291 */ |
296 function lookupSupportedLocalesOf(requestedLocales, availableLocales) { | 292 function lookupSupportedLocalesOf(requestedLocales, availableLocales) { |
297 var matchedLocales = new InternalArray(); | 293 var matchedLocales = new InternalArray(); |
298 for (var i = 0; i < requestedLocales.length; ++i) { | 294 for (var i = 0; i < requestedLocales.length; ++i) { |
299 // Remove -u- extension. | 295 // Remove -u- extension. |
300 var locale = InternalRegExpReplace( | 296 var locale = %RegExpInternalReplace( |
301 GetUnicodeExtensionRE(), requestedLocales[i], ''); | 297 GetUnicodeExtensionRE(), requestedLocales[i], ''); |
302 do { | 298 do { |
303 if (!IS_UNDEFINED(availableLocales[locale])) { | 299 if (!IS_UNDEFINED(availableLocales[locale])) { |
304 // Push requested locale not the resolved one. | 300 // Push requested locale not the resolved one. |
305 %_Call(ArrayPush, matchedLocales, requestedLocales[i]); | 301 %_Call(ArrayPush, matchedLocales, requestedLocales[i]); |
306 break; | 302 break; |
307 } | 303 } |
308 // Truncate locale if possible, if not break. | 304 // Truncate locale if possible, if not break. |
309 var pos = %StringLastIndexOf(locale, '-'); | 305 var pos = %StringLastIndexOf(locale, '-'); |
310 if (pos === -1) { | 306 if (pos === -1) { |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 | 396 |
401 return resolved; | 397 return resolved; |
402 } | 398 } |
403 | 399 |
404 | 400 |
405 /** | 401 /** |
406 * Returns best matched supported locale and extension info using basic | 402 * Returns best matched supported locale and extension info using basic |
407 * lookup algorithm. | 403 * lookup algorithm. |
408 */ | 404 */ |
409 function lookupMatcher(service, requestedLocales) { | 405 function lookupMatcher(service, requestedLocales) { |
410 if (IS_NULL(InternalRegExpMatch(GetServiceRE(), service))) { | 406 if (IS_NULL(%regexp_internal_match(GetServiceRE(), service))) { |
411 throw %make_error(kWrongServiceType, service); | 407 throw %make_error(kWrongServiceType, service); |
412 } | 408 } |
413 | 409 |
414 // Cache these, they don't ever change per service. | 410 // Cache these, they don't ever change per service. |
415 if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) { | 411 if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) { |
416 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service); | 412 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service); |
417 } | 413 } |
418 | 414 |
419 for (var i = 0; i < requestedLocales.length; ++i) { | 415 for (var i = 0; i < requestedLocales.length; ++i) { |
420 // Remove all extensions. | 416 // Remove all extensions. |
421 var locale = InternalRegExpReplace( | 417 var locale = %RegExpInternalReplace( |
422 GetAnyExtensionRE(), requestedLocales[i], ''); | 418 GetAnyExtensionRE(), requestedLocales[i], ''); |
423 do { | 419 do { |
424 if (!IS_UNDEFINED(AVAILABLE_LOCALES[service][locale])) { | 420 if (!IS_UNDEFINED(AVAILABLE_LOCALES[service][locale])) { |
425 // Return the resolved locale and extension. | 421 // Return the resolved locale and extension. |
426 var extensionMatch = InternalRegExpMatch( | 422 var extensionMatch = %regexp_internal_match( |
427 GetUnicodeExtensionRE(), requestedLocales[i]); | 423 GetUnicodeExtensionRE(), requestedLocales[i]); |
428 var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; | 424 var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; |
429 return {'locale': locale, 'extension': extension, 'position': i}; | 425 return {'locale': locale, 'extension': extension, 'position': i}; |
430 } | 426 } |
431 // Truncate locale if possible. | 427 // Truncate locale if possible. |
432 var pos = %StringLastIndexOf(locale, '-'); | 428 var pos = %StringLastIndexOf(locale, '-'); |
433 if (pos === -1) { | 429 if (pos === -1) { |
434 break; | 430 break; |
435 } | 431 } |
436 locale = %_Call(StringSubstring, locale, 0, pos); | 432 locale = %_Call(StringSubstring, locale, 0, pos); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
614 return original; | 610 return original; |
615 } | 611 } |
616 | 612 |
617 var locales = %GetLanguageTagVariants([original, resolved]); | 613 var locales = %GetLanguageTagVariants([original, resolved]); |
618 if (locales[0].maximized !== locales[1].maximized) { | 614 if (locales[0].maximized !== locales[1].maximized) { |
619 return resolved; | 615 return resolved; |
620 } | 616 } |
621 | 617 |
622 // Preserve extensions of resolved locale, but swap base tags with original. | 618 // Preserve extensions of resolved locale, but swap base tags with original. |
623 var resolvedBase = new GlobalRegExp('^' + locales[1].base, 'g'); | 619 var resolvedBase = new GlobalRegExp('^' + locales[1].base, 'g'); |
624 return InternalRegExpReplace(resolvedBase, resolved, locales[0].base); | 620 return %RegExpInternalReplace(resolvedBase, resolved, locales[0].base); |
625 } | 621 } |
626 | 622 |
627 | 623 |
628 /** | 624 /** |
629 * Returns an Object that contains all of supported locales for a given | 625 * Returns an Object that contains all of supported locales for a given |
630 * service. | 626 * service. |
631 * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ | 627 * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ |
632 * that is supported. This is required by the spec. | 628 * that is supported. This is required by the spec. |
633 */ | 629 */ |
634 function getAvailableLocalesOf(service) { | 630 function getAvailableLocalesOf(service) { |
635 var available = %AvailableLocalesOf(service); | 631 var available = %AvailableLocalesOf(service); |
636 | 632 |
637 for (var i in available) { | 633 for (var i in available) { |
638 if (HAS_OWN_PROPERTY(available, i)) { | 634 if (HAS_OWN_PROPERTY(available, i)) { |
639 var parts = InternalRegExpMatch( | 635 var parts = %regexp_internal_match( |
640 /^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/, i); | 636 /^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/, i); |
641 if (!IS_NULL(parts)) { | 637 if (!IS_NULL(parts)) { |
642 // Build xx-ZZ. We don't care about the actual value, | 638 // Build xx-ZZ. We don't care about the actual value, |
643 // as long it's not undefined. | 639 // as long it's not undefined. |
644 available[parts[1] + '-' + parts[3]] = null; | 640 available[parts[1] + '-' + parts[3]] = null; |
645 } | 641 } |
646 } | 642 } |
647 } | 643 } |
648 | 644 |
649 return available; | 645 return available; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
701 %StringToLowerCase(%_Call(StringSubstr, word, 1)); | 697 %StringToLowerCase(%_Call(StringSubstr, word, 1)); |
702 } | 698 } |
703 | 699 |
704 /** | 700 /** |
705 * Returns titlecased location, bueNos_airES -> Buenos_Aires | 701 * Returns titlecased location, bueNos_airES -> Buenos_Aires |
706 * or ho_cHi_minH -> Ho_Chi_Minh. It is locale-agnostic and only | 702 * or ho_cHi_minH -> Ho_Chi_Minh. It is locale-agnostic and only |
707 * deals with ASCII only characters. | 703 * deals with ASCII only characters. |
708 * 'of', 'au' and 'es' are special-cased and lowercased. | 704 * 'of', 'au' and 'es' are special-cased and lowercased. |
709 */ | 705 */ |
710 function toTitleCaseTimezoneLocation(location) { | 706 function toTitleCaseTimezoneLocation(location) { |
711 var match = InternalRegExpMatch(GetTimezoneNameLocationPartRE(), location) | 707 var match = %regexp_internal_match(GetTimezoneNameLocationPartRE(), location) |
712 if (IS_NULL(match)) throw %make_range_error(kExpectedLocation, location); | 708 if (IS_NULL(match)) throw %make_range_error(kExpectedLocation, location); |
713 | 709 |
714 var result = toTitleCaseWord(match[1]); | 710 var result = toTitleCaseWord(match[1]); |
715 if (!IS_UNDEFINED(match[2]) && 2 < match.length) { | 711 if (!IS_UNDEFINED(match[2]) && 2 < match.length) { |
716 // The first character is a separator, '_' or '-'. | 712 // The first character is a separator, '_' or '-'. |
717 // None of IANA zone names has both '_' and '-'. | 713 // None of IANA zone names has both '_' and '-'. |
718 var separator = %_Call(StringSubstring, match[2], 0, 1); | 714 var separator = %_Call(StringSubstring, match[2], 0, 1); |
719 var parts = %StringSplit(match[2], separator, kMaxUint32); | 715 var parts = %StringSplit(match[2], separator, kMaxUint32); |
720 for (var i = 1; i < parts.length; i++) { | 716 for (var i = 1; i < parts.length; i++) { |
721 var part = parts[i] | 717 var part = parts[i] |
(...skipping 14 matching lines...) Expand all Loading... |
736 function canonicalizeLanguageTag(localeID) { | 732 function canonicalizeLanguageTag(localeID) { |
737 // null is typeof 'object' so we have to do extra check. | 733 // null is typeof 'object' so we have to do extra check. |
738 if ((!IS_STRING(localeID) && !IS_RECEIVER(localeID)) || | 734 if ((!IS_STRING(localeID) && !IS_RECEIVER(localeID)) || |
739 IS_NULL(localeID)) { | 735 IS_NULL(localeID)) { |
740 throw %make_type_error(kLanguageID); | 736 throw %make_type_error(kLanguageID); |
741 } | 737 } |
742 | 738 |
743 // Optimize for the most common case; a language code alone in | 739 // Optimize for the most common case; a language code alone in |
744 // the canonical form/lowercase (e.g. "en", "fil"). | 740 // the canonical form/lowercase (e.g. "en", "fil"). |
745 if (IS_STRING(localeID) && | 741 if (IS_STRING(localeID) && |
746 !IS_NULL(InternalRegExpMatch(/^[a-z]{2,3}$/, localeID))) { | 742 !IS_NULL(%regexp_internal_match(/^[a-z]{2,3}$/, localeID))) { |
747 return localeID; | 743 return localeID; |
748 } | 744 } |
749 | 745 |
750 var localeString = TO_STRING(localeID); | 746 var localeString = TO_STRING(localeID); |
751 | 747 |
752 if (isStructuallyValidLanguageTag(localeString) === false) { | 748 if (isStructuallyValidLanguageTag(localeString) === false) { |
753 throw %make_range_error(kInvalidLanguageTag, localeString); | 749 throw %make_range_error(kInvalidLanguageTag, localeString); |
754 } | 750 } |
755 | 751 |
756 // ECMA 402 6.2.3 | 752 // ECMA 402 6.2.3 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
814 * primary/extended language, script, region, variant are not checked | 810 * primary/extended language, script, region, variant are not checked |
815 * against the IANA language subtag registry. | 811 * against the IANA language subtag registry. |
816 * | 812 * |
817 * ICU is too permissible and lets invalid tags, like | 813 * ICU is too permissible and lets invalid tags, like |
818 * hant-cmn-cn, through. | 814 * hant-cmn-cn, through. |
819 * | 815 * |
820 * Returns false if the language tag is invalid. | 816 * Returns false if the language tag is invalid. |
821 */ | 817 */ |
822 function isStructuallyValidLanguageTag(locale) { | 818 function isStructuallyValidLanguageTag(locale) { |
823 // Check if it's well-formed, including grandfadered tags. | 819 // Check if it's well-formed, including grandfadered tags. |
824 if (IS_NULL(InternalRegExpMatch(GetLanguageTagRE(), locale))) { | 820 if (IS_NULL(%regexp_internal_match(GetLanguageTagRE(), locale))) { |
825 return false; | 821 return false; |
826 } | 822 } |
827 | 823 |
828 // Just return if it's a x- form. It's all private. | 824 // Just return if it's a x- form. It's all private. |
829 if (%StringIndexOf(locale, 'x-', 0) === 0) { | 825 if (%StringIndexOf(locale, 'x-', 0) === 0) { |
830 return true; | 826 return true; |
831 } | 827 } |
832 | 828 |
833 // Check if there are any duplicate variants or singletons (extensions). | 829 // Check if there are any duplicate variants or singletons (extensions). |
834 | 830 |
835 // Remove private use section. | 831 // Remove private use section. |
836 locale = %StringSplit(locale, '-x-', kMaxUint32)[0]; | 832 locale = %StringSplit(locale, '-x-', kMaxUint32)[0]; |
837 | 833 |
838 // Skip language since it can match variant regex, so we start from 1. | 834 // Skip language since it can match variant regex, so we start from 1. |
839 // We are matching i-klingon here, but that's ok, since i-klingon-klingon | 835 // We are matching i-klingon here, but that's ok, since i-klingon-klingon |
840 // is not valid and would fail LANGUAGE_TAG_RE test. | 836 // is not valid and would fail LANGUAGE_TAG_RE test. |
841 var variants = new InternalArray(); | 837 var variants = new InternalArray(); |
842 var extensions = new InternalArray(); | 838 var extensions = new InternalArray(); |
843 var parts = %StringSplit(locale, '-', kMaxUint32); | 839 var parts = %StringSplit(locale, '-', kMaxUint32); |
844 for (var i = 1; i < parts.length; i++) { | 840 for (var i = 1; i < parts.length; i++) { |
845 var value = parts[i]; | 841 var value = parts[i]; |
846 if (!IS_NULL(InternalRegExpMatch(GetLanguageVariantRE(), value)) && | 842 if (!IS_NULL(%regexp_internal_match(GetLanguageVariantRE(), value)) && |
847 extensions.length === 0) { | 843 extensions.length === 0) { |
848 if (%ArrayIndexOf(variants, value, 0) === -1) { | 844 if (%ArrayIndexOf(variants, value, 0) === -1) { |
849 %_Call(ArrayPush, variants, value); | 845 %_Call(ArrayPush, variants, value); |
850 } else { | 846 } else { |
851 return false; | 847 return false; |
852 } | 848 } |
853 } | 849 } |
854 | 850 |
855 if (!IS_NULL(InternalRegExpMatch(GetLanguageSingletonRE(), value))) { | 851 if (!IS_NULL(%regexp_internal_match(GetLanguageSingletonRE(), value))) { |
856 if (%ArrayIndexOf(extensions, value, 0) === -1) { | 852 if (%ArrayIndexOf(extensions, value, 0) === -1) { |
857 %_Call(ArrayPush, extensions, value); | 853 %_Call(ArrayPush, extensions, value); |
858 } else { | 854 } else { |
859 return false; | 855 return false; |
860 } | 856 } |
861 } | 857 } |
862 } | 858 } |
863 | 859 |
864 return true; | 860 return true; |
865 } | 861 } |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1114 | 1110 |
1115 AddBoundMethod(Intl.Collator, 'compare', compare, 2, 'collator'); | 1111 AddBoundMethod(Intl.Collator, 'compare', compare, 2, 'collator'); |
1116 | 1112 |
1117 /** | 1113 /** |
1118 * Verifies that the input is a well-formed ISO 4217 currency code. | 1114 * Verifies that the input is a well-formed ISO 4217 currency code. |
1119 * Don't uppercase to test. It could convert invalid code into a valid one. | 1115 * Don't uppercase to test. It could convert invalid code into a valid one. |
1120 * For example \u00DFP (Eszett+P) becomes SSP. | 1116 * For example \u00DFP (Eszett+P) becomes SSP. |
1121 */ | 1117 */ |
1122 function isWellFormedCurrencyCode(currency) { | 1118 function isWellFormedCurrencyCode(currency) { |
1123 return typeof currency == "string" && currency.length == 3 && | 1119 return typeof currency == "string" && currency.length == 3 && |
1124 IS_NULL(InternalRegExpMatch(/[^A-Za-z]/, currency)); | 1120 IS_NULL(%regexp_internal_match(/[^A-Za-z]/, currency)); |
1125 } | 1121 } |
1126 | 1122 |
1127 | 1123 |
1128 /** | 1124 /** |
1129 * Returns the valid digit count for a property, or throws RangeError on | 1125 * Returns the valid digit count for a property, or throws RangeError on |
1130 * a value out of the range. | 1126 * a value out of the range. |
1131 */ | 1127 */ |
1132 function getNumberOption(options, property, min, max, fallback) { | 1128 function getNumberOption(options, property, min, max, fallback) { |
1133 var value = options[property]; | 1129 var value = options[property]; |
1134 if (!IS_UNDEFINED(value)) { | 1130 if (!IS_UNDEFINED(value)) { |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1432 return ''; | 1428 return ''; |
1433 } | 1429 } |
1434 } | 1430 } |
1435 | 1431 |
1436 | 1432 |
1437 /** | 1433 /** |
1438 * Returns object that matches LDML representation of the date. | 1434 * Returns object that matches LDML representation of the date. |
1439 */ | 1435 */ |
1440 function fromLDMLString(ldmlString) { | 1436 function fromLDMLString(ldmlString) { |
1441 // First remove '' quoted text, so we lose 'Uhr' strings. | 1437 // First remove '' quoted text, so we lose 'Uhr' strings. |
1442 ldmlString = InternalRegExpReplace(GetQuotedStringRE(), ldmlString, ''); | 1438 ldmlString = %RegExpInternalReplace(GetQuotedStringRE(), ldmlString, ''); |
1443 | 1439 |
1444 var options = {}; | 1440 var options = {}; |
1445 var match = InternalRegExpMatch(/E{3,5}/, ldmlString); | 1441 var match = %regexp_internal_match(/E{3,5}/, ldmlString); |
1446 options = appendToDateTimeObject( | 1442 options = appendToDateTimeObject( |
1447 options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'}); | 1443 options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'}); |
1448 | 1444 |
1449 match = InternalRegExpMatch(/G{3,5}/, ldmlString); | 1445 match = %regexp_internal_match(/G{3,5}/, ldmlString); |
1450 options = appendToDateTimeObject( | 1446 options = appendToDateTimeObject( |
1451 options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'}); | 1447 options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'}); |
1452 | 1448 |
1453 match = InternalRegExpMatch(/y{1,2}/, ldmlString); | 1449 match = %regexp_internal_match(/y{1,2}/, ldmlString); |
1454 options = appendToDateTimeObject( | 1450 options = appendToDateTimeObject( |
1455 options, 'year', match, {y: 'numeric', yy: '2-digit'}); | 1451 options, 'year', match, {y: 'numeric', yy: '2-digit'}); |
1456 | 1452 |
1457 match = InternalRegExpMatch(/M{1,5}/, ldmlString); | 1453 match = %regexp_internal_match(/M{1,5}/, ldmlString); |
1458 options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit', | 1454 options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit', |
1459 M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'}); | 1455 M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'}); |
1460 | 1456 |
1461 // Sometimes we get L instead of M for month - standalone name. | 1457 // Sometimes we get L instead of M for month - standalone name. |
1462 match = InternalRegExpMatch(/L{1,5}/, ldmlString); | 1458 match = %regexp_internal_match(/L{1,5}/, ldmlString); |
1463 options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit', | 1459 options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit', |
1464 L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'}); | 1460 L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'}); |
1465 | 1461 |
1466 match = InternalRegExpMatch(/d{1,2}/, ldmlString); | 1462 match = %regexp_internal_match(/d{1,2}/, ldmlString); |
1467 options = appendToDateTimeObject( | 1463 options = appendToDateTimeObject( |
1468 options, 'day', match, {d: 'numeric', dd: '2-digit'}); | 1464 options, 'day', match, {d: 'numeric', dd: '2-digit'}); |
1469 | 1465 |
1470 match = InternalRegExpMatch(/h{1,2}/, ldmlString); | 1466 match = %regexp_internal_match(/h{1,2}/, ldmlString); |
1471 if (match !== null) { | 1467 if (match !== null) { |
1472 options['hour12'] = true; | 1468 options['hour12'] = true; |
1473 } | 1469 } |
1474 options = appendToDateTimeObject( | 1470 options = appendToDateTimeObject( |
1475 options, 'hour', match, {h: 'numeric', hh: '2-digit'}); | 1471 options, 'hour', match, {h: 'numeric', hh: '2-digit'}); |
1476 | 1472 |
1477 match = InternalRegExpMatch(/H{1,2}/, ldmlString); | 1473 match = %regexp_internal_match(/H{1,2}/, ldmlString); |
1478 if (match !== null) { | 1474 if (match !== null) { |
1479 options['hour12'] = false; | 1475 options['hour12'] = false; |
1480 } | 1476 } |
1481 options = appendToDateTimeObject( | 1477 options = appendToDateTimeObject( |
1482 options, 'hour', match, {H: 'numeric', HH: '2-digit'}); | 1478 options, 'hour', match, {H: 'numeric', HH: '2-digit'}); |
1483 | 1479 |
1484 match = InternalRegExpMatch(/m{1,2}/, ldmlString); | 1480 match = %regexp_internal_match(/m{1,2}/, ldmlString); |
1485 options = appendToDateTimeObject( | 1481 options = appendToDateTimeObject( |
1486 options, 'minute', match, {m: 'numeric', mm: '2-digit'}); | 1482 options, 'minute', match, {m: 'numeric', mm: '2-digit'}); |
1487 | 1483 |
1488 match = InternalRegExpMatch(/s{1,2}/, ldmlString); | 1484 match = %regexp_internal_match(/s{1,2}/, ldmlString); |
1489 options = appendToDateTimeObject( | 1485 options = appendToDateTimeObject( |
1490 options, 'second', match, {s: 'numeric', ss: '2-digit'}); | 1486 options, 'second', match, {s: 'numeric', ss: '2-digit'}); |
1491 | 1487 |
1492 match = InternalRegExpMatch(/z|zzzz/, ldmlString); | 1488 match = %regexp_internal_match(/z|zzzz/, ldmlString); |
1493 options = appendToDateTimeObject( | 1489 options = appendToDateTimeObject( |
1494 options, 'timeZoneName', match, {z: 'short', zzzz: 'long'}); | 1490 options, 'timeZoneName', match, {z: 'short', zzzz: 'long'}); |
1495 | 1491 |
1496 return options; | 1492 return options; |
1497 } | 1493 } |
1498 | 1494 |
1499 | 1495 |
1500 function appendToDateTimeObject(options, option, match, pairs) { | 1496 function appendToDateTimeObject(options, option, match, pairs) { |
1501 if (IS_NULL(match)) { | 1497 if (IS_NULL(match)) { |
1502 if (!HAS_OWN_PROPERTY(options, option)) { | 1498 if (!HAS_OWN_PROPERTY(options, option)) { |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1811 var upperID = %StringToUpperCase(tzID); | 1807 var upperID = %StringToUpperCase(tzID); |
1812 if (upperID === 'UTC' || upperID === 'GMT' || | 1808 if (upperID === 'UTC' || upperID === 'GMT' || |
1813 upperID === 'ETC/UTC' || upperID === 'ETC/GMT') { | 1809 upperID === 'ETC/UTC' || upperID === 'ETC/GMT') { |
1814 return 'UTC'; | 1810 return 'UTC'; |
1815 } | 1811 } |
1816 | 1812 |
1817 // TODO(jshin): Add support for Etc/GMT[+-]([1-9]|1[0-2]) | 1813 // TODO(jshin): Add support for Etc/GMT[+-]([1-9]|1[0-2]) |
1818 | 1814 |
1819 // We expect only _, '-' and / beside ASCII letters. | 1815 // We expect only _, '-' and / beside ASCII letters. |
1820 // All inputs should conform to Area/Location(/Location)* from now on. | 1816 // All inputs should conform to Area/Location(/Location)* from now on. |
1821 var match = InternalRegExpMatch(GetTimezoneNameCheckRE(), tzID); | 1817 var match = %regexp_internal_match(GetTimezoneNameCheckRE(), tzID); |
1822 if (IS_NULL(match)) throw %make_range_error(kExpectedTimezoneID, tzID); | 1818 if (IS_NULL(match)) throw %make_range_error(kExpectedTimezoneID, tzID); |
1823 | 1819 |
1824 var result = toTitleCaseTimezoneLocation(match[1]) + '/' + | 1820 var result = toTitleCaseTimezoneLocation(match[1]) + '/' + |
1825 toTitleCaseTimezoneLocation(match[2]); | 1821 toTitleCaseTimezoneLocation(match[2]); |
1826 | 1822 |
1827 if (!IS_UNDEFINED(match[3]) && 3 < match.length) { | 1823 if (!IS_UNDEFINED(match[3]) && 3 < match.length) { |
1828 var locations = %StringSplit(match[3], '/', kMaxUint32); | 1824 var locations = %StringSplit(match[3], '/', kMaxUint32); |
1829 // The 1st element is empty. Starts with i=1. | 1825 // The 1st element is empty. Starts with i=1. |
1830 for (var i = 1; i < locations.length; i++) { | 1826 for (var i = 1; i < locations.length; i++) { |
1831 result = result + '/' + toTitleCaseTimezoneLocation(locations[i]); | 1827 result = result + '/' + toTitleCaseTimezoneLocation(locations[i]); |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2269 } | 2265 } |
2270 ); | 2266 ); |
2271 | 2267 |
2272 %FunctionRemovePrototype(FormatDateToParts); | 2268 %FunctionRemovePrototype(FormatDateToParts); |
2273 | 2269 |
2274 utils.Export(function(to) { | 2270 utils.Export(function(to) { |
2275 to.FormatDateToParts = FormatDateToParts; | 2271 to.FormatDateToParts = FormatDateToParts; |
2276 }); | 2272 }); |
2277 | 2273 |
2278 }) | 2274 }) |
OLD | NEW |