@ui5/webcomponents-localization 0.0.0-f1f9d888f → 0.0.0-f24ff9019

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 -0
  2. package/.npsrc.json +3 -0
  3. package/CHANGELOG.md +665 -0
  4. package/README.md +37 -6
  5. package/dist/Assets-static.d.ts +1 -0
  6. package/dist/Assets-static.js +3 -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 +29 -0
  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 +15 -0
  40. package/dist/dates/getRoundedTimestamp.js.map +1 -0
  41. package/dist/dates/getTodayUTCTimestamp.d.ts +7 -0
  42. package/dist/dates/getTodayUTCTimestamp.js +9 -0
  43. package/dist/dates/getTodayUTCTimestamp.js.map +1 -0
  44. package/dist/dates/modifyDateBy.d.ts +14 -0
  45. package/dist/dates/modifyDateBy.js +55 -0
  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 -5904
  61. package/dist/generated/assets/cldr/ar_EG.json +5531 -5904
  62. package/dist/generated/assets/cldr/ar_SA.json +5530 -5904
  63. package/dist/generated/assets/cldr/bg.json +4452 -4977
  64. package/dist/generated/assets/cldr/ca.json +4440 -4994
  65. package/dist/generated/assets/cldr/cs.json +4960 -5496
  66. package/dist/generated/assets/cldr/cy.json +5213 -0
  67. package/dist/generated/assets/cldr/da.json +4308 -4886
  68. package/dist/generated/assets/cldr/de.json +4313 -4914
  69. package/dist/generated/assets/cldr/de_AT.json +4314 -4915
  70. package/dist/generated/assets/cldr/de_CH.json +4312 -4913
  71. package/dist/generated/assets/cldr/el.json +4281 -4881
  72. package/dist/generated/assets/cldr/el_CY.json +4281 -4881
  73. package/dist/generated/assets/cldr/en.json +4316 -4968
  74. package/dist/generated/assets/cldr/en_AU.json +4319 -4960
  75. package/dist/generated/assets/cldr/en_GB.json +4329 -4969
  76. package/dist/generated/assets/cldr/en_HK.json +4337 -4975
  77. package/dist/generated/assets/cldr/en_IE.json +4328 -4969
  78. package/dist/generated/assets/cldr/en_IN.json +4333 -4970
  79. package/dist/generated/assets/cldr/en_NZ.json +4328 -4969
  80. package/dist/generated/assets/cldr/en_PG.json +4329 -4970
  81. package/dist/generated/assets/cldr/en_SG.json +4333 -4971
  82. package/dist/generated/assets/cldr/en_ZA.json +4329 -4970
  83. package/dist/generated/assets/cldr/es.json +4331 -4910
  84. package/dist/generated/assets/cldr/es_AR.json +4334 -4912
  85. package/dist/generated/assets/cldr/es_BO.json +4333 -4911
  86. package/dist/generated/assets/cldr/es_CL.json +4334 -4912
  87. package/dist/generated/assets/cldr/es_CO.json +4333 -4911
  88. package/dist/generated/assets/cldr/es_MX.json +4335 -4913
  89. package/dist/generated/assets/cldr/es_PE.json +4333 -4911
  90. package/dist/generated/assets/cldr/es_UY.json +4335 -4913
  91. package/dist/generated/assets/cldr/es_VE.json +4334 -4912
  92. package/dist/generated/assets/cldr/et.json +4340 -4965
  93. package/dist/generated/assets/cldr/fa.json +4367 -4881
  94. package/dist/generated/assets/cldr/fi.json +4463 -5006
  95. package/dist/generated/assets/cldr/fr.json +4357 -4977
  96. package/dist/generated/assets/cldr/fr_BE.json +4357 -4977
  97. package/dist/generated/assets/cldr/fr_CA.json +4351 -4971
  98. package/dist/generated/assets/cldr/fr_CH.json +4375 -4995
  99. package/dist/generated/assets/cldr/fr_LU.json +4357 -4977
  100. package/dist/generated/assets/cldr/he.json +4869 -5376
  101. package/dist/generated/assets/cldr/hi.json +4295 -4827
  102. package/dist/generated/assets/cldr/hr.json +4583 -4917
  103. package/dist/generated/assets/cldr/hu.json +4364 -4854
  104. package/dist/generated/assets/cldr/id.json +4060 -4656
  105. package/dist/generated/assets/cldr/it.json +4299 -4948
  106. package/dist/generated/assets/cldr/it_CH.json +4299 -4948
  107. package/dist/generated/assets/cldr/ja.json +4211 -4828
  108. package/dist/generated/assets/cldr/kk.json +4339 -4723
  109. package/dist/generated/assets/cldr/ko.json +4189 -4736
  110. package/dist/generated/assets/cldr/lt.json +4850 -5479
  111. package/dist/generated/assets/cldr/lv.json +4587 -5110
  112. package/dist/generated/assets/cldr/ms.json +4021 -4513
  113. package/dist/generated/assets/cldr/nb.json +4335 -4975
  114. package/dist/generated/assets/cldr/nl.json +4294 -4882
  115. package/dist/generated/assets/cldr/nl_BE.json +4294 -4882
  116. package/dist/generated/assets/cldr/pl.json +4667 -5174
  117. package/dist/generated/assets/cldr/pt.json +4235 -4803
  118. package/dist/generated/assets/cldr/pt_PT.json +4372 -4938
  119. package/dist/generated/assets/cldr/ro.json +4563 -5088
  120. package/dist/generated/assets/cldr/ru.json +4909 -5405
  121. package/dist/generated/assets/cldr/ru_UA.json +4909 -5405
  122. package/dist/generated/assets/cldr/sk.json +4939 -5368
  123. package/dist/generated/assets/cldr/sl.json +4910 -5338
  124. package/dist/generated/assets/cldr/sr.json +4585 -5124
  125. package/dist/generated/assets/cldr/sr_Latn.json +4576 -0
  126. package/dist/generated/assets/cldr/sv.json +4362 -5009
  127. package/dist/generated/assets/cldr/th.json +4214 -4795
  128. package/dist/generated/assets/cldr/tr.json +4400 -4977
  129. package/dist/generated/assets/cldr/uk.json +4858 -5351
  130. package/dist/generated/assets/cldr/vi.json +4070 -4671
  131. package/dist/generated/assets/cldr/zh_CN.json +4100 -4630
  132. package/dist/generated/assets/cldr/zh_HK.json +4108 -4638
  133. package/dist/generated/assets/cldr/zh_SG.json +4108 -4638
  134. package/dist/generated/assets/cldr/zh_TW.json +4131 -4726
  135. package/dist/generated/json-imports/LocaleData-static.js +90 -0
  136. package/dist/generated/json-imports/LocaleData.js +88 -91
  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 -37
  144. package/dist/sap/base/assert.js +5 -10
  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 +11 -4
  154. package/dist/sap/base/util/LoaderExtensions.js.map +1 -0
  155. package/dist/sap/base/util/array/uniqueSort.js +7 -7
  156. package/dist/sap/base/util/deepEqual.js +1 -5
  157. package/dist/sap/ui/base/Interface.js +3 -5
  158. package/dist/sap/ui/base/Metadata.js +21 -12
  159. package/dist/sap/ui/base/Object.js +26 -2
  160. package/dist/sap/ui/core/CalendarType.js +2 -8
  161. package/dist/sap/ui/core/Configuration.d.ts +18 -0
  162. package/dist/sap/ui/core/Configuration.js +23 -0
  163. package/dist/sap/ui/core/Configuration.js.map +1 -0
  164. package/dist/sap/ui/core/Core.d.ts +27 -0
  165. package/dist/sap/ui/core/Core.js +7 -32
  166. package/dist/sap/ui/core/Core.js.map +1 -0
  167. package/dist/sap/ui/core/FormatSettings.d.ts +10 -0
  168. package/dist/sap/ui/core/FormatSettings.js +14 -0
  169. package/dist/sap/ui/core/FormatSettings.js.map +1 -0
  170. package/dist/sap/ui/core/Locale.js +28 -86
  171. package/dist/sap/ui/core/LocaleData.js +237 -1538
  172. package/dist/sap/ui/core/date/Buddhist.js +0 -6
  173. package/dist/sap/ui/core/date/CalendarUtils.js +25 -0
  174. package/dist/sap/ui/core/date/CalendarWeekNumbering.js +2 -0
  175. package/dist/sap/ui/core/date/Islamic.js +3 -3
  176. package/dist/sap/ui/core/date/Japanese.js +4 -4
  177. package/dist/sap/ui/core/date/UI5Date.js +305 -0
  178. package/dist/sap/ui/core/date/UniversalDate.js +74 -25
  179. package/dist/sap/ui/core/format/DateFormat.js +881 -517
  180. package/dist/sap/ui/core/format/TimezoneUtil.js +2 -0
  181. package/package-scripts.cjs +37 -0
  182. package/package.json +14 -14
  183. package/tsconfig.json +14 -0
  184. package/used-modules.txt +9 -1
  185. package/package-scripts.js +0 -31
  186. package/src/Assets.js +0 -2
  187. package/src/DateFormat.js +0 -3
  188. package/src/LocaleData.js +0 -3
  189. package/src/dates/CalendarDate.js +0 -223
  190. package/src/dates/calculateWeekNumber.js +0 -51
  191. package/src/getCachedLocaleDataInstance.js +0 -13
  192. package/src/locale/getLocaleData.js +0 -27
  193. package/src/sap/base/util/LoaderExtensions.js +0 -7
  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;
336
+ aFallbackFormatOptions = DateFormat._createFallbackOptionsWithoutDelimiter(oFormat.oFormatOptions.pattern).concat(aFallbackFormatOptions);
235
337
  }
236
- if (oFormat.oFormatOptions.interval) {
237
- sKey = sKey + '-' + 'interval';
238
- }
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,53 +441,84 @@ 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
- parseTZ: function (sValue, bISO) {
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);
359
480
  var iTZDiffHour = parseInt(sPart);
360
481
  iLength += 2;
361
- if (bISO) {
482
+ if (bColonSeparated) {
362
483
  iLength++;
363
484
  }
364
485
  sPart = this.findNumbers(sValue.substr(iLength), 2);
365
- iLength += 2;
366
- var iTZDiff = parseInt(sPart);
486
+ var iTZDiff = 0;
487
+ if (sPart) {
488
+ iLength += 2;
489
+ iTZDiff = parseInt(sPart);
490
+ }
367
491
  return {
368
492
  length: iLength,
369
- tzDiff: (iTZDiff + 60 * iTZDiffHour) * iTZFactor
493
+ tzDiff: (iTZDiff + 60 * iTZDiffHour) * 60 * iTZFactor
370
494
  };
371
495
  },
372
- checkValid: function (sType, bPartInvalid, oFormat) {
373
- if (sType in oFormat.oRequiredParts && bPartInvalid) {
496
+ checkValid: function (sSymbolName, bPartInvalid, oFormat) {
497
+ if (sSymbolName in oFormat.oRequiredParts && bPartInvalid) {
374
498
  return false;
375
499
  }
500
+ return true;
376
501
  }
377
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
+ };
378
518
  DateFormat.prototype.oSymbols = {
379
- '': {
519
+ '': DateFormat._createPatternSymbol({
380
520
  name: 'text',
381
- format: function (oField, oDate, bUTC, oFormat) {
521
+ format: function (oField, oDate) {
382
522
  return oField.value;
383
523
  },
384
524
  parse: function (sValue, oPart, oFormat, oConfig) {
@@ -418,11 +558,11 @@ DateFormat.prototype.oSymbols = {
418
558
  return { valid: oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat) };
419
559
  }
420
560
  }
421
- },
422
- 'G': {
561
+ }),
562
+ 'G': DateFormat._createPatternSymbol({
423
563
  name: 'era',
424
564
  format: function (oField, oDate, bUTC, oFormat) {
425
- var iEra = bUTC ? oDate.getUTCEra() : oDate.getEra();
565
+ var iEra = oDate.getUTCEra();
426
566
  if (oField.digits <= 3) {
427
567
  return oFormat.aErasAbbrev[iEra];
428
568
  } else if (oField.digits === 4) {
@@ -439,11 +579,11 @@ DateFormat.prototype.oSymbols = {
439
579
  ];
440
580
  for (var i = 0; i < aErasVariants.length; i++) {
441
581
  var aVariants = aErasVariants[i];
442
- var oFound = oParseHelper.findEntry(sValue, aVariants);
582
+ var oFound = oParseHelper.findEntry(sValue, aVariants, oFormat.oLocaleData.sCLDRLocaleId);
443
583
  if (oFound.index !== -1) {
444
584
  return {
445
585
  era: oFound.index,
446
- length: oFound.value.length
586
+ length: oFound.length
447
587
  };
448
588
  }
449
589
  }
@@ -452,34 +592,35 @@ DateFormat.prototype.oSymbols = {
452
592
  valid: oParseHelper.checkValid(oPart.type, true, oFormat)
453
593
  };
454
594
  }
455
- },
456
- 'y': {
595
+ }),
596
+ 'y': DateFormat._createPatternSymbol({
457
597
  name: 'year',
458
598
  format: function (oField, oDate, bUTC, oFormat) {
459
- var iYear = bUTC ? oDate.getUTCFullYear() : oDate.getFullYear();
599
+ var iYear = oDate.getUTCFullYear();
460
600
  var sYear = String(iYear);
461
601
  var sCalendarType = oFormat.oFormatOptions.calendarType;
462
- if (oField.digits == 2 && sYear.length > 2) {
602
+ if (oField.digits === 2 && sYear.length > 2) {
463
603
  sYear = sYear.substr(sYear.length - 2);
464
604
  }
465
- if (sCalendarType != CalendarType.Japanese && oField.digits == 1 && iYear < 100) {
605
+ if (sCalendarType !== CalendarType.Japanese && oField.digits === 1 && iYear < 100) {
466
606
  sYear = sYear.padStart(4, '0');
467
607
  }
468
608
  return sYear.padStart(oField.digits, '0');
469
609
  },
470
610
  parse: function (sValue, oPart, oFormat, oConfig) {
471
- var sCalendarType = oFormat.oFormatOptions.calendarType;
472
- var sPart;
473
- if (oPart.digits == 1) {
474
- sPart = oParseHelper.findNumbers(sValue, 4);
475
- } else if (oPart.digits == 2) {
476
- 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;
477
616
  } else {
478
- sPart = oParseHelper.findNumbers(sValue, oPart.digits);
617
+ iExpectedDigits = oPart.digits;
479
618
  }
619
+ sPart = oParseHelper.findNumbers(sValue, iExpectedDigits);
620
+ bPartInvalid = sPart === '' || oConfig.exactLength && sPart.length !== iExpectedDigits;
480
621
  var iYear = parseInt(sPart);
481
- if (sCalendarType != CalendarType.Japanese && sPart.length <= 2) {
482
- 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;
483
624
  if (iYearDiff < -70) {
484
625
  iYear += (iCurrentCentury + 1) * 100;
485
626
  } else if (iYearDiff < 30) {
@@ -490,40 +631,42 @@ DateFormat.prototype.oSymbols = {
490
631
  }
491
632
  return {
492
633
  length: sPart.length,
493
- valid: oParseHelper.checkValid(oPart.type, sPart === '', oFormat),
634
+ valid: oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat),
494
635
  year: iYear
495
636
  };
496
- }
497
- },
498
- 'Y': {
637
+ },
638
+ isNumeric: true
639
+ }),
640
+ 'Y': DateFormat._createPatternSymbol({
499
641
  name: 'weekYear',
500
642
  format: function (oField, oDate, bUTC, oFormat) {
501
- var oWeek = bUTC ? oDate.getUTCWeek() : oDate.getWeek();
643
+ var oWeek = oDate.getUTCWeek(oFormat.oLocale, getCalendarWeekParameter(oFormat.oFormatOptions));
502
644
  var iWeekYear = oWeek.year;
503
645
  var sWeekYear = String(iWeekYear);
504
646
  var sCalendarType = oFormat.oFormatOptions.calendarType;
505
- if (oField.digits == 2 && sWeekYear.length > 2) {
647
+ if (oField.digits === 2 && sWeekYear.length > 2) {
506
648
  sWeekYear = sWeekYear.substr(sWeekYear.length - 2);
507
649
  }
508
- if (sCalendarType != CalendarType.Japanese && oField.digits == 1 && iWeekYear < 100) {
650
+ if (sCalendarType !== CalendarType.Japanese && oField.digits === 1 && iWeekYear < 100) {
509
651
  sWeekYear = sWeekYear.padStart(4, '0');
510
652
  }
511
653
  return sWeekYear.padStart(oField.digits, '0');
512
654
  },
513
655
  parse: function (sValue, oPart, oFormat, oConfig) {
514
- var sCalendarType = oFormat.oFormatOptions.calendarType;
515
- var sPart;
516
- if (oPart.digits == 1) {
517
- sPart = oParseHelper.findNumbers(sValue, 4);
518
- } else if (oPart.digits == 2) {
519
- 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;
520
661
  } else {
521
- sPart = oParseHelper.findNumbers(sValue, oPart.digits);
662
+ iExpectedDigits = oPart.digits;
522
663
  }
664
+ sPart = oParseHelper.findNumbers(sValue, iExpectedDigits);
665
+ bPartInvalid = sPart === '' || oConfig.exactLength && sPart.length !== iExpectedDigits;
523
666
  var iYear = parseInt(sPart);
524
- var iWeekYear;
525
- if (sCalendarType != CalendarType.Japanese && sPart.length <= 2) {
526
- 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;
527
670
  if (iYearDiff < -70) {
528
671
  iWeekYear += (iCurrentCentury + 1) * 100;
529
672
  } else if (iYearDiff < 30) {
@@ -534,19 +677,20 @@ DateFormat.prototype.oSymbols = {
534
677
  }
535
678
  return {
536
679
  length: sPart.length,
537
- valid: oParseHelper.checkValid(oPart.type, sPart === '', oFormat),
680
+ valid: oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat),
538
681
  year: iYear,
539
682
  weekYear: iWeekYear
540
683
  };
541
- }
542
- },
543
- 'M': {
684
+ },
685
+ isNumeric: true
686
+ }),
687
+ 'M': DateFormat._createPatternSymbol({
544
688
  name: 'month',
545
689
  format: function (oField, oDate, bUTC, oFormat) {
546
- var iMonth = bUTC ? oDate.getUTCMonth() : oDate.getMonth();
547
- if (oField.digits == 3) {
690
+ var iMonth = oDate.getUTCMonth();
691
+ if (oField.digits === 3) {
548
692
  return oFormat.aMonthsAbbrev[iMonth];
549
- } else if (oField.digits == 4) {
693
+ } else if (oField.digits === 4) {
550
694
  return oFormat.aMonthsWide[iMonth];
551
695
  } else if (oField.digits > 4) {
552
696
  return oFormat.aMonthsNarrow[iMonth];
@@ -555,20 +699,18 @@ DateFormat.prototype.oSymbols = {
555
699
  }
556
700
  },
557
701
  parse: function (sValue, oPart, oFormat, oConfig) {
558
- var aMonthsVariants = [
559
- oFormat.aMonthsWide,
560
- oFormat.aMonthsWideSt,
561
- oFormat.aMonthsAbbrev,
562
- oFormat.aMonthsAbbrevSt,
563
- oFormat.aMonthsNarrow,
564
- oFormat.aMonthsNarrowSt
565
- ];
566
- var bValid;
567
- var iMonth;
568
- 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
+ ];
569
710
  if (oPart.digits < 3) {
570
711
  sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
571
- bValid = oParseHelper.checkValid(oPart.type, sPart === '', oFormat);
712
+ bPartInvalid = sPart === '' || oConfig.exactLength && sPart.length < 2;
713
+ bValid = oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat);
572
714
  iMonth = parseInt(sPart) - 1;
573
715
  if (oConfig.strict && (iMonth > 11 || iMonth < 0)) {
574
716
  bValid = false;
@@ -576,11 +718,11 @@ DateFormat.prototype.oSymbols = {
576
718
  } else {
577
719
  for (var i = 0; i < aMonthsVariants.length; i++) {
578
720
  var aVariants = aMonthsVariants[i];
579
- var oFound = oParseHelper.findEntry(sValue, aVariants);
721
+ var oFound = oParseHelper.findEntry(sValue, aVariants, oFormat.oLocaleData.sCLDRLocaleId);
580
722
  if (oFound.index !== -1) {
581
723
  return {
582
724
  month: oFound.index,
583
- length: oFound.value.length
725
+ length: oFound.length
584
726
  };
585
727
  }
586
728
  }
@@ -591,15 +733,18 @@ DateFormat.prototype.oSymbols = {
591
733
  length: sPart ? sPart.length : 0,
592
734
  valid: bValid
593
735
  };
736
+ },
737
+ isNumeric: function (iDigits) {
738
+ return iDigits < 3;
594
739
  }
595
- },
596
- 'L': {
740
+ }),
741
+ 'L': DateFormat._createPatternSymbol({
597
742
  name: 'monthStandalone',
598
743
  format: function (oField, oDate, bUTC, oFormat) {
599
- var iMonth = bUTC ? oDate.getUTCMonth() : oDate.getMonth();
600
- if (oField.digits == 3) {
744
+ var iMonth = oDate.getUTCMonth();
745
+ if (oField.digits === 3) {
601
746
  return oFormat.aMonthsAbbrevSt[iMonth];
602
- } else if (oField.digits == 4) {
747
+ } else if (oField.digits === 4) {
603
748
  return oFormat.aMonthsWideSt[iMonth];
604
749
  } else if (oField.digits > 4) {
605
750
  return oFormat.aMonthsNarrowSt[iMonth];
@@ -608,20 +753,18 @@ DateFormat.prototype.oSymbols = {
608
753
  }
609
754
  },
610
755
  parse: function (sValue, oPart, oFormat, oConfig) {
611
- var aMonthsVariants = [
612
- oFormat.aMonthsWide,
613
- oFormat.aMonthsWideSt,
614
- oFormat.aMonthsAbbrev,
615
- oFormat.aMonthsAbbrevSt,
616
- oFormat.aMonthsNarrow,
617
- oFormat.aMonthsNarrowSt
618
- ];
619
- var bValid;
620
- var iMonth;
621
- 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
+ ];
622
764
  if (oPart.digits < 3) {
623
765
  sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
624
- bValid = oParseHelper.checkValid(oPart.type, sPart === '', oFormat);
766
+ bPartInvalid = sPart === '' || oConfig.exactLength && sPart.length < 2;
767
+ bValid = oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat);
625
768
  iMonth = parseInt(sPart) - 1;
626
769
  if (oConfig.strict && (iMonth > 11 || iMonth < 0)) {
627
770
  bValid = false;
@@ -629,11 +772,11 @@ DateFormat.prototype.oSymbols = {
629
772
  } else {
630
773
  for (var i = 0; i < aMonthsVariants.length; i++) {
631
774
  var aVariants = aMonthsVariants[i];
632
- var oFound = oParseHelper.findEntry(sValue, aVariants);
775
+ var oFound = oParseHelper.findEntry(sValue, aVariants, oFormat.oLocaleData.sCLDRLocaleId);
633
776
  if (oFound.index !== -1) {
634
777
  return {
635
778
  month: oFound.index,
636
- length: oFound.value.length
779
+ length: oFound.length
637
780
  };
638
781
  }
639
782
  }
@@ -644,12 +787,15 @@ DateFormat.prototype.oSymbols = {
644
787
  length: sPart ? sPart.length : 0,
645
788
  valid: bValid
646
789
  };
790
+ },
791
+ isNumeric: function (iDigits) {
792
+ return iDigits < 3;
647
793
  }
648
- },
649
- 'w': {
794
+ }),
795
+ 'w': DateFormat._createPatternSymbol({
650
796
  name: 'weekInYear',
651
797
  format: function (oField, oDate, bUTC, oFormat) {
652
- var oWeek = bUTC ? oDate.getUTCWeek() : oDate.getWeek();
798
+ var oWeek = oDate.getUTCWeek(oFormat.oLocale, getCalendarWeekParameter(oFormat.oFormatOptions));
653
799
  var iWeek = oWeek.week;
654
800
  var sWeek = String(iWeek + 1);
655
801
  if (oField.digits < 3) {
@@ -660,22 +806,20 @@ DateFormat.prototype.oSymbols = {
660
806
  return sWeek;
661
807
  },
662
808
  parse: function (sValue, oPart, oFormat, oConfig) {
663
- var bValid;
664
- var sPart;
665
- var iWeek;
666
- var iLength = 0;
809
+ var sPart, bPartInvalid, bValid, iWeek, iLength = 0;
667
810
  if (oPart.digits < 3) {
668
811
  sPart = oParseHelper.findNumbers(sValue, 2);
669
812
  iLength = sPart.length;
670
813
  iWeek = parseInt(sPart) - 1;
671
- bValid = oParseHelper.checkValid(oPart.type, !sPart, oFormat);
814
+ bPartInvalid = !sPart || oConfig.exactLength && iLength < 2;
815
+ bValid = oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat);
672
816
  } else {
673
817
  sPart = oFormat.oLocaleData.getCalendarWeek(oPart.digits === 3 ? 'narrow' : 'wide');
674
- sPart = sPart.replace('{0}', '[0-9]+');
818
+ sPart = sPart.replace('{0}', '([0-9]+)');
675
819
  var rWeekNumber = new RegExp(sPart), oResult = rWeekNumber.exec(sValue);
676
820
  if (oResult) {
677
821
  iLength = oResult[0].length;
678
- iWeek = parseInt(oResult[0]) - 1;
822
+ iWeek = parseInt(oResult[oResult.length - 1]) - 1;
679
823
  } else {
680
824
  bValid = oParseHelper.checkValid(oPart.type, true, oFormat);
681
825
  }
@@ -685,35 +829,21 @@ DateFormat.prototype.oSymbols = {
685
829
  valid: bValid,
686
830
  week: iWeek
687
831
  };
688
- }
689
- },
690
- 'W': {
691
- name: 'weekInMonth',
692
- format: function (oField, oDate, bUTC, oFormat) {
693
- return '';
694
- },
695
- parse: function () {
696
- return {};
697
- }
698
- },
699
- 'D': {
700
- name: 'dayInYear',
701
- format: function (oField, oDate, bUTC, oFormat) {
702
832
  },
703
- parse: function () {
704
- return {};
833
+ isNumeric: function (iDigits) {
834
+ return iDigits < 3;
705
835
  }
706
- },
707
- 'd': {
836
+ }),
837
+ 'W': DateFormat._createPatternSymbol({ name: 'weekInMonth' }),
838
+ 'D': DateFormat._createPatternSymbol({ name: 'dayInYear' }),
839
+ 'd': DateFormat._createPatternSymbol({
708
840
  name: 'day',
709
- format: function (oField, oDate, bUTC, oFormat) {
710
- var iDate = bUTC ? oDate.getUTCDate() : oDate.getDate();
841
+ format: function (oField, oDate) {
842
+ var iDate = oDate.getUTCDate();
711
843
  return String(iDate).padStart(oField.digits, '0');
712
844
  },
713
845
  parse: function (sValue, oPart, oFormat, oConfig) {
714
- var sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
715
- var bValid = oParseHelper.checkValid(oPart.type, sPart === '', oFormat);
716
- 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);
717
847
  if (oConfig.strict && (iDay > 31 || iDay < 1)) {
718
848
  bValid = false;
719
849
  }
@@ -722,15 +852,16 @@ DateFormat.prototype.oSymbols = {
722
852
  length: sPart.length,
723
853
  valid: bValid
724
854
  };
725
- }
726
- },
727
- 'Q': {
855
+ },
856
+ isNumeric: true
857
+ }),
858
+ 'Q': DateFormat._createPatternSymbol({
728
859
  name: 'quarter',
729
860
  format: function (oField, oDate, bUTC, oFormat) {
730
- var iQuarter = bUTC ? oDate.getUTCQuarter() : oDate.getQuarter();
731
- if (oField.digits == 3) {
861
+ var iQuarter = oDate.getUTCQuarter();
862
+ if (oField.digits === 3) {
732
863
  return oFormat.aQuartersAbbrev[iQuarter];
733
- } else if (oField.digits == 4) {
864
+ } else if (oField.digits === 4) {
734
865
  return oFormat.aQuartersWide[iQuarter];
735
866
  } else if (oField.digits > 4) {
736
867
  return oFormat.aQuartersNarrow[iQuarter];
@@ -739,9 +870,7 @@ DateFormat.prototype.oSymbols = {
739
870
  }
740
871
  },
741
872
  parse: function (sValue, oPart, oFormat, oConfig) {
742
- var bValid;
743
- var iQuarter;
744
- var sPart;
873
+ var sPart, bPartInvalid, iQuarter, bValid;
745
874
  var aQuartersVariants = [
746
875
  oFormat.aQuartersWide,
747
876
  oFormat.aQuartersWideSt,
@@ -752,7 +881,8 @@ DateFormat.prototype.oSymbols = {
752
881
  ];
753
882
  if (oPart.digits < 3) {
754
883
  sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
755
- bValid = oParseHelper.checkValid(oPart.type, sPart === '', oFormat);
884
+ bPartInvalid = sPart === '' || oConfig.exactLength && sPart.length < 2;
885
+ bValid = oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat);
756
886
  iQuarter = parseInt(sPart) - 1;
757
887
  if (oConfig.strict && iQuarter > 3) {
758
888
  bValid = false;
@@ -760,11 +890,11 @@ DateFormat.prototype.oSymbols = {
760
890
  } else {
761
891
  for (var i = 0; i < aQuartersVariants.length; i++) {
762
892
  var aVariants = aQuartersVariants[i];
763
- var oFound = oParseHelper.findEntry(sValue, aVariants);
893
+ var oFound = oParseHelper.findEntry(sValue, aVariants, oFormat.oLocaleData.sCLDRLocaleId);
764
894
  if (oFound.index !== -1) {
765
895
  return {
766
896
  quarter: oFound.index,
767
- length: oFound.value.length
897
+ length: oFound.length
768
898
  };
769
899
  }
770
900
  }
@@ -775,15 +905,18 @@ DateFormat.prototype.oSymbols = {
775
905
  quarter: iQuarter,
776
906
  valid: bValid
777
907
  };
908
+ },
909
+ isNumeric: function (iDigits) {
910
+ return iDigits < 3;
778
911
  }
779
- },
780
- 'q': {
912
+ }),
913
+ 'q': DateFormat._createPatternSymbol({
781
914
  name: 'quarterStandalone',
782
915
  format: function (oField, oDate, bUTC, oFormat) {
783
- var iQuarter = bUTC ? oDate.getUTCQuarter() : oDate.getQuarter();
784
- if (oField.digits == 3) {
916
+ var iQuarter = oDate.getUTCQuarter();
917
+ if (oField.digits === 3) {
785
918
  return oFormat.aQuartersAbbrevSt[iQuarter];
786
- } else if (oField.digits == 4) {
919
+ } else if (oField.digits === 4) {
787
920
  return oFormat.aQuartersWideSt[iQuarter];
788
921
  } else if (oField.digits > 4) {
789
922
  return oFormat.aQuartersNarrowSt[iQuarter];
@@ -792,9 +925,7 @@ DateFormat.prototype.oSymbols = {
792
925
  }
793
926
  },
794
927
  parse: function (sValue, oPart, oFormat, oConfig) {
795
- var bValid;
796
- var iQuarter;
797
- var sPart;
928
+ var sPart, bPartInvalid, iQuarter, bValid;
798
929
  var aQuartersVariants = [
799
930
  oFormat.aQuartersWide,
800
931
  oFormat.aQuartersWideSt,
@@ -805,7 +936,8 @@ DateFormat.prototype.oSymbols = {
805
936
  ];
806
937
  if (oPart.digits < 3) {
807
938
  sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
808
- bValid = oParseHelper.checkValid(oPart.type, sPart === '', oFormat);
939
+ bPartInvalid = sPart === '' || oConfig.exactLength && sPart.length < 2;
940
+ bValid = oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat);
809
941
  iQuarter = parseInt(sPart) - 1;
810
942
  if (oConfig.strict && iQuarter > 3) {
811
943
  bValid = false;
@@ -813,11 +945,11 @@ DateFormat.prototype.oSymbols = {
813
945
  } else {
814
946
  for (var i = 0; i < aQuartersVariants.length; i++) {
815
947
  var aVariants = aQuartersVariants[i];
816
- var oFound = oParseHelper.findEntry(sValue, aVariants);
948
+ var oFound = oParseHelper.findEntry(sValue, aVariants, oFormat.oLocaleData.sCLDRLocaleId);
817
949
  if (oFound.index !== -1) {
818
950
  return {
819
951
  quarter: oFound.index,
820
- length: oFound.value.length
952
+ length: oFound.length
821
953
  };
822
954
  }
823
955
  }
@@ -828,26 +960,21 @@ DateFormat.prototype.oSymbols = {
828
960
  quarter: iQuarter,
829
961
  valid: bValid
830
962
  };
831
- }
832
- },
833
- 'F': {
834
- name: 'dayOfWeekInMonth',
835
- format: function (oField, oDate, bUTC, oFormat) {
836
- return '';
837
963
  },
838
- parse: function () {
839
- return {};
964
+ isNumeric: function (iDigits) {
965
+ return iDigits < 3;
840
966
  }
841
- },
842
- 'E': {
967
+ }),
968
+ 'F': DateFormat._createPatternSymbol({ name: 'dayOfWeekInMonth' }),
969
+ 'E': DateFormat._createPatternSymbol({
843
970
  name: 'dayNameInWeek',
844
971
  format: function (oField, oDate, bUTC, oFormat) {
845
- var iDay = bUTC ? oDate.getUTCDay() : oDate.getDay();
972
+ var iDay = oDate.getUTCDay();
846
973
  if (oField.digits < 4) {
847
974
  return oFormat.aDaysAbbrev[iDay];
848
- } else if (oField.digits == 4) {
975
+ } else if (oField.digits === 4) {
849
976
  return oFormat.aDaysWide[iDay];
850
- } else if (oField.digits == 5) {
977
+ } else if (oField.digits === 5) {
851
978
  return oFormat.aDaysNarrow[iDay];
852
979
  } else {
853
980
  return oFormat.aDaysShort[iDay];
@@ -866,25 +993,25 @@ DateFormat.prototype.oSymbols = {
866
993
  ];
867
994
  for (var i = 0; i < aDaysVariants.length; i++) {
868
995
  var aVariants = aDaysVariants[i];
869
- var oFound = oParseHelper.findEntry(sValue, aVariants);
996
+ var oFound = oParseHelper.findEntry(sValue, aVariants, oFormat.oLocaleData.sCLDRLocaleId);
870
997
  if (oFound.index !== -1) {
871
998
  return {
872
999
  dayOfWeek: oFound.index,
873
- length: oFound.value.length
1000
+ length: oFound.length
874
1001
  };
875
1002
  }
876
1003
  }
877
1004
  }
878
- },
879
- 'c': {
1005
+ }),
1006
+ 'c': DateFormat._createPatternSymbol({
880
1007
  name: 'dayNameInWeekStandalone',
881
1008
  format: function (oField, oDate, bUTC, oFormat) {
882
- var iDay = bUTC ? oDate.getUTCDay() : oDate.getDay();
1009
+ var iDay = oDate.getUTCDay();
883
1010
  if (oField.digits < 4) {
884
1011
  return oFormat.aDaysAbbrevSt[iDay];
885
- } else if (oField.digits == 4) {
1012
+ } else if (oField.digits === 4) {
886
1013
  return oFormat.aDaysWideSt[iDay];
887
- } else if (oField.digits == 5) {
1014
+ } else if (oField.digits === 5) {
888
1015
  return oFormat.aDaysNarrowSt[iDay];
889
1016
  } else {
890
1017
  return oFormat.aDaysShortSt[iDay];
@@ -903,72 +1030,129 @@ DateFormat.prototype.oSymbols = {
903
1030
  ];
904
1031
  for (var i = 0; i < aDaysVariants.length; i++) {
905
1032
  var aVariants = aDaysVariants[i];
906
- var oFound = oParseHelper.findEntry(sValue, aVariants);
1033
+ var oFound = oParseHelper.findEntry(sValue, aVariants, oFormat.oLocaleData.sCLDRLocaleId);
907
1034
  if (oFound.index !== -1) {
908
1035
  return {
909
1036
  day: oFound.index,
910
- length: oFound.value.length
1037
+ length: oFound.length
911
1038
  };
912
1039
  }
913
1040
  }
914
1041
  }
915
- },
916
- 'u': {
1042
+ }),
1043
+ 'u': DateFormat._createPatternSymbol({
917
1044
  name: 'dayNumberOfWeek',
918
1045
  format: function (oField, oDate, bUTC, oFormat) {
919
- var iDay = bUTC ? oDate.getUTCDay() : oDate.getDay();
1046
+ var iDay = oDate.getUTCDay();
920
1047
  return oFormat._adaptDayOfWeek(iDay);
921
1048
  },
922
1049
  parse: function (sValue, oPart, oFormat, oConfig) {
923
- var sPart = oParseHelper.findNumbers(sValue, oPart.digits);
1050
+ var sPart = oParseHelper.findNumbers(sValue, oPart.digits), bPartInvalid = oConfig.exactLength && sPart.length !== oPart.digits;
924
1051
  return {
925
1052
  dayNumberOfWeek: parseInt(sPart),
926
- length: sPart.length
1053
+ length: sPart.length,
1054
+ valid: oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat)
927
1055
  };
928
- }
929
- },
930
- 'a': {
1056
+ },
1057
+ isNumeric: true
1058
+ }),
1059
+ 'a': DateFormat._createPatternSymbol({
931
1060
  name: 'amPmMarker',
932
1061
  format: function (oField, oDate, bUTC, oFormat) {
933
- var iDayPeriod = bUTC ? oDate.getUTCDayPeriod() : oDate.getDayPeriod();
934
- 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];
935
1124
  },
936
1125
  parse: function (sValue, oPart, oFormat, oConfig) {
937
- var bPM;
938
- var iLength;
939
- var sAM = oFormat.aDayPeriods[0], sPM = oFormat.aDayPeriods[1];
940
- var rAMPM = /[aApP](?:\.)?[mM](?:\.)?/;
941
- var aMatch = sValue.match(rAMPM);
942
- var bVariant = aMatch && aMatch.index === 0;
943
- if (bVariant) {
944
- sValue = aMatch[0].replace(/\./g, '').toLowerCase() + sValue.substring(aMatch[0].length);
945
- sAM = sAM.replace(/\./g, '').toLowerCase();
946
- sPM = sPM.replace(/\./g, '').toLowerCase();
947
- }
948
- if (sValue.indexOf(sAM) === 0) {
949
- bPM = false;
950
- iLength = bVariant ? aMatch[0].length : sAM.length;
951
- } else if (sValue.indexOf(sPM) === 0) {
952
- bPM = true;
953
- 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
+ }
954
1144
  }
955
- return {
956
- pm: bPM,
957
- length: iLength
958
- };
1145
+ return { valid: false };
959
1146
  }
960
- },
961
- 'H': {
1147
+ }),
1148
+ 'H': DateFormat._createPatternSymbol({
962
1149
  name: 'hour0_23',
963
- format: function (oField, oDate, bUTC, oFormat) {
964
- var iHours = bUTC ? oDate.getUTCHours() : oDate.getHours();
1150
+ format: function (oField, oDate) {
1151
+ var iHours = oDate.getUTCHours();
965
1152
  return String(iHours).padStart(oField.digits, '0');
966
1153
  },
967
1154
  parse: function (sValue, oPart, oFormat, oConfig) {
968
- var bValid;
969
- var sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
970
- var iHours = parseInt(sPart);
971
- 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);
972
1156
  if (oConfig.strict && iHours > 23) {
973
1157
  bValid = false;
974
1158
  }
@@ -977,21 +1161,19 @@ DateFormat.prototype.oSymbols = {
977
1161
  length: sPart.length,
978
1162
  valid: bValid
979
1163
  };
980
- }
981
- },
982
- 'k': {
1164
+ },
1165
+ isNumeric: true
1166
+ }),
1167
+ 'k': DateFormat._createPatternSymbol({
983
1168
  name: 'hour1_24',
984
- format: function (oField, oDate, bUTC, oFormat) {
985
- var iHours = bUTC ? oDate.getUTCHours() : oDate.getHours();
1169
+ format: function (oField, oDate) {
1170
+ var iHours = oDate.getUTCHours();
986
1171
  var sHours = iHours === 0 ? '24' : String(iHours);
987
1172
  return sHours.padStart(oField.digits, '0');
988
1173
  },
989
1174
  parse: function (sValue, oPart, oFormat, oConfig) {
990
- var bValid;
991
- var sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
992
- var iHours = parseInt(sPart);
993
- bValid = oParseHelper.checkValid(oPart.type, sPart === '', oFormat);
994
- 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) {
995
1177
  iHours = 0;
996
1178
  }
997
1179
  if (oConfig.strict && iHours > 23) {
@@ -1002,20 +1184,18 @@ DateFormat.prototype.oSymbols = {
1002
1184
  length: sPart.length,
1003
1185
  valid: bValid
1004
1186
  };
1005
- }
1006
- },
1007
- 'K': {
1187
+ },
1188
+ isNumeric: true
1189
+ }),
1190
+ 'K': DateFormat._createPatternSymbol({
1008
1191
  name: 'hour0_11',
1009
- format: function (oField, oDate, bUTC, oFormat) {
1010
- var iHours = bUTC ? oDate.getUTCHours() : oDate.getHours();
1192
+ format: function (oField, oDate) {
1193
+ var iHours = oDate.getUTCHours();
1011
1194
  var sHours = String(iHours > 11 ? iHours - 12 : iHours);
1012
1195
  return sHours.padStart(oField.digits, '0');
1013
1196
  },
1014
1197
  parse: function (sValue, oPart, oFormat, oConfig) {
1015
- var bValid;
1016
- var sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
1017
- var iHours = parseInt(sPart);
1018
- 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);
1019
1199
  if (oConfig.strict && iHours > 11) {
1020
1200
  bValid = false;
1021
1201
  }
@@ -1024,16 +1204,17 @@ DateFormat.prototype.oSymbols = {
1024
1204
  length: sPart.length,
1025
1205
  valid: bValid
1026
1206
  };
1027
- }
1028
- },
1029
- 'h': {
1207
+ },
1208
+ isNumeric: true
1209
+ }),
1210
+ 'h': DateFormat._createPatternSymbol({
1030
1211
  name: 'hour1_12',
1031
- format: function (oField, oDate, bUTC, oFormat) {
1032
- var iHours = bUTC ? oDate.getUTCHours() : oDate.getHours();
1212
+ format: function (oField, oDate) {
1213
+ var iHours = oDate.getUTCHours();
1033
1214
  var sHours;
1034
1215
  if (iHours > 12) {
1035
1216
  sHours = String(iHours - 12);
1036
- } else if (iHours == 0) {
1217
+ } else if (iHours === 0) {
1037
1218
  sHours = '12';
1038
1219
  } else {
1039
1220
  sHours = String(iHours);
@@ -1041,11 +1222,8 @@ DateFormat.prototype.oSymbols = {
1041
1222
  return sHours.padStart(oField.digits, '0');
1042
1223
  },
1043
1224
  parse: function (sValue, oPart, oFormat, oConfig) {
1044
- var bPM = oConfig.dateValue.pm;
1045
- var sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
1046
- var iHours = parseInt(sPart);
1047
- var bValid = oParseHelper.checkValid(oPart.type, sPart === '', oFormat);
1048
- 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) {
1049
1227
  iHours = 0;
1050
1228
  bPM = bPM === undefined ? true : bPM;
1051
1229
  }
@@ -1058,19 +1236,17 @@ DateFormat.prototype.oSymbols = {
1058
1236
  pm: bPM,
1059
1237
  valid: bValid
1060
1238
  };
1061
- }
1062
- },
1063
- 'm': {
1239
+ },
1240
+ isNumeric: true
1241
+ }),
1242
+ 'm': DateFormat._createPatternSymbol({
1064
1243
  name: 'minute',
1065
- format: function (oField, oDate, bUTC, oFormat) {
1066
- var iMinutes = bUTC ? oDate.getUTCMinutes() : oDate.getMinutes();
1244
+ format: function (oField, oDate) {
1245
+ var iMinutes = oDate.getUTCMinutes();
1067
1246
  return String(iMinutes).padStart(oField.digits, '0');
1068
1247
  },
1069
1248
  parse: function (sValue, oPart, oFormat, oConfig) {
1070
- var bValid;
1071
- var sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
1072
- var iMinutes = parseInt(sPart);
1073
- 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);
1074
1250
  if (oConfig.strict && iMinutes > 59) {
1075
1251
  bValid = false;
1076
1252
  }
@@ -1079,19 +1255,17 @@ DateFormat.prototype.oSymbols = {
1079
1255
  minute: iMinutes,
1080
1256
  valid: bValid
1081
1257
  };
1082
- }
1083
- },
1084
- 's': {
1258
+ },
1259
+ isNumeric: true
1260
+ }),
1261
+ 's': DateFormat._createPatternSymbol({
1085
1262
  name: 'second',
1086
- format: function (oField, oDate, bUTC, oFormat) {
1087
- var iSeconds = bUTC ? oDate.getUTCSeconds() : oDate.getSeconds();
1263
+ format: function (oField, oDate) {
1264
+ var iSeconds = oDate.getUTCSeconds();
1088
1265
  return String(iSeconds).padStart(oField.digits, '0');
1089
1266
  },
1090
1267
  parse: function (sValue, oPart, oFormat, oConfig) {
1091
- var bValid;
1092
- var sPart = oParseHelper.findNumbers(sValue, Math.max(oPart.digits, 2));
1093
- var iSeconds = parseInt(sPart);
1094
- 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);
1095
1269
  if (oConfig.strict && iSeconds > 59) {
1096
1270
  bValid = false;
1097
1271
  }
@@ -1100,12 +1274,13 @@ DateFormat.prototype.oSymbols = {
1100
1274
  second: iSeconds,
1101
1275
  valid: bValid
1102
1276
  };
1103
- }
1104
- },
1105
- 'S': {
1277
+ },
1278
+ isNumeric: true
1279
+ }),
1280
+ 'S': DateFormat._createPatternSymbol({
1106
1281
  name: 'fractionalsecond',
1107
- format: function (oField, oDate, bUTC, oFormat) {
1108
- var iMilliseconds = bUTC ? oDate.getUTCMilliseconds() : oDate.getMilliseconds();
1282
+ format: function (oField, oDate) {
1283
+ var iMilliseconds = oDate.getUTCMilliseconds();
1109
1284
  var sMilliseconds = String(iMilliseconds);
1110
1285
  var sFractionalseconds = sMilliseconds.padStart(3, '0');
1111
1286
  sFractionalseconds = sFractionalseconds.substr(0, oField.digits);
@@ -1113,31 +1288,33 @@ DateFormat.prototype.oSymbols = {
1113
1288
  return sFractionalseconds;
1114
1289
  },
1115
1290
  parse: function (sValue, oPart, oFormat, oConfig) {
1116
- var sPart = oParseHelper.findNumbers(sValue, oPart.digits);
1117
- var iLength = sPart.length;
1291
+ var sPart = oParseHelper.findNumbers(sValue, oPart.digits), iLength = sPart.length, bPartInvalid = oConfig.exactLength && iLength < oPart.digits;
1118
1292
  sPart = sPart.substr(0, 3);
1119
1293
  sPart = sPart.padEnd(3, '0');
1120
1294
  var iMilliseconds = parseInt(sPart);
1121
1295
  return {
1122
1296
  length: iLength,
1123
- millisecond: iMilliseconds
1297
+ millisecond: iMilliseconds,
1298
+ valid: oParseHelper.checkValid(oPart.type, bPartInvalid, oFormat)
1124
1299
  };
1125
- }
1126
- },
1127
- 'z': {
1300
+ },
1301
+ isNumeric: true
1302
+ }),
1303
+ 'z': DateFormat._createPatternSymbol({
1128
1304
  name: 'timezoneGeneral',
1129
- format: function (oField, oDate, bUTC, oFormat) {
1130
- if (oField.digits > 3 && oDate.getTimezoneLong()) {
1305
+ format: function (oField, oDate, bUTC, oFormat, sTimezone) {
1306
+ if (oField.digits > 3 && oDate.getTimezoneLong && oDate.getTimezoneLong()) {
1131
1307
  return oDate.getTimezoneLong();
1132
- } else if (oDate.getTimezoneShort()) {
1308
+ } else if (oDate.getTimezoneShort && oDate.getTimezoneShort()) {
1133
1309
  return oDate.getTimezoneShort();
1134
1310
  }
1311
+ var iTimezoneOffset = TimezoneUtil.calculateOffset(oDate, sTimezone);
1135
1312
  var sTimeZone = 'GMT';
1136
- var iTZOffset = Math.abs(oDate.getTimezoneOffset());
1137
- var bPositiveOffset = oDate.getTimezoneOffset() > 0;
1313
+ var iTZOffset = Math.abs(iTimezoneOffset / 60);
1314
+ var bPositiveOffset = iTimezoneOffset > 0;
1138
1315
  var iHourOffset = Math.floor(iTZOffset / 60);
1139
- var iMinuteOffset = iTZOffset % 60;
1140
- if (!bUTC && iTZOffset != 0) {
1316
+ var iMinuteOffset = Math.floor(iTZOffset % 60);
1317
+ if (!bUTC && iTZOffset !== 0) {
1141
1318
  sTimeZone += bPositiveOffset ? '-' : '+';
1142
1319
  sTimeZone += String(iHourOffset).padStart(2, '0');
1143
1320
  sTimeZone += ':';
@@ -1155,13 +1332,13 @@ DateFormat.prototype.oSymbols = {
1155
1332
  iLength = 3;
1156
1333
  } else if (sValue.substring(0, 2) === 'UT') {
1157
1334
  iLength = 2;
1158
- } else if (sValue.charAt(0) == 'Z') {
1335
+ } else if (sValue.charAt(0) === 'Z') {
1159
1336
  iLength = 1;
1160
1337
  iTZDiff = 0;
1161
1338
  } else {
1162
- return { error: 'cannot be parsed correcly by sap.ui.core.format.DateFormat: The given timezone is not supported!' };
1339
+ return { error: 'cannot be parsed correctly by sap.ui.core.format.DateFormat: The given timezone is not supported!' };
1163
1340
  }
1164
- if (sValue.charAt(0) != 'Z') {
1341
+ if (sValue.charAt(0) !== 'Z') {
1165
1342
  var oParsedTZ = oParseHelper.parseTZ(sValue.substr(iLength), true);
1166
1343
  iLength += oParsedTZ.length;
1167
1344
  iTZDiff = oParsedTZ.tzDiff;
@@ -1171,16 +1348,17 @@ DateFormat.prototype.oSymbols = {
1171
1348
  tzDiff: iTZDiff
1172
1349
  };
1173
1350
  }
1174
- },
1175
- 'Z': {
1351
+ }),
1352
+ 'Z': DateFormat._createPatternSymbol({
1176
1353
  name: 'timezoneRFC822',
1177
- format: function (oField, oDate, bUTC, oFormat) {
1178
- var iTZOffset = Math.abs(oDate.getTimezoneOffset());
1179
- 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;
1180
1358
  var iHourOffset = Math.floor(iTZOffset / 60);
1181
- var iMinuteOffset = iTZOffset % 60;
1359
+ var iMinuteOffset = Math.floor(iTZOffset % 60);
1182
1360
  var sTimeZone = '';
1183
- if (!bUTC && iTZOffset != 0) {
1361
+ if (!bUTC) {
1184
1362
  sTimeZone += bPositiveOffset ? '-' : '+';
1185
1363
  sTimeZone += String(iHourOffset).padStart(2, '0');
1186
1364
  sTimeZone += String(iMinuteOffset).padStart(2, '0');
@@ -1190,40 +1368,86 @@ DateFormat.prototype.oSymbols = {
1190
1368
  parse: function (sValue, oPart, oFormat, oConfig) {
1191
1369
  return oParseHelper.parseTZ(sValue, false);
1192
1370
  }
1193
- },
1194
- 'X': {
1371
+ }),
1372
+ 'X': DateFormat._createPatternSymbol({
1195
1373
  name: 'timezoneISO8601',
1196
- format: function (oField, oDate, bUTC, oFormat) {
1197
- var iTZOffset = Math.abs(oDate.getTimezoneOffset());
1198
- 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;
1199
1378
  var iHourOffset = Math.floor(iTZOffset / 60);
1200
- var iMinuteOffset = iTZOffset % 60;
1379
+ var iMinuteOffset = Math.floor(iTZOffset % 60);
1201
1380
  var sTimeZone = '';
1202
- if (!bUTC && iTZOffset != 0) {
1381
+ if (!bUTC && iTZOffset !== 0) {
1203
1382
  sTimeZone += bPositiveOffset ? '-' : '+';
1204
1383
  sTimeZone += String(iHourOffset).padStart(2, '0');
1205
- sTimeZone += ':';
1206
- sTimeZone += String(iMinuteOffset).padStart(2, '0');
1384
+ if (oField.digits > 1 || iMinuteOffset > 0) {
1385
+ if (oField.digits === 3 || oField.digits === 5) {
1386
+ sTimeZone += ':';
1387
+ }
1388
+ sTimeZone += String(iMinuteOffset).padStart(2, '0');
1389
+ }
1207
1390
  } else {
1208
1391
  sTimeZone += 'Z';
1209
1392
  }
1210
1393
  return sTimeZone;
1211
1394
  },
1212
1395
  parse: function (sValue, oPart, oFormat, oConfig) {
1213
- if (sValue.charAt(0) == 'Z') {
1396
+ if (sValue.charAt(0) === 'Z') {
1214
1397
  return {
1215
1398
  length: 1,
1216
1399
  tzDiff: 0
1217
1400
  };
1218
1401
  } else {
1219
- return oParseHelper.parseTZ(sValue, true);
1402
+ return oParseHelper.parseTZ(sValue, oPart.digits === 3 || oPart.digits === 5);
1220
1403
  }
1221
1404
  }
1222
- }
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
+ })
1223
1447
  };
1224
- DateFormat.prototype._format = function (oJSDate, bUTC) {
1448
+ DateFormat.prototype._format = function (oJSDate, bUTC, sTimezone) {
1225
1449
  if (this.oFormatOptions.relative) {
1226
- var sRes = this.formatRelative(oJSDate, bUTC, this.oFormatOptions.relativeRange);
1450
+ var sRes = this.formatRelative(oJSDate, bUTC, this.oFormatOptions.relativeRange, sTimezone);
1227
1451
  if (sRes) {
1228
1452
  return sRes;
1229
1453
  }
@@ -1234,10 +1458,10 @@ DateFormat.prototype._format = function (oJSDate, bUTC) {
1234
1458
  for (var i = 0; i < this.aFormatArray.length; i++) {
1235
1459
  oPart = this.aFormatArray[i];
1236
1460
  sSymbol = oPart.symbol || '';
1237
- aBuffer.push(this.oSymbols[sSymbol].format(oPart, oDate, bUTC, this));
1461
+ aBuffer.push(this.oSymbols[sSymbol].format(oPart, oDate, bUTC, this, sTimezone));
1238
1462
  }
1239
1463
  sResult = aBuffer.join('');
1240
- if (Core.getConfiguration().getOriginInfo()) {
1464
+ if (Configuration.getOriginInfo()) {
1241
1465
  sResult = new String(sResult);
1242
1466
  sResult.originInfo = {
1243
1467
  source: 'Common Locale Data Repository',
@@ -1249,10 +1473,21 @@ DateFormat.prototype._format = function (oJSDate, bUTC) {
1249
1473
  return sResult;
1250
1474
  };
1251
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
+ }
1252
1486
  var sCalendarType = this.oFormatOptions.calendarType, sResult;
1253
1487
  if (bUTC === undefined) {
1254
1488
  bUTC = this.oFormatOptions.UTC;
1255
1489
  }
1490
+ sTimezone = sTimezone || Configuration.getTimezone();
1256
1491
  if (Array.isArray(vJSDate)) {
1257
1492
  if (!this.oFormatOptions.interval) {
1258
1493
  Log.error('Non-interval DateFormat can\'t format more than one date instance.');
@@ -1262,27 +1497,30 @@ DateFormat.prototype.format = function (vJSDate, bUTC) {
1262
1497
  Log.error('Interval DateFormat can only format with 2 date instances but ' + vJSDate.length + ' is given.');
1263
1498
  return '';
1264
1499
  }
1500
+ vJSDate = vJSDate.map(function (oJSDate) {
1501
+ return convertToTimezone(oJSDate, sTimezone, bUTC);
1502
+ });
1265
1503
  if (this.oFormatOptions.singleIntervalValue) {
1266
1504
  if (vJSDate[0] === null) {
1267
1505
  Log.error('First date instance which is passed to the interval DateFormat shouldn\'t be null.');
1268
1506
  return '';
1269
1507
  }
1270
1508
  if (vJSDate[1] === null) {
1271
- sResult = this._format(vJSDate[0], bUTC);
1509
+ sResult = this._format(vJSDate[0], bUTC, sTimezone);
1272
1510
  }
1273
1511
  }
1274
1512
  if (sResult === undefined) {
1275
- var bValid = vJSDate.every(function (oJSDate) {
1276
- return oJSDate && !isNaN(oJSDate.getTime());
1277
- });
1278
- if (!bValid) {
1513
+ if (!vJSDate.every(isValidDateObject)) {
1279
1514
  Log.error('At least one date instance which is passed to the interval DateFormat isn\'t valid.');
1280
1515
  return '';
1281
1516
  }
1282
1517
  sResult = this._formatInterval(vJSDate, bUTC);
1283
1518
  }
1284
1519
  } else {
1285
- 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
+ }
1286
1524
  Log.error('The given date instance isn\'t valid.');
1287
1525
  return '';
1288
1526
  }
@@ -1290,32 +1528,39 @@ DateFormat.prototype.format = function (vJSDate, bUTC) {
1290
1528
  Log.error('Interval DateFormat expects an array with two dates for the first argument but only one date is given.');
1291
1529
  return '';
1292
1530
  }
1293
- sResult = this._format(vJSDate, bUTC);
1531
+ vJSDate = convertToTimezone(vJSDate, sTimezone, bUTC);
1532
+ sResult = this._format(vJSDate, bUTC, sTimezone);
1294
1533
  }
1295
- if (sCalendarType == CalendarType.Japanese && this.oLocale.getLanguage() === 'ja') {
1534
+ if (sCalendarType === CalendarType.Japanese && this.oLocale.getLanguage() === 'ja') {
1296
1535
  sResult = sResult.replace(/(^|[^\d])1年/g, '$1元年');
1297
1536
  }
1298
1537
  return sResult;
1299
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
+ };
1300
1552
  DateFormat.prototype._formatInterval = function (aJSDates, bUTC) {
1301
- var sCalendarType = this.oFormatOptions.calendarType;
1302
- var oFromDate = UniversalDate.getInstance(aJSDates[0], sCalendarType);
1303
- var oToDate = UniversalDate.getInstance(aJSDates[1], sCalendarType);
1304
- var oDate;
1305
- var oPart;
1306
- var sSymbol;
1307
- var aBuffer = [];
1308
- var sPattern;
1309
- var aFormatArray = [];
1310
- var oDiffField = this._getGreatestDiffField([
1311
- oFromDate,
1312
- oToDate
1313
- ], bUTC);
1314
- 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) {
1315
1558
  return this._format(aJSDates[0], bUTC);
1316
1559
  }
1317
- if (this.oFormatOptions.format) {
1318
- 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);
1319
1564
  } else {
1320
1565
  sPattern = this.oLocaleData.getCombinedIntervalPattern(this.oFormatOptions.pattern, sCalendarType);
1321
1566
  }
@@ -1343,10 +1588,10 @@ var mFieldToGroup = {
1343
1588
  Minutes: 'Minute',
1344
1589
  Seconds: 'Second'
1345
1590
  };
1346
- DateFormat.prototype._getGreatestDiffField = function (aDates, bUTC) {
1591
+ DateFormat.prototype._getDiffFields = function (aDates) {
1347
1592
  var bDiffFound = false, mDiff = {};
1348
1593
  this.aIntervalCompareFields.forEach(function (sField) {
1349
- 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]);
1350
1595
  if (!deepEqual(vFromValue, vToValue)) {
1351
1596
  bDiffFound = true;
1352
1597
  mDiff[sFieldGroup] = true;
@@ -1357,19 +1602,32 @@ DateFormat.prototype._getGreatestDiffField = function (aDates, bUTC) {
1357
1602
  }
1358
1603
  return null;
1359
1604
  };
1360
- DateFormat.prototype._parse = function (sValue, aFormatArray, bUTC, bStrict) {
1361
- var iIndex = 0, oPart, sSubValue, oResult;
1362
- var oDateValue = { valid: true };
1363
- var oParseConf = {
1364
- formatArray: aFormatArray,
1365
- dateValue: oDateValue,
1366
- strict: bStrict
1367
- };
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
+ }
1368
1620
  for (var i = 0; i < aFormatArray.length; i++) {
1369
1621
  sSubValue = sValue.substr(iIndex);
1370
1622
  oPart = aFormatArray[i];
1623
+ oPrevPart = aFormatArray[i - 1];
1624
+ oNextPart = aFormatArray[i + 1];
1371
1625
  oParseConf.index = i;
1372
- 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
+ }
1373
1631
  oDateValue = extend(oDateValue, oResult);
1374
1632
  if (oResult.valid === false) {
1375
1633
  break;
@@ -1377,7 +1635,12 @@ DateFormat.prototype._parse = function (sValue, aFormatArray, bUTC, bStrict) {
1377
1635
  iIndex += oResult.length || 0;
1378
1636
  }
1379
1637
  oDateValue.index = iIndex;
1380
- 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) {
1381
1644
  oDateValue.hour += 12;
1382
1645
  }
1383
1646
  if (oDateValue.dayNumberOfWeek === undefined && oDateValue.dayOfWeek !== undefined) {
@@ -1389,7 +1652,7 @@ DateFormat.prototype._parse = function (sValue, aFormatArray, bUTC, bStrict) {
1389
1652
  }
1390
1653
  return oDateValue;
1391
1654
  };
1392
- DateFormat.prototype._parseInterval = function (sValue, sCalendarType, bUTC, bStrict) {
1655
+ DateFormat.prototype._parseInterval = function (sValue, sCalendarType, bUTC, bStrict, sTimezone) {
1393
1656
  var aDateValues, iRepeat, oDateValue;
1394
1657
  this.intervalPatterns.some(function (sPattern) {
1395
1658
  var aFormatArray = this.parseCldrDatePattern(sPattern);
@@ -1401,7 +1664,7 @@ DateFormat.prototype._parseInterval = function (sValue, sCalendarType, bUTC, bSt
1401
1664
  }
1402
1665
  }
1403
1666
  if (iRepeat === undefined) {
1404
- oDateValue = this._parse(sValue, aFormatArray, bUTC, bStrict);
1667
+ oDateValue = this._parse(sValue, aFormatArray, bUTC, bStrict, sTimezone);
1405
1668
  if (oDateValue.index === 0 || oDateValue.index < sValue.length) {
1406
1669
  oDateValue.valid = false;
1407
1670
  }
@@ -1415,13 +1678,13 @@ DateFormat.prototype._parseInterval = function (sValue, sCalendarType, bUTC, bSt
1415
1678
  return true;
1416
1679
  } else {
1417
1680
  aDateValues = [];
1418
- oDateValue = this._parse(sValue, aFormatArray.slice(0, iRepeat), bUTC, bStrict);
1681
+ oDateValue = this._parse(sValue, aFormatArray.slice(0, iRepeat), bUTC, bStrict, sTimezone);
1419
1682
  if (oDateValue.valid === false) {
1420
1683
  return;
1421
1684
  }
1422
1685
  aDateValues.push(oDateValue);
1423
1686
  var iLength = oDateValue.index;
1424
- oDateValue = this._parse(sValue.substring(iLength), aFormatArray.slice(iRepeat), bUTC, bStrict);
1687
+ oDateValue = this._parse(sValue.substring(iLength), aFormatArray.slice(iRepeat), bUTC, bStrict, sTimezone);
1425
1688
  if (oDateValue.index === 0 || oDateValue.index + iLength < sValue.length) {
1426
1689
  oDateValue.valid = false;
1427
1690
  }
@@ -1434,65 +1697,62 @@ DateFormat.prototype._parseInterval = function (sValue, sCalendarType, bUTC, bSt
1434
1697
  }.bind(this));
1435
1698
  return aDateValues;
1436
1699
  };
1437
- 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
+ }
1438
1721
  var oDate, iYear = typeof oDateValue.year === 'number' ? oDateValue.year : 1970;
1439
- if (oDateValue.valid) {
1440
- if (bUTC || oDateValue.tzDiff !== undefined) {
1441
- oDate = UniversalDate.getInstance(new Date(0), sCalendarType);
1442
- oDate.setUTCEra(oDateValue.era || UniversalDate.getCurrentEra(sCalendarType));
1443
- oDate.setUTCFullYear(iYear);
1444
- oDate.setUTCMonth(oDateValue.month || 0);
1445
- oDate.setUTCDate(oDateValue.day || 1);
1446
- oDate.setUTCHours(oDateValue.hour || 0);
1447
- oDate.setUTCMinutes(oDateValue.minute || 0);
1448
- oDate.setUTCSeconds(oDateValue.second || 0);
1449
- oDate.setUTCMilliseconds(oDateValue.millisecond || 0);
1450
- if (bStrict && (oDateValue.day || 1) !== oDate.getUTCDate()) {
1451
- oDateValue.valid = false;
1452
- oDate = undefined;
1453
- } else {
1454
- if (oDateValue.tzDiff) {
1455
- oDate.setUTCMinutes((oDateValue.minute || 0) + oDateValue.tzDiff);
1456
- }
1457
- if (oDateValue.week !== undefined && (oDateValue.month === undefined || oDateValue.day === undefined)) {
1458
- oDate.setUTCWeek({
1459
- year: oDateValue.weekYear || oDateValue.year,
1460
- week: oDateValue.week
1461
- });
1462
- if (oDateValue.dayNumberOfWeek !== undefined) {
1463
- oDate.setUTCDate(oDate.getUTCDate() + oDateValue.dayNumberOfWeek - 1);
1464
- }
1465
- }
1466
- }
1467
- } else {
1468
- oDate = UniversalDate.getInstance(new Date(1970, 0, 1, 0, 0, 0), sCalendarType);
1469
- oDate.setEra(oDateValue.era || UniversalDate.getCurrentEra(sCalendarType));
1470
- oDate.setFullYear(iYear);
1471
- oDate.setMonth(oDateValue.month || 0);
1472
- oDate.setDate(oDateValue.day || 1);
1473
- oDate.setHours(oDateValue.hour || 0);
1474
- oDate.setMinutes(oDateValue.minute || 0);
1475
- oDate.setSeconds(oDateValue.second || 0);
1476
- oDate.setMilliseconds(oDateValue.millisecond || 0);
1477
- if (bStrict && (oDateValue.day || 1) !== oDate.getDate()) {
1478
- oDateValue.valid = false;
1479
- oDate = undefined;
1480
- } else if (oDateValue.week !== undefined && (oDateValue.month === undefined || oDateValue.day === undefined)) {
1481
- oDate.setWeek({
1482
- year: oDateValue.weekYear || oDateValue.year,
1483
- week: oDateValue.week
1484
- });
1485
- if (oDateValue.dayNumberOfWeek !== undefined) {
1486
- oDate.setDate(oDate.getDate() + oDateValue.dayNumberOfWeek - 1);
1487
- }
1488
- }
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);
1741
+ }
1742
+ }
1743
+ oDate = oDate.getJSDate();
1744
+ if (!bUTC && (oDateValue.lastTimezonePatternSymbol === 'V' && oDateValue.timezone || oDateValue.tzDiff === undefined)) {
1745
+ if (oDateValue.timezone) {
1746
+ sTimezone = oDateValue.timezone;
1489
1747
  }
1490
- if (oDateValue.valid) {
1491
- oDate = oDate.getJSDate();
1492
- return oDate;
1748
+ if (sTimezone) {
1749
+ oDateValue.tzDiff = TimezoneUtil.calculateOffset(oDate, sTimezone);
1493
1750
  }
1494
1751
  }
1495
- return null;
1752
+ if (oDateValue.tzDiff) {
1753
+ oDate.setUTCSeconds(oDate.getUTCSeconds() + oDateValue.tzDiff);
1754
+ }
1755
+ return oDate;
1496
1756
  };
1497
1757
  function mergeWithoutOverwrite(object1, object2) {
1498
1758
  if (object1 === object2) {
@@ -1515,17 +1775,37 @@ function isValidDateRange(oStartDate, oEndDate) {
1515
1775
  }
1516
1776
  return true;
1517
1777
  }
1778
+ function isValidDateObject(oDate) {
1779
+ return oDate && typeof oDate.getTime === 'function' && !isNaN(oDate.getTime());
1780
+ }
1518
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
+ }
1519
1801
  sValue = sValue == null ? '' : String(sValue).trim();
1520
1802
  var oDateValue;
1521
1803
  var sCalendarType = this.oFormatOptions.calendarType;
1522
- if (bUTC === undefined) {
1523
- bUTC = this.oFormatOptions.UTC;
1524
- }
1804
+ sTimezone = sTimezone || Configuration.getTimezone();
1525
1805
  if (bStrict === undefined) {
1526
1806
  bStrict = this.oFormatOptions.strictParsing;
1527
1807
  }
1528
- if (sCalendarType == CalendarType.Japanese && this.oLocale.getLanguage() === 'ja') {
1808
+ if (sCalendarType === CalendarType.Japanese && this.oLocale.getLanguage() === 'ja') {
1529
1809
  sValue = sValue.replace(/元年/g, '1年');
1530
1810
  }
1531
1811
  if (!this.oFormatOptions.interval) {
@@ -1533,22 +1813,40 @@ DateFormat.prototype.parse = function (sValue, bUTC, bStrict) {
1533
1813
  if (oJSDate) {
1534
1814
  return oJSDate;
1535
1815
  }
1536
- oDateValue = this._parse(sValue, this.aFormatArray, bUTC, bStrict);
1816
+ oDateValue = this._parse(sValue, this.aFormatArray, bUTC, bStrict, sTimezone);
1537
1817
  if (oDateValue.index === 0 || oDateValue.index < sValue.length) {
1538
1818
  oDateValue.valid = false;
1539
1819
  }
1540
- oJSDate = fnCreateDate(oDateValue, sCalendarType, bUTC, bStrict);
1820
+ oJSDate = fnCreateDate(oDateValue, sCalendarType, bUTC, bStrict, sTimezone, this.oFormatOptions, this.oLocale);
1541
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
+ }
1542
1840
  return oJSDate;
1543
1841
  }
1544
1842
  } else {
1545
- var aDateValues = this._parseInterval(sValue, sCalendarType, bUTC, bStrict);
1843
+ var aDateValues = this._parseInterval(sValue, sCalendarType, bUTC, bStrict, sTimezone);
1546
1844
  var oJSDate1, oJSDate2;
1547
- if (aDateValues && aDateValues.length == 2) {
1845
+ if (aDateValues && aDateValues.length === 2) {
1548
1846
  var oDateValue1 = mergeWithoutOverwrite(aDateValues[0], aDateValues[1]);
1549
1847
  var oDateValue2 = mergeWithoutOverwrite(aDateValues[1], aDateValues[0]);
1550
- oJSDate1 = fnCreateDate(oDateValue1, sCalendarType, bUTC, bStrict);
1551
- 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);
1552
1850
  if (oJSDate1 && oJSDate2) {
1553
1851
  if (this.oFormatOptions.singleIntervalValue && oJSDate1.getTime() === oJSDate2.getTime()) {
1554
1852
  return [
@@ -1571,11 +1869,14 @@ DateFormat.prototype.parse = function (sValue, bUTC, bStrict) {
1571
1869
  }
1572
1870
  }
1573
1871
  }
1574
- if (!this.bIsFallback) {
1872
+ if (this.aFallbackFormats) {
1575
1873
  var vDate;
1576
1874
  this.aFallbackFormats.every(function (oFallbackFormat) {
1577
- vDate = oFallbackFormat.parse(sValue, bUTC, bStrict);
1875
+ vDate = oFallbackFormat.parse(sValue, bUTCInputParameter, bStrict);
1578
1876
  if (Array.isArray(vDate)) {
1877
+ if (oFallbackFormat.type === mDateFormatTypes.DATETIME_WITH_TIMEZONE) {
1878
+ return false;
1879
+ }
1579
1880
  return !(vDate[0] && vDate[1]);
1580
1881
  } else {
1581
1882
  return !vDate;
@@ -1600,20 +1901,20 @@ DateFormat.prototype.parseCldrDatePattern = function (sPattern) {
1600
1901
  for (i = 0; i < sPattern.length; i++) {
1601
1902
  var sCurChar = sPattern.charAt(i), sNextChar, sPrevChar, sPrevPrevChar;
1602
1903
  if (bQuoted) {
1603
- if (sCurChar == '\'') {
1904
+ if (sCurChar === '\'') {
1604
1905
  sPrevChar = sPattern.charAt(i - 1);
1605
1906
  sPrevPrevChar = sPattern.charAt(i - 2);
1606
1907
  sNextChar = sPattern.charAt(i + 1);
1607
- if (sPrevChar == '\'' && sPrevPrevChar != '\'') {
1908
+ if (sPrevChar === '\'' && sPrevPrevChar !== '\'') {
1608
1909
  bQuoted = false;
1609
- } else if (sNextChar == '\'') {
1910
+ } else if (sNextChar === '\'') {
1610
1911
  i += 1;
1611
1912
  } else {
1612
1913
  bQuoted = false;
1613
1914
  continue;
1614
1915
  }
1615
1916
  }
1616
- if (sState == 'text') {
1917
+ if (sState === 'text') {
1617
1918
  oCurrentObject.value += sCurChar;
1618
1919
  } else {
1619
1920
  oCurrentObject = {
@@ -1624,11 +1925,11 @@ DateFormat.prototype.parseCldrDatePattern = function (sPattern) {
1624
1925
  sState = 'text';
1625
1926
  }
1626
1927
  } else {
1627
- if (sCurChar == '\'') {
1928
+ if (sCurChar === '\'') {
1628
1929
  bQuoted = true;
1629
1930
  } else if (this.oSymbols[sCurChar]) {
1630
1931
  sNewState = this.oSymbols[sCurChar].name;
1631
- if (sState == sNewState) {
1932
+ if (sState === sNewState) {
1632
1933
  oCurrentObject.digits++;
1633
1934
  } else {
1634
1935
  oCurrentObject = {
@@ -1648,7 +1949,7 @@ DateFormat.prototype.parseCldrDatePattern = function (sPattern) {
1648
1949
  }
1649
1950
  }
1650
1951
  } else {
1651
- if (sState == 'text') {
1952
+ if (sState === 'text') {
1652
1953
  oCurrentObject.value += sCurChar;
1653
1954
  } else {
1654
1955
  oCurrentObject = {
@@ -1684,70 +1985,88 @@ DateFormat.prototype.parseRelative = function (sValue, bUTC) {
1684
1985
  }
1685
1986
  }
1686
1987
  function computeRelativeDate(iDiff, sScale) {
1687
- var iToday, oToday = new Date(), oJSDate;
1988
+ var oResult = UI5Date.getInstance();
1688
1989
  if (bUTC) {
1689
- iToday = oToday.getTime();
1690
- } else {
1691
- iToday = Date.UTC(oToday.getFullYear(), oToday.getMonth(), oToday.getDate(), oToday.getHours(), oToday.getMinutes(), oToday.getSeconds(), oToday.getMilliseconds());
1692
- }
1693
- oJSDate = new Date(iToday);
1694
- switch (sScale) {
1695
- case 'second':
1696
- oJSDate.setUTCSeconds(oJSDate.getUTCSeconds() + iDiff);
1697
- break;
1698
- case 'minute':
1699
- oJSDate.setUTCMinutes(oJSDate.getUTCMinutes() + iDiff);
1700
- break;
1701
- case 'hour':
1702
- oJSDate.setUTCHours(oJSDate.getUTCHours() + iDiff);
1703
- break;
1704
- case 'day':
1705
- oJSDate.setUTCDate(oJSDate.getUTCDate() + iDiff);
1706
- break;
1707
- case 'week':
1708
- oJSDate.setUTCDate(oJSDate.getUTCDate() + iDiff * 7);
1709
- break;
1710
- case 'month':
1711
- oJSDate.setUTCMonth(oJSDate.getUTCMonth() + iDiff);
1712
- break;
1713
- case 'quarter':
1714
- oJSDate.setUTCMonth(oJSDate.getUTCMonth() + iDiff * 3);
1715
- break;
1716
- case 'year':
1717
- oJSDate.setUTCFullYear(oJSDate.getUTCFullYear() + iDiff);
1718
- break;
1719
- }
1720
- if (bUTC) {
1721
- 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
+ }
1722
2018
  } else {
1723
- 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
+ }
1724
2045
  }
2046
+ return oResult;
1725
2047
  }
1726
2048
  };
1727
- DateFormat.prototype.formatRelative = function (oJSDate, bUTC, aRange) {
1728
- 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';
1729
2051
  iDiffSeconds = (oJSDate.getTime() - oToday.getTime()) / 1000;
1730
- if (this.oFormatOptions.relativeScale == 'auto') {
2052
+ if (this.oFormatOptions.relativeScale === 'auto') {
1731
2053
  sScale = this._getScale(iDiffSeconds, this.aRelativeScales);
2054
+ sScale = fixScaleForMonths(oJSDate, oToday, sScale, iDiffSeconds);
1732
2055
  }
1733
2056
  if (!aRange) {
1734
2057
  aRange = this._mRanges[sScale];
1735
2058
  }
1736
- if (sScale == 'year' || sScale == 'month' || sScale == 'day') {
1737
- 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()));
1738
2061
  oDateUTC = new Date(0);
1739
- if (bUTC) {
1740
- oDateUTC.setUTCFullYear(oJSDate.getUTCFullYear(), oJSDate.getUTCMonth(), oJSDate.getUTCDate());
1741
- } else {
1742
- oDateUTC.setUTCFullYear(oJSDate.getFullYear(), oJSDate.getMonth(), oJSDate.getDate());
1743
- }
2062
+ oDateUTC.setUTCFullYear(oJSDate.getUTCFullYear(), oJSDate.getUTCMonth(), oJSDate.getUTCDate());
1744
2063
  oJSDate = oDateUTC;
1745
2064
  }
1746
2065
  iDiff = this._getDifference(sScale, [
1747
2066
  oToday,
1748
2067
  oJSDate
1749
2068
  ]);
1750
- if (this.oFormatOptions.relativeScale != 'auto' && (iDiff < aRange[0] || iDiff > aRange[1])) {
2069
+ if (this.oFormatOptions.relativeScale !== 'auto' && (iDiff < aRange[0] || iDiff > aRange[1])) {
1751
2070
  return null;
1752
2071
  }
1753
2072
  sPattern = this.oLocaleData.getRelativePattern(sScale, iDiff, iDiffSeconds > 0, this.oFormatOptions.relativeStyle);
@@ -1808,8 +2127,23 @@ DateFormat.prototype._getScale = function (iDiffSeconds, aScales) {
1808
2127
  }
1809
2128
  return sScale;
1810
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
+ }
1811
2145
  function cutDateFields(oDate, iStartIndex) {
1812
- var aFields = [
2146
+ var sMethodName, aFields = [
1813
2147
  'FullYear',
1814
2148
  'Month',
1815
2149
  'Date',
@@ -1817,49 +2151,55 @@ function cutDateFields(oDate, iStartIndex) {
1817
2151
  'Minutes',
1818
2152
  'Seconds',
1819
2153
  'Milliseconds'
1820
- ], sMethodName;
2154
+ ], oDateCopy = new Date(oDate.getTime());
1821
2155
  for (var i = iStartIndex; i < aFields.length; i++) {
1822
- sMethodName = 'set' + aFields[iStartIndex];
1823
- oDate[sMethodName].apply(oDate, [0]);
2156
+ sMethodName = 'setUTC' + aFields[iStartIndex];
2157
+ oDateCopy[sMethodName].apply(oDateCopy, [0]);
1824
2158
  }
2159
+ return oDateCopy;
1825
2160
  }
1826
2161
  var mRelativeDiffs = {
1827
2162
  year: function (oFromDate, oToDate) {
1828
- return oToDate.getFullYear() - oFromDate.getFullYear();
2163
+ return oToDate.getUTCFullYear() - oFromDate.getUTCFullYear();
1829
2164
  },
1830
2165
  month: function (oFromDate, oToDate) {
1831
- return oToDate.getMonth() - oFromDate.getMonth() + this.year(oFromDate, oToDate) * 12;
2166
+ return oToDate.getUTCMonth() - oFromDate.getUTCMonth() + this.year(oFromDate, oToDate) * 12;
1832
2167
  },
1833
2168
  week: function (oFromDate, oToDate, oFormat) {
1834
- var iFromDay = oFormat._adaptDayOfWeek(oFromDate.getDay());
1835
- var iToDay = oFormat._adaptDayOfWeek(oToDate.getDay());
1836
- cutDateFields(oFromDate, 3);
1837
- cutDateFields(oToDate, 3);
2169
+ var iFromDay = oFormat._adaptDayOfWeek(oFromDate.getUTCDay());
2170
+ var iToDay = oFormat._adaptDayOfWeek(oToDate.getUTCDay());
2171
+ oFromDate = cutDateFields(oFromDate, 3);
2172
+ oToDate = cutDateFields(oToDate, 3);
1838
2173
  return (oToDate.getTime() - oFromDate.getTime() - (iToDay - iFromDay) * oFormat._mScales.day * 1000) / (oFormat._mScales.week * 1000);
1839
2174
  },
1840
2175
  day: function (oFromDate, oToDate, oFormat) {
1841
- cutDateFields(oFromDate, 3);
1842
- cutDateFields(oToDate, 3);
2176
+ oFromDate = cutDateFields(oFromDate, 3);
2177
+ oToDate = cutDateFields(oToDate, 3);
1843
2178
  return (oToDate.getTime() - oFromDate.getTime()) / (oFormat._mScales.day * 1000);
1844
2179
  },
1845
2180
  hour: function (oFromDate, oToDate, oFormat) {
1846
- cutDateFields(oFromDate, 4);
1847
- cutDateFields(oToDate, 4);
2181
+ oFromDate = cutDateFields(oFromDate, 4);
2182
+ oToDate = cutDateFields(oToDate, 4);
1848
2183
  return (oToDate.getTime() - oFromDate.getTime()) / (oFormat._mScales.hour * 1000);
1849
2184
  },
1850
2185
  minute: function (oFromDate, oToDate, oFormat) {
1851
- cutDateFields(oFromDate, 5);
1852
- cutDateFields(oToDate, 5);
2186
+ oFromDate = cutDateFields(oFromDate, 5);
2187
+ oToDate = cutDateFields(oToDate, 5);
1853
2188
  return (oToDate.getTime() - oFromDate.getTime()) / (oFormat._mScales.minute * 1000);
1854
2189
  },
1855
2190
  second: function (oFromDate, oToDate, oFormat) {
1856
- cutDateFields(oFromDate, 6);
1857
- cutDateFields(oToDate, 6);
2191
+ oFromDate = cutDateFields(oFromDate, 6);
2192
+ oToDate = cutDateFields(oToDate, 6);
1858
2193
  return (oToDate.getTime() - oFromDate.getTime()) / (oFormat._mScales.second * 1000);
1859
2194
  }
1860
2195
  };
1861
2196
  DateFormat.prototype._adaptDayOfWeek = function (iDayOfWeek) {
1862
- 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
+ }
1863
2203
  var iDayNumberOfWeek = iDayOfWeek - (iFirstDayOfWeek - 1);
1864
2204
  if (iDayNumberOfWeek <= 0) {
1865
2205
  iDayNumberOfWeek += 7;
@@ -1925,4 +2265,28 @@ DateFormat.prototype.getAllowedCharacters = function (aFormatArray) {
1925
2265
  }
1926
2266
  return sAllowedCharacters;
1927
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
+ };
1928
2292
  export default DateFormat;