@ui5/webcomponents-localization 0.0.0-c638668a1 → 0.0.0-c6c04c609

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/.eslintignore +1 -1
  2. package/.npsrc.json +3 -0
  3. package/CHANGELOG.md +607 -0
  4. package/README.md +6 -6
  5. package/{src/Assets-static.js → dist/Assets-static.d.ts} +0 -1
  6. package/dist/Assets-static.js +1 -0
  7. package/dist/Assets-static.js.map +1 -0
  8. package/dist/Assets.d.ts +1 -0
  9. package/dist/Assets.js +1 -0
  10. package/dist/Assets.js.map +1 -0
  11. package/dist/DateFormat.d.ts +6 -0
  12. package/dist/DateFormat.js +6 -2
  13. package/dist/DateFormat.js.map +1 -0
  14. package/dist/LocaleData.d.ts +6 -0
  15. package/dist/LocaleData.js +6 -2
  16. package/dist/LocaleData.js.map +1 -0
  17. package/dist/dates/CalendarDate.d.ts +43 -0
  18. package/dist/dates/CalendarDate.js +171 -201
  19. package/dist/dates/CalendarDate.js.map +1 -0
  20. package/dist/dates/ExtremeDates.d.ts +5 -0
  21. package/dist/dates/ExtremeDates.js +25 -35
  22. package/dist/dates/ExtremeDates.js.map +1 -0
  23. package/dist/dates/UI5Date.d.ts +6 -0
  24. package/dist/dates/UI5Date.js +7 -0
  25. package/dist/dates/UI5Date.js.map +1 -0
  26. package/dist/dates/UniversalDate.d.ts +47 -0
  27. package/dist/dates/UniversalDate.js +5 -0
  28. package/dist/dates/UniversalDate.js.map +1 -0
  29. package/dist/dates/calculateWeekNumber.d.ts +5 -0
  30. package/dist/dates/calculateWeekNumber.js +42 -48
  31. package/dist/dates/calculateWeekNumber.js.map +1 -0
  32. package/dist/dates/convertMonthNumbersToMonthNames.d.ts +16 -0
  33. package/dist/dates/convertMonthNumbersToMonthNames.js +30 -0
  34. package/dist/dates/convertMonthNumbersToMonthNames.js.map +1 -0
  35. package/dist/dates/getDaysInMonth.d.ts +3 -0
  36. package/dist/dates/getDaysInMonth.js +10 -0
  37. package/dist/dates/getDaysInMonth.js.map +1 -0
  38. package/dist/dates/getRoundedTimestamp.d.ts +7 -0
  39. package/dist/dates/getRoundedTimestamp.js +10 -9
  40. package/dist/dates/getRoundedTimestamp.js.map +1 -0
  41. package/dist/dates/getTodayUTCTimestamp.d.ts +7 -0
  42. package/dist/dates/getTodayUTCTimestamp.js +3 -3
  43. package/dist/dates/getTodayUTCTimestamp.js.map +1 -0
  44. package/dist/dates/modifyDateBy.d.ts +14 -0
  45. package/dist/dates/modifyDateBy.js +42 -29
  46. package/dist/dates/modifyDateBy.js.map +1 -0
  47. package/dist/dates/transformDateToSecondaryType.d.ts +7 -0
  48. package/dist/dates/transformDateToSecondaryType.js +18 -0
  49. package/dist/dates/transformDateToSecondaryType.js.map +1 -0
  50. package/dist/features/calendar/Buddhist.js +1 -0
  51. package/dist/features/calendar/Buddhist.js.map +1 -0
  52. package/dist/features/calendar/Gregorian.js +1 -0
  53. package/dist/features/calendar/Gregorian.js.map +1 -0
  54. package/dist/features/calendar/Islamic.js +1 -0
  55. package/dist/features/calendar/Islamic.js.map +1 -0
  56. package/dist/features/calendar/Japanese.js +1 -0
  57. package/dist/features/calendar/Japanese.js.map +1 -0
  58. package/dist/features/calendar/Persian.js +1 -0
  59. package/dist/features/calendar/Persian.js.map +1 -0
  60. package/dist/generated/assets/cldr/ar.json +5531 -5906
  61. package/dist/generated/assets/cldr/ar_EG.json +5531 -5906
  62. package/dist/generated/assets/cldr/ar_SA.json +5530 -5906
  63. package/dist/generated/assets/cldr/bg.json +4452 -4979
  64. package/dist/generated/assets/cldr/ca.json +4440 -4996
  65. package/dist/generated/assets/cldr/cs.json +4960 -5498
  66. package/dist/generated/assets/cldr/cy.json +5211 -5884
  67. package/dist/generated/assets/cldr/da.json +4308 -4888
  68. package/dist/generated/assets/cldr/de.json +4313 -4916
  69. package/dist/generated/assets/cldr/de_AT.json +4314 -4917
  70. package/dist/generated/assets/cldr/de_CH.json +4312 -4915
  71. package/dist/generated/assets/cldr/el.json +4281 -4883
  72. package/dist/generated/assets/cldr/el_CY.json +4281 -4883
  73. package/dist/generated/assets/cldr/en.json +4316 -4971
  74. package/dist/generated/assets/cldr/en_AU.json +4319 -4962
  75. package/dist/generated/assets/cldr/en_GB.json +4329 -4971
  76. package/dist/generated/assets/cldr/en_HK.json +4337 -4977
  77. package/dist/generated/assets/cldr/en_IE.json +4328 -4971
  78. package/dist/generated/assets/cldr/en_IN.json +4333 -4972
  79. package/dist/generated/assets/cldr/en_NZ.json +4328 -4971
  80. package/dist/generated/assets/cldr/en_PG.json +4329 -4972
  81. package/dist/generated/assets/cldr/en_SG.json +4333 -4973
  82. package/dist/generated/assets/cldr/en_ZA.json +4329 -4972
  83. package/dist/generated/assets/cldr/es.json +4331 -4912
  84. package/dist/generated/assets/cldr/es_AR.json +4334 -4914
  85. package/dist/generated/assets/cldr/es_BO.json +4333 -4913
  86. package/dist/generated/assets/cldr/es_CL.json +4334 -4914
  87. package/dist/generated/assets/cldr/es_CO.json +4333 -4913
  88. package/dist/generated/assets/cldr/es_MX.json +4335 -4915
  89. package/dist/generated/assets/cldr/es_PE.json +4333 -4913
  90. package/dist/generated/assets/cldr/es_UY.json +4335 -4915
  91. package/dist/generated/assets/cldr/es_VE.json +4334 -4914
  92. package/dist/generated/assets/cldr/et.json +4340 -4967
  93. package/dist/generated/assets/cldr/fa.json +4367 -4883
  94. package/dist/generated/assets/cldr/fi.json +4463 -5008
  95. package/dist/generated/assets/cldr/fr.json +4357 -4979
  96. package/dist/generated/assets/cldr/fr_BE.json +4357 -4979
  97. package/dist/generated/assets/cldr/fr_CA.json +4351 -4973
  98. package/dist/generated/assets/cldr/fr_CH.json +4375 -4997
  99. package/dist/generated/assets/cldr/fr_LU.json +4357 -4979
  100. package/dist/generated/assets/cldr/he.json +4869 -5378
  101. package/dist/generated/assets/cldr/hi.json +4295 -4829
  102. package/dist/generated/assets/cldr/hr.json +4583 -4919
  103. package/dist/generated/assets/cldr/hu.json +4364 -4856
  104. package/dist/generated/assets/cldr/id.json +4060 -4658
  105. package/dist/generated/assets/cldr/it.json +4299 -4950
  106. package/dist/generated/assets/cldr/it_CH.json +4299 -4950
  107. package/dist/generated/assets/cldr/ja.json +4211 -4830
  108. package/dist/generated/assets/cldr/kk.json +4339 -4725
  109. package/dist/generated/assets/cldr/ko.json +4189 -4738
  110. package/dist/generated/assets/cldr/lt.json +4850 -5481
  111. package/dist/generated/assets/cldr/lv.json +4587 -5112
  112. package/dist/generated/assets/cldr/ms.json +4021 -4515
  113. package/dist/generated/assets/cldr/nb.json +4335 -4977
  114. package/dist/generated/assets/cldr/nl.json +4294 -4884
  115. package/dist/generated/assets/cldr/nl_BE.json +4294 -4884
  116. package/dist/generated/assets/cldr/pl.json +4667 -5176
  117. package/dist/generated/assets/cldr/pt.json +4235 -4805
  118. package/dist/generated/assets/cldr/pt_PT.json +4372 -4940
  119. package/dist/generated/assets/cldr/ro.json +4563 -5090
  120. package/dist/generated/assets/cldr/ru.json +4909 -5407
  121. package/dist/generated/assets/cldr/ru_UA.json +4909 -5407
  122. package/dist/generated/assets/cldr/sk.json +4939 -5370
  123. package/dist/generated/assets/cldr/sl.json +4910 -5340
  124. package/dist/generated/assets/cldr/sr.json +4585 -5126
  125. package/dist/generated/assets/cldr/sr_Latn.json +4574 -5127
  126. package/dist/generated/assets/cldr/sv.json +4362 -5011
  127. package/dist/generated/assets/cldr/th.json +4214 -4797
  128. package/dist/generated/assets/cldr/tr.json +4400 -4979
  129. package/dist/generated/assets/cldr/uk.json +4858 -5353
  130. package/dist/generated/assets/cldr/vi.json +4070 -4673
  131. package/dist/generated/assets/cldr/zh_CN.json +4100 -4632
  132. package/dist/generated/assets/cldr/zh_HK.json +4108 -4640
  133. package/dist/generated/assets/cldr/zh_SG.json +4108 -4640
  134. package/dist/generated/assets/cldr/zh_TW.json +4131 -4728
  135. package/dist/generated/json-imports/LocaleData-static.js +2 -1
  136. package/dist/generated/json-imports/LocaleData.js +75 -74
  137. package/dist/getCachedLocaleDataInstance.d.ts +4 -0
  138. package/dist/getCachedLocaleDataInstance.js +6 -9
  139. package/dist/getCachedLocaleDataInstance.js.map +1 -0
  140. package/dist/locale/getLocaleData.d.ts +11 -0
  141. package/dist/locale/getLocaleData.js +13 -17
  142. package/dist/locale/getLocaleData.js.map +1 -0
  143. package/dist/sap/base/Log.js +28 -29
  144. package/dist/sap/base/assert.js +5 -6
  145. package/dist/sap/base/i18n/LanguageTag.js +35 -0
  146. package/dist/sap/base/i18n/Localization.d.ts +4 -0
  147. package/dist/sap/base/i18n/Localization.js +12 -0
  148. package/dist/sap/base/i18n/Localization.js.map +1 -0
  149. package/dist/sap/base/i18n/date/CalendarType.js +8 -0
  150. package/dist/sap/base/i18n/date/CalendarWeekNumbering.js +30 -0
  151. package/dist/sap/base/i18n/date/TimezoneUtils.js +89 -0
  152. package/dist/sap/base/util/LoaderExtensions.d.ts +4 -0
  153. package/dist/sap/base/util/LoaderExtensions.js +9 -12
  154. package/dist/sap/base/util/LoaderExtensions.js.map +1 -0
  155. package/dist/sap/ui/base/Metadata.js +20 -9
  156. package/dist/sap/ui/core/CalendarType.js +2 -8
  157. package/dist/sap/ui/core/Configuration.d.ts +18 -0
  158. package/dist/sap/ui/core/Configuration.js +23 -0
  159. package/dist/sap/ui/core/Configuration.js.map +1 -0
  160. package/dist/sap/ui/core/Core.d.ts +27 -0
  161. package/dist/sap/ui/core/Core.js +7 -32
  162. package/dist/sap/ui/core/Core.js.map +1 -0
  163. package/dist/sap/ui/core/FormatSettings.d.ts +10 -0
  164. package/dist/sap/ui/core/FormatSettings.js +14 -0
  165. package/dist/sap/ui/core/FormatSettings.js.map +1 -0
  166. package/dist/sap/ui/core/Locale.js +28 -112
  167. package/dist/sap/ui/core/LocaleData.js +213 -40
  168. package/dist/sap/ui/core/date/Buddhist.js +0 -6
  169. package/dist/sap/ui/core/date/CalendarUtils.js +25 -0
  170. package/dist/sap/ui/core/date/CalendarWeekNumbering.js +2 -0
  171. package/dist/sap/ui/core/date/Islamic.js +3 -3
  172. package/dist/sap/ui/core/date/Japanese.js +4 -4
  173. package/dist/sap/ui/core/date/UI5Date.js +305 -0
  174. package/dist/sap/ui/core/date/UniversalDate.js +73 -26
  175. package/dist/sap/ui/core/format/DateFormat.js +848 -497
  176. package/dist/sap/ui/core/format/TimezoneUtil.js +2 -0
  177. package/{package-scripts.js → package-scripts.cjs} +7 -10
  178. package/package.json +7 -5
  179. package/tsconfig.json +14 -0
  180. package/used-modules.txt +9 -1
  181. package/hash.txt +0 -1
  182. package/src/Assets.js +0 -2
  183. package/src/DateFormat.js +0 -3
  184. package/src/LocaleData.js +0 -3
  185. package/src/dates/CalendarDate.js +0 -223
  186. package/src/dates/ExtremeDates.js +0 -39
  187. package/src/dates/calculateWeekNumber.js +0 -51
  188. package/src/dates/getRoundedTimestamp.js +0 -14
  189. package/src/dates/getTodayUTCTimestamp.js +0 -9
  190. package/src/dates/modifyDateBy.js +0 -42
  191. package/src/getCachedLocaleDataInstance.js +0 -13
  192. package/src/locale/getLocaleData.js +0 -27
  193. package/src/sap/base/util/LoaderExtensions.js +0 -17
  194. package/src/sap/ui/core/Core.js +0 -38
  195. /package/{config/.eslintrc.js → .eslintrc.cjs} +0 -0
  196. /package/{src/features/calendar/Buddhist.js → dist/features/calendar/Buddhist.d.ts} +0 -0
  197. /package/{src/features/calendar/Gregorian.js → dist/features/calendar/Gregorian.d.ts} +0 -0
  198. /package/{src/features/calendar/Islamic.js → dist/features/calendar/Islamic.d.ts} +0 -0
  199. /package/{src/features/calendar/Japanese.js → dist/features/calendar/Japanese.d.ts} +0 -0
  200. /package/{src/features/calendar/Persian.js → dist/features/calendar/Persian.d.ts} +0 -0
@@ -1,17 +1,34 @@
1
- import Core from '../Core.js';
1
+ import Log from '../../../base/Log.js';
2
+ import formatMessage from '../../../base/strings/formatMessage.js';
3
+ import deepEqual from '../../../base/util/deepEqual.js';
4
+ import extend from '../../../base/util/extend.js';
2
5
  import CalendarType from '../CalendarType.js';
6
+ import Configuration from '../Configuration.js';
7
+ import Core from '../Core.js';
3
8
  import Locale from '../Locale.js';
4
9
  import LocaleData from '../LocaleData.js';
10
+ import CalendarUtils from '../date/CalendarUtils.js';
11
+ import CalendarWeekNumbering from '../date/CalendarWeekNumbering.js';
12
+ import UI5Date from '../date/UI5Date.js';
5
13
  import UniversalDate from '../date/UniversalDate.js';
6
- import deepEqual from '../../../base/util/deepEqual.js';
7
- import formatMessage from '../../../base/strings/formatMessage.js';
8
- import Log from '../../../base/Log.js';
9
- import extend from '../../../base/util/extend.js';
14
+ import TimezoneUtil from './TimezoneUtil.js';
10
15
  var DateFormat = function () {
11
16
  throw new Error();
12
17
  };
18
+ var mDateFormatTypes = {
19
+ DATE: 'date',
20
+ TIME: 'time',
21
+ DATETIME: 'datetime',
22
+ DATETIME_WITH_TIMEZONE: 'datetimeWithTimezone'
23
+ };
13
24
  var mCldrDatePattern = {};
25
+ var checkTimezoneParameterType = function (sTimezone) {
26
+ if (typeof sTimezone !== 'string' && !(sTimezone instanceof String) && sTimezone != null) {
27
+ throw new TypeError('The given timezone must be a string.');
28
+ }
29
+ };
14
30
  DateFormat.oDateInfo = {
31
+ type: mDateFormatTypes.DATE,
15
32
  oDefaultFormatOptions: {
16
33
  style: 'medium',
17
34
  relativeScale: 'day',
@@ -64,6 +81,7 @@ DateFormat.oDateInfo = {
64
81
  ]
65
82
  };
66
83
  DateFormat.oDateTimeInfo = {
84
+ type: mDateFormatTypes.DATETIME,
67
85
  oDefaultFormatOptions: {
68
86
  style: 'medium',
69
87
  relativeScale: 'auto',
@@ -126,7 +144,41 @@ DateFormat.oDateTimeInfo = {
126
144
  'Seconds'
127
145
  ]
128
146
  };
147
+ DateFormat._getDateTimeWithTimezoneInfo = function (oFormatOptions) {
148
+ var bShowDate = oFormatOptions.showDate === undefined || oFormatOptions.showDate;
149
+ var bShowTime = oFormatOptions.showTime === undefined || oFormatOptions.showTime;
150
+ var bShowTimezone = oFormatOptions.showTimezone === undefined || oFormatOptions.showTimezone;
151
+ var oBaselineType = DateFormat.oDateTimeInfo;
152
+ if (bShowDate && !bShowTime) {
153
+ oBaselineType = DateFormat.oDateInfo;
154
+ } else if (!bShowDate && bShowTime) {
155
+ oBaselineType = DateFormat.oTimeInfo;
156
+ }
157
+ return Object.assign({}, oBaselineType, {
158
+ type: mDateFormatTypes.DATETIME_WITH_TIMEZONE,
159
+ getTimezonePattern: function (sPattern) {
160
+ if (!bShowDate && !bShowTime && bShowTimezone) {
161
+ return 'VV';
162
+ } else if (!bShowTimezone) {
163
+ return sPattern;
164
+ } else {
165
+ return sPattern + ' VV';
166
+ }
167
+ },
168
+ getPattern: function (oLocaleData, sStyle, sCalendarType) {
169
+ if (!bShowDate && !bShowTime && bShowTimezone) {
170
+ return 'VV';
171
+ }
172
+ if (!bShowTimezone) {
173
+ return oBaselineType.getPattern(oLocaleData, sStyle, sCalendarType);
174
+ }
175
+ var sPattern = oBaselineType.getPattern(oLocaleData, sStyle, sCalendarType);
176
+ return oLocaleData.applyTimezonePattern(sPattern);
177
+ }
178
+ });
179
+ };
129
180
  DateFormat.oTimeInfo = {
181
+ type: mDateFormatTypes.TIME,
130
182
  oDefaultFormatOptions: {
131
183
  style: 'medium',
132
184
  relativeScale: 'auto',
@@ -179,6 +231,29 @@ DateFormat.getDateInstance = function (oFormatOptions, oLocale) {
179
231
  DateFormat.getDateTimeInstance = function (oFormatOptions, oLocale) {
180
232
  return this.createInstance(oFormatOptions, oLocale, this.oDateTimeInfo);
181
233
  };
234
+ DateFormat.getDateTimeWithTimezoneInstance = function (oFormatOptions, oLocale) {
235
+ if (oFormatOptions && !(oFormatOptions instanceof Locale)) {
236
+ (function () {
237
+ oFormatOptions = Object.assign({}, oFormatOptions);
238
+ if (typeof oFormatOptions.showTimezone === 'string') {
239
+ var sShowTimezone = oFormatOptions.showTimezone;
240
+ if (oFormatOptions.showDate === undefined && oFormatOptions.showTime === undefined) {
241
+ if (sShowTimezone === 'Hide') {
242
+ oFormatOptions.showTimezone = false;
243
+ } else if (sShowTimezone === 'Only') {
244
+ oFormatOptions.showDate = false;
245
+ oFormatOptions.showTime = false;
246
+ }
247
+ }
248
+ oFormatOptions.showTimezone = sShowTimezone !== 'Hide';
249
+ }
250
+ }());
251
+ if (oFormatOptions.showDate === false && oFormatOptions.showTime === false && oFormatOptions.showTimezone === false) {
252
+ throw new TypeError('Invalid Configuration. One of the following format options must be true: ' + 'showDate, showTime or showTimezone.');
253
+ }
254
+ }
255
+ return this.createInstance(oFormatOptions, oLocale, DateFormat._getDateTimeWithTimezoneInfo(oFormatOptions || {}));
256
+ };
182
257
  DateFormat.getTimeInstance = function (oFormatOptions, oLocale) {
183
258
  return this.createInstance(oFormatOptions, oLocale, this.oTimeInfo);
184
259
  };
@@ -187,20 +262,37 @@ function createIntervalPatternWithNormalConnector(oFormat) {
187
262
  sPattern = sPattern.replace(/[^\{\}01 ]/, '-');
188
263
  return sPattern.replace(/\{(0|1)\}/g, oFormat.oFormatOptions.pattern);
189
264
  }
190
- DateFormat.createInstance = function (oFormatOptions, oLocale, oInfo) {
191
- var oFormat = Object.create(this.prototype);
265
+ DateFormat.createInstance = function (oFormatOptions, oLocale, oInfo, bIsFallback) {
266
+ var aFallbackFormatOptions, oFormat, sPattern;
267
+ oFormat = Object.create(this.prototype);
192
268
  if (oFormatOptions instanceof Locale) {
193
269
  oLocale = oFormatOptions;
194
270
  oFormatOptions = undefined;
195
271
  }
196
272
  if (!oLocale) {
197
- oLocale = Core.getConfiguration().getFormatSettings().getFormatLocale();
273
+ oLocale = Configuration.getFormatSettings().getFormatLocale();
198
274
  }
199
275
  oFormat.oLocale = oLocale;
200
276
  oFormat.oLocaleData = LocaleData.getInstance(oLocale);
201
277
  oFormat.oFormatOptions = extend({}, oInfo.oDefaultFormatOptions, oFormatOptions);
278
+ if (oInfo.type === mDateFormatTypes.DATETIME_WITH_TIMEZONE) {
279
+ oFormat.oFormatOptions.interval = false;
280
+ oFormat.oFormatOptions.singleIntervalValue = false;
281
+ oFormat.oFormatOptions.UTC = false;
282
+ } else {
283
+ oFormat.oFormatOptions.showTimezone = undefined;
284
+ oFormat.oFormatOptions.showDate = undefined;
285
+ oFormat.oFormatOptions.showTime = undefined;
286
+ }
287
+ oFormat.type = oInfo.type;
202
288
  if (!oFormat.oFormatOptions.calendarType) {
203
- oFormat.oFormatOptions.calendarType = Core.getConfiguration().getCalendarType();
289
+ oFormat.oFormatOptions.calendarType = Configuration.getCalendarType();
290
+ }
291
+ if (oFormat.oFormatOptions.firstDayOfWeek === undefined && oFormat.oFormatOptions.minimalDaysInFirstWeek !== undefined || oFormat.oFormatOptions.firstDayOfWeek !== undefined && oFormat.oFormatOptions.minimalDaysInFirstWeek === undefined) {
292
+ throw new TypeError('Format options firstDayOfWeek and minimalDaysInFirstWeek need both to be set, but only one was provided.');
293
+ }
294
+ if (oFormat.oFormatOptions.calendarWeekNumbering && !Object.values(CalendarWeekNumbering).includes(oFormat.oFormatOptions.calendarWeekNumbering)) {
295
+ throw new TypeError('Illegal format option calendarWeekNumbering: \'' + oFormat.oFormatOptions.calendarWeekNumbering + '\'');
204
296
  }
205
297
  if (!oFormat.oFormatOptions.pattern) {
206
298
  if (oFormat.oFormatOptions.format) {
@@ -210,13 +302,16 @@ DateFormat.createInstance = function (oFormatOptions, oLocale, oInfo) {
210
302
  }
211
303
  }
212
304
  if (oFormat.oFormatOptions.interval) {
305
+ var sSinglePattern, sDelimiter = oFormat.oFormatOptions.intervalDelimiter;
213
306
  if (oFormat.oFormatOptions.format) {
214
307
  oFormat.intervalPatterns = oFormat.oLocaleData.getCustomIntervalPattern(oFormat.oFormatOptions.format, null, oFormat.oFormatOptions.calendarType);
215
308
  if (typeof oFormat.intervalPatterns === 'string') {
216
309
  oFormat.intervalPatterns = [oFormat.intervalPatterns];
217
310
  }
218
- oFormat.intervalPatterns.push(oFormat.oLocaleData.getCustomDateTimePattern(oFormat.oFormatOptions.format, oFormat.oFormatOptions.calendarType));
311
+ sSinglePattern = oFormat.oLocaleData.getCustomDateTimePattern(oFormat.oFormatOptions.format, oFormat.oFormatOptions.calendarType);
312
+ oFormat.intervalPatterns.push(sSinglePattern);
219
313
  } else {
314
+ sSinglePattern = oFormat.oFormatOptions.pattern;
220
315
  oFormat.intervalPatterns = [
221
316
  oFormat.oLocaleData.getCombinedIntervalPattern(oFormat.oFormatOptions.pattern, oFormat.oFormatOptions.calendarType),
222
317
  oFormat.oFormatOptions.pattern
@@ -224,31 +319,34 @@ DateFormat.createInstance = function (oFormatOptions, oLocale, oInfo) {
224
319
  }
225
320
  var sCommonConnectorPattern = createIntervalPatternWithNormalConnector(oFormat);
226
321
  oFormat.intervalPatterns.push(sCommonConnectorPattern);
322
+ if (sDelimiter) {
323
+ sDelimiter = sDelimiter.replace(/'/g, '\'\'');
324
+ sDelimiter = '\'' + sDelimiter + '\'';
325
+ oFormat.intervalPatterns.unshift(sSinglePattern + sDelimiter + sSinglePattern);
326
+ }
327
+ oFormat.intervalPatterns = Array.from(new Set(oFormat.intervalPatterns));
227
328
  }
228
- if (!oFormat.oFormatOptions.fallback) {
229
- if (!oInfo.oFallbackFormats) {
230
- oInfo.oFallbackFormats = {};
329
+ if (!bIsFallback) {
330
+ aFallbackFormatOptions = oInfo.aFallbackFormatOptions;
331
+ if (oInfo.bShortFallbackFormatOptions) {
332
+ sPattern = oInfo.getPattern(oFormat.oLocaleData, 'short');
333
+ aFallbackFormatOptions = aFallbackFormatOptions.concat(DateFormat._createFallbackOptionsWithoutDelimiter(sPattern));
231
334
  }
232
- var sLocale = oLocale.toString(), sCalendarType = oFormat.oFormatOptions.calendarType, sKey = sLocale + '-' + sCalendarType, sPattern, aFallbackFormatOptions;
233
335
  if (oFormat.oFormatOptions.pattern && oInfo.bPatternFallbackWithoutDelimiter) {
234
- sKey = sKey + '-' + oFormat.oFormatOptions.pattern;
235
- }
236
- if (oFormat.oFormatOptions.interval) {
237
- sKey = sKey + '-' + 'interval';
336
+ aFallbackFormatOptions = DateFormat._createFallbackOptionsWithoutDelimiter(oFormat.oFormatOptions.pattern).concat(aFallbackFormatOptions);
238
337
  }
239
- var oFallbackFormats = oInfo.oFallbackFormats[sKey] ? Object.assign({}, oInfo.oFallbackFormats[sKey]) : undefined;
240
- if (!oFallbackFormats) {
241
- aFallbackFormatOptions = oInfo.aFallbackFormatOptions;
242
- if (oInfo.bShortFallbackFormatOptions) {
243
- sPattern = oInfo.getPattern(oFormat.oLocaleData, 'short');
244
- aFallbackFormatOptions = aFallbackFormatOptions.concat(DateFormat._createFallbackOptionsWithoutDelimiter(sPattern));
245
- }
246
- if (oFormat.oFormatOptions.pattern && oInfo.bPatternFallbackWithoutDelimiter) {
247
- aFallbackFormatOptions = DateFormat._createFallbackOptionsWithoutDelimiter(oFormat.oFormatOptions.pattern).concat(aFallbackFormatOptions);
338
+ aFallbackFormatOptions = aFallbackFormatOptions.reduce(function (aFallbacks, oOptions) {
339
+ var aKeys = Object.keys(oOptions), bDuplicate = aFallbacks.some(function (oOptions0) {
340
+ return Object.keys(oOptions0).length === aKeys.length && aKeys.every(function (sKey) {
341
+ return oOptions0[sKey] === oOptions[sKey];
342
+ });
343
+ });
344
+ if (!bDuplicate) {
345
+ aFallbacks.push(oOptions);
248
346
  }
249
- oFallbackFormats = DateFormat._createFallbackFormat(aFallbackFormatOptions, sCalendarType, oLocale, oInfo, oFormat.oFormatOptions.interval);
250
- }
251
- oFormat.aFallbackFormats = oFallbackFormats;
347
+ return aFallbacks;
348
+ }, []);
349
+ oFormat.aFallbackFormats = DateFormat._createFallbackFormat(aFallbackFormatOptions, oFormat.oFormatOptions.calendarType, oLocale, oInfo, oFormat.oFormatOptions);
252
350
  }
253
351
  oFormat.oRequiredParts = oInfo.oRequiredParts;
254
352
  oFormat.aRelativeScales = oInfo.aRelativeScales;
@@ -282,21 +380,32 @@ DateFormat.prototype.init = function () {
282
380
  this.aErasNarrow = this.oLocaleData.getEras('narrow', sCalendarType);
283
381
  this.aErasAbbrev = this.oLocaleData.getEras('abbreviated', sCalendarType);
284
382
  this.aErasWide = this.oLocaleData.getEras('wide', sCalendarType);
285
- this.aDayPeriods = this.oLocaleData.getDayPeriods('abbreviated', sCalendarType);
383
+ this.aDayPeriodsAbbrev = this.oLocaleData.getDayPeriods('abbreviated', sCalendarType);
384
+ this.aDayPeriodsNarrow = this.oLocaleData.getDayPeriods('narrow', sCalendarType);
385
+ this.aDayPeriodsWide = this.oLocaleData.getDayPeriods('wide', sCalendarType);
386
+ this.oFlexibleDayPeriodsAbbrev = this.oLocaleData.getFlexibleDayPeriods('abbreviated', sCalendarType);
387
+ this.oFlexibleDayPeriodsNarrow = this.oLocaleData.getFlexibleDayPeriods('narrow', sCalendarType);
388
+ this.oFlexibleDayPeriodsWide = this.oLocaleData.getFlexibleDayPeriods('wide', sCalendarType);
389
+ this.oFlexibleDayPeriodsAbbrevSt = this.oLocaleData.getFlexibleDayPeriodsStandAlone('abbreviated', sCalendarType);
390
+ this.oFlexibleDayPeriodsNarrowSt = this.oLocaleData.getFlexibleDayPeriodsStandAlone('narrow', sCalendarType);
391
+ this.oFlexibleDayPeriodsWideSt = this.oLocaleData.getFlexibleDayPeriodsStandAlone('wide', sCalendarType);
286
392
  this.aFormatArray = this.parseCldrDatePattern(this.oFormatOptions.pattern);
287
393
  this.sAllowedCharacters = this.getAllowedCharacters(this.aFormatArray);
288
394
  };
289
- DateFormat._createFallbackFormat = function (aFallbackFormatOptions, sCalendarType, oLocale, oInfo, bInterval) {
395
+ DateFormat._createFallbackFormat = function (aFallbackFormatOptions, sCalendarType, oLocale, oInfo, oParentFormatOptions) {
290
396
  return aFallbackFormatOptions.map(function (oOptions) {
291
397
  var oFormatOptions = Object.assign({}, oOptions);
292
- if (bInterval) {
398
+ oFormatOptions.showDate = oParentFormatOptions.showDate;
399
+ oFormatOptions.showTime = oParentFormatOptions.showTime;
400
+ oFormatOptions.showTimezone = oParentFormatOptions.showTimezone;
401
+ if (typeof oInfo.getTimezonePattern === 'function' && oFormatOptions.pattern) {
402
+ oFormatOptions.pattern = oInfo.getTimezonePattern(oFormatOptions.pattern);
403
+ }
404
+ if (oParentFormatOptions.interval) {
293
405
  oFormatOptions.interval = true;
294
406
  }
295
407
  oFormatOptions.calendarType = sCalendarType;
296
- oFormatOptions.fallback = true;
297
- var oFallbackFormat = DateFormat.createInstance(oFormatOptions, oLocale, oInfo);
298
- oFallbackFormat.bIsFallback = true;
299
- return oFallbackFormat;
408
+ return DateFormat.createInstance(oFormatOptions, oLocale, oInfo, true);
300
409
  });
301
410
  };
302
411
  DateFormat._createFallbackOptionsWithoutDelimiter = function (sBasePattern) {
@@ -332,27 +441,39 @@ var oParseHelper = {
332
441
  while (iLength < iMaxLength && this.isNumber(sValue.charCodeAt(iLength))) {
333
442
  iLength++;
334
443
  }
335
- if (typeof sValue !== 'string') {
336
- sValue = sValue.toString();
337
- }
338
444
  return sValue.substr(0, iLength);
339
445
  },
340
- findEntry: function (sValue, aList) {
446
+ startsWithIgnoreCase: function (sValue, sSubstring, sLocale) {
447
+ if (sValue.startsWith(sSubstring)) {
448
+ return true;
449
+ }
450
+ try {
451
+ var sSubToLocaleUpperCase = sSubstring.toLocaleUpperCase(sLocale);
452
+ var sValueUpperCase = sValue.toLocaleUpperCase(sLocale);
453
+ if (sSubToLocaleUpperCase.length !== sSubstring.length || sValueUpperCase.length !== sValue.length) {
454
+ return false;
455
+ }
456
+ return sValueUpperCase.startsWith(sSubToLocaleUpperCase);
457
+ } catch (e) {
458
+ return false;
459
+ }
460
+ },
461
+ findEntry: function (sValue, aList, sLocale) {
341
462
  var iFoundIndex = -1, iMatchedLength = 0;
342
463
  for (var j = 0; j < aList.length; j++) {
343
- if (aList[j] && aList[j].length > iMatchedLength && sValue.indexOf(aList[j]) === 0) {
464
+ if (aList[j] && aList[j].length > iMatchedLength && this.startsWithIgnoreCase(sValue, aList[j], sLocale)) {
344
465
  iFoundIndex = j;
345
466
  iMatchedLength = aList[j].length;
346
467
  }
347
468
  }
348
469
  return {
349
470
  index: iFoundIndex,
350
- value: iFoundIndex === -1 ? null : aList[iFoundIndex]
471
+ length: iMatchedLength
351
472
  };
352
473
  },
353
474
  parseTZ: function (sValue, bColonSeparated) {
354
475
  var iLength = 0;
355
- var iTZFactor = sValue.charAt(0) == '+' ? -1 : 1;
476
+ var iTZFactor = sValue.charAt(0) === '+' ? -1 : 1;
356
477
  var sPart;
357
478
  iLength++;
358
479
  sPart = this.findNumbers(sValue.substr(iLength), 2);
@@ -369,19 +490,35 @@ var oParseHelper = {
369
490
  }
370
491
  return {
371
492
  length: iLength,
372
- tzDiff: (iTZDiff + 60 * iTZDiffHour) * iTZFactor
493
+ tzDiff: (iTZDiff + 60 * iTZDiffHour) * 60 * iTZFactor
373
494
  };
374
495
  },
375
- checkValid: function (sType, bPartInvalid, oFormat) {
376
- if (sType in oFormat.oRequiredParts && bPartInvalid) {
496
+ checkValid: function (sSymbolName, bPartInvalid, oFormat) {
497
+ if (sSymbolName in oFormat.oRequiredParts && bPartInvalid) {
377
498
  return false;
378
499
  }
500
+ return true;
379
501
  }
380
502
  };
503
+ DateFormat._createPatternSymbol = function (mParameters) {
504
+ var fnIsNumeric = typeof mParameters.isNumeric === 'function' && mParameters.isNumeric || function () {
505
+ return mParameters.isNumeric || false;
506
+ };
507
+ return {
508
+ name: mParameters.name,
509
+ format: mParameters.format || function () {
510
+ return '';
511
+ },
512
+ parse: mParameters.parse || function () {
513
+ return {};
514
+ },
515
+ isNumeric: fnIsNumeric
516
+ };
517
+ };
381
518
  DateFormat.prototype.oSymbols = {
382
- '': {
519
+ '': DateFormat._createPatternSymbol({
383
520
  name: 'text',
384
- format: function (oField, oDate, bUTC, oFormat) {
521
+ format: function (oField, oDate) {
385
522
  return oField.value;
386
523
  },
387
524
  parse: function (sValue, oPart, oFormat, oConfig) {
@@ -421,11 +558,11 @@ DateFormat.prototype.oSymbols = {
421
558
  return { valid: oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat) };
422
559
  }
423
560
  }
424
- },
425
- 'G': {
561
+ }),
562
+ 'G': DateFormat._createPatternSymbol({
426
563
  name: 'era',
427
564
  format: function (oField, oDate, bUTC, oFormat) {
428
- var iEra = bUTC ? oDate.getUTCEra() : oDate.getEra();
565
+ var iEra = oDate.getUTCEra();
429
566
  if (oField.digits <= 3) {
430
567
  return oFormat.aErasAbbrev[iEra];
431
568
  } else if (oField.digits === 4) {
@@ -442,11 +579,11 @@ DateFormat.prototype.oSymbols = {
442
579
  ];
443
580
  for (var i = 0; i < aErasVariants.length; i++) {
444
581
  var aVariants = aErasVariants[i];
445
- var oFound = oParseHelper.findEntry(sValue, aVariants);
582
+ var oFound = oParseHelper.findEntry(sValue, aVariants, oFormat.oLocaleData.sCLDRLocaleId);
446
583
  if (oFound.index !== -1) {
447
584
  return {
448
585
  era: oFound.index,
449
- length: oFound.value.length
586
+ length: oFound.length
450
587
  };
451
588
  }
452
589
  }
@@ -455,34 +592,35 @@ DateFormat.prototype.oSymbols = {
455
592
  valid: oParseHelper.checkValid(oPart.type, true, oFormat)
456
593
  };
457
594
  }
458
- },
459
- 'y': {
595
+ }),
596
+ 'y': DateFormat._createPatternSymbol({
460
597
  name: 'year',
461
598
  format: function (oField, oDate, bUTC, oFormat) {
462
- var iYear = bUTC ? oDate.getUTCFullYear() : oDate.getFullYear();
599
+ var iYear = oDate.getUTCFullYear();
463
600
  var sYear = String(iYear);
464
601
  var sCalendarType = oFormat.oFormatOptions.calendarType;
465
- if (oField.digits == 2 && sYear.length > 2) {
602
+ if (oField.digits === 2 && sYear.length > 2) {
466
603
  sYear = sYear.substr(sYear.length - 2);
467
604
  }
468
- if (sCalendarType != CalendarType.Japanese && oField.digits == 1 && iYear < 100) {
605
+ if (sCalendarType !== CalendarType.Japanese && oField.digits === 1 && iYear < 100) {
469
606
  sYear = sYear.padStart(4, '0');
470
607
  }
471
608
  return sYear.padStart(oField.digits, '0');
472
609
  },
473
610
  parse: function (sValue, oPart, oFormat, oConfig) {
474
- var sCalendarType = oFormat.oFormatOptions.calendarType;
475
- var sPart;
476
- if (oPart.digits == 1) {
477
- sPart = oParseHelper.findNumbers(sValue, 4);
478
- } else if (oPart.digits == 2) {
479
- sPart = oParseHelper.findNumbers(sValue, 2);
611
+ var iExpectedDigits, sPart, bPartInvalid, sCalendarType = oFormat.oFormatOptions.calendarType;
612
+ if (oPart.digits === 1) {
613
+ iExpectedDigits = 4;
614
+ } else if (oPart.digits === 2) {
615
+ iExpectedDigits = 2;
480
616
  } else {
481
- sPart = oParseHelper.findNumbers(sValue, oPart.digits);
617
+ iExpectedDigits = oPart.digits;
482
618
  }
619
+ sPart = oParseHelper.findNumbers(sValue, iExpectedDigits);
620
+ bPartInvalid = sPart === '' || oConfig.exactLength && sPart.length !== iExpectedDigits;
483
621
  var iYear = parseInt(sPart);
484
- if (sCalendarType != CalendarType.Japanese && sPart.length <= 2) {
485
- var oCurrentDate = UniversalDate.getInstance(new Date(), sCalendarType), iCurrentYear = oCurrentDate.getFullYear(), iCurrentCentury = Math.floor(iCurrentYear / 100), iYearDiff = iCurrentCentury * 100 + iYear - iCurrentYear;
622
+ if (sCalendarType !== CalendarType.Japanese && sPart.length <= 2) {
623
+ var oCurrentDate = UniversalDate.getInstance(UI5Date.getInstance(), sCalendarType), iCurrentYear = oCurrentDate.getUTCFullYear(), iCurrentCentury = Math.floor(iCurrentYear / 100), iYearDiff = iCurrentCentury * 100 + iYear - iCurrentYear;
486
624
  if (iYearDiff < -70) {
487
625
  iYear += (iCurrentCentury + 1) * 100;
488
626
  } else if (iYearDiff < 30) {
@@ -493,40 +631,42 @@ DateFormat.prototype.oSymbols = {
493
631
  }
494
632
  return {
495
633
  length: sPart.length,
496
- valid: oParseHelper.checkValid(oPart.type, sPart === '', oFormat),
634
+ valid: oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat),
497
635
  year: iYear
498
636
  };
499
- }
500
- },
501
- 'Y': {
637
+ },
638
+ isNumeric: true
639
+ }),
640
+ 'Y': DateFormat._createPatternSymbol({
502
641
  name: 'weekYear',
503
642
  format: function (oField, oDate, bUTC, oFormat) {
504
- var oWeek = bUTC ? oDate.getUTCWeek() : oDate.getWeek();
643
+ var oWeek = oDate.getUTCWeek(oFormat.oLocale, getCalendarWeekParameter(oFormat.oFormatOptions));
505
644
  var iWeekYear = oWeek.year;
506
645
  var sWeekYear = String(iWeekYear);
507
646
  var sCalendarType = oFormat.oFormatOptions.calendarType;
508
- if (oField.digits == 2 && sWeekYear.length > 2) {
647
+ if (oField.digits === 2 && sWeekYear.length > 2) {
509
648
  sWeekYear = sWeekYear.substr(sWeekYear.length - 2);
510
649
  }
511
- if (sCalendarType != CalendarType.Japanese && oField.digits == 1 && iWeekYear < 100) {
650
+ if (sCalendarType !== CalendarType.Japanese && oField.digits === 1 && iWeekYear < 100) {
512
651
  sWeekYear = sWeekYear.padStart(4, '0');
513
652
  }
514
653
  return sWeekYear.padStart(oField.digits, '0');
515
654
  },
516
655
  parse: function (sValue, oPart, oFormat, oConfig) {
517
- var sCalendarType = oFormat.oFormatOptions.calendarType;
518
- var sPart;
519
- if (oPart.digits == 1) {
520
- sPart = oParseHelper.findNumbers(sValue, 4);
521
- } else if (oPart.digits == 2) {
522
- sPart = oParseHelper.findNumbers(sValue, 2);
656
+ var iExpectedDigits, sPart, bPartInvalid, sCalendarType = oFormat.oFormatOptions.calendarType;
657
+ if (oPart.digits === 1) {
658
+ iExpectedDigits = 4;
659
+ } else if (oPart.digits === 2) {
660
+ iExpectedDigits = 2;
523
661
  } else {
524
- sPart = oParseHelper.findNumbers(sValue, oPart.digits);
662
+ iExpectedDigits = oPart.digits;
525
663
  }
664
+ sPart = oParseHelper.findNumbers(sValue, iExpectedDigits);
665
+ bPartInvalid = sPart === '' || oConfig.exactLength && sPart.length !== iExpectedDigits;
526
666
  var iYear = parseInt(sPart);
527
- var iWeekYear;
528
- if (sCalendarType != CalendarType.Japanese && sPart.length <= 2) {
529
- var oCurrentDate = UniversalDate.getInstance(new Date(), sCalendarType), iCurrentYear = oCurrentDate.getFullYear(), iCurrentCentury = Math.floor(iCurrentYear / 100), iYearDiff = iCurrentCentury * 100 + iWeekYear - iCurrentYear;
667
+ var iWeekYear = iYear;
668
+ if (sCalendarType !== CalendarType.Japanese && sPart.length <= 2) {
669
+ var oCurrentDate = UniversalDate.getInstance(UI5Date.getInstance(), sCalendarType), iCurrentYear = oCurrentDate.getUTCFullYear(), iCurrentCentury = Math.floor(iCurrentYear / 100), iYearDiff = iCurrentCentury * 100 + iWeekYear - iCurrentYear;
530
670
  if (iYearDiff < -70) {
531
671
  iWeekYear += (iCurrentCentury + 1) * 100;
532
672
  } else if (iYearDiff < 30) {
@@ -537,19 +677,20 @@ DateFormat.prototype.oSymbols = {
537
677
  }
538
678
  return {
539
679
  length: sPart.length,
540
- valid: oParseHelper.checkValid(oPart.type, sPart === '', oFormat),
680
+ valid: oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat),
541
681
  year: iYear,
542
682
  weekYear: iWeekYear
543
683
  };
544
- }
545
- },
546
- 'M': {
684
+ },
685
+ isNumeric: true
686
+ }),
687
+ 'M': DateFormat._createPatternSymbol({
547
688
  name: 'month',
548
689
  format: function (oField, oDate, bUTC, oFormat) {
549
- var iMonth = bUTC ? oDate.getUTCMonth() : oDate.getMonth();
550
- if (oField.digits == 3) {
690
+ var iMonth = oDate.getUTCMonth();
691
+ if (oField.digits === 3) {
551
692
  return oFormat.aMonthsAbbrev[iMonth];
552
- } else if (oField.digits == 4) {
693
+ } else if (oField.digits === 4) {
553
694
  return oFormat.aMonthsWide[iMonth];
554
695
  } else if (oField.digits > 4) {
555
696
  return oFormat.aMonthsNarrow[iMonth];
@@ -558,20 +699,18 @@ DateFormat.prototype.oSymbols = {
558
699
  }
559
700
  },
560
701
  parse: function (sValue, oPart, oFormat, oConfig) {
561
- var aMonthsVariants = [
562
- oFormat.aMonthsWide,
563
- oFormat.aMonthsWideSt,
564
- oFormat.aMonthsAbbrev,
565
- oFormat.aMonthsAbbrevSt,
566
- oFormat.aMonthsNarrow,
567
- oFormat.aMonthsNarrowSt
568
- ];
569
- var bValid;
570
- var iMonth;
571
- var sPart;
702
+ var iMonth, sPart, bPartInvalid, bValid, aMonthsVariants = [
703
+ oFormat.aMonthsWide,
704
+ oFormat.aMonthsWideSt,
705
+ oFormat.aMonthsAbbrev,
706
+ oFormat.aMonthsAbbrevSt,
707
+ oFormat.aMonthsNarrow,
708
+ oFormat.aMonthsNarrowSt
709
+ ];
572
710
  if (oPart.digits < 3) {
573
711
  sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
574
- bValid = oParseHelper.checkValid(oPart.type, sPart === '', oFormat);
712
+ bPartInvalid = sPart === '' || oConfig.exactLength && sPart.length < 2;
713
+ bValid = oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat);
575
714
  iMonth = parseInt(sPart) - 1;
576
715
  if (oConfig.strict && (iMonth > 11 || iMonth < 0)) {
577
716
  bValid = false;
@@ -579,11 +718,11 @@ DateFormat.prototype.oSymbols = {
579
718
  } else {
580
719
  for (var i = 0; i < aMonthsVariants.length; i++) {
581
720
  var aVariants = aMonthsVariants[i];
582
- var oFound = oParseHelper.findEntry(sValue, aVariants);
721
+ var oFound = oParseHelper.findEntry(sValue, aVariants, oFormat.oLocaleData.sCLDRLocaleId);
583
722
  if (oFound.index !== -1) {
584
723
  return {
585
724
  month: oFound.index,
586
- length: oFound.value.length
725
+ length: oFound.length
587
726
  };
588
727
  }
589
728
  }
@@ -594,15 +733,18 @@ DateFormat.prototype.oSymbols = {
594
733
  length: sPart ? sPart.length : 0,
595
734
  valid: bValid
596
735
  };
736
+ },
737
+ isNumeric: function (iDigits) {
738
+ return iDigits < 3;
597
739
  }
598
- },
599
- 'L': {
740
+ }),
741
+ 'L': DateFormat._createPatternSymbol({
600
742
  name: 'monthStandalone',
601
743
  format: function (oField, oDate, bUTC, oFormat) {
602
- var iMonth = bUTC ? oDate.getUTCMonth() : oDate.getMonth();
603
- if (oField.digits == 3) {
744
+ var iMonth = oDate.getUTCMonth();
745
+ if (oField.digits === 3) {
604
746
  return oFormat.aMonthsAbbrevSt[iMonth];
605
- } else if (oField.digits == 4) {
747
+ } else if (oField.digits === 4) {
606
748
  return oFormat.aMonthsWideSt[iMonth];
607
749
  } else if (oField.digits > 4) {
608
750
  return oFormat.aMonthsNarrowSt[iMonth];
@@ -611,20 +753,18 @@ DateFormat.prototype.oSymbols = {
611
753
  }
612
754
  },
613
755
  parse: function (sValue, oPart, oFormat, oConfig) {
614
- var aMonthsVariants = [
615
- oFormat.aMonthsWide,
616
- oFormat.aMonthsWideSt,
617
- oFormat.aMonthsAbbrev,
618
- oFormat.aMonthsAbbrevSt,
619
- oFormat.aMonthsNarrow,
620
- oFormat.aMonthsNarrowSt
621
- ];
622
- var bValid;
623
- var iMonth;
624
- var sPart;
756
+ var iMonth, sPart, bPartInvalid, bValid, aMonthsVariants = [
757
+ oFormat.aMonthsWide,
758
+ oFormat.aMonthsWideSt,
759
+ oFormat.aMonthsAbbrev,
760
+ oFormat.aMonthsAbbrevSt,
761
+ oFormat.aMonthsNarrow,
762
+ oFormat.aMonthsNarrowSt
763
+ ];
625
764
  if (oPart.digits < 3) {
626
765
  sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
627
- bValid = oParseHelper.checkValid(oPart.type, sPart === '', oFormat);
766
+ bPartInvalid = sPart === '' || oConfig.exactLength && sPart.length < 2;
767
+ bValid = oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat);
628
768
  iMonth = parseInt(sPart) - 1;
629
769
  if (oConfig.strict && (iMonth > 11 || iMonth < 0)) {
630
770
  bValid = false;
@@ -632,11 +772,11 @@ DateFormat.prototype.oSymbols = {
632
772
  } else {
633
773
  for (var i = 0; i < aMonthsVariants.length; i++) {
634
774
  var aVariants = aMonthsVariants[i];
635
- var oFound = oParseHelper.findEntry(sValue, aVariants);
775
+ var oFound = oParseHelper.findEntry(sValue, aVariants, oFormat.oLocaleData.sCLDRLocaleId);
636
776
  if (oFound.index !== -1) {
637
777
  return {
638
778
  month: oFound.index,
639
- length: oFound.value.length
779
+ length: oFound.length
640
780
  };
641
781
  }
642
782
  }
@@ -647,12 +787,15 @@ DateFormat.prototype.oSymbols = {
647
787
  length: sPart ? sPart.length : 0,
648
788
  valid: bValid
649
789
  };
790
+ },
791
+ isNumeric: function (iDigits) {
792
+ return iDigits < 3;
650
793
  }
651
- },
652
- 'w': {
794
+ }),
795
+ 'w': DateFormat._createPatternSymbol({
653
796
  name: 'weekInYear',
654
797
  format: function (oField, oDate, bUTC, oFormat) {
655
- var oWeek = bUTC ? oDate.getUTCWeek() : oDate.getWeek();
798
+ var oWeek = oDate.getUTCWeek(oFormat.oLocale, getCalendarWeekParameter(oFormat.oFormatOptions));
656
799
  var iWeek = oWeek.week;
657
800
  var sWeek = String(iWeek + 1);
658
801
  if (oField.digits < 3) {
@@ -663,22 +806,20 @@ DateFormat.prototype.oSymbols = {
663
806
  return sWeek;
664
807
  },
665
808
  parse: function (sValue, oPart, oFormat, oConfig) {
666
- var bValid;
667
- var sPart;
668
- var iWeek;
669
- var iLength = 0;
809
+ var sPart, bPartInvalid, bValid, iWeek, iLength = 0;
670
810
  if (oPart.digits < 3) {
671
811
  sPart = oParseHelper.findNumbers(sValue, 2);
672
812
  iLength = sPart.length;
673
813
  iWeek = parseInt(sPart) - 1;
674
- bValid = oParseHelper.checkValid(oPart.type, !sPart, oFormat);
814
+ bPartInvalid = !sPart || oConfig.exactLength && iLength < 2;
815
+ bValid = oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat);
675
816
  } else {
676
817
  sPart = oFormat.oLocaleData.getCalendarWeek(oPart.digits === 3 ? 'narrow' : 'wide');
677
- sPart = sPart.replace('{0}', '[0-9]+');
818
+ sPart = sPart.replace('{0}', '([0-9]+)');
678
819
  var rWeekNumber = new RegExp(sPart), oResult = rWeekNumber.exec(sValue);
679
820
  if (oResult) {
680
821
  iLength = oResult[0].length;
681
- iWeek = parseInt(oResult[0]) - 1;
822
+ iWeek = parseInt(oResult[oResult.length - 1]) - 1;
682
823
  } else {
683
824
  bValid = oParseHelper.checkValid(oPart.type, true, oFormat);
684
825
  }
@@ -688,35 +829,21 @@ DateFormat.prototype.oSymbols = {
688
829
  valid: bValid,
689
830
  week: iWeek
690
831
  };
691
- }
692
- },
693
- 'W': {
694
- name: 'weekInMonth',
695
- format: function (oField, oDate, bUTC, oFormat) {
696
- return '';
697
832
  },
698
- parse: function () {
699
- return {};
833
+ isNumeric: function (iDigits) {
834
+ return iDigits < 3;
700
835
  }
701
- },
702
- 'D': {
703
- name: 'dayInYear',
704
- format: function (oField, oDate, bUTC, oFormat) {
705
- },
706
- parse: function () {
707
- return {};
708
- }
709
- },
710
- 'd': {
836
+ }),
837
+ 'W': DateFormat._createPatternSymbol({ name: 'weekInMonth' }),
838
+ 'D': DateFormat._createPatternSymbol({ name: 'dayInYear' }),
839
+ 'd': DateFormat._createPatternSymbol({
711
840
  name: 'day',
712
- format: function (oField, oDate, bUTC, oFormat) {
713
- var iDate = bUTC ? oDate.getUTCDate() : oDate.getDate();
841
+ format: function (oField, oDate) {
842
+ var iDate = oDate.getUTCDate();
714
843
  return String(iDate).padStart(oField.digits, '0');
715
844
  },
716
845
  parse: function (sValue, oPart, oFormat, oConfig) {
717
- var sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
718
- var bValid = oParseHelper.checkValid(oPart.type, sPart === '', oFormat);
719
- var iDay = parseInt(sPart);
846
+ var sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2)), bPartInvalid = sPart === '' || oConfig.exactLength && sPart.length < 2, bValid = oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat), iDay = parseInt(sPart);
720
847
  if (oConfig.strict && (iDay > 31 || iDay < 1)) {
721
848
  bValid = false;
722
849
  }
@@ -725,15 +852,16 @@ DateFormat.prototype.oSymbols = {
725
852
  length: sPart.length,
726
853
  valid: bValid
727
854
  };
728
- }
729
- },
730
- 'Q': {
855
+ },
856
+ isNumeric: true
857
+ }),
858
+ 'Q': DateFormat._createPatternSymbol({
731
859
  name: 'quarter',
732
860
  format: function (oField, oDate, bUTC, oFormat) {
733
- var iQuarter = bUTC ? oDate.getUTCQuarter() : oDate.getQuarter();
734
- if (oField.digits == 3) {
861
+ var iQuarter = oDate.getUTCQuarter();
862
+ if (oField.digits === 3) {
735
863
  return oFormat.aQuartersAbbrev[iQuarter];
736
- } else if (oField.digits == 4) {
864
+ } else if (oField.digits === 4) {
737
865
  return oFormat.aQuartersWide[iQuarter];
738
866
  } else if (oField.digits > 4) {
739
867
  return oFormat.aQuartersNarrow[iQuarter];
@@ -742,9 +870,7 @@ DateFormat.prototype.oSymbols = {
742
870
  }
743
871
  },
744
872
  parse: function (sValue, oPart, oFormat, oConfig) {
745
- var bValid;
746
- var iQuarter;
747
- var sPart;
873
+ var sPart, bPartInvalid, iQuarter, bValid;
748
874
  var aQuartersVariants = [
749
875
  oFormat.aQuartersWide,
750
876
  oFormat.aQuartersWideSt,
@@ -755,7 +881,8 @@ DateFormat.prototype.oSymbols = {
755
881
  ];
756
882
  if (oPart.digits < 3) {
757
883
  sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
758
- bValid = oParseHelper.checkValid(oPart.type, sPart === '', oFormat);
884
+ bPartInvalid = sPart === '' || oConfig.exactLength && sPart.length < 2;
885
+ bValid = oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat);
759
886
  iQuarter = parseInt(sPart) - 1;
760
887
  if (oConfig.strict && iQuarter > 3) {
761
888
  bValid = false;
@@ -763,11 +890,11 @@ DateFormat.prototype.oSymbols = {
763
890
  } else {
764
891
  for (var i = 0; i < aQuartersVariants.length; i++) {
765
892
  var aVariants = aQuartersVariants[i];
766
- var oFound = oParseHelper.findEntry(sValue, aVariants);
893
+ var oFound = oParseHelper.findEntry(sValue, aVariants, oFormat.oLocaleData.sCLDRLocaleId);
767
894
  if (oFound.index !== -1) {
768
895
  return {
769
896
  quarter: oFound.index,
770
- length: oFound.value.length
897
+ length: oFound.length
771
898
  };
772
899
  }
773
900
  }
@@ -778,15 +905,18 @@ DateFormat.prototype.oSymbols = {
778
905
  quarter: iQuarter,
779
906
  valid: bValid
780
907
  };
908
+ },
909
+ isNumeric: function (iDigits) {
910
+ return iDigits < 3;
781
911
  }
782
- },
783
- 'q': {
912
+ }),
913
+ 'q': DateFormat._createPatternSymbol({
784
914
  name: 'quarterStandalone',
785
915
  format: function (oField, oDate, bUTC, oFormat) {
786
- var iQuarter = bUTC ? oDate.getUTCQuarter() : oDate.getQuarter();
787
- if (oField.digits == 3) {
916
+ var iQuarter = oDate.getUTCQuarter();
917
+ if (oField.digits === 3) {
788
918
  return oFormat.aQuartersAbbrevSt[iQuarter];
789
- } else if (oField.digits == 4) {
919
+ } else if (oField.digits === 4) {
790
920
  return oFormat.aQuartersWideSt[iQuarter];
791
921
  } else if (oField.digits > 4) {
792
922
  return oFormat.aQuartersNarrowSt[iQuarter];
@@ -795,9 +925,7 @@ DateFormat.prototype.oSymbols = {
795
925
  }
796
926
  },
797
927
  parse: function (sValue, oPart, oFormat, oConfig) {
798
- var bValid;
799
- var iQuarter;
800
- var sPart;
928
+ var sPart, bPartInvalid, iQuarter, bValid;
801
929
  var aQuartersVariants = [
802
930
  oFormat.aQuartersWide,
803
931
  oFormat.aQuartersWideSt,
@@ -808,7 +936,8 @@ DateFormat.prototype.oSymbols = {
808
936
  ];
809
937
  if (oPart.digits < 3) {
810
938
  sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
811
- bValid = oParseHelper.checkValid(oPart.type, sPart === '', oFormat);
939
+ bPartInvalid = sPart === '' || oConfig.exactLength && sPart.length < 2;
940
+ bValid = oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat);
812
941
  iQuarter = parseInt(sPart) - 1;
813
942
  if (oConfig.strict && iQuarter > 3) {
814
943
  bValid = false;
@@ -816,11 +945,11 @@ DateFormat.prototype.oSymbols = {
816
945
  } else {
817
946
  for (var i = 0; i < aQuartersVariants.length; i++) {
818
947
  var aVariants = aQuartersVariants[i];
819
- var oFound = oParseHelper.findEntry(sValue, aVariants);
948
+ var oFound = oParseHelper.findEntry(sValue, aVariants, oFormat.oLocaleData.sCLDRLocaleId);
820
949
  if (oFound.index !== -1) {
821
950
  return {
822
951
  quarter: oFound.index,
823
- length: oFound.value.length
952
+ length: oFound.length
824
953
  };
825
954
  }
826
955
  }
@@ -831,26 +960,21 @@ DateFormat.prototype.oSymbols = {
831
960
  quarter: iQuarter,
832
961
  valid: bValid
833
962
  };
834
- }
835
- },
836
- 'F': {
837
- name: 'dayOfWeekInMonth',
838
- format: function (oField, oDate, bUTC, oFormat) {
839
- return '';
840
963
  },
841
- parse: function () {
842
- return {};
964
+ isNumeric: function (iDigits) {
965
+ return iDigits < 3;
843
966
  }
844
- },
845
- 'E': {
967
+ }),
968
+ 'F': DateFormat._createPatternSymbol({ name: 'dayOfWeekInMonth' }),
969
+ 'E': DateFormat._createPatternSymbol({
846
970
  name: 'dayNameInWeek',
847
971
  format: function (oField, oDate, bUTC, oFormat) {
848
- var iDay = bUTC ? oDate.getUTCDay() : oDate.getDay();
972
+ var iDay = oDate.getUTCDay();
849
973
  if (oField.digits < 4) {
850
974
  return oFormat.aDaysAbbrev[iDay];
851
- } else if (oField.digits == 4) {
975
+ } else if (oField.digits === 4) {
852
976
  return oFormat.aDaysWide[iDay];
853
- } else if (oField.digits == 5) {
977
+ } else if (oField.digits === 5) {
854
978
  return oFormat.aDaysNarrow[iDay];
855
979
  } else {
856
980
  return oFormat.aDaysShort[iDay];
@@ -869,25 +993,25 @@ DateFormat.prototype.oSymbols = {
869
993
  ];
870
994
  for (var i = 0; i < aDaysVariants.length; i++) {
871
995
  var aVariants = aDaysVariants[i];
872
- var oFound = oParseHelper.findEntry(sValue, aVariants);
996
+ var oFound = oParseHelper.findEntry(sValue, aVariants, oFormat.oLocaleData.sCLDRLocaleId);
873
997
  if (oFound.index !== -1) {
874
998
  return {
875
999
  dayOfWeek: oFound.index,
876
- length: oFound.value.length
1000
+ length: oFound.length
877
1001
  };
878
1002
  }
879
1003
  }
880
1004
  }
881
- },
882
- 'c': {
1005
+ }),
1006
+ 'c': DateFormat._createPatternSymbol({
883
1007
  name: 'dayNameInWeekStandalone',
884
1008
  format: function (oField, oDate, bUTC, oFormat) {
885
- var iDay = bUTC ? oDate.getUTCDay() : oDate.getDay();
1009
+ var iDay = oDate.getUTCDay();
886
1010
  if (oField.digits < 4) {
887
1011
  return oFormat.aDaysAbbrevSt[iDay];
888
- } else if (oField.digits == 4) {
1012
+ } else if (oField.digits === 4) {
889
1013
  return oFormat.aDaysWideSt[iDay];
890
- } else if (oField.digits == 5) {
1014
+ } else if (oField.digits === 5) {
891
1015
  return oFormat.aDaysNarrowSt[iDay];
892
1016
  } else {
893
1017
  return oFormat.aDaysShortSt[iDay];
@@ -906,76 +1030,129 @@ DateFormat.prototype.oSymbols = {
906
1030
  ];
907
1031
  for (var i = 0; i < aDaysVariants.length; i++) {
908
1032
  var aVariants = aDaysVariants[i];
909
- var oFound = oParseHelper.findEntry(sValue, aVariants);
1033
+ var oFound = oParseHelper.findEntry(sValue, aVariants, oFormat.oLocaleData.sCLDRLocaleId);
910
1034
  if (oFound.index !== -1) {
911
1035
  return {
912
1036
  day: oFound.index,
913
- length: oFound.value.length
1037
+ length: oFound.length
914
1038
  };
915
1039
  }
916
1040
  }
917
1041
  }
918
- },
919
- 'u': {
1042
+ }),
1043
+ 'u': DateFormat._createPatternSymbol({
920
1044
  name: 'dayNumberOfWeek',
921
1045
  format: function (oField, oDate, bUTC, oFormat) {
922
- var iDay = bUTC ? oDate.getUTCDay() : oDate.getDay();
1046
+ var iDay = oDate.getUTCDay();
923
1047
  return oFormat._adaptDayOfWeek(iDay);
924
1048
  },
925
1049
  parse: function (sValue, oPart, oFormat, oConfig) {
926
- var sPart = oParseHelper.findNumbers(sValue, oPart.digits);
1050
+ var sPart = oParseHelper.findNumbers(sValue, oPart.digits), bPartInvalid = oConfig.exactLength && sPart.length !== oPart.digits;
927
1051
  return {
928
1052
  dayNumberOfWeek: parseInt(sPart),
929
- length: sPart.length
1053
+ length: sPart.length,
1054
+ valid: oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat)
930
1055
  };
931
- }
932
- },
933
- 'a': {
1056
+ },
1057
+ isNumeric: true
1058
+ }),
1059
+ 'a': DateFormat._createPatternSymbol({
934
1060
  name: 'amPmMarker',
935
1061
  format: function (oField, oDate, bUTC, oFormat) {
936
- var iDayPeriod = bUTC ? oDate.getUTCDayPeriod() : oDate.getDayPeriod();
937
- return oFormat.aDayPeriods[iDayPeriod];
1062
+ var iDayPeriod = oDate.getUTCDayPeriod();
1063
+ if (oField.digits <= 3) {
1064
+ return oFormat.aDayPeriodsAbbrev[iDayPeriod];
1065
+ } else if (oField.digits === 4) {
1066
+ return oFormat.aDayPeriodsWide[iDayPeriod];
1067
+ } else {
1068
+ return oFormat.aDayPeriodsNarrow[iDayPeriod];
1069
+ }
1070
+ },
1071
+ parse: function (sValue, oPart, oFormat, oConfig, sTimezone) {
1072
+ var rAMPM, bAMPMAlternativeCase, oEntry, i, aMatch, normalize, aVariants, aDayPeriodsVariants = [
1073
+ oFormat.aDayPeriodsWide,
1074
+ oFormat.aDayPeriodsAbbrev,
1075
+ oFormat.aDayPeriodsNarrow
1076
+ ];
1077
+ rAMPM = /[aApP](?:\.)?[\x20\xA0]?[mM](?:\.)?/;
1078
+ aMatch = sValue.match(rAMPM);
1079
+ bAMPMAlternativeCase = aMatch && aMatch.index === 0;
1080
+ function normalize(sValue) {
1081
+ return sValue.replace(/[\x20\xA0]/g, '').replace(/\./g, '');
1082
+ }
1083
+ if (bAMPMAlternativeCase) {
1084
+ sValue = normalize(sValue);
1085
+ }
1086
+ for (i = 0; i < aDayPeriodsVariants.length; i += 1) {
1087
+ aVariants = aDayPeriodsVariants[i];
1088
+ if (bAMPMAlternativeCase) {
1089
+ aVariants = aVariants.map(normalize);
1090
+ }
1091
+ oEntry = oParseHelper.findEntry(sValue, aVariants, oFormat.oLocaleData.sCLDRLocaleId);
1092
+ if (oEntry.index !== -1) {
1093
+ return {
1094
+ pm: oEntry.index === 1,
1095
+ length: bAMPMAlternativeCase ? aMatch[0].length : oEntry.length
1096
+ };
1097
+ }
1098
+ }
1099
+ return { valid: false };
1100
+ }
1101
+ }),
1102
+ 'B': DateFormat._createPatternSymbol({
1103
+ name: 'flexibleDayPeriod',
1104
+ format: function (oField, oDate, bUTC, oFormat) {
1105
+ var bContainsHour = oFormat.aFormatArray.some(function (oFormatElement) {
1106
+ return 'hHKk'.includes(oFormatElement.symbol);
1107
+ }), sFlexibleDayPeriod = oFormat.oLocaleData.getFlexibleDayPeriodOfTime(oDate.getUTCHours(), oDate.getUTCMinutes());
1108
+ if (bContainsHour) {
1109
+ if (oField.digits <= 3) {
1110
+ return oFormat.oFlexibleDayPeriodsAbbrev[sFlexibleDayPeriod];
1111
+ }
1112
+ if (oField.digits === 4) {
1113
+ return oFormat.oFlexibleDayPeriodsWide[sFlexibleDayPeriod];
1114
+ }
1115
+ return oFormat.oFlexibleDayPeriodsNarrow[sFlexibleDayPeriod];
1116
+ }
1117
+ if (oField.digits <= 3) {
1118
+ return oFormat.oFlexibleDayPeriodsAbbrevSt[sFlexibleDayPeriod];
1119
+ }
1120
+ if (oField.digits === 4) {
1121
+ return oFormat.oFlexibleDayPeriodsWideSt[sFlexibleDayPeriod];
1122
+ }
1123
+ return oFormat.oFlexibleDayPeriodsNarrowSt[sFlexibleDayPeriod];
938
1124
  },
939
1125
  parse: function (sValue, oPart, oFormat, oConfig) {
940
- var bPM;
941
- var iLength;
942
- var sAM = oFormat.aDayPeriods[0], sPM = oFormat.aDayPeriods[1];
943
- var rAMPM = /[aApP](?:\.)?[\x20\xA0]?[mM](?:\.)?/;
944
- var aMatch = sValue.match(rAMPM);
945
- var bVariant = aMatch && aMatch.index === 0;
946
- if (bVariant) {
947
- sValue = aMatch[0];
948
- sAM = sAM.replace(/[\x20\xA0]/g, '');
949
- sPM = sPM.replace(/[\x20\xA0]/g, '');
950
- sValue = sValue.replace(/[\x20\xA0]/g, '');
951
- sAM = sAM.replace(/\./g, '').toLowerCase();
952
- sPM = sPM.replace(/\./g, '').toLowerCase();
953
- sValue = sValue.replace(/\./g, '').toLowerCase();
954
- }
955
- if (sValue.indexOf(sAM) === 0) {
956
- bPM = false;
957
- iLength = bVariant ? aMatch[0].length : sAM.length;
958
- } else if (sValue.indexOf(sPM) === 0) {
959
- bPM = true;
960
- iLength = bVariant ? aMatch[0].length : sPM.length;
1126
+ var i, oFound, oVariant, bContainsHour = oFormat.aFormatArray.some(function (oFormatElement) {
1127
+ return 'hHKk'.includes(oFormatElement.symbol);
1128
+ }), aFlexibleDayPeriodVariants = [
1129
+ oFormat.oFlexibleDayPeriodsWide,
1130
+ oFormat.oFlexibleDayPeriodsAbbrev,
1131
+ oFormat.oFlexibleDayPeriodsNarrow
1132
+ ];
1133
+ if (bContainsHour) {
1134
+ for (i = 0; i < aFlexibleDayPeriodVariants.length; i++) {
1135
+ oVariant = aFlexibleDayPeriodVariants[i];
1136
+ oFound = oParseHelper.findEntry(sValue, Object.values(oVariant), oFormat.oLocaleData.sCLDRLocaleId);
1137
+ if (oFound.index !== -1) {
1138
+ return {
1139
+ flexDayPeriod: Object.keys(oVariant)[oFound.index],
1140
+ length: oFound.length
1141
+ };
1142
+ }
1143
+ }
961
1144
  }
962
- return {
963
- pm: bPM,
964
- length: iLength
965
- };
1145
+ return { valid: false };
966
1146
  }
967
- },
968
- 'H': {
1147
+ }),
1148
+ 'H': DateFormat._createPatternSymbol({
969
1149
  name: 'hour0_23',
970
- format: function (oField, oDate, bUTC, oFormat) {
971
- var iHours = bUTC ? oDate.getUTCHours() : oDate.getHours();
1150
+ format: function (oField, oDate) {
1151
+ var iHours = oDate.getUTCHours();
972
1152
  return String(iHours).padStart(oField.digits, '0');
973
1153
  },
974
1154
  parse: function (sValue, oPart, oFormat, oConfig) {
975
- var bValid;
976
- var sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
977
- var iHours = parseInt(sPart);
978
- bValid = oParseHelper.checkValid(oPart.type, sPart === '', oFormat);
1155
+ var sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2)), iHours = parseInt(sPart), bPartInvalid = sPart === '' || oConfig.exactLength && sPart.length < 2, bValid = oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat);
979
1156
  if (oConfig.strict && iHours > 23) {
980
1157
  bValid = false;
981
1158
  }
@@ -984,21 +1161,19 @@ DateFormat.prototype.oSymbols = {
984
1161
  length: sPart.length,
985
1162
  valid: bValid
986
1163
  };
987
- }
988
- },
989
- 'k': {
1164
+ },
1165
+ isNumeric: true
1166
+ }),
1167
+ 'k': DateFormat._createPatternSymbol({
990
1168
  name: 'hour1_24',
991
- format: function (oField, oDate, bUTC, oFormat) {
992
- var iHours = bUTC ? oDate.getUTCHours() : oDate.getHours();
1169
+ format: function (oField, oDate) {
1170
+ var iHours = oDate.getUTCHours();
993
1171
  var sHours = iHours === 0 ? '24' : String(iHours);
994
1172
  return sHours.padStart(oField.digits, '0');
995
1173
  },
996
1174
  parse: function (sValue, oPart, oFormat, oConfig) {
997
- var bValid;
998
- var sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
999
- var iHours = parseInt(sPart);
1000
- bValid = oParseHelper.checkValid(oPart.type, sPart === '', oFormat);
1001
- if (iHours == 24) {
1175
+ var sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2)), iHours = parseInt(sPart), bPartInvalid = sPart === '' || oConfig.exactLength && sPart.length < 2, bValid = oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat);
1176
+ if (iHours === 24) {
1002
1177
  iHours = 0;
1003
1178
  }
1004
1179
  if (oConfig.strict && iHours > 23) {
@@ -1009,20 +1184,18 @@ DateFormat.prototype.oSymbols = {
1009
1184
  length: sPart.length,
1010
1185
  valid: bValid
1011
1186
  };
1012
- }
1013
- },
1014
- 'K': {
1187
+ },
1188
+ isNumeric: true
1189
+ }),
1190
+ 'K': DateFormat._createPatternSymbol({
1015
1191
  name: 'hour0_11',
1016
- format: function (oField, oDate, bUTC, oFormat) {
1017
- var iHours = bUTC ? oDate.getUTCHours() : oDate.getHours();
1192
+ format: function (oField, oDate) {
1193
+ var iHours = oDate.getUTCHours();
1018
1194
  var sHours = String(iHours > 11 ? iHours - 12 : iHours);
1019
1195
  return sHours.padStart(oField.digits, '0');
1020
1196
  },
1021
1197
  parse: function (sValue, oPart, oFormat, oConfig) {
1022
- var bValid;
1023
- var sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
1024
- var iHours = parseInt(sPart);
1025
- bValid = oParseHelper.checkValid(oPart.type, sPart === '', oFormat);
1198
+ var sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2)), iHours = parseInt(sPart), bPartInvalid = sPart === '' || oConfig.exactLength && sPart.length < 2, bValid = oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat);
1026
1199
  if (oConfig.strict && iHours > 11) {
1027
1200
  bValid = false;
1028
1201
  }
@@ -1031,16 +1204,17 @@ DateFormat.prototype.oSymbols = {
1031
1204
  length: sPart.length,
1032
1205
  valid: bValid
1033
1206
  };
1034
- }
1035
- },
1036
- 'h': {
1207
+ },
1208
+ isNumeric: true
1209
+ }),
1210
+ 'h': DateFormat._createPatternSymbol({
1037
1211
  name: 'hour1_12',
1038
- format: function (oField, oDate, bUTC, oFormat) {
1039
- var iHours = bUTC ? oDate.getUTCHours() : oDate.getHours();
1212
+ format: function (oField, oDate) {
1213
+ var iHours = oDate.getUTCHours();
1040
1214
  var sHours;
1041
1215
  if (iHours > 12) {
1042
1216
  sHours = String(iHours - 12);
1043
- } else if (iHours == 0) {
1217
+ } else if (iHours === 0) {
1044
1218
  sHours = '12';
1045
1219
  } else {
1046
1220
  sHours = String(iHours);
@@ -1048,11 +1222,8 @@ DateFormat.prototype.oSymbols = {
1048
1222
  return sHours.padStart(oField.digits, '0');
1049
1223
  },
1050
1224
  parse: function (sValue, oPart, oFormat, oConfig) {
1051
- var bPM = oConfig.dateValue.pm;
1052
- var sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
1053
- var iHours = parseInt(sPart);
1054
- var bValid = oParseHelper.checkValid(oPart.type, sPart === '', oFormat);
1055
- if (iHours == 12) {
1225
+ var bPM = oConfig.dateValue.pm, sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2)), iHours = parseInt(sPart), bPartInvalid = sPart === '' || oConfig.exactLength && sPart.length < 2, bValid = oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat);
1226
+ if (iHours === 12) {
1056
1227
  iHours = 0;
1057
1228
  bPM = bPM === undefined ? true : bPM;
1058
1229
  }
@@ -1065,19 +1236,17 @@ DateFormat.prototype.oSymbols = {
1065
1236
  pm: bPM,
1066
1237
  valid: bValid
1067
1238
  };
1068
- }
1069
- },
1070
- 'm': {
1239
+ },
1240
+ isNumeric: true
1241
+ }),
1242
+ 'm': DateFormat._createPatternSymbol({
1071
1243
  name: 'minute',
1072
- format: function (oField, oDate, bUTC, oFormat) {
1073
- var iMinutes = bUTC ? oDate.getUTCMinutes() : oDate.getMinutes();
1244
+ format: function (oField, oDate) {
1245
+ var iMinutes = oDate.getUTCMinutes();
1074
1246
  return String(iMinutes).padStart(oField.digits, '0');
1075
1247
  },
1076
1248
  parse: function (sValue, oPart, oFormat, oConfig) {
1077
- var bValid;
1078
- var sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
1079
- var iMinutes = parseInt(sPart);
1080
- bValid = oParseHelper.checkValid(oPart.type, sPart === '', oFormat);
1249
+ var sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2)), iMinutes = parseInt(sPart), bPartInvalid = sPart === '' || oConfig.exactLength && sPart.length < 2, bValid = oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat);
1081
1250
  if (oConfig.strict && iMinutes > 59) {
1082
1251
  bValid = false;
1083
1252
  }
@@ -1086,19 +1255,17 @@ DateFormat.prototype.oSymbols = {
1086
1255
  minute: iMinutes,
1087
1256
  valid: bValid
1088
1257
  };
1089
- }
1090
- },
1091
- 's': {
1258
+ },
1259
+ isNumeric: true
1260
+ }),
1261
+ 's': DateFormat._createPatternSymbol({
1092
1262
  name: 'second',
1093
- format: function (oField, oDate, bUTC, oFormat) {
1094
- var iSeconds = bUTC ? oDate.getUTCSeconds() : oDate.getSeconds();
1263
+ format: function (oField, oDate) {
1264
+ var iSeconds = oDate.getUTCSeconds();
1095
1265
  return String(iSeconds).padStart(oField.digits, '0');
1096
1266
  },
1097
1267
  parse: function (sValue, oPart, oFormat, oConfig) {
1098
- var bValid;
1099
- var sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
1100
- var iSeconds = parseInt(sPart);
1101
- bValid = oParseHelper.checkValid(oPart.type, sPart === '', oFormat);
1268
+ var iExpectedDigits = Math.max(oPart.digits, 2), sPart = oParseHelper.findNumbers(sValue, iExpectedDigits), bPartInvalid = sPart === '' || oConfig.exactLength && sPart.length < iExpectedDigits, iSeconds = parseInt(sPart), bValid = oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat);
1102
1269
  if (oConfig.strict && iSeconds > 59) {
1103
1270
  bValid = false;
1104
1271
  }
@@ -1107,12 +1274,13 @@ DateFormat.prototype.oSymbols = {
1107
1274
  second: iSeconds,
1108
1275
  valid: bValid
1109
1276
  };
1110
- }
1111
- },
1112
- 'S': {
1277
+ },
1278
+ isNumeric: true
1279
+ }),
1280
+ 'S': DateFormat._createPatternSymbol({
1113
1281
  name: 'fractionalsecond',
1114
- format: function (oField, oDate, bUTC, oFormat) {
1115
- var iMilliseconds = bUTC ? oDate.getUTCMilliseconds() : oDate.getMilliseconds();
1282
+ format: function (oField, oDate) {
1283
+ var iMilliseconds = oDate.getUTCMilliseconds();
1116
1284
  var sMilliseconds = String(iMilliseconds);
1117
1285
  var sFractionalseconds = sMilliseconds.padStart(3, '0');
1118
1286
  sFractionalseconds = sFractionalseconds.substr(0, oField.digits);
@@ -1120,31 +1288,33 @@ DateFormat.prototype.oSymbols = {
1120
1288
  return sFractionalseconds;
1121
1289
  },
1122
1290
  parse: function (sValue, oPart, oFormat, oConfig) {
1123
- var sPart = oParseHelper.findNumbers(sValue, oPart.digits);
1124
- var iLength = sPart.length;
1291
+ var sPart = oParseHelper.findNumbers(sValue, oPart.digits), iLength = sPart.length, bPartInvalid = oConfig.exactLength && iLength < oPart.digits;
1125
1292
  sPart = sPart.substr(0, 3);
1126
1293
  sPart = sPart.padEnd(3, '0');
1127
1294
  var iMilliseconds = parseInt(sPart);
1128
1295
  return {
1129
1296
  length: iLength,
1130
- millisecond: iMilliseconds
1297
+ millisecond: iMilliseconds,
1298
+ valid: oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat)
1131
1299
  };
1132
- }
1133
- },
1134
- 'z': {
1300
+ },
1301
+ isNumeric: true
1302
+ }),
1303
+ 'z': DateFormat._createPatternSymbol({
1135
1304
  name: 'timezoneGeneral',
1136
- format: function (oField, oDate, bUTC, oFormat) {
1305
+ format: function (oField, oDate, bUTC, oFormat, sTimezone) {
1137
1306
  if (oField.digits > 3 && oDate.getTimezoneLong && oDate.getTimezoneLong()) {
1138
1307
  return oDate.getTimezoneLong();
1139
1308
  } else if (oDate.getTimezoneShort && oDate.getTimezoneShort()) {
1140
1309
  return oDate.getTimezoneShort();
1141
1310
  }
1311
+ var iTimezoneOffset = TimezoneUtil.calculateOffset(oDate, sTimezone);
1142
1312
  var sTimeZone = 'GMT';
1143
- var iTZOffset = Math.abs(oDate.getTimezoneOffset());
1144
- var bPositiveOffset = oDate.getTimezoneOffset() > 0;
1313
+ var iTZOffset = Math.abs(iTimezoneOffset / 60);
1314
+ var bPositiveOffset = iTimezoneOffset > 0;
1145
1315
  var iHourOffset = Math.floor(iTZOffset / 60);
1146
- var iMinuteOffset = iTZOffset % 60;
1147
- if (!bUTC && iTZOffset != 0) {
1316
+ var iMinuteOffset = Math.floor(iTZOffset % 60);
1317
+ if (!bUTC && iTZOffset !== 0) {
1148
1318
  sTimeZone += bPositiveOffset ? '-' : '+';
1149
1319
  sTimeZone += String(iHourOffset).padStart(2, '0');
1150
1320
  sTimeZone += ':';
@@ -1178,14 +1348,15 @@ DateFormat.prototype.oSymbols = {
1178
1348
  tzDiff: iTZDiff
1179
1349
  };
1180
1350
  }
1181
- },
1182
- 'Z': {
1351
+ }),
1352
+ 'Z': DateFormat._createPatternSymbol({
1183
1353
  name: 'timezoneRFC822',
1184
- format: function (oField, oDate, bUTC, oFormat) {
1185
- var iTZOffset = Math.abs(oDate.getTimezoneOffset());
1186
- var bPositiveOffset = oDate.getTimezoneOffset() > 0;
1354
+ format: function (oField, oDate, bUTC, oFormat, sTimezone) {
1355
+ var iTimezoneOffset = TimezoneUtil.calculateOffset(oDate, sTimezone);
1356
+ var iTZOffset = Math.abs(iTimezoneOffset / 60);
1357
+ var bPositiveOffset = iTimezoneOffset > 0;
1187
1358
  var iHourOffset = Math.floor(iTZOffset / 60);
1188
- var iMinuteOffset = iTZOffset % 60;
1359
+ var iMinuteOffset = Math.floor(iTZOffset % 60);
1189
1360
  var sTimeZone = '';
1190
1361
  if (!bUTC) {
1191
1362
  sTimeZone += bPositiveOffset ? '-' : '+';
@@ -1197,16 +1368,17 @@ DateFormat.prototype.oSymbols = {
1197
1368
  parse: function (sValue, oPart, oFormat, oConfig) {
1198
1369
  return oParseHelper.parseTZ(sValue, false);
1199
1370
  }
1200
- },
1201
- 'X': {
1371
+ }),
1372
+ 'X': DateFormat._createPatternSymbol({
1202
1373
  name: 'timezoneISO8601',
1203
- format: function (oField, oDate, bUTC, oFormat) {
1204
- var iTZOffset = Math.abs(oDate.getTimezoneOffset());
1205
- var bPositiveOffset = oDate.getTimezoneOffset() > 0;
1374
+ format: function (oField, oDate, bUTC, oFormat, sTimezone) {
1375
+ var iTimezoneOffset = TimezoneUtil.calculateOffset(oDate, sTimezone);
1376
+ var iTZOffset = Math.abs(iTimezoneOffset / 60);
1377
+ var bPositiveOffset = iTimezoneOffset > 0;
1206
1378
  var iHourOffset = Math.floor(iTZOffset / 60);
1207
- var iMinuteOffset = iTZOffset % 60;
1379
+ var iMinuteOffset = Math.floor(iTZOffset % 60);
1208
1380
  var sTimeZone = '';
1209
- if (!bUTC && iTZOffset != 0) {
1381
+ if (!bUTC && iTZOffset !== 0) {
1210
1382
  sTimeZone += bPositiveOffset ? '-' : '+';
1211
1383
  sTimeZone += String(iHourOffset).padStart(2, '0');
1212
1384
  if (oField.digits > 1 || iMinuteOffset > 0) {
@@ -1230,11 +1402,52 @@ DateFormat.prototype.oSymbols = {
1230
1402
  return oParseHelper.parseTZ(sValue, oPart.digits === 3 || oPart.digits === 5);
1231
1403
  }
1232
1404
  }
1233
- }
1405
+ }),
1406
+ 'V': DateFormat._createPatternSymbol({
1407
+ name: 'timezoneID',
1408
+ format: function (oField, oDate, bUTC, oFormat, sTimezone) {
1409
+ if (!bUTC && oField.digits === 2) {
1410
+ return oFormat.oLocaleData.getTimezoneTranslations()[sTimezone] || sTimezone;
1411
+ }
1412
+ return '';
1413
+ },
1414
+ parse: function (sValue, oPart, oFormat, oConfig, sTimezone) {
1415
+ var oTimezoneParsed = {
1416
+ timezone: '',
1417
+ length: 0
1418
+ };
1419
+ if (oPart.digits === 2) {
1420
+ var mTimezoneTranslations = oFormat.oLocaleData.getTimezoneTranslations();
1421
+ if (sValue === mTimezoneTranslations[sTimezone]) {
1422
+ return {
1423
+ timezone: sTimezone,
1424
+ length: sValue.length
1425
+ };
1426
+ }
1427
+ var aTimezoneTranslations = Object.values(mTimezoneTranslations);
1428
+ var oTimezoneResult = oParseHelper.findEntry(sValue, aTimezoneTranslations, oFormat.oLocaleData.sCLDRLocaleId);
1429
+ if (oTimezoneResult.index !== -1) {
1430
+ return {
1431
+ timezone: Object.keys(mTimezoneTranslations)[oTimezoneResult.index],
1432
+ length: oTimezoneResult.length
1433
+ };
1434
+ }
1435
+ var sCurrentValue = '';
1436
+ for (var i = 0; i < sValue.length; i++) {
1437
+ sCurrentValue += sValue[i];
1438
+ if (TimezoneUtil.isValidTimezone(sCurrentValue)) {
1439
+ oTimezoneParsed.timezone = sCurrentValue;
1440
+ oTimezoneParsed.length = sCurrentValue.length;
1441
+ }
1442
+ }
1443
+ }
1444
+ return oTimezoneParsed;
1445
+ }
1446
+ })
1234
1447
  };
1235
- DateFormat.prototype._format = function (oJSDate, bUTC) {
1448
+ DateFormat.prototype._format = function (oJSDate, bUTC, sTimezone) {
1236
1449
  if (this.oFormatOptions.relative) {
1237
- var sRes = this.formatRelative(oJSDate, bUTC, this.oFormatOptions.relativeRange);
1450
+ var sRes = this.formatRelative(oJSDate, bUTC, this.oFormatOptions.relativeRange, sTimezone);
1238
1451
  if (sRes) {
1239
1452
  return sRes;
1240
1453
  }
@@ -1245,10 +1458,10 @@ DateFormat.prototype._format = function (oJSDate, bUTC) {
1245
1458
  for (var i = 0; i < this.aFormatArray.length; i++) {
1246
1459
  oPart = this.aFormatArray[i];
1247
1460
  sSymbol = oPart.symbol || '';
1248
- aBuffer.push(this.oSymbols[sSymbol].format(oPart, oDate, bUTC, this));
1461
+ aBuffer.push(this.oSymbols[sSymbol].format(oPart, oDate, bUTC, this, sTimezone));
1249
1462
  }
1250
1463
  sResult = aBuffer.join('');
1251
- if (Core.getConfiguration().getOriginInfo()) {
1464
+ if (Configuration.getOriginInfo()) {
1252
1465
  sResult = new String(sResult);
1253
1466
  sResult.originInfo = {
1254
1467
  source: 'Common Locale Data Repository',
@@ -1260,10 +1473,21 @@ DateFormat.prototype._format = function (oJSDate, bUTC) {
1260
1473
  return sResult;
1261
1474
  };
1262
1475
  DateFormat.prototype.format = function (vJSDate, bUTC) {
1476
+ var sTimezone;
1477
+ if (this.type === mDateFormatTypes.DATETIME_WITH_TIMEZONE) {
1478
+ sTimezone = bUTC;
1479
+ bUTC = false;
1480
+ checkTimezoneParameterType(sTimezone);
1481
+ if (sTimezone && !TimezoneUtil.isValidTimezone(sTimezone)) {
1482
+ Log.error('The given timezone isn\'t valid.');
1483
+ return '';
1484
+ }
1485
+ }
1263
1486
  var sCalendarType = this.oFormatOptions.calendarType, sResult;
1264
1487
  if (bUTC === undefined) {
1265
1488
  bUTC = this.oFormatOptions.UTC;
1266
1489
  }
1490
+ sTimezone = sTimezone || Configuration.getTimezone();
1267
1491
  if (Array.isArray(vJSDate)) {
1268
1492
  if (!this.oFormatOptions.interval) {
1269
1493
  Log.error('Non-interval DateFormat can\'t format more than one date instance.');
@@ -1273,27 +1497,30 @@ DateFormat.prototype.format = function (vJSDate, bUTC) {
1273
1497
  Log.error('Interval DateFormat can only format with 2 date instances but ' + vJSDate.length + ' is given.');
1274
1498
  return '';
1275
1499
  }
1500
+ vJSDate = vJSDate.map(function (oJSDate) {
1501
+ return convertToTimezone(oJSDate, sTimezone, bUTC);
1502
+ });
1276
1503
  if (this.oFormatOptions.singleIntervalValue) {
1277
1504
  if (vJSDate[0] === null) {
1278
1505
  Log.error('First date instance which is passed to the interval DateFormat shouldn\'t be null.');
1279
1506
  return '';
1280
1507
  }
1281
1508
  if (vJSDate[1] === null) {
1282
- sResult = this._format(vJSDate[0], bUTC);
1509
+ sResult = this._format(vJSDate[0], bUTC, sTimezone);
1283
1510
  }
1284
1511
  }
1285
1512
  if (sResult === undefined) {
1286
- var bValid = vJSDate.every(function (oJSDate) {
1287
- return oJSDate && !isNaN(oJSDate.getTime());
1288
- });
1289
- if (!bValid) {
1513
+ if (!vJSDate.every(isValidDateObject)) {
1290
1514
  Log.error('At least one date instance which is passed to the interval DateFormat isn\'t valid.');
1291
1515
  return '';
1292
1516
  }
1293
1517
  sResult = this._formatInterval(vJSDate, bUTC);
1294
1518
  }
1295
1519
  } else {
1296
- if (!vJSDate || isNaN(vJSDate.getTime())) {
1520
+ if (!isValidDateObject(vJSDate)) {
1521
+ if (this.type === mDateFormatTypes.DATETIME_WITH_TIMEZONE && this.oFormatOptions.pattern.includes('VV')) {
1522
+ return this.oLocaleData.getTimezoneTranslations()[sTimezone] || sTimezone;
1523
+ }
1297
1524
  Log.error('The given date instance isn\'t valid.');
1298
1525
  return '';
1299
1526
  }
@@ -1301,32 +1528,39 @@ DateFormat.prototype.format = function (vJSDate, bUTC) {
1301
1528
  Log.error('Interval DateFormat expects an array with two dates for the first argument but only one date is given.');
1302
1529
  return '';
1303
1530
  }
1304
- sResult = this._format(vJSDate, bUTC);
1531
+ vJSDate = convertToTimezone(vJSDate, sTimezone, bUTC);
1532
+ sResult = this._format(vJSDate, bUTC, sTimezone);
1305
1533
  }
1306
- if (sCalendarType == CalendarType.Japanese && this.oLocale.getLanguage() === 'ja') {
1534
+ if (sCalendarType === CalendarType.Japanese && this.oLocale.getLanguage() === 'ja') {
1307
1535
  sResult = sResult.replace(/(^|[^\d])1年/g, '$1元年');
1308
1536
  }
1309
1537
  return sResult;
1310
1538
  };
1539
+ DateFormat.prototype._useCustomIntervalDelimiter = function (oDiffFields) {
1540
+ var aTokens;
1541
+ if (!this.oFormatOptions.intervalDelimiter) {
1542
+ return false;
1543
+ }
1544
+ if (this.oFormatOptions.format) {
1545
+ aTokens = this.oLocaleData._parseSkeletonFormat(this.oFormatOptions.format);
1546
+ return aTokens.some(function (oToken) {
1547
+ return oDiffFields[oToken.group];
1548
+ });
1549
+ }
1550
+ return true;
1551
+ };
1311
1552
  DateFormat.prototype._formatInterval = function (aJSDates, bUTC) {
1312
- var sCalendarType = this.oFormatOptions.calendarType;
1313
- var oFromDate = UniversalDate.getInstance(aJSDates[0], sCalendarType);
1314
- var oToDate = UniversalDate.getInstance(aJSDates[1], sCalendarType);
1315
- var oDate;
1316
- var oPart;
1317
- var sSymbol;
1318
- var aBuffer = [];
1319
- var sPattern;
1320
- var aFormatArray = [];
1321
- var oDiffField = this._getGreatestDiffField([
1322
- oFromDate,
1323
- oToDate
1324
- ], bUTC);
1325
- if (!oDiffField) {
1553
+ var oDate, oPart, sPattern, sSymbol, aBuffer = [], sCalendarType = this.oFormatOptions.calendarType, aFormatArray = [], oFromDate = UniversalDate.getInstance(aJSDates[0], sCalendarType), oToDate = UniversalDate.getInstance(aJSDates[1], sCalendarType), oDiffFields = this._getDiffFields([
1554
+ oFromDate,
1555
+ oToDate
1556
+ ]);
1557
+ if (!oDiffFields) {
1326
1558
  return this._format(aJSDates[0], bUTC);
1327
1559
  }
1328
- if (this.oFormatOptions.format) {
1329
- sPattern = this.oLocaleData.getCustomIntervalPattern(this.oFormatOptions.format, oDiffField, sCalendarType);
1560
+ if (this._useCustomIntervalDelimiter(oDiffFields)) {
1561
+ sPattern = this.intervalPatterns[0];
1562
+ } else if (this.oFormatOptions.format) {
1563
+ sPattern = this.oLocaleData.getCustomIntervalPattern(this.oFormatOptions.format, oDiffFields, sCalendarType);
1330
1564
  } else {
1331
1565
  sPattern = this.oLocaleData.getCombinedIntervalPattern(this.oFormatOptions.pattern, sCalendarType);
1332
1566
  }
@@ -1354,10 +1588,10 @@ var mFieldToGroup = {
1354
1588
  Minutes: 'Minute',
1355
1589
  Seconds: 'Second'
1356
1590
  };
1357
- DateFormat.prototype._getGreatestDiffField = function (aDates, bUTC) {
1591
+ DateFormat.prototype._getDiffFields = function (aDates) {
1358
1592
  var bDiffFound = false, mDiff = {};
1359
1593
  this.aIntervalCompareFields.forEach(function (sField) {
1360
- var sGetterPrefix = 'get' + (bUTC ? 'UTC' : ''), sMethodName = sGetterPrefix + sField, sFieldGroup = mFieldToGroup[sField], vFromValue = aDates[0][sMethodName].apply(aDates[0]), vToValue = aDates[1][sMethodName].apply(aDates[1]);
1594
+ var sGetterPrefix = 'getUTC', sMethodName = sGetterPrefix + sField, sFieldGroup = mFieldToGroup[sField], vFromValue = aDates[0][sMethodName].apply(aDates[0]), vToValue = aDates[1][sMethodName].apply(aDates[1]);
1361
1595
  if (!deepEqual(vFromValue, vToValue)) {
1362
1596
  bDiffFound = true;
1363
1597
  mDiff[sFieldGroup] = true;
@@ -1368,19 +1602,32 @@ DateFormat.prototype._getGreatestDiffField = function (aDates, bUTC) {
1368
1602
  }
1369
1603
  return null;
1370
1604
  };
1371
- DateFormat.prototype._parse = function (sValue, aFormatArray, bUTC, bStrict) {
1372
- var iIndex = 0, oPart, sSubValue, oResult;
1373
- var oDateValue = { valid: true };
1374
- var oParseConf = {
1375
- formatArray: aFormatArray,
1376
- dateValue: oDateValue,
1377
- strict: bStrict
1378
- };
1605
+ DateFormat.prototype._parse = function (sValue, aFormatArray, bUTC, bStrict, sTimezone) {
1606
+ var sFlexibleDayPeriod, oNextPart, oPart, bPM, oPrevPart, oResult, sSubValue, oDateValue = {
1607
+ valid: true,
1608
+ lastTimezonePatternSymbol: ''
1609
+ }, iIndex = 0, oParseConf = {
1610
+ formatArray: aFormatArray,
1611
+ dateValue: oDateValue,
1612
+ strict: bStrict
1613
+ }, that = this;
1614
+ function getSymbol(oPart0) {
1615
+ return that.oSymbols[oPart0.symbol || ''];
1616
+ }
1617
+ function isNumeric(oPart0) {
1618
+ return !!oPart0 && getSymbol(oPart0).isNumeric(oPart0.digits);
1619
+ }
1379
1620
  for (var i = 0; i < aFormatArray.length; i++) {
1380
1621
  sSubValue = sValue.substr(iIndex);
1381
1622
  oPart = aFormatArray[i];
1623
+ oPrevPart = aFormatArray[i - 1];
1624
+ oNextPart = aFormatArray[i + 1];
1382
1625
  oParseConf.index = i;
1383
- oResult = this.oSymbols[oPart.symbol || ''].parse(sSubValue, oPart, this, oParseConf) || {};
1626
+ oParseConf.exactLength = isNumeric(oPart) && (isNumeric(oPrevPart) || isNumeric(oNextPart));
1627
+ oResult = getSymbol(oPart).parse(sSubValue, oPart, this, oParseConf, sTimezone) || {};
1628
+ if (oResult.tzDiff !== undefined || oResult.timezone) {
1629
+ oResult.lastTimezonePatternSymbol = oPart.symbol;
1630
+ }
1384
1631
  oDateValue = extend(oDateValue, oResult);
1385
1632
  if (oResult.valid === false) {
1386
1633
  break;
@@ -1388,7 +1635,12 @@ DateFormat.prototype._parse = function (sValue, aFormatArray, bUTC, bStrict) {
1388
1635
  iIndex += oResult.length || 0;
1389
1636
  }
1390
1637
  oDateValue.index = iIndex;
1391
- if (oDateValue.pm) {
1638
+ bPM = oDateValue.pm;
1639
+ if (oDateValue.flexDayPeriod && oDateValue.hour * 60 + (oDateValue.minute || 0) < 720) {
1640
+ sFlexibleDayPeriod = this.oLocaleData.getFlexibleDayPeriodOfTime(oDateValue.hour + 12, oDateValue.minute || 0);
1641
+ bPM = oDateValue.flexDayPeriod === sFlexibleDayPeriod;
1642
+ }
1643
+ if (bPM) {
1392
1644
  oDateValue.hour += 12;
1393
1645
  }
1394
1646
  if (oDateValue.dayNumberOfWeek === undefined && oDateValue.dayOfWeek !== undefined) {
@@ -1400,7 +1652,7 @@ DateFormat.prototype._parse = function (sValue, aFormatArray, bUTC, bStrict) {
1400
1652
  }
1401
1653
  return oDateValue;
1402
1654
  };
1403
- DateFormat.prototype._parseInterval = function (sValue, sCalendarType, bUTC, bStrict) {
1655
+ DateFormat.prototype._parseInterval = function (sValue, sCalendarType, bUTC, bStrict, sTimezone) {
1404
1656
  var aDateValues, iRepeat, oDateValue;
1405
1657
  this.intervalPatterns.some(function (sPattern) {
1406
1658
  var aFormatArray = this.parseCldrDatePattern(sPattern);
@@ -1412,7 +1664,7 @@ DateFormat.prototype._parseInterval = function (sValue, sCalendarType, bUTC, bSt
1412
1664
  }
1413
1665
  }
1414
1666
  if (iRepeat === undefined) {
1415
- oDateValue = this._parse(sValue, aFormatArray, bUTC, bStrict);
1667
+ oDateValue = this._parse(sValue, aFormatArray, bUTC, bStrict, sTimezone);
1416
1668
  if (oDateValue.index === 0 || oDateValue.index < sValue.length) {
1417
1669
  oDateValue.valid = false;
1418
1670
  }
@@ -1426,13 +1678,13 @@ DateFormat.prototype._parseInterval = function (sValue, sCalendarType, bUTC, bSt
1426
1678
  return true;
1427
1679
  } else {
1428
1680
  aDateValues = [];
1429
- oDateValue = this._parse(sValue, aFormatArray.slice(0, iRepeat), bUTC, bStrict);
1681
+ oDateValue = this._parse(sValue, aFormatArray.slice(0, iRepeat), bUTC, bStrict, sTimezone);
1430
1682
  if (oDateValue.valid === false) {
1431
1683
  return;
1432
1684
  }
1433
1685
  aDateValues.push(oDateValue);
1434
1686
  var iLength = oDateValue.index;
1435
- oDateValue = this._parse(sValue.substring(iLength), aFormatArray.slice(iRepeat), bUTC, bStrict);
1687
+ oDateValue = this._parse(sValue.substring(iLength), aFormatArray.slice(iRepeat), bUTC, bStrict, sTimezone);
1436
1688
  if (oDateValue.index === 0 || oDateValue.index + iLength < sValue.length) {
1437
1689
  oDateValue.valid = false;
1438
1690
  }
@@ -1445,65 +1697,62 @@ DateFormat.prototype._parseInterval = function (sValue, sCalendarType, bUTC, bSt
1445
1697
  }.bind(this));
1446
1698
  return aDateValues;
1447
1699
  };
1448
- var fnCreateDate = function (oDateValue, sCalendarType, bUTC, bStrict) {
1700
+ function getCalendarWeekParameter(oFormatOptions) {
1701
+ if (oFormatOptions.calendarWeekNumbering) {
1702
+ return oFormatOptions.calendarWeekNumbering;
1703
+ } else if (oFormatOptions.firstDayOfWeek !== undefined && oFormatOptions.minimalDaysInFirstWeek !== undefined) {
1704
+ return {
1705
+ firstDayOfWeek: oFormatOptions.firstDayOfWeek,
1706
+ minimalDaysInFirstWeek: oFormatOptions.minimalDaysInFirstWeek
1707
+ };
1708
+ }
1709
+ return undefined;
1710
+ }
1711
+ var convertToTimezone = function (oJSDate, sTimezone, bUTC) {
1712
+ if (!bUTC && isValidDateObject(oJSDate)) {
1713
+ return TimezoneUtil.convertToTimezone(oJSDate, sTimezone);
1714
+ }
1715
+ return oJSDate;
1716
+ };
1717
+ var fnCreateDate = function (oDateValue, sCalendarType, bUTC, bStrict, sTimezone, oFormatOptions, oLocale) {
1718
+ if (!oDateValue.valid) {
1719
+ return null;
1720
+ }
1449
1721
  var oDate, iYear = typeof oDateValue.year === 'number' ? oDateValue.year : 1970;
1450
- if (oDateValue.valid) {
1451
- if (bUTC || oDateValue.tzDiff !== undefined) {
1452
- oDate = UniversalDate.getInstance(new Date(0), sCalendarType);
1453
- oDate.setUTCEra(oDateValue.era || UniversalDate.getCurrentEra(sCalendarType));
1454
- oDate.setUTCFullYear(iYear);
1455
- oDate.setUTCMonth(oDateValue.month || 0);
1456
- oDate.setUTCDate(oDateValue.day || 1);
1457
- oDate.setUTCHours(oDateValue.hour || 0);
1458
- oDate.setUTCMinutes(oDateValue.minute || 0);
1459
- oDate.setUTCSeconds(oDateValue.second || 0);
1460
- oDate.setUTCMilliseconds(oDateValue.millisecond || 0);
1461
- if (bStrict && (oDateValue.day || 1) !== oDate.getUTCDate()) {
1462
- oDateValue.valid = false;
1463
- oDate = undefined;
1464
- } else {
1465
- if (oDateValue.tzDiff) {
1466
- oDate.setUTCMinutes((oDateValue.minute || 0) + oDateValue.tzDiff);
1467
- }
1468
- if (oDateValue.week !== undefined && (oDateValue.month === undefined || oDateValue.day === undefined)) {
1469
- oDate.setUTCWeek({
1470
- year: oDateValue.weekYear || oDateValue.year,
1471
- week: oDateValue.week
1472
- });
1473
- if (oDateValue.dayNumberOfWeek !== undefined) {
1474
- oDate.setUTCDate(oDate.getUTCDate() + oDateValue.dayNumberOfWeek - 1);
1475
- }
1476
- }
1477
- }
1478
- } else {
1479
- oDate = UniversalDate.getInstance(new Date(1970, 0, 1, 0, 0, 0), sCalendarType);
1480
- oDate.setEra(oDateValue.era || UniversalDate.getCurrentEra(sCalendarType));
1481
- oDate.setFullYear(iYear);
1482
- oDate.setMonth(oDateValue.month || 0);
1483
- oDate.setDate(oDateValue.day || 1);
1484
- oDate.setHours(oDateValue.hour || 0);
1485
- oDate.setMinutes(oDateValue.minute || 0);
1486
- oDate.setSeconds(oDateValue.second || 0);
1487
- oDate.setMilliseconds(oDateValue.millisecond || 0);
1488
- if (bStrict && (oDateValue.day || 1) !== oDate.getDate()) {
1489
- oDateValue.valid = false;
1490
- oDate = undefined;
1491
- } else if (oDateValue.week !== undefined && (oDateValue.month === undefined || oDateValue.day === undefined)) {
1492
- oDate.setWeek({
1493
- year: oDateValue.weekYear || oDateValue.year,
1494
- week: oDateValue.week
1495
- });
1496
- if (oDateValue.dayNumberOfWeek !== undefined) {
1497
- oDate.setDate(oDate.getDate() + oDateValue.dayNumberOfWeek - 1);
1498
- }
1499
- }
1722
+ oDate = UniversalDate.getInstance(new Date(0), sCalendarType);
1723
+ oDate.setUTCEra(oDateValue.era || UniversalDate.getCurrentEra(sCalendarType));
1724
+ oDate.setUTCFullYear(iYear);
1725
+ oDate.setUTCMonth(oDateValue.month || 0);
1726
+ oDate.setUTCDate(oDateValue.day || 1);
1727
+ oDate.setUTCHours(oDateValue.hour || 0);
1728
+ oDate.setUTCMinutes(oDateValue.minute || 0);
1729
+ oDate.setUTCSeconds(oDateValue.second || 0);
1730
+ oDate.setUTCMilliseconds(oDateValue.millisecond || 0);
1731
+ if (bStrict && (oDateValue.day || 1) !== oDate.getUTCDate()) {
1732
+ return null;
1733
+ }
1734
+ if (oDateValue.week !== undefined && (oDateValue.month === undefined || oDateValue.day === undefined)) {
1735
+ oDate.setUTCWeek({
1736
+ year: oDateValue.weekYear || oDateValue.year,
1737
+ week: oDateValue.week
1738
+ }, oLocale, getCalendarWeekParameter(oFormatOptions));
1739
+ if (oDateValue.dayNumberOfWeek !== undefined) {
1740
+ oDate.setUTCDate(oDate.getUTCDate() + oDateValue.dayNumberOfWeek - 1);
1500
1741
  }
1501
- if (oDateValue.valid) {
1502
- oDate = oDate.getJSDate();
1503
- return oDate;
1742
+ }
1743
+ oDate = oDate.getJSDate();
1744
+ if (!bUTC && (oDateValue.lastTimezonePatternSymbol === 'V' && oDateValue.timezone || oDateValue.tzDiff === undefined)) {
1745
+ if (oDateValue.timezone) {
1746
+ sTimezone = oDateValue.timezone;
1747
+ }
1748
+ if (sTimezone) {
1749
+ oDateValue.tzDiff = TimezoneUtil.calculateOffset(oDate, sTimezone);
1504
1750
  }
1505
1751
  }
1506
- return null;
1752
+ if (oDateValue.tzDiff) {
1753
+ oDate.setUTCSeconds(oDate.getUTCSeconds() + oDateValue.tzDiff);
1754
+ }
1755
+ return oDate;
1507
1756
  };
1508
1757
  function mergeWithoutOverwrite(object1, object2) {
1509
1758
  if (object1 === object2) {
@@ -1526,17 +1775,37 @@ function isValidDateRange(oStartDate, oEndDate) {
1526
1775
  }
1527
1776
  return true;
1528
1777
  }
1778
+ function isValidDateObject(oDate) {
1779
+ return oDate && typeof oDate.getTime === 'function' && !isNaN(oDate.getTime());
1780
+ }
1529
1781
  DateFormat.prototype.parse = function (sValue, bUTC, bStrict) {
1782
+ var bShowDate = this.oFormatOptions.showDate === undefined || this.oFormatOptions.showDate;
1783
+ var bShowTime = this.oFormatOptions.showTime === undefined || this.oFormatOptions.showTime;
1784
+ if (this.type === mDateFormatTypes.DATETIME_WITH_TIMEZONE && (bShowDate && !bShowTime || !bShowDate && bShowTime)) {
1785
+ throw new TypeError('The input can only be parsed back to date if both date and time are supplied.');
1786
+ }
1787
+ var sTimezone;
1788
+ if (bUTC === undefined && this.type !== mDateFormatTypes.DATETIME_WITH_TIMEZONE) {
1789
+ bUTC = this.oFormatOptions.UTC;
1790
+ }
1791
+ var bUTCInputParameter = bUTC;
1792
+ if (this.type === mDateFormatTypes.DATETIME_WITH_TIMEZONE) {
1793
+ sTimezone = bUTC;
1794
+ bUTC = false;
1795
+ checkTimezoneParameterType(sTimezone);
1796
+ if (sTimezone && !TimezoneUtil.isValidTimezone(sTimezone)) {
1797
+ Log.error('The given timezone isn\'t valid.');
1798
+ return null;
1799
+ }
1800
+ }
1530
1801
  sValue = sValue == null ? '' : String(sValue).trim();
1531
1802
  var oDateValue;
1532
1803
  var sCalendarType = this.oFormatOptions.calendarType;
1533
- if (bUTC === undefined) {
1534
- bUTC = this.oFormatOptions.UTC;
1535
- }
1804
+ sTimezone = sTimezone || Configuration.getTimezone();
1536
1805
  if (bStrict === undefined) {
1537
1806
  bStrict = this.oFormatOptions.strictParsing;
1538
1807
  }
1539
- if (sCalendarType == CalendarType.Japanese && this.oLocale.getLanguage() === 'ja') {
1808
+ if (sCalendarType === CalendarType.Japanese && this.oLocale.getLanguage() === 'ja') {
1540
1809
  sValue = sValue.replace(/元年/g, '1年');
1541
1810
  }
1542
1811
  if (!this.oFormatOptions.interval) {
@@ -1544,22 +1813,40 @@ DateFormat.prototype.parse = function (sValue, bUTC, bStrict) {
1544
1813
  if (oJSDate) {
1545
1814
  return oJSDate;
1546
1815
  }
1547
- oDateValue = this._parse(sValue, this.aFormatArray, bUTC, bStrict);
1816
+ oDateValue = this._parse(sValue, this.aFormatArray, bUTC, bStrict, sTimezone);
1548
1817
  if (oDateValue.index === 0 || oDateValue.index < sValue.length) {
1549
1818
  oDateValue.valid = false;
1550
1819
  }
1551
- oJSDate = fnCreateDate(oDateValue, sCalendarType, bUTC, bStrict);
1820
+ oJSDate = fnCreateDate(oDateValue, sCalendarType, bUTC, bStrict, sTimezone, this.oFormatOptions, this.oLocale);
1552
1821
  if (oJSDate) {
1822
+ if (this.type === mDateFormatTypes.DATETIME_WITH_TIMEZONE) {
1823
+ var bShowTimezone = this.oFormatOptions.showTimezone === undefined || this.oFormatOptions.showTimezone;
1824
+ if (!bShowTimezone && bShowDate && bShowTime) {
1825
+ return [
1826
+ oJSDate,
1827
+ undefined
1828
+ ];
1829
+ } else if (bShowTimezone && !bShowDate && !bShowTime) {
1830
+ return [
1831
+ undefined,
1832
+ oDateValue.timezone
1833
+ ];
1834
+ }
1835
+ return [
1836
+ oJSDate,
1837
+ oDateValue.timezone || undefined
1838
+ ];
1839
+ }
1553
1840
  return oJSDate;
1554
1841
  }
1555
1842
  } else {
1556
- var aDateValues = this._parseInterval(sValue, sCalendarType, bUTC, bStrict);
1843
+ var aDateValues = this._parseInterval(sValue, sCalendarType, bUTC, bStrict, sTimezone);
1557
1844
  var oJSDate1, oJSDate2;
1558
- if (aDateValues && aDateValues.length == 2) {
1845
+ if (aDateValues && aDateValues.length === 2) {
1559
1846
  var oDateValue1 = mergeWithoutOverwrite(aDateValues[0], aDateValues[1]);
1560
1847
  var oDateValue2 = mergeWithoutOverwrite(aDateValues[1], aDateValues[0]);
1561
- oJSDate1 = fnCreateDate(oDateValue1, sCalendarType, bUTC, bStrict);
1562
- oJSDate2 = fnCreateDate(oDateValue2, sCalendarType, bUTC, bStrict);
1848
+ oJSDate1 = fnCreateDate(oDateValue1, sCalendarType, bUTC, bStrict, sTimezone, this.oFormatOptions, this.oLocale);
1849
+ oJSDate2 = fnCreateDate(oDateValue2, sCalendarType, bUTC, bStrict, sTimezone, this.oFormatOptions, this.oLocale);
1563
1850
  if (oJSDate1 && oJSDate2) {
1564
1851
  if (this.oFormatOptions.singleIntervalValue && oJSDate1.getTime() === oJSDate2.getTime()) {
1565
1852
  return [
@@ -1582,11 +1869,14 @@ DateFormat.prototype.parse = function (sValue, bUTC, bStrict) {
1582
1869
  }
1583
1870
  }
1584
1871
  }
1585
- if (!this.bIsFallback) {
1872
+ if (this.aFallbackFormats) {
1586
1873
  var vDate;
1587
1874
  this.aFallbackFormats.every(function (oFallbackFormat) {
1588
- vDate = oFallbackFormat.parse(sValue, bUTC, bStrict);
1875
+ vDate = oFallbackFormat.parse(sValue, bUTCInputParameter, bStrict);
1589
1876
  if (Array.isArray(vDate)) {
1877
+ if (oFallbackFormat.type === mDateFormatTypes.DATETIME_WITH_TIMEZONE) {
1878
+ return false;
1879
+ }
1590
1880
  return !(vDate[0] && vDate[1]);
1591
1881
  } else {
1592
1882
  return !vDate;
@@ -1611,20 +1901,20 @@ DateFormat.prototype.parseCldrDatePattern = function (sPattern) {
1611
1901
  for (i = 0; i < sPattern.length; i++) {
1612
1902
  var sCurChar = sPattern.charAt(i), sNextChar, sPrevChar, sPrevPrevChar;
1613
1903
  if (bQuoted) {
1614
- if (sCurChar == '\'') {
1904
+ if (sCurChar === '\'') {
1615
1905
  sPrevChar = sPattern.charAt(i - 1);
1616
1906
  sPrevPrevChar = sPattern.charAt(i - 2);
1617
1907
  sNextChar = sPattern.charAt(i + 1);
1618
- if (sPrevChar == '\'' && sPrevPrevChar != '\'') {
1908
+ if (sPrevChar === '\'' && sPrevPrevChar !== '\'') {
1619
1909
  bQuoted = false;
1620
- } else if (sNextChar == '\'') {
1910
+ } else if (sNextChar === '\'') {
1621
1911
  i += 1;
1622
1912
  } else {
1623
1913
  bQuoted = false;
1624
1914
  continue;
1625
1915
  }
1626
1916
  }
1627
- if (sState == 'text') {
1917
+ if (sState === 'text') {
1628
1918
  oCurrentObject.value += sCurChar;
1629
1919
  } else {
1630
1920
  oCurrentObject = {
@@ -1635,11 +1925,11 @@ DateFormat.prototype.parseCldrDatePattern = function (sPattern) {
1635
1925
  sState = 'text';
1636
1926
  }
1637
1927
  } else {
1638
- if (sCurChar == '\'') {
1928
+ if (sCurChar === '\'') {
1639
1929
  bQuoted = true;
1640
1930
  } else if (this.oSymbols[sCurChar]) {
1641
1931
  sNewState = this.oSymbols[sCurChar].name;
1642
- if (sState == sNewState) {
1932
+ if (sState === sNewState) {
1643
1933
  oCurrentObject.digits++;
1644
1934
  } else {
1645
1935
  oCurrentObject = {
@@ -1659,7 +1949,7 @@ DateFormat.prototype.parseCldrDatePattern = function (sPattern) {
1659
1949
  }
1660
1950
  }
1661
1951
  } else {
1662
- if (sState == 'text') {
1952
+ if (sState === 'text') {
1663
1953
  oCurrentObject.value += sCurChar;
1664
1954
  } else {
1665
1955
  oCurrentObject = {
@@ -1695,70 +1985,88 @@ DateFormat.prototype.parseRelative = function (sValue, bUTC) {
1695
1985
  }
1696
1986
  }
1697
1987
  function computeRelativeDate(iDiff, sScale) {
1698
- var iToday, oToday = new Date(), oJSDate;
1699
- if (bUTC) {
1700
- iToday = oToday.getTime();
1701
- } else {
1702
- iToday = Date.UTC(oToday.getFullYear(), oToday.getMonth(), oToday.getDate(), oToday.getHours(), oToday.getMinutes(), oToday.getSeconds(), oToday.getMilliseconds());
1703
- }
1704
- oJSDate = new Date(iToday);
1705
- switch (sScale) {
1706
- case 'second':
1707
- oJSDate.setUTCSeconds(oJSDate.getUTCSeconds() + iDiff);
1708
- break;
1709
- case 'minute':
1710
- oJSDate.setUTCMinutes(oJSDate.getUTCMinutes() + iDiff);
1711
- break;
1712
- case 'hour':
1713
- oJSDate.setUTCHours(oJSDate.getUTCHours() + iDiff);
1714
- break;
1715
- case 'day':
1716
- oJSDate.setUTCDate(oJSDate.getUTCDate() + iDiff);
1717
- break;
1718
- case 'week':
1719
- oJSDate.setUTCDate(oJSDate.getUTCDate() + iDiff * 7);
1720
- break;
1721
- case 'month':
1722
- oJSDate.setUTCMonth(oJSDate.getUTCMonth() + iDiff);
1723
- break;
1724
- case 'quarter':
1725
- oJSDate.setUTCMonth(oJSDate.getUTCMonth() + iDiff * 3);
1726
- break;
1727
- case 'year':
1728
- oJSDate.setUTCFullYear(oJSDate.getUTCFullYear() + iDiff);
1729
- break;
1730
- }
1988
+ var oResult = UI5Date.getInstance();
1731
1989
  if (bUTC) {
1732
- return oJSDate;
1990
+ oResult.setUTCFullYear(oResult.getFullYear(), oResult.getMonth(), oResult.getDate());
1991
+ oResult.setUTCHours(oResult.getHours(), oResult.getMinutes(), oResult.getSeconds(), oResult.getMilliseconds());
1992
+ switch (sScale) {
1993
+ case 'second':
1994
+ oResult.setUTCSeconds(oResult.getUTCSeconds() + iDiff);
1995
+ break;
1996
+ case 'minute':
1997
+ oResult.setUTCMinutes(oResult.getUTCMinutes() + iDiff);
1998
+ break;
1999
+ case 'hour':
2000
+ oResult.setUTCHours(oResult.getUTCHours() + iDiff);
2001
+ break;
2002
+ case 'day':
2003
+ oResult.setUTCDate(oResult.getUTCDate() + iDiff);
2004
+ break;
2005
+ case 'week':
2006
+ oResult.setUTCDate(oResult.getUTCDate() + iDiff * 7);
2007
+ break;
2008
+ case 'month':
2009
+ oResult.setUTCMonth(oResult.getUTCMonth() + iDiff);
2010
+ break;
2011
+ case 'quarter':
2012
+ oResult.setUTCMonth(oResult.getUTCMonth() + iDiff * 3);
2013
+ break;
2014
+ case 'year':
2015
+ oResult.setUTCFullYear(oResult.getUTCFullYear() + iDiff);
2016
+ break;
2017
+ }
1733
2018
  } else {
1734
- return new Date(oJSDate.getUTCFullYear(), oJSDate.getUTCMonth(), oJSDate.getUTCDate(), oJSDate.getUTCHours(), oJSDate.getUTCMinutes(), oJSDate.getUTCSeconds(), oJSDate.getUTCMilliseconds());
2019
+ switch (sScale) {
2020
+ case 'second':
2021
+ oResult.setSeconds(oResult.getSeconds() + iDiff);
2022
+ break;
2023
+ case 'minute':
2024
+ oResult.setMinutes(oResult.getMinutes() + iDiff);
2025
+ break;
2026
+ case 'hour':
2027
+ oResult.setHours(oResult.getHours() + iDiff);
2028
+ break;
2029
+ case 'day':
2030
+ oResult.setDate(oResult.getDate() + iDiff);
2031
+ break;
2032
+ case 'week':
2033
+ oResult.setDate(oResult.getDate() + iDiff * 7);
2034
+ break;
2035
+ case 'month':
2036
+ oResult.setMonth(oResult.getMonth() + iDiff);
2037
+ break;
2038
+ case 'quarter':
2039
+ oResult.setMonth(oResult.getMonth() + iDiff * 3);
2040
+ break;
2041
+ case 'year':
2042
+ oResult.setFullYear(oResult.getFullYear() + iDiff);
2043
+ break;
2044
+ }
1735
2045
  }
2046
+ return oResult;
1736
2047
  }
1737
2048
  };
1738
- DateFormat.prototype.formatRelative = function (oJSDate, bUTC, aRange) {
1739
- var oToday = new Date(), oDateUTC, sScale = this.oFormatOptions.relativeScale || 'day', iDiff, sPattern, iDiffSeconds;
2049
+ DateFormat.prototype.formatRelative = function (oJSDate, bUTC, aRange, sTimezone) {
2050
+ var oDateUTC, iDiff, iDiffSeconds, sPattern, oToday = convertToTimezone(new Date(), sTimezone), sScale = this.oFormatOptions.relativeScale || 'day';
1740
2051
  iDiffSeconds = (oJSDate.getTime() - oToday.getTime()) / 1000;
1741
- if (this.oFormatOptions.relativeScale == 'auto') {
2052
+ if (this.oFormatOptions.relativeScale === 'auto') {
1742
2053
  sScale = this._getScale(iDiffSeconds, this.aRelativeScales);
2054
+ sScale = fixScaleForMonths(oJSDate, oToday, sScale, iDiffSeconds);
1743
2055
  }
1744
2056
  if (!aRange) {
1745
2057
  aRange = this._mRanges[sScale];
1746
2058
  }
1747
- if (sScale == 'year' || sScale == 'month' || sScale == 'day') {
1748
- oToday = new Date(Date.UTC(oToday.getFullYear(), oToday.getMonth(), oToday.getDate()));
2059
+ if (sScale === 'year' || sScale === 'month' || sScale === 'day') {
2060
+ oToday = new Date(Date.UTC(oToday.getUTCFullYear(), oToday.getUTCMonth(), oToday.getUTCDate()));
1749
2061
  oDateUTC = new Date(0);
1750
- if (bUTC) {
1751
- oDateUTC.setUTCFullYear(oJSDate.getUTCFullYear(), oJSDate.getUTCMonth(), oJSDate.getUTCDate());
1752
- } else {
1753
- oDateUTC.setUTCFullYear(oJSDate.getFullYear(), oJSDate.getMonth(), oJSDate.getDate());
1754
- }
2062
+ oDateUTC.setUTCFullYear(oJSDate.getUTCFullYear(), oJSDate.getUTCMonth(), oJSDate.getUTCDate());
1755
2063
  oJSDate = oDateUTC;
1756
2064
  }
1757
2065
  iDiff = this._getDifference(sScale, [
1758
2066
  oToday,
1759
2067
  oJSDate
1760
2068
  ]);
1761
- if (this.oFormatOptions.relativeScale != 'auto' && (iDiff < aRange[0] || iDiff > aRange[1])) {
2069
+ if (this.oFormatOptions.relativeScale !== 'auto' && (iDiff < aRange[0] || iDiff > aRange[1])) {
1762
2070
  return null;
1763
2071
  }
1764
2072
  sPattern = this.oLocaleData.getRelativePattern(sScale, iDiff, iDiffSeconds > 0, this.oFormatOptions.relativeStyle);
@@ -1819,8 +2127,23 @@ DateFormat.prototype._getScale = function (iDiffSeconds, aScales) {
1819
2127
  }
1820
2128
  return sScale;
1821
2129
  };
2130
+ function fixScaleForMonths(oJSDate, oToday, sScale, iDiffSeconds) {
2131
+ var iMonthDiff = Math.abs(oJSDate.getUTCMonth() - oToday.getUTCMonth());
2132
+ if (sScale === 'week' && iMonthDiff === 2) {
2133
+ return 'month';
2134
+ } else if (sScale === 'week' && iMonthDiff === 1) {
2135
+ if (oJSDate.getUTCDate() === oToday.getUTCDate() || iDiffSeconds < 0 && oJSDate.getUTCDate() < oToday.getUTCDate() || iDiffSeconds > 0 && oJSDate.getUTCDate() > oToday.getUTCDate()) {
2136
+ return 'month';
2137
+ }
2138
+ } else if (sScale === 'month' && iMonthDiff === 1) {
2139
+ if (iDiffSeconds > 0 && oJSDate.getUTCDate() < oToday.getUTCDate() || iDiffSeconds < 0 && oJSDate.getUTCDate() > oToday.getUTCDate()) {
2140
+ return 'week';
2141
+ }
2142
+ }
2143
+ return sScale;
2144
+ }
1822
2145
  function cutDateFields(oDate, iStartIndex) {
1823
- var aFields = [
2146
+ var sMethodName, aFields = [
1824
2147
  'FullYear',
1825
2148
  'Month',
1826
2149
  'Date',
@@ -1828,24 +2151,23 @@ function cutDateFields(oDate, iStartIndex) {
1828
2151
  'Minutes',
1829
2152
  'Seconds',
1830
2153
  'Milliseconds'
1831
- ], sMethodName;
1832
- var oDateCopy = new Date(oDate.getTime());
2154
+ ], oDateCopy = new Date(oDate.getTime());
1833
2155
  for (var i = iStartIndex; i < aFields.length; i++) {
1834
- sMethodName = 'set' + aFields[iStartIndex];
2156
+ sMethodName = 'setUTC' + aFields[iStartIndex];
1835
2157
  oDateCopy[sMethodName].apply(oDateCopy, [0]);
1836
2158
  }
1837
2159
  return oDateCopy;
1838
2160
  }
1839
2161
  var mRelativeDiffs = {
1840
2162
  year: function (oFromDate, oToDate) {
1841
- return oToDate.getFullYear() - oFromDate.getFullYear();
2163
+ return oToDate.getUTCFullYear() - oFromDate.getUTCFullYear();
1842
2164
  },
1843
2165
  month: function (oFromDate, oToDate) {
1844
- return oToDate.getMonth() - oFromDate.getMonth() + this.year(oFromDate, oToDate) * 12;
2166
+ return oToDate.getUTCMonth() - oFromDate.getUTCMonth() + this.year(oFromDate, oToDate) * 12;
1845
2167
  },
1846
2168
  week: function (oFromDate, oToDate, oFormat) {
1847
- var iFromDay = oFormat._adaptDayOfWeek(oFromDate.getDay());
1848
- var iToDay = oFormat._adaptDayOfWeek(oToDate.getDay());
2169
+ var iFromDay = oFormat._adaptDayOfWeek(oFromDate.getUTCDay());
2170
+ var iToDay = oFormat._adaptDayOfWeek(oToDate.getUTCDay());
1849
2171
  oFromDate = cutDateFields(oFromDate, 3);
1850
2172
  oToDate = cutDateFields(oToDate, 3);
1851
2173
  return (oToDate.getTime() - oFromDate.getTime() - (iToDay - iFromDay) * oFormat._mScales.day * 1000) / (oFormat._mScales.week * 1000);
@@ -1872,7 +2194,12 @@ var mRelativeDiffs = {
1872
2194
  }
1873
2195
  };
1874
2196
  DateFormat.prototype._adaptDayOfWeek = function (iDayOfWeek) {
1875
- var iFirstDayOfWeek = LocaleData.getInstance(Core.getConfiguration().getFormatSettings().getFormatLocale()).getFirstDayOfWeek();
2197
+ var vCalendarWeekParameter = getCalendarWeekParameter(this.oFormatOptions), iFirstDayOfWeek;
2198
+ if (typeof vCalendarWeekParameter === 'object') {
2199
+ iFirstDayOfWeek = vCalendarWeekParameter.firstDayOfWeek;
2200
+ } else {
2201
+ iFirstDayOfWeek = CalendarUtils.getWeekConfigurationValues(vCalendarWeekParameter, this.oLocale).firstDayOfWeek;
2202
+ }
1876
2203
  var iDayNumberOfWeek = iDayOfWeek - (iFirstDayOfWeek - 1);
1877
2204
  if (iDayNumberOfWeek <= 0) {
1878
2205
  iDayNumberOfWeek += 7;
@@ -1938,4 +2265,28 @@ DateFormat.prototype.getAllowedCharacters = function (aFormatArray) {
1938
2265
  }
1939
2266
  return sAllowedCharacters;
1940
2267
  };
2268
+ DateFormat.prototype.getPlaceholderText = function () {
2269
+ var oResourceBundle = Core.getLibraryResourceBundle();
2270
+ return oResourceBundle.getText('date.placeholder', [this.format.apply(this, this.getSampleValue())]);
2271
+ };
2272
+ DateFormat.prototype.getSampleValue = function () {
2273
+ var oDate, iFullYear = UI5Date.getInstance().getFullYear(), bUTC = this.oFormatOptions.UTC;
2274
+ function getDate(iYear, iMonth, iDay, iHours, iMinutes, iSeconds, iMilliseconds) {
2275
+ return bUTC ? UI5Date.getInstance(Date.UTC(iYear, iMonth, iDay, iHours, iMinutes, iSeconds, iMilliseconds)) : UI5Date.getInstance(iYear, iMonth, iDay, iHours, iMinutes, iSeconds, iMilliseconds);
2276
+ }
2277
+ oDate = getDate(iFullYear, 11, 31, 23, 59, 58, 123);
2278
+ if (this.type === mDateFormatTypes.DATETIME_WITH_TIMEZONE) {
2279
+ return [
2280
+ oDate,
2281
+ Configuration.getTimezone()
2282
+ ];
2283
+ }
2284
+ if (this.oFormatOptions.interval) {
2285
+ return [[
2286
+ getDate(iFullYear, 11, 22, 9, 12, 34, 567),
2287
+ oDate
2288
+ ]];
2289
+ }
2290
+ return [oDate];
2291
+ };
1941
2292
  export default DateFormat;