@ui5/webcomponents-localization 0.0.0-f734ea2da → 0.0.0-f79db712b

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