@ui5/webcomponents-localization
Version:
Localization for UI5 Web Components
842 lines (813 loc) • 142 kB
JavaScript
/*!
* OpenUI5
* (c) Copyright 2009-2024 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
// Provides class sap.ui.core.format.DateFormat
import Log from "../../../base/Log.js";
import formatMessage from "../../../base/strings/formatMessage.js";
import deepEqual from "../../../base/util/deepEqual.js";
import extend from "../../../base/util/extend.js";
import CalendarType from "../CalendarType.js";
import Configuration from "../Configuration.js";
import Core from "../Core.js";
import Locale from "../Locale.js";
import LocaleData from "../LocaleData.js";
import Supportability from "../Supportability.js";
import CalendarUtils from "../date/CalendarUtils.js";
import CalendarWeekNumbering from "../date/CalendarWeekNumbering.js";
import UI5Date from "../date/UI5Date.js";
import UniversalDate from "../date/UniversalDate.js";
import TimezoneUtil from "./TimezoneUtil.js";
/**
* Constructor for DateFormat - must not be used:
* <ul>
* <li>To get a {@link sap.ui.core.format.DateFormat} instance, please use {@link sap.ui.core.format.DateFormat.getDateInstance}, {@link sap.ui.core.format.DateFormat.getDateTimeInstance} or {@link sap.ui.core.format.DateFormat.getTimeInstance}</li>
* <li>To get a {@link sap.ui.core.format.DateFormat.DateTimeWithTimezone} instance, please use {@link sap.ui.core.format.DateFormat.getDateTimeWithTimezoneInstance}</li>
* </ul>
*
* @class
* The DateFormat is a static class for formatting and parsing single date and time values or date and time intervals according
* to a set of format options.
*
* Important:
* Every Date is converted with the timezone taken from {@link sap.ui.core.Configuration#getTimezone}.
* The timezone falls back to the browser's local timezone.
*
* Supported format options are pattern based on Unicode LDML Date Format notation. Please note that only a subset of the LDML date symbols
* is supported.
* If no pattern is specified a default pattern according to the locale settings is used.
*
* Documentation links:
* <ul>
* <li>{@link topic:91f2eba36f4d1014b6dd926db0e91070 Date Format}</li>
* <li>{@link http://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table}</li>
* </ul>
*
* @public
* @hideconstructor
* @alias sap.ui.core.format.DateFormat
*/
var DateFormat = function () {
// Do not use the constructor
throw new Error();
};
/**
* Internal enumeration to differentiate DateFormat types
*/
var mDateFormatTypes = {
DATE: "date",
TIME: "time",
DATETIME: "datetime",
DATETIME_WITH_TIMEZONE: "datetimeWithTimezone"
};
// Cache for parsed CLDR DatePattern
var mCldrDatePattern = {};
/**
* Timezone parameter type check
*
* @param {string} sTimezone The timezone to check
* @throws {TypeError} Thrown if the parameter <code>sTimezone</code> is provided and has the wrong type.
*/
var checkTimezoneParameterType = function (sTimezone) {
if (typeof sTimezone !== "string" && !(sTimezone instanceof String) && sTimezone != null) {
throw new TypeError("The given timezone must be a string.");
}
};
DateFormat.oDateInfo = {
type: mDateFormatTypes.DATE,
oDefaultFormatOptions: {
style: "medium",
relativeScale: "day",
relativeStyle: "wide"
},
aFallbackFormatOptions: [{
style: "short"
}, {
style: "medium"
}, {
pattern: "yyyy-MM-dd"
}, {
pattern: "yyyyMMdd",
strictParsing: true
}],
bShortFallbackFormatOptions: true,
bPatternFallbackWithoutDelimiter: true,
getPattern: function (oLocaleData, sStyle, sCalendarType) {
return oLocaleData.getDatePattern(sStyle, sCalendarType);
},
oRequiredParts: {
"text": true,
"year": true,
"weekYear": true,
"month": true,
"day": true
},
aRelativeScales: ["year", "month", "week", "day"],
aRelativeParseScales: ["year", "quarter", "month", "week", "day", "hour", "minute", "second"],
aIntervalCompareFields: ["Era", "FullYear", "Quarter", "Month", "Week", "Date"]
};
DateFormat.oDateTimeInfo = {
type: mDateFormatTypes.DATETIME,
oDefaultFormatOptions: {
style: "medium",
relativeScale: "auto",
relativeStyle: "wide"
},
aFallbackFormatOptions: [{
style: "short"
}, {
style: "medium"
}, {
pattern: "yyyy-MM-dd'T'HH:mm:ss"
}, {
pattern: "yyyyMMdd HHmmss"
}],
getPattern: function (oLocaleData, sStyle, sCalendarType) {
// If style is mixed ("medium/short") split it and pass both parts separately
var iSlashIndex = sStyle.indexOf("/");
if (iSlashIndex > 0) {
return oLocaleData.getCombinedDateTimePattern(sStyle.substr(0, iSlashIndex), sStyle.substr(iSlashIndex + 1), sCalendarType);
} else {
return oLocaleData.getCombinedDateTimePattern(sStyle, sStyle, sCalendarType);
}
},
oRequiredParts: {
"text": true,
"year": true,
"weekYear": true,
"month": true,
"day": true,
"hour0_23": true,
"hour1_24": true,
"hour0_11": true,
"hour1_12": true
},
aRelativeScales: ["year", "month", "week", "day", "hour", "minute", "second"],
aRelativeParseScales: ["year", "quarter", "month", "week", "day", "hour", "minute", "second"],
aIntervalCompareFields: ["Era", "FullYear", "Quarter", "Month", "Week", "Date", "DayPeriod", "Hours", "Minutes", "Seconds"]
};
/**
* Retrieves info object for timezone instance
*
* @param {object} oFormatOptions the format options, relevant are: showDate, showTime and showTimezone
* @returns {object} info object
* @private
*/
DateFormat._getDateTimeWithTimezoneInfo = function (oFormatOptions) {
var bShowDate = oFormatOptions.showDate === undefined || oFormatOptions.showDate;
var bShowTime = oFormatOptions.showTime === undefined || oFormatOptions.showTime;
var bShowTimezone = oFormatOptions.showTimezone === undefined || oFormatOptions.showTimezone;
var oBaselineType = DateFormat.oDateTimeInfo;
if (bShowDate && !bShowTime) {
oBaselineType = DateFormat.oDateInfo;
} else if (!bShowDate && bShowTime) {
oBaselineType = DateFormat.oTimeInfo;
}
return Object.assign({}, oBaselineType, {
type: mDateFormatTypes.DATETIME_WITH_TIMEZONE,
// This function is used to transform the pattern of the fallbackFormatOptions to a timezone pattern.
getTimezonePattern: function (sPattern) {
if (!bShowDate && !bShowTime && bShowTimezone) {
return "VV";
} else if (!bShowTimezone) {
return sPattern;
} else {
return sPattern + " VV";
}
},
getPattern: function (oLocaleData, sStyle, sCalendarType) {
if (!bShowDate && !bShowTime && bShowTimezone) {
return "VV";
}
if (!bShowTimezone) {
return oBaselineType.getPattern(oLocaleData, sStyle, sCalendarType);
}
var sPattern = oBaselineType.getPattern(oLocaleData, sStyle, sCalendarType);
return oLocaleData.applyTimezonePattern(sPattern);
}
});
};
DateFormat.oTimeInfo = {
type: mDateFormatTypes.TIME,
oDefaultFormatOptions: {
style: "medium",
relativeScale: "auto",
relativeStyle: "wide"
},
aFallbackFormatOptions: [{
style: "short"
}, {
style: "medium"
}, {
pattern: "HH:mm:ss"
}, {
pattern: "HHmmss"
}],
getPattern: function (oLocaleData, sStyle, sCalendarType) {
return oLocaleData.getTimePattern(sStyle, sCalendarType);
},
oRequiredParts: {
"text": true,
"hour0_23": true,
"hour1_24": true,
"hour0_11": true,
"hour1_12": true
},
aRelativeScales: ["hour", "minute", "second"],
aRelativeParseScales: ["year", "quarter", "month", "week", "day", "hour", "minute", "second"],
aIntervalCompareFields: ["DayPeriod", "Hours", "Minutes", "Seconds"]
};
/**
* @see sap.ui.core.format.DateFormat.getDateInstance
*/
DateFormat.getInstance = function (oFormatOptions, oLocale) {
return this.getDateInstance(oFormatOptions, oLocale);
};
/**
* Get a date instance of the DateFormat, which can be used for formatting.
*
* @param {object} [oFormatOptions] Object which defines the format options
* @param {sap.ui.core.date.CalendarWeekNumbering} [oFormatOptions.calendarWeekNumbering] since 1.108.0 specifies the calendar week numbering.
* If specified, this overwrites <code>oFormatOptions.firstDayOfWeek</code> and <code>oFormatOptions.minimalDaysInFirstWeek</code>.
* @param {int} [oFormatOptions.firstDayOfWeek] since 1.105.0 specifies the first day of the week starting with <code>0</code> (which is Sunday); if not defined, the value taken from the locale is used
* @param {int} [oFormatOptions.minimalDaysInFirstWeek] since 1.105.0 minimal days at the beginning of the year which define the first calendar week; if not defined, the value taken from the locale is used
* @param {string} [oFormatOptions.format] since 1.34.0 contains pattern symbols (e.g. "yMMMd" or "Hms") which will be converted into the pattern in the used locale, which matches the wanted symbols best.
* The symbols must be in canonical order, that is: Era (G), Year (y/Y), Quarter (q/Q), Month (M/L), Week (w), Day-Of-Week (E/e/c), Day (d), Hour (h/H/k/K/j/J), Minute (m), Second (s), Timezone (z/Z/v/V/O/X/x)
* See {@link http://unicode.org/reports/tr35/tr35-dates.html#availableFormats_appendItems}
* @param {string} [oFormatOptions.pattern] a data pattern in LDML format. It is not verified whether the pattern represents only a date.
* @param {string} [oFormatOptions.style] can be either 'short, 'medium', 'long' or 'full'. If no pattern is given, a locale dependent default date pattern of that style is used from the LocaleData class.
* @param {boolean} [oFormatOptions.strictParsing] if true, by parsing it is checked if the value is a valid date
* @param {boolean} [oFormatOptions.relative] if true, the date is formatted relatively to todays date if it is within the given day range, e.g. "today", "1 day ago", "in 5 days"
* @param {int[]} [oFormatOptions.relativeRange] the day range used for relative formatting. If <code>oFormatOptions.relativeScale</code> is set to default value 'day', the relativeRange is by default [-6, 6], which means only the last 6 days, today and the next 6 days are formatted relatively. Otherwise when <code>oFormatOptions.relativeScale</code> is set to 'auto', all dates are formatted relatively.
* @param {string} [oFormatOptions.relativeScale="day"] if 'auto' is set, new relative time format is switched on for all Date/Time Instances. The relative scale is chosen depending on the difference between the given date and now.
* @param {string} [oFormatOptions.relativeStyle="wide"] since 1.32.10, 1.34.4 the style of the relative format. The valid values are "wide", "short", "narrow"
* @param {boolean} [oFormatOptions.interval=false] since 1.48.0 if true, the {@link sap.ui.core.format.DateFormat#format format} method expects an array with two dates as the first argument and formats them as interval. Further interval "Jan 10, 2008 - Jan 12, 2008" will be formatted as "Jan 10-12, 2008" if the 'format' option is set with necessary symbols.
* Otherwise the two given dates are formatted separately and concatenated with local dependent pattern.
* @param {string} [oFormatOptions.intervalDelimiter]
* Since 1.113.0, a delimiter for intervals. With a given interval delimiter a specific interval format is
* created. <b>Example:</b> If <code>oFormatOptions.intervalDelimiter</code> is set to "...", an interval would be
* given as "Jan 10, 2008...Feb 12, 2008".
* <b>Note:</b> If this format option is set, the locale-specific interval notation is overruled, for example
* "Jan 10 – Feb 12, 2008" becomes "Jan 10, 2008...Feb 12, 2008".
* @param {boolean} [oFormatOptions.singleIntervalValue=false] Only relevant if oFormatOptions.interval is set to 'true'. This allows to pass an array with only one date object to the {@link sap.ui.core.format.DateFormat#format format} method.
* @param {boolean} [oFormatOptions.UTC] if true, the date is formatted and parsed as UTC instead of the local timezone
* @param {sap.ui.core.CalendarType} [oFormatOptions.calendarType] The calender type which is used to format and parse the date. This value is by default either set in configuration or calculated based on current locale.
* @param {sap.ui.core.Locale} [oLocale] Locale to ask for locale specific texts/settings
* @ui5-omissible-params oFormatOptions
* @return {sap.ui.core.format.DateFormat} date instance of the DateFormat
* @static
* @public
* @throws {TypeError} If:
* <ul>
* <li>The <code>calendarWeekNumbering</code> format option has an unsupported value, or</li>
* <li>only one of the <code>firstDayOfWeek</code> and <code>minimalDaysInFirstWeek</code> parameters was provided.</li>
* </ul>
*/
DateFormat.getDateInstance = function (oFormatOptions, oLocale) {
return this.createInstance(oFormatOptions, oLocale, this.oDateInfo);
};
/**
* Get a datetime instance of the DateFormat, which can be used for formatting.
*
* @param {object} [oFormatOptions] Object which defines the format options
* @param {sap.ui.core.date.CalendarWeekNumbering} [oFormatOptions.calendarWeekNumbering] since 1.108.0 specifies the calendar week numbering.
* If specified, this overwrites <code>oFormatOptions.firstDayOfWeek</code> and <code>oFormatOptions.minimalDaysInFirstWeek</code>.
* @param {int} [oFormatOptions.firstDayOfWeek] since 1.105.0 specifies the first day of the week starting with <code>0</code> (which is Sunday); if not defined, the value taken from the locale is used
* @param {int} [oFormatOptions.minimalDaysInFirstWeek] since 1.105.0 minimal days at the beginning of the year which define the first calendar week; if not defined, the value taken from the locale is used
* @param {string} [oFormatOptions.format] since 1.34.0 contains pattern symbols (e.g. "yMMMd" or "Hms") which will be converted into the pattern in the used locale, which matches the wanted symbols best.
* The symbols must be in canonical order, that is: Era (G), Year (y/Y), Quarter (q/Q), Month (M/L), Week (w), Day-Of-Week (E/e/c), Day (d), Hour (h/H/k/K/j/J), Minute (m), Second (s), Timezone (z/Z/v/V/O/X/x)
* See http://unicode.org/reports/tr35/tr35-dates.html#availableFormats_appendItems
* @param {string} [oFormatOptions.pattern] a datetime pattern in LDML format. It is not verified whether the pattern represents a full datetime.
* @param {string} [oFormatOptions.style] can be either 'short, 'medium', 'long' or 'full'. For datetime you can also define mixed styles, separated with a slash, where the first part is the date style and the second part is the time style (e.g. "medium/short"). If no pattern is given, a locale dependent default datetime pattern of that style is used from the LocaleData class.
* @param {boolean} [oFormatOptions.strictParsing] if true, by parsing it is checked if the value is a valid datetime
* @param {boolean} [oFormatOptions.relative] if true, the date is formatted relatively to today's date if it is within the given day range, e.g. "today", "1 day ago", "in 5 days"
* @param {int[]} [oFormatOptions.relativeRange] the day range used for relative formatting. If <code>oFormatOptions.relativeScale</code> is set to default value 'day', the relativeRange is by default [-6, 6], which means only the last 6 days, today and the next 6 days are formatted relatively. Otherwise when <code>oFormatOptions.relativeScale</code> is set to 'auto', all dates are formatted relatively.
* @param {string} [oFormatOptions.relativeScale="day"] if 'auto' is set, new relative time format is switched on for all Date/Time Instances. The relative scale is chosen depending on the difference between the given date and now.
* @param {string} [oFormatOptions.relativeStyle="wide"] since 1.32.10, 1.34.4 the style of the relative format. The valid values are "wide", "short", "narrow"
* @param {boolean} [oFormatOptions.interval=false] since 1.48.0 if true, the {@link sap.ui.core.format.DateFormat#format format} method expects an array with two dates as the first argument and formats them as interval. Further interval "Jan 10, 2008 - Jan 12, 2008" will be formatted as "Jan 10-12, 2008" if the 'format' option is set with necessary symbols.
* Otherwise the two given dates are formatted separately and concatenated with local dependent pattern.
* @param {string} [oFormatOptions.intervalDelimiter]
* Since 1.113.0, a delimiter for intervals. With a given interval delimiter a specific interval format is
* created. <b>Example:</b> If <code>oFormatOptions.intervalDelimiter</code> is set to "...", an interval would be
* given as "Jan 10, 2008, 9:15:00 AM...Jan 10, 2008, 11:45:00 AM".
* <b>Note:</b> If this format option is set, the locale-specific interval notation is overruled, for example
* "Jan 10, 2008, 9:15 – 11:45 AM" becomes "Jan 10, 2008, 9:15 AM...Jan 10, 2008, 11:45 AM".
* @param {boolean} [oFormatOptions.singleIntervalValue=false] Only relevant if oFormatOptions.interval is set to 'true'. This allows to pass an array with only one date object to the {@link sap.ui.core.format.DateFormat#format format} method.
* @param {boolean} [oFormatOptions.UTC] if true, the date is formatted and parsed as UTC instead of the local timezone
* @param {sap.ui.core.CalendarType} [oFormatOptions.calendarType] The calender type which is used to format and parse the date. This value is by default either set in configuration or calculated based on current locale.
* @param {sap.ui.core.Locale} [oLocale] Locale to ask for locale specific texts/settings
* @ui5-omissible-params oFormatOptions
* @return {sap.ui.core.format.DateFormat} datetime instance of the DateFormat
* @static
* @public
* @throws {TypeError} If:
* <ul>
* <li>The <code>calendarWeekNumbering</code> format option has an unsupported value, or</li>
* <li>only one of the <code>firstDayOfWeek</code> and <code>minimalDaysInFirstWeek</code> parameters was provided.</li>
* </ul>
*/
DateFormat.getDateTimeInstance = function (oFormatOptions, oLocale) {
return this.createInstance(oFormatOptions, oLocale, this.oDateTimeInfo);
};
/**
* Interface for a timezone-specific DateFormat, which is able to format and parse a date
* based on a given timezone. The timezone is used to convert the given date, and also for
* timezone-related pattern symbols. The timezone is an IANA timezone ID, e.g. "America/New_York".
*
* @see sap.ui.core.format.DateFormat
*
* @author SAP SE
* @since 1.99
* @interface
* @name sap.ui.core.format.DateFormat.DateTimeWithTimezone
* @public
*/
/**
* Format a date object to a string according to the given timezone and format options.
*
* @example <caption>Format option showTimezone: true (default)</caption>
* var oDate = UI5Date.getInstance("2021-12-24T13:37:00Z");
*
* DateFormat.getDateTimeWithTimezoneInstance().format(oDate, "Europe/Berlin");
* // output: "Dec 24, 2021, 2:37:00 PM Europe, Berlin"
*
* DateFormat.getDateTimeWithTimezoneInstance().format(oDate, "America/New_York");
* // output: "Dec 24, 2021, 8:37:00 AM Americas, New York"
*
* @example <caption>Format option showTimezone: false</caption>
* var oDate = UI5Date.getInstance("2021-12-24T13:37:00Z");
* DateFormat.getDateTimeWithTimezoneInstance({showTimezone: false}).format(oDate, "America/New_York");
* // output: "Dec 24, 2021, 8:37:00 AM"
*
* @example <caption>Format option showDate: false and showTime:false</caption>
* var oDate = UI5Date.getInstance("2021-12-24T13:37:00Z");
* DateFormat.getDateTimeWithTimezoneInstance({showDate: false, showTime: false}).format(oDate, "America/New_York");
* // output: "Americas, New York"
*
* @param {Date} oJSDate The date to format
* @param {string} [sTimezone] The IANA timezone ID in which the date will be calculated and
* formatted e.g. "America/New_York". If the parameter is omitted, <code>null</code> or an empty string, the timezone
* will be taken from {@link sap.ui.core.Configuration#getTimezone}. For an invalid IANA timezone ID, an empty string will be returned.
* @throws {TypeError} Thrown if the parameter <code>sTimezone</code> is provided and has the wrong type.
* @return {string} the formatted output value. If an invalid date or timezone is given, an empty string is returned.
* @name sap.ui.core.format.DateFormat.DateTimeWithTimezone.format
* @function
* @public
* @since 1.99
*/
/**
* Parse a string which is formatted according to the given format options to an array
* containing a date object and the timezone.
*
* @example <caption>Format option showTimezone: true (default)</caption>
* var oDate = UI5Date.getInstance("2021-12-24T13:37:00Z");
*
* DateFormat.getDateTimeWithTimezoneInstance().parse("Dec 24, 2021, 2:37:00 PM Europe, Berlin", "Europe/Berlin");
* // output: [oDate, "Europe/Berlin"]
*
* DateFormat.getDateTimeWithTimezoneInstance().parse("Dec 24, 2021, 8:37:00 AM Americas, New York", "America/New_York");
* // output: [oDate, "America/New_York"]
*
* @example <caption>Format option showTimezone: false</caption>
* var oDate = UI5Date.getInstance("2021-12-24T13:37:00Z");
* DateFormat.getDateTimeWithTimezoneInstance({showTimezone: false}).parse("Dec 24, 2021, 8:37:00 AM", "America/New_York");
* // output: [oDate, undefined]
*
* @example <caption>Format option showDate: false and showTime: false</caption>
* DateFormat.getDateTimeWithTimezoneInstance({showDate: false, showTime: false}).parse("Americas, New York", "America/New_York");
* // output: [undefined, "America/New_York"]
*
* @param {string} sValue the string containing a formatted date/time value
* @param {string} [sTimezone] The IANA timezone ID which should be used to convert the date
* e.g. "America/New_York". If the parameter is omitted, <code>null</code> or an empty string, the timezone will be taken
* from {@link sap.ui.core.Configuration#getTimezone}. For an invalid IANA timezone ID, <code>null</code> will be returned.
* @param {boolean} [bStrict] Whether to be strict with regards to the value ranges of date fields,
* e.g. for a month pattern of <code>MM</code> and a value range of [1-12]
* <code>strict</code> ensures that the value is within the range;
* if it is larger than <code>12</code> it cannot be parsed and <code>null</code> is returned
* @throws {TypeError} Thrown if one of the following applies:
* <ul>
* <li>the <code>sTimezone</code> parameter is provided and has the wrong type</li>
* <li>only the time is shown (<code>showDate</code> is <code>false</code>), or only the
* date is shown (<code>showTime</code> is <code>false</code>)</li>
* </ul>
* @return {Array} the parsed values
* <ul>
* <li>An array containing datetime and timezone depending on the showDate, showTime and showTimezone options
* <ul>
* <li>(Default): [Date, string], e.g.
* [UI5Date.getInstance("2021-11-13T13:22:33Z"), "America/New_York"]</li>
* <li><code>showTimezone: false</code>: [Date, undefined], e.g.
* [UI5Date.getInstance("2021-11-13T13:22:33Z"), undefined]</li>
* <li><code>showDate: false, showTime: false</code>: [undefined, string], e.g.
* [undefined, "America/New_York"]</li>
* </ul>
* </li>
* </ul>
*
* @public
* @name sap.ui.core.format.DateFormat.DateTimeWithTimezone.parse
* @function
* @since 1.99
*/
// This method has a TypeScript specific overlay for a better return value documentation,
// see 'src/sap.ui.core/.dtsgenrc'
/**
* Get a datetimeWithTimezone instance of the DateFormat, which can be used for formatting.
*
* @param {object} [oFormatOptions] An object which defines the format options
* @param {sap.ui.core.date.CalendarWeekNumbering} [oFormatOptions.calendarWeekNumbering] since 1.108.0 specifies the calendar week numbering.
* If specified, this overwrites <code>oFormatOptions.firstDayOfWeek</code> and <code>oFormatOptions.minimalDaysInFirstWeek</code>.
* @param {int} [oFormatOptions.firstDayOfWeek] since 1.105.0 specifies the first day of the week starting with <code>0</code> (which is Sunday); if not defined, the value taken from the locale is used
* @param {int} [oFormatOptions.minimalDaysInFirstWeek] since 1.105.0 minimal days at the beginning of the year which define the first calendar week; if not defined, the value taken from the locale is used
* @param {string} [oFormatOptions.format] A string containing pattern symbols (e.g. "yMMMd" or "Hms") which will be converted into a pattern for the used locale that matches the wanted symbols best.
* The symbols must be in canonical order, that is: Era (G), Year (y/Y), Quarter (q/Q), Month (M/L), Week (w), Day-Of-Week (E/e/c), Day (d), Hour (h/H/k/K/j/J), Minute (m), Second (s), Timezone (z/Z/v/V/O/X/x)
* See http://unicode.org/reports/tr35/tr35-dates.html#availableFormats_appendItems
* @param {string} [oFormatOptions.pattern] a datetime pattern in LDML format. It is not verified whether the pattern represents a full datetime.
* @param {boolean} [oFormatOptions.showDate=true] Specifies if the date should be displayed.
* It is ignored for formatting when an options pattern or a format are supplied.
* @param {boolean} [oFormatOptions.showTime=true] Specifies if the time should be displayed.
* It is ignored for formatting when an options pattern or a format are supplied.
* @param {boolean} [oFormatOptions.showTimezone=true] Specifies if the timezone should be displayed.
* It is ignored for formatting when an options pattern or a format are supplied.
* @param {string} [oFormatOptions.style] Can be either 'short, 'medium', 'long' or 'full'. For datetime you can also define mixed styles, separated with a slash, where the first part is the date style and the second part is the time style (e.g. "medium/short"). If no pattern is given, a locale-dependent default datetime pattern of that style from the LocaleData class is used.
* @param {boolean} [oFormatOptions.strictParsing] Whether to check by parsing if the value is a valid datetime
* @param {boolean} [oFormatOptions.relative] Whether the date is formatted relatively to today's date if it is within the given day range, e.g. "today", "1 day ago", "in 5 days"
* @param {int[]} [oFormatOptions.relativeRange] The day range used for relative formatting. If <code>oFormatOptions.relativeScale</code> is set to the default value 'day', the <code>relativeRange<code> is by default [-6, 6], which means that only the previous 6 and the following 6 days are formatted relatively. If <code>oFormatOptions.relativeScale</code> is set to 'auto', all dates are formatted relatively.
* @param {string} [oFormatOptions.relativeScale] If 'auto' is set, a new relative time format is switched on for all Date/Time instances. The default value depends on <code>showDate</code> and <code>showTime</code> options.
* @param {string} [oFormatOptions.relativeStyle="wide"] The style of the relative format. The valid values are "wide", "short", "narrow"
* @param {sap.ui.core.CalendarType} [oFormatOptions.calendarType] The calendar type which is used to format and parse the date. This value is by default either set in the configuration or calculated based on the current locale.
* @param {sap.ui.core.Locale} [oLocale] Locale to ask for locale-specific texts/settings
* @ui5-omissible-params oFormatOptions
* @throws {TypeError} If an invalid configuration was supplied, i.e. when the
* <code>showDate</code>, <code>showTime</code>, and <code>showTimezone</code> format options
* are all <code>false</code>
* @return {sap.ui.core.format.DateFormat.DateTimeWithTimezone} dateTimeWithTimezone instance of the DateFormat
* @static
* @public
* @since 1.99.0
* @throws {TypeError} If:
* <ul>
* <li>The <code>calendarWeekNumbering</code> format option has an unsupported value, or</li>
* <li>only one of the <code>firstDayOfWeek</code> and <code>minimalDaysInFirstWeek</code> parameters was provided.</li>
* </ul>
*/
DateFormat.getDateTimeWithTimezoneInstance = function (oFormatOptions, oLocale) {
if (oFormatOptions && !(oFormatOptions instanceof Locale)) {
/** @deprecated As of version 1.101.0 */
(function () {
// do not modify the input format options
oFormatOptions = Object.assign({}, oFormatOptions);
// translate old showTimezone values (backward compatibility)
if (typeof oFormatOptions.showTimezone === "string") {
var sShowTimezone = oFormatOptions.showTimezone;
if (oFormatOptions.showDate === undefined && oFormatOptions.showTime === undefined) {
if (sShowTimezone === "Hide") {
oFormatOptions.showTimezone = false;
} else if (sShowTimezone === "Only") {
oFormatOptions.showDate = false;
oFormatOptions.showTime = false;
}
}
oFormatOptions.showTimezone = sShowTimezone !== "Hide";
}
})();
if (oFormatOptions.showDate === false && oFormatOptions.showTime === false && oFormatOptions.showTimezone === false) {
throw new TypeError("Invalid Configuration. One of the following format options must be true: " + "showDate, showTime or showTimezone.");
}
}
return this.createInstance(oFormatOptions, oLocale, DateFormat._getDateTimeWithTimezoneInfo(oFormatOptions || {}));
};
/**
* Get a time instance of the DateFormat, which can be used for formatting.
*
* @param {object} [oFormatOptions] Object which defines the format options
* @param {sap.ui.core.date.CalendarWeekNumbering} [oFormatOptions.calendarWeekNumbering] since 1.108.0 specifies the calendar week numbering.
* If specified, this overwrites <code>oFormatOptions.firstDayOfWeek</code> and <code>oFormatOptions.minimalDaysInFirstWeek</code>.
* @param {int} [oFormatOptions.firstDayOfWeek] since 1.105.0 specifies the first day of the week starting with <code>0</code> (which is Sunday); if not defined, the value taken from the locale is used
* @param {int} [oFormatOptions.minimalDaysInFirstWeek] since 1.105.0 minimal days at the beginning of the year which define the first calendar week; if not defined, the value taken from the locale is used
* @param {string} [oFormatOptions.format] since 1.34.0 contains pattern symbols (e.g. "yMMMd" or "Hms") which will be converted into the pattern in the used locale, which matches the wanted symbols best.
* The symbols must be in canonical order, that is: Era (G), Year (y/Y), Quarter (q/Q), Month (M/L), Week (w), Day-Of-Week (E/e/c), Day (d), Hour (h/H/k/K/j/J), Minute (m), Second (s), Timezone (z/Z/v/V/O/X/x)
* See http://unicode.org/reports/tr35/tr35-dates.html#availableFormats_appendItems
* @param {string} [oFormatOptions.pattern] a time pattern in LDML format. It is not verified whether the pattern only represents a time.
* @param {string} [oFormatOptions.style] can be either 'short, 'medium', 'long' or 'full'. If no pattern is given, a locale dependent default time pattern of that style is used from the LocaleData class.
* @param {boolean} [oFormatOptions.strictParsing] if true, by parsing it is checked if the value is a valid time
* @param {boolean} [oFormatOptions.relative] if true, the date is formatted relatively to todays date if it is within the given day range, e.g. "today", "1 day ago", "in 5 days"
* @param {int[]} [oFormatOptions.relativeRange] the day range used for relative formatting. If <code>oFormatOptions.relativeScale</code> is set to default value 'day', the relativeRange is by default [-6, 6], which means only the last 6 days, today and the next 6 days are formatted relatively. Otherwise when <code>oFormatOptions.relativeScale</code> is set to 'auto', all dates are formatted relatively.
* @param {string} [oFormatOptions.relativeScale="day"] if 'auto' is set, new relative time format is switched on for all Date/Time Instances. The relative scale is chosen depending on the difference between the given date and now.
* @param {string} [oFormatOptions.relativeStyle="wide"] since 1.32.10, 1.34.4 the style of the relative format. The valid values are "wide", "short", "narrow"
* @param {boolean} [oFormatOptions.interval=false] since 1.48.0 if true, the {@link sap.ui.core.format.DateFormat#format format} method expects an array with two dates as the first argument and formats them as interval. Further interval "Jan 10, 2008 - Jan 12, 2008" will be formatted as "Jan 10-12, 2008" if the 'format' option is set with necessary symbols.
* Otherwise the two given dates are formatted separately and concatenated with local dependent pattern.
* @param {string} [oFormatOptions.intervalDelimiter]
* Since 1.113.0, a delimiter for intervals. With a given interval delimiter a specific interval format is
* created. <b>Example:</b> If <code>oFormatOptions.intervalDelimiter</code> is set to "...", an interval would be
* given as "09:15 AM...11:45 AM".
* <b>Note:</b> If this format option is set, the locale-specific interval notation is overruled, for example
* "09:15 – 11:45 AM" becomes "9:15 AM...11:45 AM".
* @param {boolean} [oFormatOptions.singleIntervalValue=false] Only relevant if oFormatOptions.interval is set to 'true'. This allows to pass an array with only one date object to the {@link sap.ui.core.format.DateFormat#format format} method.
* @param {boolean} [oFormatOptions.UTC] if true, the time is formatted and parsed as UTC instead of the local timezone
* @param {sap.ui.core.CalendarType} [oFormatOptions.calendarType] The calender type which is used to format and parse the date. This value is by default either set in configuration or calculated based on current locale.
* @param {sap.ui.core.Locale} [oLocale] Locale to ask for locale specific texts/settings
* @ui5-omissible-params oFormatOptions
* @return {sap.ui.core.format.DateFormat} time instance of the DateFormat
* @static
* @public
* @throws {TypeError} If:
* <ul>
* <li>The <code>calendarWeekNumbering</code> format option has an unsupported value, or</li>
* <li>only one of the <code>firstDayOfWeek</code> and <code>minimalDaysInFirstWeek</code> parameters was provided.</li>
* </ul>
*/
DateFormat.getTimeInstance = function (oFormatOptions, oLocale) {
return this.createInstance(oFormatOptions, oLocale, this.oTimeInfo);
};
/**
* Create instance of the DateFormat.
*
* @param {object} [oFormatOptions] Object which defines the format options
* @param {sap.ui.core.Locale} [oLocale] Locale to ask for locale specific texts/settings
* @param {object} [oInfo] Info information common to all instances of the created "type",
* e.g. default format options
* @param {boolean} [bIsFallback=false] Whether this is a fallback format instance
* @return {sap.ui.core.format.DateFormat} time instance of the DateFormat
* @static
* @private
* @throws {TypeError} If:
* <ul>
* <li>The <code>calendarWeekNumbering</code> format option has an unsupported value, or</li>
* <li>only one of the <code>firstDayOfWeek</code> and <code>minimalDaysInFirstWeek</code> parameters was provided.</li>
* </ul>
*/
DateFormat.createInstance = function (oFormatOptions, oLocale, oInfo, bIsFallback) {
var aFallbackFormatOptions, oFormat, sPattern;
// Create an instance of the DateFormat
oFormat = Object.create(this.prototype);
// Handle optional parameters
if (oFormatOptions instanceof Locale) {
oLocale = oFormatOptions;
oFormatOptions = undefined;
}
// Get Locale and LocaleData to use
if (!oLocale) {
oLocale = Configuration.getFormatSettings().getFormatLocale();
}
oFormat.oLocale = oLocale;
oFormat.oLocaleData = LocaleData.getInstance(oLocale);
// Extend the default format options with custom format options and retrieve the pattern
// from the LocaleData, in case it is not defined yet
oFormat.oFormatOptions = extend({}, oInfo.oDefaultFormatOptions, oFormatOptions);
// set unsupported properties to false/undefined
if (oInfo.type === mDateFormatTypes.DATETIME_WITH_TIMEZONE) {
oFormat.oFormatOptions.interval = false;
oFormat.oFormatOptions.singleIntervalValue = false;
oFormat.oFormatOptions.UTC = false;
} else {
oFormat.oFormatOptions.showTimezone = undefined;
oFormat.oFormatOptions.showDate = undefined;
oFormat.oFormatOptions.showTime = undefined;
}
// type cannot be changed and should be an instance property instead of a format option
oFormat.type = oInfo.type;
if (!oFormat.oFormatOptions.calendarType) {
oFormat.oFormatOptions.calendarType = Configuration.getCalendarType();
}
if (oFormat.oFormatOptions.firstDayOfWeek === undefined && oFormat.oFormatOptions.minimalDaysInFirstWeek !== undefined || oFormat.oFormatOptions.firstDayOfWeek !== undefined && oFormat.oFormatOptions.minimalDaysInFirstWeek === undefined) {
throw new TypeError("Format options firstDayOfWeek and minimalDaysInFirstWeek need both to be set, but only one was provided.");
}
if (oFormat.oFormatOptions.calendarWeekNumbering && !Object.values(CalendarWeekNumbering).includes(oFormat.oFormatOptions.calendarWeekNumbering)) {
throw new TypeError("Illegal format option calendarWeekNumbering: '" + oFormat.oFormatOptions.calendarWeekNumbering + "'");
}
if (!oFormat.oFormatOptions.pattern) {
if (oFormat.oFormatOptions.format) {
oFormat.oFormatOptions.pattern = oFormat.oLocaleData.getCustomDateTimePattern(oFormat.oFormatOptions.format, oFormat.oFormatOptions.calendarType);
} else {
oFormat.oFormatOptions.pattern = oInfo.getPattern(oFormat.oLocaleData, oFormat.oFormatOptions.style, oFormat.oFormatOptions.calendarType);
}
}
if (oFormat.oFormatOptions.interval) {
var sSinglePattern,
sDelimiter = oFormat.oFormatOptions.intervalDelimiter;
if (oFormat.oFormatOptions.format) {
// when 'format' option is set, generate the pattern based on the greatest difference
oFormat.intervalPatterns = oFormat.oLocaleData.getCustomIntervalPattern(oFormat.oFormatOptions.format, null /*=no diff*/, oFormat.oFormatOptions.calendarType);
// In case oFormat.intervalPatterns is a string, put the single string into array
if (typeof oFormat.intervalPatterns === "string") {
oFormat.intervalPatterns = [oFormat.intervalPatterns];
}
sSinglePattern = oFormat.oLocaleData.getCustomDateTimePattern(oFormat.oFormatOptions.format, oFormat.oFormatOptions.calendarType);
// Put the single date pattern, which is generated based on the oFormatOptions.format, into the array in
// case the date interval is formatted as a single date
oFormat.intervalPatterns.push(sSinglePattern);
} else {
sSinglePattern = oFormat.oFormatOptions.pattern;
oFormat.intervalPatterns = [
// when 'format' option is not set, generate the combined interval pattern
oFormat.oLocaleData.getCombinedIntervalPattern(oFormat.oFormatOptions.pattern, oFormat.oFormatOptions.calendarType),
// Put the single date pattern into the array in case the date interval is formatted as a single date
oFormat.oFormatOptions.pattern];
}
oFormat.intervalPatterns.push(oFormat.oFormatOptions.pattern + " - " + oFormat.oFormatOptions.pattern);
if (sDelimiter) {
// use delimiter pattern as first choice
sDelimiter = sDelimiter.replace(/'/g, "''");
sDelimiter = "'" + sDelimiter + "'";
oFormat.intervalPatterns.unshift(sSinglePattern + sDelimiter + sSinglePattern);
}
oFormat.intervalPatterns = Array.from(new Set(oFormat.intervalPatterns));
}
// if the current format isn't a fallback format, create its fallback formats
if (!bIsFallback) {
aFallbackFormatOptions = oInfo.aFallbackFormatOptions;
// Add two fallback patterns for locale-dependent short format without delimiters
if (oInfo.bShortFallbackFormatOptions) {
sPattern = oInfo.getPattern(oFormat.oLocaleData, "short");
// add the options of fallback formats without delimiters to the fallback options array
aFallbackFormatOptions = aFallbackFormatOptions.concat(DateFormat._createFallbackOptionsWithoutDelimiter(sPattern));
}
if (oFormat.oFormatOptions.pattern && oInfo.bPatternFallbackWithoutDelimiter) {
// create options of fallback formats by removing delimiters from the given pattern
// insert the new fallback format options to the front of the array
aFallbackFormatOptions = DateFormat._createFallbackOptionsWithoutDelimiter(oFormat.oFormatOptions.pattern).concat(aFallbackFormatOptions);
}
// remove duplicate format options (e.g. fallback format with same pattern is not needed twice)
aFallbackFormatOptions = aFallbackFormatOptions.reduce(function (aFallbacks, oOptions) {
var aKeys = Object.keys(oOptions),
bDuplicate = aFallbacks.some(function (oOptions0) {
return Object.keys(oOptions0).length === aKeys.length && aKeys.every(function (sKey) {
return oOptions0[sKey] === oOptions[sKey];
});
});
if (!bDuplicate) {
aFallbacks.push(oOptions);
}
return aFallbacks;
}, []);
oFormat.aFallbackFormats = DateFormat._createFallbackFormat(aFallbackFormatOptions, oFormat.oFormatOptions.calendarType, oLocale, oInfo, oFormat.oFormatOptions);
}
oFormat.oRequiredParts = oInfo.oRequiredParts;
oFormat.aRelativeScales = oInfo.aRelativeScales;
oFormat.aRelativeParseScales = oInfo.aRelativeParseScales;
oFormat.aIntervalCompareFields = oInfo.aIntervalCompareFields;
oFormat.init();
return oFormat;
};
/**
* Initialize date format
*/
DateFormat.prototype.init = function () {
var sCalendarType = this.oFormatOptions.calendarType;
this.aMonthsAbbrev = this.oLocaleData._getMonthsWithAlternatives("abbreviated", sCalendarType);
this.aMonthsWide = this.oLocaleData.getMonths("wide", sCalendarType);
this.aMonthsNarrow = this.oLocaleData.getMonths("narrow", sCalendarType);
this.aMonthsAbbrevSt = this.oLocaleData._getMonthsStandAloneWithAlternatives("abbreviated", sCalendarType);
this.aMonthsWideSt = this.oLocaleData.getMonthsStandAlone("wide", sCalendarType);
this.aMonthsNarrowSt = this.oLocaleData.getMonthsStandAlone("narrow", sCalendarType);
this.aDaysAbbrev = this.oLocaleData.getDays("abbreviated", sCalendarType);
this.aDaysWide = this.oLocaleData.getDays("wide", sCalendarType);
this.aDaysNarrow = this.oLocaleData.getDays("narrow", sCalendarType);
this.aDaysShort = this.oLocaleData.getDays("short", sCalendarType);
this.aDaysAbbrevSt = this.oLocaleData.getDaysStandAlone("abbreviated", sCalendarType);
this.aDaysWideSt = this.oLocaleData.getDaysStandAlone("wide", sCalendarType);
this.aDaysNarrowSt = this.oLocaleData.getDaysStandAlone("narrow", sCalendarType);
this.aDaysShortSt = this.oLocaleData.getDaysStandAlone("short", sCalendarType);
this.aQuartersAbbrev = this.oLocaleData.getQuarters("abbreviated", sCalendarType);
this.aQuartersWide = this.oLocaleData.getQuarters("wide", sCalendarType);
this.aQuartersNarrow = this.oLocaleData.getQuarters("narrow", sCalendarType);
this.aQuartersAbbrevSt = this.oLocaleData.getQuartersStandAlone("abbreviated", sCalendarType);
this.aQuartersWideSt = this.oLocaleData.getQuartersStandAlone("wide", sCalendarType);
this.aQuartersNarrowSt = this.oLocaleData.getQuartersStandAlone("narrow", sCalendarType);
this.aErasNarrow = this.oLocaleData.getEras("narrow", sCalendarType);
this.aErasAbbrev = this.oLocaleData.getEras("abbreviated", sCalendarType);
this.aErasWide = this.oLocaleData.getEras("wide", sCalendarType);
this.aDayPeriodsAbbrev = this.oLocaleData.getDayPeriods("abbreviated", sCalendarType);
this.aDayPeriodsNarrow = this.oLocaleData.getDayPeriods("narrow", sCalendarType);
this.aDayPeriodsWide = this.oLocaleData.getDayPeriods("wide", sCalendarType);
this.oFlexibleDayPeriodsAbbrev = this.oLocaleData.getFlexibleDayPeriods("abbreviated", sCalendarType);
this.oFlexibleDayPeriodsNarrow = this.oLocaleData.getFlexibleDayPeriods("narrow", sCalendarType);
this.oFlexibleDayPeriodsWide = this.oLocaleData.getFlexibleDayPeriods("wide", sCalendarType);
this.oFlexibleDayPeriodsAbbrevSt = this.oLocaleData.getFlexibleDayPeriodsStandAlone("abbreviated", sCalendarType);
this.oFlexibleDayPeriodsNarrowSt = this.oLocaleData.getFlexibleDayPeriodsStandAlone("narrow", sCalendarType);
this.oFlexibleDayPeriodsWideSt = this.oLocaleData.getFlexibleDayPeriodsStandAlone("wide", sCalendarType);
this.aFormatArray = this.parseCldrDatePattern(this.oFormatOptions.pattern);
this.sAllowedCharacters = this.getAllowedCharacters(this.aFormatArray);
};
/**
* Creates DateFormat instances based on the given format options. The created
* instances are used as fallback formats of another DateFormat instances.
*
* @param {Object[]} aFallbackFormatOptions the options for creating the fallback DateFormat
* @param {sap.ui.core.CalendarType} sCalendarType the type of the current calendarType
* @param {sap.ui.core.Locale} oLocale Locale to ask for locale specific texts/settings
* @param {Object} oInfo The default info object of the current date type
* @param {object} oParentFormatOptions the format options, relevant are: interval, showDate, showTime and showTimezone
* @return {sap.ui.core.DateFormat[]} an array of fallback DateFormat instances
* @private
*/
DateFormat._createFallbackFormat = function (aFallbackFormatOptions, sCalendarType, oLocale, oInfo, oParentFormatOptions) {
return aFallbackFormatOptions.map(function (oOptions) {
// The format options within the aFallbackFormatOptions array are static
// and shouldn't be manipulated. Hence, cloning each format option is required.
var oFormatOptions = Object.assign({}, oOptions);
// Pass the showDate, showTime and showTimezone format options to the fallback instance.
oFormatOptions.showDate = oParentFormatOptions.showDate;
oFormatOptions.showTime = oParentFormatOptions.showTime;
oFormatOptions.showTimezone = oParentFormatOptions.showTimezone;
// the timezone instance's fallback patterns depend on the showDate, showTime and
// showTimezone format option which means they cannot be static,
// therefore they are generated using the getTimezonePattern function
if (typeof oInfo.getTimezonePattern === "function" && oFormatOptions.pattern) {
oFormatOptions.pattern = oInfo.getTimezonePattern(oFormatOptions.pattern);
}
if (oParentFormatOptions.interval) {
oFormatOptions.interval = true;
}
oFormatOptions.calendarType = sCalendarType;
return DateFormat.createInstance(oFormatOptions, oLocale, oInfo, true);
});
};
/**
* Creates options for fallback DateFormat instance by removing all delimiters
* from the given base pattern.
*
* @param {string} sBasePattern The pattern where the result pattern will be
* generated by removing the delimiters
* @return {Object} Format option object which contains the new pattern
*/
DateFormat._createFallbackOptionsWithoutDelimiter = function (sBasePattern) {
var rNonDateFields = /[^dMyGU]/g,
oDayReplace = {
regex: /d+/g,
replace: "dd"
},
oMonthReplace = {
regex: /M+/g,
replace: "MM"
},
oYearReplace = {
regex: /[yU]+/g,
replace: ["yyyy", "yy"]
};
sBasePattern = sBasePattern.replace(rNonDateFields, ""); //remove all delimiters
sBasePattern = sBasePattern.replace(oDayReplace.regex, oDayReplace.replace); // replace day entries with 2 digits
sBasePattern = sBasePattern.replace(oMonthReplace.regex, oMonthReplace.replace); // replace month entries with 2 digits
return oYearReplace.replace.map(function (sReplace) {
return {
pattern: sBasePattern.replace(oYearReplace.regex, sReplace),
strictParsing: true
};
});
};
var oParseHelper = {
isNumber: function (iCharCode) {
return iCharCode >= 48 && iCharCode <= 57;
},
findNumbers: function (sValue, iMaxLength) {
var iLength = 0;
while (iLength < iMaxLength && this.isNumber(sValue.charCodeAt(iLength))) {
iLength++;
}
return sValue.substr(0, iLength);
},
/**
* Returns if the given string starts with another given string ignoring the case.
*
* Takes the locale into account to ensure the characters are interpreted the right way.
*
* First, an exact case check is performed to remain backward compatible, then a case-insensitive check
* based on the locale is done.
*
* When during the case conversion the length of the string changes we cannot safely match
* it and return <code>false</code>.
*
* @param {string} sValue the value to check, e.g. "März 2013"
* @param {string} sSubstring the string to compare it with, e.g. "MÄRZ"
* @param {string} sLocale the locale, e.g. "de-DE"
* @returns {boolean} true if the given string <code>sValue</code> starts with <code>sSubstring</code>
* @private
*/
startsWithIgnoreCase: function (sValue, sSubstring, sLocale) {
// exact case comparison (backward compatible)
if (sValue.startsWith(sSubstring)) {
return true;
}
try {
// Use String#toLocaleUpperCase instead of String#toLocaleLowerCase because there
// are known cases where an upper case letter has 2 lower case variants, e.g. Greek sigma.
var sSubToLocaleUpperCase = sSubstring.toLocaleUpperCase(sLocale);
var sValueUpperCase = sValue.toLocaleUpperCase(sLocale);
// During the upper-case conversion there are cases where length changes, e.g. ß -> SS.
// This cannot be properly determined without probing therefore we do not support this case.
if (sSubToLocaleUpperCase.length !== sSubstring.length || sValueUpperCase.length !== sValue.length) {
return false;
}
return sValueUpperCase.startsWith(sSubToLocaleUpperCase);
} catch (e) {
// Can fail for String#toLocaleUpperCase with an invalid locale
// the API fails in the case with: Incorrect locale information provided
return false;
}
},
/**
* Finds the longest matching entry for which the following applies:
* * <code>sValue</code> starts with