globalize-rpk 1.7.1 → 1.7.2
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.
- package/CONTRIBUTING.md +5 -0
- package/README.md +818 -0
- package/{globalize → dist/globalize}/currency.js +3 -3
- package/{globalize → dist/globalize}/date.js +3 -3
- package/{globalize → dist/globalize}/message.js +2 -2
- package/{globalize → dist/globalize}/number.js +3 -3
- package/{globalize → dist/globalize}/plural.js +3 -3
- package/{globalize → dist/globalize}/relative-time.js +3 -3
- package/{globalize → dist/globalize}/unit.js +0 -0
- package/dist/globalize-runtime/currency.js +183 -0
- package/dist/globalize-runtime/date.js +1657 -0
- package/dist/globalize-runtime/message.js +120 -0
- package/dist/globalize-runtime/number.js +919 -0
- package/dist/globalize-runtime/plural.js +90 -0
- package/dist/globalize-runtime/relative-time.js +120 -0
- package/dist/globalize-runtime/unit.js +132 -0
- package/{globalize → dist}/globalize-runtime.js +0 -0
- package/{globalize → dist}/globalize.js +2 -2
- package/{node-main.js → dist/node-main.js} +0 -0
- package/doc/api/core/constructor.md +28 -0
- package/doc/api/core/load.md +96 -0
- package/doc/api/core/locale.md +43 -0
- package/doc/api/currency/currency-formatter.md +196 -0
- package/doc/api/currency/currency-to-parts-formatter.md +117 -0
- package/doc/api/date/date-formatter.md +203 -0
- package/doc/api/date/date-parser.md +60 -0
- package/doc/api/date/date-to-parts-formatter.md +176 -0
- package/doc/api/date/load-iana-time-zone.md +29 -0
- package/doc/api/message/load-messages.md +105 -0
- package/doc/api/message/message-formatter.md +208 -0
- package/doc/api/number/number-formatter.md +202 -0
- package/doc/api/number/number-parser.md +130 -0
- package/doc/api/number/number-to-parts-formatter.md +140 -0
- package/doc/api/plural/plural-generator.md +84 -0
- package/doc/api/relative-time/relative-time-formatter.md +60 -0
- package/doc/api/unit/unit-formatter.md +72 -0
- package/doc/blog-post/2017-07-xx-1.3.0-announcement.md +177 -0
- package/doc/cldr.md +114 -0
- package/doc/error/e-default-locale-not-defined.md +9 -0
- package/doc/error/e-invalid-cldr.md +14 -0
- package/doc/error/e-invalid-par-type.md +12 -0
- package/doc/error/e-invalid-par-value.md +11 -0
- package/doc/error/e-missing-cldr.md +11 -0
- package/doc/error/e-missing-parameter.md +10 -0
- package/doc/error/e-missing-plural-module.md +9 -0
- package/doc/error/e-par-missing-key.md +11 -0
- package/doc/error/e-par-out-of-range.md +13 -0
- package/doc/error/e-unsupported.md +10 -0
- package/doc/migrating-from-0.x.md +64 -0
- package/examples/amd-bower/.bowerrc +7 -0
- package/examples/amd-bower/README.md +65 -0
- package/examples/amd-bower/bower.json +13 -0
- package/examples/amd-bower/index.html +46 -0
- package/examples/amd-bower/main.js +141 -0
- package/examples/amd-bower/messages/en.json +12 -0
- package/examples/amd-bower/package.json +14 -0
- package/examples/app-npm-webpack/README.md +74 -0
- package/examples/app-npm-webpack/app/index.js +89 -0
- package/examples/app-npm-webpack/index-template.html +71 -0
- package/examples/app-npm-webpack/messages/ar.json +25 -0
- package/examples/app-npm-webpack/messages/de.json +21 -0
- package/examples/app-npm-webpack/messages/en.json +21 -0
- package/examples/app-npm-webpack/messages/es.json +21 -0
- package/examples/app-npm-webpack/messages/pt.json +21 -0
- package/examples/app-npm-webpack/messages/ru.json +23 -0
- package/examples/app-npm-webpack/messages/zh.json +20 -0
- package/examples/app-npm-webpack/package.json +17 -0
- package/examples/app-npm-webpack/webpack-config.js +63 -0
- package/examples/globalize-compiler/README.md +45 -0
- package/examples/globalize-compiler/app.js +58 -0
- package/examples/globalize-compiler/development.html +121 -0
- package/examples/globalize-compiler/messages.json +12 -0
- package/examples/globalize-compiler/package.json +15 -0
- package/examples/globalize-compiler/production.html +75 -0
- package/examples/node-npm/README.md +57 -0
- package/examples/node-npm/main.js +65 -0
- package/examples/node-npm/messages/en.json +12 -0
- package/examples/node-npm/package.json +10 -0
- package/examples/plain-javascript/README.md +81 -0
- package/examples/plain-javascript/index.html +445 -0
- package/package.json +27 -4
@@ -0,0 +1,1657 @@
|
|
1
|
+
/**
|
2
|
+
* Globalize Runtime v1.7.0
|
3
|
+
*
|
4
|
+
* https://github.com/globalizejs/globalize
|
5
|
+
*
|
6
|
+
* Copyright OpenJS Foundation and other contributors
|
7
|
+
* Released under the MIT license
|
8
|
+
* https://jquery.org/license
|
9
|
+
*
|
10
|
+
* Date: 2021-08-02T11:53Z
|
11
|
+
*/
|
12
|
+
/*!
|
13
|
+
* Globalize Runtime v1.7.0 2021-08-02T11:53Z Released under the MIT license
|
14
|
+
* http://git.io/TrdQbw
|
15
|
+
*/
|
16
|
+
(function( root, factory ) {
|
17
|
+
|
18
|
+
"use strict";
|
19
|
+
|
20
|
+
// UMD returnExports
|
21
|
+
if ( typeof define === "function" && define.amd ) {
|
22
|
+
|
23
|
+
// AMD
|
24
|
+
define([
|
25
|
+
"../globalize-runtime",
|
26
|
+
"./number"
|
27
|
+
], factory );
|
28
|
+
} else if ( typeof exports === "object" ) {
|
29
|
+
|
30
|
+
// Node, CommonJS
|
31
|
+
module.exports = factory(
|
32
|
+
require( "../globalize-runtime" ),
|
33
|
+
require( "./number" )
|
34
|
+
);
|
35
|
+
} else {
|
36
|
+
|
37
|
+
// Extend global
|
38
|
+
factory( root.Globalize );
|
39
|
+
}
|
40
|
+
}(this, function( Globalize ) {
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
var createErrorUnsupportedFeature = Globalize._createErrorUnsupportedFeature,
|
45
|
+
looseMatching = Globalize._looseMatching,
|
46
|
+
partsJoin = Globalize._partsJoin,
|
47
|
+
partsPush = Globalize._partsPush,
|
48
|
+
regexpEscape = Globalize._regexpEscape,
|
49
|
+
removeLiteralQuotes = Globalize._removeLiteralQuotes,
|
50
|
+
runtimeKey = Globalize._runtimeKey,
|
51
|
+
stringPad = Globalize._stringPad,
|
52
|
+
validateParameterPresence = Globalize._validateParameterPresence,
|
53
|
+
validateParameterType = Globalize._validateParameterType,
|
54
|
+
validateParameterTypeString = Globalize._validateParameterTypeString;
|
55
|
+
|
56
|
+
|
57
|
+
var validateParameterTypeDate = function( value, name ) {
|
58
|
+
validateParameterType( value, name, value === undefined || value instanceof Date, "Date" );
|
59
|
+
};
|
60
|
+
|
61
|
+
|
62
|
+
var ZonedDateTime = (function() {
|
63
|
+
function definePrivateProperty(object, property, value) {
|
64
|
+
Object.defineProperty(object, property, {
|
65
|
+
value: value
|
66
|
+
});
|
67
|
+
}
|
68
|
+
|
69
|
+
function getUntilsIndex(original, untils) {
|
70
|
+
var index = 0;
|
71
|
+
var originalTime = original.getTime();
|
72
|
+
|
73
|
+
// TODO Should we do binary search for improved performance?
|
74
|
+
while (index < untils.length - 1 && originalTime >= untils[index]) {
|
75
|
+
index++;
|
76
|
+
}
|
77
|
+
return index;
|
78
|
+
}
|
79
|
+
|
80
|
+
function setWrap(fn) {
|
81
|
+
var offset1 = this.getTimezoneOffset();
|
82
|
+
var ret = fn();
|
83
|
+
this.original.setTime(new Date(this.getTime()));
|
84
|
+
var offset2 = this.getTimezoneOffset();
|
85
|
+
if (offset2 - offset1) {
|
86
|
+
this.original.setMinutes(this.original.getMinutes() + offset2 - offset1);
|
87
|
+
}
|
88
|
+
return ret;
|
89
|
+
}
|
90
|
+
|
91
|
+
var ZonedDateTime = function(date, timeZoneData) {
|
92
|
+
definePrivateProperty(this, "original", new Date(date.getTime()));
|
93
|
+
definePrivateProperty(this, "local", new Date(date.getTime()));
|
94
|
+
definePrivateProperty(this, "timeZoneData", timeZoneData);
|
95
|
+
definePrivateProperty(this, "setWrap", setWrap);
|
96
|
+
if (!(timeZoneData.untils && timeZoneData.offsets && timeZoneData.isdsts)) {
|
97
|
+
throw new Error("Invalid IANA data");
|
98
|
+
}
|
99
|
+
this.setTime(this.local.getTime() - this.getTimezoneOffset() * 60 * 1000);
|
100
|
+
};
|
101
|
+
|
102
|
+
ZonedDateTime.prototype.clone = function() {
|
103
|
+
return new ZonedDateTime(this.original, this.timeZoneData);
|
104
|
+
};
|
105
|
+
|
106
|
+
// Date field getters.
|
107
|
+
["getFullYear", "getMonth", "getDate", "getDay", "getHours", "getMinutes",
|
108
|
+
"getSeconds", "getMilliseconds"].forEach(function(method) {
|
109
|
+
// Corresponding UTC method, e.g., "getUTCFullYear" if method === "getFullYear".
|
110
|
+
var utcMethod = "getUTC" + method.substr(3);
|
111
|
+
ZonedDateTime.prototype[method] = function() {
|
112
|
+
return this.local[utcMethod]();
|
113
|
+
};
|
114
|
+
});
|
115
|
+
|
116
|
+
// Note: Define .valueOf = .getTime for arithmetic operations like date1 - date2.
|
117
|
+
ZonedDateTime.prototype.valueOf =
|
118
|
+
ZonedDateTime.prototype.getTime = function() {
|
119
|
+
return this.local.getTime() + this.getTimezoneOffset() * 60 * 1000;
|
120
|
+
};
|
121
|
+
|
122
|
+
ZonedDateTime.prototype.getTimezoneOffset = function() {
|
123
|
+
var index = getUntilsIndex(this.original, this.timeZoneData.untils);
|
124
|
+
return this.timeZoneData.offsets[index];
|
125
|
+
};
|
126
|
+
|
127
|
+
// Date field setters.
|
128
|
+
["setFullYear", "setMonth", "setDate", "setHours", "setMinutes", "setSeconds", "setMilliseconds"].forEach(function(method) {
|
129
|
+
// Corresponding UTC method, e.g., "setUTCFullYear" if method === "setFullYear".
|
130
|
+
var utcMethod = "setUTC" + method.substr(3);
|
131
|
+
ZonedDateTime.prototype[method] = function(value) {
|
132
|
+
var local = this.local;
|
133
|
+
// Note setWrap is needed for seconds and milliseconds just because
|
134
|
+
// abs(value) could be >= a minute.
|
135
|
+
return this.setWrap(function() {
|
136
|
+
return local[utcMethod](value);
|
137
|
+
});
|
138
|
+
};
|
139
|
+
});
|
140
|
+
|
141
|
+
ZonedDateTime.prototype.setTime = function(time) {
|
142
|
+
return this.local.setTime(time);
|
143
|
+
};
|
144
|
+
|
145
|
+
ZonedDateTime.prototype.isDST = function() {
|
146
|
+
var index = getUntilsIndex(this.original, this.timeZoneData.untils);
|
147
|
+
return Boolean(this.timeZoneData.isdsts[index]);
|
148
|
+
};
|
149
|
+
|
150
|
+
ZonedDateTime.prototype.inspect = function() {
|
151
|
+
var index = getUntilsIndex(this.original, this.timeZoneData.untils);
|
152
|
+
var abbrs = this.timeZoneData.abbrs;
|
153
|
+
return this.local.toISOString().replace(/Z$/, "") + " " +
|
154
|
+
(abbrs && abbrs[index] + " " || (this.getTimezoneOffset() * -1) + " ") +
|
155
|
+
(this.isDST() ? "(daylight savings)" : "");
|
156
|
+
};
|
157
|
+
|
158
|
+
ZonedDateTime.prototype.toDate = function() {
|
159
|
+
return new Date(this.getTime());
|
160
|
+
};
|
161
|
+
|
162
|
+
// Type cast getters.
|
163
|
+
["toISOString", "toJSON", "toUTCString"].forEach(function(method) {
|
164
|
+
ZonedDateTime.prototype[method] = function() {
|
165
|
+
return this.toDate()[method]();
|
166
|
+
};
|
167
|
+
});
|
168
|
+
|
169
|
+
return ZonedDateTime;
|
170
|
+
}());
|
171
|
+
|
172
|
+
|
173
|
+
/**
|
174
|
+
* dayOfWeek( date, firstDay )
|
175
|
+
*
|
176
|
+
* @date
|
177
|
+
*
|
178
|
+
* @firstDay the result of `dateFirstDayOfWeek( cldr )`
|
179
|
+
*
|
180
|
+
* Return the day of the week normalized by the territory's firstDay [0-6].
|
181
|
+
* Eg for "mon":
|
182
|
+
* - return 0 if territory is GB, or BR, or DE, or FR (week starts on "mon");
|
183
|
+
* - return 1 if territory is US (week starts on "sun");
|
184
|
+
* - return 2 if territory is EG (week starts on "sat");
|
185
|
+
*/
|
186
|
+
var dateDayOfWeek = function( date, firstDay ) {
|
187
|
+
return ( date.getDay() - firstDay + 7 ) % 7;
|
188
|
+
};
|
189
|
+
|
190
|
+
|
191
|
+
|
192
|
+
|
193
|
+
/**
|
194
|
+
* distanceInDays( from, to )
|
195
|
+
*
|
196
|
+
* Return the distance in days between from and to Dates.
|
197
|
+
*/
|
198
|
+
var dateDistanceInDays = function( from, to ) {
|
199
|
+
var inDays = 864e5;
|
200
|
+
return ( to.getTime() - from.getTime() ) / inDays;
|
201
|
+
};
|
202
|
+
|
203
|
+
|
204
|
+
|
205
|
+
|
206
|
+
/**
|
207
|
+
* startOf changes the input to the beginning of the given unit.
|
208
|
+
*
|
209
|
+
* For example, starting at the start of a day, resets hours, minutes
|
210
|
+
* seconds and milliseconds to 0. Starting at the month does the same, but
|
211
|
+
* also sets the date to 1.
|
212
|
+
*
|
213
|
+
* Returns the modified date
|
214
|
+
*/
|
215
|
+
var dateStartOf = function( date, unit ) {
|
216
|
+
date = date instanceof ZonedDateTime ? date.clone() : new Date( date.getTime() );
|
217
|
+
switch ( unit ) {
|
218
|
+
case "year":
|
219
|
+
date.setMonth( 0 );
|
220
|
+
/* falls through */
|
221
|
+
case "month":
|
222
|
+
date.setDate( 1 );
|
223
|
+
/* falls through */
|
224
|
+
case "day":
|
225
|
+
date.setHours( 0 );
|
226
|
+
/* falls through */
|
227
|
+
case "hour":
|
228
|
+
date.setMinutes( 0 );
|
229
|
+
/* falls through */
|
230
|
+
case "minute":
|
231
|
+
date.setSeconds( 0 );
|
232
|
+
/* falls through */
|
233
|
+
case "second":
|
234
|
+
date.setMilliseconds( 0 );
|
235
|
+
}
|
236
|
+
return date;
|
237
|
+
};
|
238
|
+
|
239
|
+
|
240
|
+
|
241
|
+
|
242
|
+
/**
|
243
|
+
* dayOfYear
|
244
|
+
*
|
245
|
+
* Return the distance in days of the date to the begin of the year [0-d].
|
246
|
+
*/
|
247
|
+
var dateDayOfYear = function( date ) {
|
248
|
+
return Math.floor( dateDistanceInDays( dateStartOf( date, "year" ), date ) );
|
249
|
+
};
|
250
|
+
|
251
|
+
|
252
|
+
|
253
|
+
|
254
|
+
/**
|
255
|
+
* Returns a new object created by using `object`'s values as keys, and the keys as values.
|
256
|
+
*/
|
257
|
+
var objectInvert = function( object, fn ) {
|
258
|
+
fn = fn || function( object, key, value ) {
|
259
|
+
object[ value ] = key;
|
260
|
+
return object;
|
261
|
+
};
|
262
|
+
return Object.keys( object ).reduce(function( newObject, key ) {
|
263
|
+
return fn( newObject, key, object[ key ] );
|
264
|
+
}, {});
|
265
|
+
};
|
266
|
+
|
267
|
+
|
268
|
+
|
269
|
+
|
270
|
+
// Invert key and values, e.g., {"year": "yY"} ==> {"y": "year", "Y": "year"}
|
271
|
+
var dateFieldsMap = objectInvert({
|
272
|
+
"era": "G",
|
273
|
+
"year": "yY",
|
274
|
+
"quarter": "qQ",
|
275
|
+
"month": "ML",
|
276
|
+
"week": "wW",
|
277
|
+
"day": "dDF",
|
278
|
+
"weekday": "ecE",
|
279
|
+
"dayperiod": "a",
|
280
|
+
"hour": "hHkK",
|
281
|
+
"minute": "m",
|
282
|
+
"second": "sSA",
|
283
|
+
"zone": "zvVOxX"
|
284
|
+
}, function( object, key, value ) {
|
285
|
+
value.split( "" ).forEach(function( symbol ) {
|
286
|
+
object[ symbol ] = key;
|
287
|
+
});
|
288
|
+
return object;
|
289
|
+
});
|
290
|
+
|
291
|
+
|
292
|
+
|
293
|
+
|
294
|
+
/**
|
295
|
+
* millisecondsInDay
|
296
|
+
*/
|
297
|
+
var dateMillisecondsInDay = function( date ) {
|
298
|
+
|
299
|
+
// TODO Handle daylight savings discontinuities
|
300
|
+
return date - dateStartOf( date, "day" );
|
301
|
+
};
|
302
|
+
|
303
|
+
|
304
|
+
|
305
|
+
|
306
|
+
var datePatternRe = ( /([a-z])\1*|'([^']|'')+'|''|./ig );
|
307
|
+
|
308
|
+
|
309
|
+
|
310
|
+
|
311
|
+
/**
|
312
|
+
* hourFormat( date, format, timeSeparator, formatNumber )
|
313
|
+
*
|
314
|
+
* Return date's timezone offset according to the format passed.
|
315
|
+
* Eg for format when timezone offset is 180:
|
316
|
+
* - "+H;-H": -3
|
317
|
+
* - "+HHmm;-HHmm": -0300
|
318
|
+
* - "+HH:mm;-HH:mm": -03:00
|
319
|
+
* - "+HH:mm:ss;-HH:mm:ss": -03:00:00
|
320
|
+
*/
|
321
|
+
var dateTimezoneHourFormat = function( date, format, timeSeparator, formatNumber ) {
|
322
|
+
var absOffset,
|
323
|
+
offset = date.getTimezoneOffset();
|
324
|
+
|
325
|
+
absOffset = Math.abs( offset );
|
326
|
+
formatNumber = formatNumber || {
|
327
|
+
1: function( value ) {
|
328
|
+
return stringPad( value, 1 );
|
329
|
+
},
|
330
|
+
2: function( value ) {
|
331
|
+
return stringPad( value, 2 );
|
332
|
+
}
|
333
|
+
};
|
334
|
+
|
335
|
+
return format
|
336
|
+
|
337
|
+
// Pick the correct sign side (+ or -).
|
338
|
+
.split( ";" )[ offset > 0 ? 1 : 0 ]
|
339
|
+
|
340
|
+
// Localize time separator
|
341
|
+
.replace( ":", timeSeparator )
|
342
|
+
|
343
|
+
// Update hours offset.
|
344
|
+
.replace( /HH?/, function( match ) {
|
345
|
+
return formatNumber[ match.length ]( Math.floor( absOffset / 60 ) );
|
346
|
+
})
|
347
|
+
|
348
|
+
// Update minutes offset and return.
|
349
|
+
.replace( /mm/, function() {
|
350
|
+
return formatNumber[ 2 ]( Math.floor( absOffset % 60 ) );
|
351
|
+
})
|
352
|
+
|
353
|
+
// Update minutes offset and return.
|
354
|
+
.replace( /ss/, function() {
|
355
|
+
return formatNumber[ 2 ]( Math.floor( absOffset % 1 * 60 ) );
|
356
|
+
});
|
357
|
+
};
|
358
|
+
|
359
|
+
|
360
|
+
|
361
|
+
|
362
|
+
var dateWeekDays = [ "sun", "mon", "tue", "wed", "thu", "fri", "sat" ];
|
363
|
+
|
364
|
+
|
365
|
+
|
366
|
+
|
367
|
+
/**
|
368
|
+
* format( date, properties )
|
369
|
+
*
|
370
|
+
* @date [Date instance].
|
371
|
+
*
|
372
|
+
* @properties
|
373
|
+
*
|
374
|
+
* TODO Support other calendar types.
|
375
|
+
*
|
376
|
+
* Disclosure: this function borrows excerpts of dojo/date/locale.
|
377
|
+
*/
|
378
|
+
var dateFormat = function( date, numberFormatters, properties ) {
|
379
|
+
var parts = [];
|
380
|
+
|
381
|
+
var timeSeparator = properties.timeSeparator;
|
382
|
+
|
383
|
+
// create globalize date with given timezone data
|
384
|
+
if ( properties.timeZoneData ) {
|
385
|
+
date = new ZonedDateTime( date, properties.timeZoneData() );
|
386
|
+
}
|
387
|
+
|
388
|
+
properties.pattern.replace( datePatternRe, function( current ) {
|
389
|
+
var aux, dateField, type, value,
|
390
|
+
chr = current.charAt( 0 ),
|
391
|
+
length = current.length;
|
392
|
+
|
393
|
+
if ( chr === "j" ) {
|
394
|
+
|
395
|
+
// Locale preferred hHKk.
|
396
|
+
// http://www.unicode.org/reports/tr35/tr35-dates.html#Time_Data
|
397
|
+
chr = properties.preferredTime;
|
398
|
+
}
|
399
|
+
|
400
|
+
if ( chr === "Z" ) {
|
401
|
+
|
402
|
+
// Z..ZZZ: same as "xxxx".
|
403
|
+
if ( length < 4 ) {
|
404
|
+
chr = "x";
|
405
|
+
length = 4;
|
406
|
+
|
407
|
+
// ZZZZ: same as "OOOO".
|
408
|
+
} else if ( length < 5 ) {
|
409
|
+
chr = "O";
|
410
|
+
length = 4;
|
411
|
+
|
412
|
+
// ZZZZZ: same as "XXXXX"
|
413
|
+
} else {
|
414
|
+
chr = "X";
|
415
|
+
length = 5;
|
416
|
+
}
|
417
|
+
}
|
418
|
+
|
419
|
+
// z...zzz: "{shortRegion}", e.g., "PST" or "PDT".
|
420
|
+
// zzzz: "{regionName} {Standard Time}" or "{regionName} {Daylight Time}",
|
421
|
+
// e.g., "Pacific Standard Time" or "Pacific Daylight Time".
|
422
|
+
if ( chr === "z" ) {
|
423
|
+
if ( date.isDST ) {
|
424
|
+
value = date.isDST() ? properties.daylightTzName : properties.standardTzName;
|
425
|
+
}
|
426
|
+
|
427
|
+
// Fall back to "O" format.
|
428
|
+
if ( !value ) {
|
429
|
+
chr = "O";
|
430
|
+
if ( length < 4 ) {
|
431
|
+
length = 1;
|
432
|
+
}
|
433
|
+
}
|
434
|
+
}
|
435
|
+
|
436
|
+
switch ( chr ) {
|
437
|
+
|
438
|
+
// Era
|
439
|
+
case "G":
|
440
|
+
value = properties.eras[ date.getFullYear() < 0 ? 0 : 1 ];
|
441
|
+
break;
|
442
|
+
|
443
|
+
// Year
|
444
|
+
case "y":
|
445
|
+
|
446
|
+
// Plain year.
|
447
|
+
// The length specifies the padding, but for two letters it also specifies the
|
448
|
+
// maximum length.
|
449
|
+
value = date.getFullYear();
|
450
|
+
if ( length === 2 ) {
|
451
|
+
value = String( value );
|
452
|
+
value = +value.substr( value.length - 2 );
|
453
|
+
}
|
454
|
+
break;
|
455
|
+
|
456
|
+
case "Y":
|
457
|
+
|
458
|
+
// Year in "Week of Year"
|
459
|
+
// The length specifies the padding, but for two letters it also specifies the
|
460
|
+
// maximum length.
|
461
|
+
// yearInWeekofYear = date + DaysInAWeek - (dayOfWeek - firstDay) - minDays
|
462
|
+
value = new Date( date.getTime() );
|
463
|
+
value.setDate(
|
464
|
+
value.getDate() + 7 -
|
465
|
+
dateDayOfWeek( date, properties.firstDay ) -
|
466
|
+
properties.firstDay -
|
467
|
+
properties.minDays
|
468
|
+
);
|
469
|
+
value = value.getFullYear();
|
470
|
+
if ( length === 2 ) {
|
471
|
+
value = String( value );
|
472
|
+
value = +value.substr( value.length - 2 );
|
473
|
+
}
|
474
|
+
break;
|
475
|
+
|
476
|
+
// Quarter
|
477
|
+
case "Q":
|
478
|
+
case "q":
|
479
|
+
value = Math.ceil( ( date.getMonth() + 1 ) / 3 );
|
480
|
+
if ( length > 2 ) {
|
481
|
+
value = properties.quarters[ chr ][ length ][ value ];
|
482
|
+
}
|
483
|
+
break;
|
484
|
+
|
485
|
+
// Month
|
486
|
+
case "M":
|
487
|
+
case "L":
|
488
|
+
value = date.getMonth() + 1;
|
489
|
+
if ( length > 2 ) {
|
490
|
+
value = properties.months[ chr ][ length ][ value ];
|
491
|
+
}
|
492
|
+
break;
|
493
|
+
|
494
|
+
// Week
|
495
|
+
case "w":
|
496
|
+
|
497
|
+
// Week of Year.
|
498
|
+
// woy = ceil( ( doy + dow of 1/1 ) / 7 ) - minDaysStuff ? 1 : 0.
|
499
|
+
// TODO should pad on ww? Not documented, but I guess so.
|
500
|
+
value = dateDayOfWeek( dateStartOf( date, "year" ), properties.firstDay );
|
501
|
+
value = Math.ceil( ( dateDayOfYear( date ) + value ) / 7 ) -
|
502
|
+
( 7 - value >= properties.minDays ? 0 : 1 );
|
503
|
+
break;
|
504
|
+
|
505
|
+
case "W":
|
506
|
+
|
507
|
+
// Week of Month.
|
508
|
+
// wom = ceil( ( dom + dow of `1/month` ) / 7 ) - minDaysStuff ? 1 : 0.
|
509
|
+
value = dateDayOfWeek( dateStartOf( date, "month" ), properties.firstDay );
|
510
|
+
value = Math.ceil( ( date.getDate() + value ) / 7 ) -
|
511
|
+
( 7 - value >= properties.minDays ? 0 : 1 );
|
512
|
+
break;
|
513
|
+
|
514
|
+
// Day
|
515
|
+
case "d":
|
516
|
+
value = date.getDate();
|
517
|
+
break;
|
518
|
+
|
519
|
+
case "D":
|
520
|
+
value = dateDayOfYear( date ) + 1;
|
521
|
+
break;
|
522
|
+
|
523
|
+
case "F":
|
524
|
+
|
525
|
+
// Day of Week in month. eg. 2nd Wed in July.
|
526
|
+
value = Math.floor( date.getDate() / 7 ) + 1;
|
527
|
+
break;
|
528
|
+
|
529
|
+
// Week day
|
530
|
+
case "e":
|
531
|
+
case "c":
|
532
|
+
if ( length <= 2 ) {
|
533
|
+
|
534
|
+
// Range is [1-7] (deduced by example provided on documentation)
|
535
|
+
// TODO Should pad with zeros (not specified in the docs)?
|
536
|
+
value = dateDayOfWeek( date, properties.firstDay ) + 1;
|
537
|
+
break;
|
538
|
+
}
|
539
|
+
|
540
|
+
/* falls through */
|
541
|
+
case "E":
|
542
|
+
value = dateWeekDays[ date.getDay() ];
|
543
|
+
value = properties.days[ chr ][ length ][ value ];
|
544
|
+
break;
|
545
|
+
|
546
|
+
// Period (AM or PM)
|
547
|
+
case "a":
|
548
|
+
value = properties.dayPeriods[ date.getHours() < 12 ? "am" : "pm" ];
|
549
|
+
break;
|
550
|
+
|
551
|
+
// Hour
|
552
|
+
case "h": // 1-12
|
553
|
+
value = ( date.getHours() % 12 ) || 12;
|
554
|
+
break;
|
555
|
+
|
556
|
+
case "H": // 0-23
|
557
|
+
value = date.getHours();
|
558
|
+
break;
|
559
|
+
|
560
|
+
case "K": // 0-11
|
561
|
+
value = date.getHours() % 12;
|
562
|
+
break;
|
563
|
+
|
564
|
+
case "k": // 1-24
|
565
|
+
value = date.getHours() || 24;
|
566
|
+
break;
|
567
|
+
|
568
|
+
// Minute
|
569
|
+
case "m":
|
570
|
+
value = date.getMinutes();
|
571
|
+
break;
|
572
|
+
|
573
|
+
// Second
|
574
|
+
case "s":
|
575
|
+
value = date.getSeconds();
|
576
|
+
break;
|
577
|
+
|
578
|
+
case "S":
|
579
|
+
value = Math.round( date.getMilliseconds() * Math.pow( 10, length - 3 ) );
|
580
|
+
break;
|
581
|
+
|
582
|
+
case "A":
|
583
|
+
value = Math.round( dateMillisecondsInDay( date ) * Math.pow( 10, length - 3 ) );
|
584
|
+
break;
|
585
|
+
|
586
|
+
// Zone
|
587
|
+
case "z":
|
588
|
+
break;
|
589
|
+
|
590
|
+
case "v":
|
591
|
+
|
592
|
+
// v...vvv: "{shortRegion}", eg. "PT".
|
593
|
+
// vvvv: "{regionName} {Time}",
|
594
|
+
// e.g., "Pacific Time".
|
595
|
+
if ( properties.genericTzName ) {
|
596
|
+
value = properties.genericTzName;
|
597
|
+
break;
|
598
|
+
}
|
599
|
+
|
600
|
+
/* falls through */
|
601
|
+
case "V":
|
602
|
+
|
603
|
+
//VVVV: "{explarCity} {Time}", e.g., "Los Angeles Time"
|
604
|
+
if ( properties.timeZoneName ) {
|
605
|
+
value = properties.timeZoneName;
|
606
|
+
break;
|
607
|
+
}
|
608
|
+
|
609
|
+
if ( current === "v" ) {
|
610
|
+
length = 1;
|
611
|
+
}
|
612
|
+
|
613
|
+
/* falls through */
|
614
|
+
case "O":
|
615
|
+
|
616
|
+
// O: "{gmtFormat}+H;{gmtFormat}-H" or "{gmtZeroFormat}", eg. "GMT-8" or "GMT".
|
617
|
+
// OOOO: "{gmtFormat}{hourFormat}" or "{gmtZeroFormat}", eg. "GMT-08:00" or "GMT".
|
618
|
+
if ( date.getTimezoneOffset() === 0 ) {
|
619
|
+
value = properties.gmtZeroFormat;
|
620
|
+
} else {
|
621
|
+
|
622
|
+
// If O..OOO and timezone offset has non-zero minutes, show minutes.
|
623
|
+
if ( length < 4 ) {
|
624
|
+
aux = date.getTimezoneOffset();
|
625
|
+
aux = properties.hourFormat[ aux % 60 - aux % 1 === 0 ? 0 : 1 ];
|
626
|
+
} else {
|
627
|
+
aux = properties.hourFormat;
|
628
|
+
}
|
629
|
+
|
630
|
+
value = dateTimezoneHourFormat(
|
631
|
+
date,
|
632
|
+
aux,
|
633
|
+
timeSeparator,
|
634
|
+
numberFormatters
|
635
|
+
);
|
636
|
+
value = properties.gmtFormat.replace( /\{0\}/, value );
|
637
|
+
}
|
638
|
+
break;
|
639
|
+
|
640
|
+
case "X":
|
641
|
+
|
642
|
+
// Same as x*, except it uses "Z" for zero offset.
|
643
|
+
if ( date.getTimezoneOffset() === 0 ) {
|
644
|
+
value = "Z";
|
645
|
+
break;
|
646
|
+
}
|
647
|
+
|
648
|
+
/* falls through */
|
649
|
+
case "x":
|
650
|
+
|
651
|
+
// x: hourFormat("+HH[mm];-HH[mm]")
|
652
|
+
// xx: hourFormat("+HHmm;-HHmm")
|
653
|
+
// xxx: hourFormat("+HH:mm;-HH:mm")
|
654
|
+
// xxxx: hourFormat("+HHmm[ss];-HHmm[ss]")
|
655
|
+
// xxxxx: hourFormat("+HH:mm[:ss];-HH:mm[:ss]")
|
656
|
+
aux = date.getTimezoneOffset();
|
657
|
+
|
658
|
+
// If x and timezone offset has non-zero minutes, use xx (i.e., show minutes).
|
659
|
+
if ( length === 1 && aux % 60 - aux % 1 !== 0 ) {
|
660
|
+
length += 1;
|
661
|
+
}
|
662
|
+
|
663
|
+
// If (xxxx or xxxxx) and timezone offset has zero seconds, use xx or xxx
|
664
|
+
// respectively (i.e., don't show optional seconds).
|
665
|
+
if ( ( length === 4 || length === 5 ) && aux % 1 === 0 ) {
|
666
|
+
length -= 2;
|
667
|
+
}
|
668
|
+
|
669
|
+
value = [
|
670
|
+
"+HH;-HH",
|
671
|
+
"+HHmm;-HHmm",
|
672
|
+
"+HH:mm;-HH:mm",
|
673
|
+
"+HHmmss;-HHmmss",
|
674
|
+
"+HH:mm:ss;-HH:mm:ss"
|
675
|
+
][ length - 1 ];
|
676
|
+
|
677
|
+
value = dateTimezoneHourFormat( date, value, ":" );
|
678
|
+
break;
|
679
|
+
|
680
|
+
// timeSeparator
|
681
|
+
case ":":
|
682
|
+
value = timeSeparator;
|
683
|
+
break;
|
684
|
+
|
685
|
+
// ' literals.
|
686
|
+
case "'":
|
687
|
+
value = removeLiteralQuotes( current );
|
688
|
+
break;
|
689
|
+
|
690
|
+
// Anything else is considered a literal, including [ ,:/.@#], chinese, japonese, and
|
691
|
+
// arabic characters.
|
692
|
+
default:
|
693
|
+
value = current;
|
694
|
+
|
695
|
+
}
|
696
|
+
if ( typeof value === "number" ) {
|
697
|
+
value = numberFormatters[ length ]( value );
|
698
|
+
}
|
699
|
+
|
700
|
+
dateField = dateFieldsMap[ chr ];
|
701
|
+
type = dateField ? dateField : "literal";
|
702
|
+
|
703
|
+
partsPush( parts, type, value );
|
704
|
+
});
|
705
|
+
|
706
|
+
return parts;
|
707
|
+
|
708
|
+
};
|
709
|
+
|
710
|
+
|
711
|
+
|
712
|
+
|
713
|
+
var dateFormatterFn = function( dateToPartsFormatter ) {
|
714
|
+
return function dateFormatter( value ) {
|
715
|
+
return partsJoin( dateToPartsFormatter( value ));
|
716
|
+
};
|
717
|
+
};
|
718
|
+
|
719
|
+
|
720
|
+
|
721
|
+
|
722
|
+
/**
|
723
|
+
* isLeapYear( year )
|
724
|
+
*
|
725
|
+
* @year [Number]
|
726
|
+
*
|
727
|
+
* Returns an indication whether the specified year is a leap year.
|
728
|
+
*/
|
729
|
+
var dateIsLeapYear = function( year ) {
|
730
|
+
return new Date( year, 1, 29 ).getMonth() === 1;
|
731
|
+
};
|
732
|
+
|
733
|
+
|
734
|
+
|
735
|
+
|
736
|
+
/**
|
737
|
+
* lastDayOfMonth( date )
|
738
|
+
*
|
739
|
+
* @date [Date]
|
740
|
+
*
|
741
|
+
* Return the last day of the given date's month
|
742
|
+
*/
|
743
|
+
var dateLastDayOfMonth = function( date ) {
|
744
|
+
return new Date( date.getFullYear(), date.getMonth() + 1, 0 ).getDate();
|
745
|
+
};
|
746
|
+
|
747
|
+
|
748
|
+
|
749
|
+
|
750
|
+
/**
|
751
|
+
* Differently from native date.setDate(), this function returns a date whose
|
752
|
+
* day remains inside the month boundaries. For example:
|
753
|
+
*
|
754
|
+
* setDate( FebDate, 31 ): a "Feb 28" date.
|
755
|
+
* setDate( SepDate, 31 ): a "Sep 30" date.
|
756
|
+
*/
|
757
|
+
var dateSetDate = function( date, day ) {
|
758
|
+
var lastDay = new Date( date.getFullYear(), date.getMonth() + 1, 0 ).getDate();
|
759
|
+
|
760
|
+
date.setDate( day < 1 ? 1 : day < lastDay ? day : lastDay );
|
761
|
+
};
|
762
|
+
|
763
|
+
|
764
|
+
|
765
|
+
|
766
|
+
/**
|
767
|
+
* Differently from native date.setMonth(), this function adjusts date if
|
768
|
+
* needed, so final month is always the one set.
|
769
|
+
*
|
770
|
+
* setMonth( Jan31Date, 1 ): a "Feb 28" date.
|
771
|
+
* setDate( Jan31Date, 8 ): a "Sep 30" date.
|
772
|
+
*/
|
773
|
+
var dateSetMonth = function( date, month ) {
|
774
|
+
var originalDate = date.getDate();
|
775
|
+
|
776
|
+
date.setDate( 1 );
|
777
|
+
date.setMonth( month );
|
778
|
+
dateSetDate( date, originalDate );
|
779
|
+
};
|
780
|
+
|
781
|
+
|
782
|
+
|
783
|
+
|
784
|
+
var outOfRange = function( value, low, high ) {
|
785
|
+
return value < low || value > high;
|
786
|
+
};
|
787
|
+
|
788
|
+
|
789
|
+
|
790
|
+
|
791
|
+
/**
|
792
|
+
* parse( value, tokens, properties )
|
793
|
+
*
|
794
|
+
* @value [String] string date.
|
795
|
+
*
|
796
|
+
* @tokens [Object] tokens returned by date/tokenizer.
|
797
|
+
*
|
798
|
+
* @properties [Object] output returned by date/tokenizer-properties.
|
799
|
+
*
|
800
|
+
* ref: http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns
|
801
|
+
*/
|
802
|
+
var dateParse = function( _value, tokens, properties ) {
|
803
|
+
var amPm, day, daysOfYear, month, era, hour, hour12, timezoneOffset, valid,
|
804
|
+
YEAR = 0,
|
805
|
+
MONTH = 1,
|
806
|
+
DAY = 2,
|
807
|
+
HOUR = 3,
|
808
|
+
MINUTE = 4,
|
809
|
+
SECOND = 5,
|
810
|
+
MILLISECONDS = 6,
|
811
|
+
date = new Date(),
|
812
|
+
truncateAt = [],
|
813
|
+
units = [ "year", "month", "day", "hour", "minute", "second", "milliseconds" ];
|
814
|
+
|
815
|
+
// Create globalize date with given timezone data.
|
816
|
+
if ( properties.timeZoneData ) {
|
817
|
+
date = new ZonedDateTime( date, properties.timeZoneData() );
|
818
|
+
}
|
819
|
+
|
820
|
+
if ( !tokens.length ) {
|
821
|
+
return null;
|
822
|
+
}
|
823
|
+
|
824
|
+
valid = tokens.every(function( token ) {
|
825
|
+
var century, chr, value, length;
|
826
|
+
|
827
|
+
if ( token.type === "literal" ) {
|
828
|
+
|
829
|
+
// continue
|
830
|
+
return true;
|
831
|
+
}
|
832
|
+
|
833
|
+
chr = token.type.charAt( 0 );
|
834
|
+
length = token.type.length;
|
835
|
+
|
836
|
+
if ( chr === "j" ) {
|
837
|
+
|
838
|
+
// Locale preferred hHKk.
|
839
|
+
// http://www.unicode.org/reports/tr35/tr35-dates.html#Time_Data
|
840
|
+
chr = properties.preferredTimeData;
|
841
|
+
}
|
842
|
+
|
843
|
+
switch ( chr ) {
|
844
|
+
|
845
|
+
// Era
|
846
|
+
case "G":
|
847
|
+
truncateAt.push( YEAR );
|
848
|
+
era = +token.value;
|
849
|
+
break;
|
850
|
+
|
851
|
+
// Year
|
852
|
+
case "y":
|
853
|
+
value = token.value;
|
854
|
+
if ( length === 2 ) {
|
855
|
+
if ( outOfRange( value, 0, 99 ) ) {
|
856
|
+
return false;
|
857
|
+
}
|
858
|
+
|
859
|
+
// mimic dojo/date/locale: choose century to apply, according to a sliding
|
860
|
+
// window of 80 years before and 20 years after present year.
|
861
|
+
century = Math.floor( date.getFullYear() / 100 ) * 100;
|
862
|
+
value += century;
|
863
|
+
if ( value > date.getFullYear() + 20 ) {
|
864
|
+
value -= 100;
|
865
|
+
}
|
866
|
+
}
|
867
|
+
date.setFullYear( value );
|
868
|
+
truncateAt.push( YEAR );
|
869
|
+
break;
|
870
|
+
|
871
|
+
case "Y": // Year in "Week of Year"
|
872
|
+
throw createErrorUnsupportedFeature({
|
873
|
+
feature: "year pattern `" + chr + "`"
|
874
|
+
});
|
875
|
+
|
876
|
+
// Quarter (skip)
|
877
|
+
case "Q":
|
878
|
+
case "q":
|
879
|
+
break;
|
880
|
+
|
881
|
+
// Month
|
882
|
+
case "M":
|
883
|
+
case "L":
|
884
|
+
if ( length <= 2 ) {
|
885
|
+
value = token.value;
|
886
|
+
} else {
|
887
|
+
value = +token.value;
|
888
|
+
}
|
889
|
+
if ( outOfRange( value, 1, 12 ) ) {
|
890
|
+
return false;
|
891
|
+
}
|
892
|
+
|
893
|
+
// Setting the month later so that we have the correct year and can determine
|
894
|
+
// the correct last day of February in case of leap year.
|
895
|
+
month = value;
|
896
|
+
truncateAt.push( MONTH );
|
897
|
+
break;
|
898
|
+
|
899
|
+
// Week (skip)
|
900
|
+
case "w": // Week of Year.
|
901
|
+
case "W": // Week of Month.
|
902
|
+
break;
|
903
|
+
|
904
|
+
// Day
|
905
|
+
case "d":
|
906
|
+
day = token.value;
|
907
|
+
truncateAt.push( DAY );
|
908
|
+
break;
|
909
|
+
|
910
|
+
case "D":
|
911
|
+
daysOfYear = token.value;
|
912
|
+
truncateAt.push( DAY );
|
913
|
+
break;
|
914
|
+
|
915
|
+
case "F":
|
916
|
+
|
917
|
+
// Day of Week in month. eg. 2nd Wed in July.
|
918
|
+
// Skip
|
919
|
+
break;
|
920
|
+
|
921
|
+
// Week day
|
922
|
+
case "e":
|
923
|
+
case "c":
|
924
|
+
case "E":
|
925
|
+
|
926
|
+
// Skip.
|
927
|
+
// value = arrayIndexOf( dateWeekDays, token.value );
|
928
|
+
break;
|
929
|
+
|
930
|
+
// Period (AM or PM)
|
931
|
+
case "a":
|
932
|
+
amPm = token.value;
|
933
|
+
break;
|
934
|
+
|
935
|
+
// Hour
|
936
|
+
case "h": // 1-12
|
937
|
+
value = token.value;
|
938
|
+
if ( outOfRange( value, 1, 12 ) ) {
|
939
|
+
return false;
|
940
|
+
}
|
941
|
+
hour = hour12 = true;
|
942
|
+
date.setHours( value === 12 ? 0 : value );
|
943
|
+
truncateAt.push( HOUR );
|
944
|
+
break;
|
945
|
+
|
946
|
+
case "K": // 0-11
|
947
|
+
value = token.value;
|
948
|
+
if ( outOfRange( value, 0, 11 ) ) {
|
949
|
+
return false;
|
950
|
+
}
|
951
|
+
hour = hour12 = true;
|
952
|
+
date.setHours( value );
|
953
|
+
truncateAt.push( HOUR );
|
954
|
+
break;
|
955
|
+
|
956
|
+
case "k": // 1-24
|
957
|
+
value = token.value;
|
958
|
+
if ( outOfRange( value, 1, 24 ) ) {
|
959
|
+
return false;
|
960
|
+
}
|
961
|
+
hour = true;
|
962
|
+
date.setHours( value === 24 ? 0 : value );
|
963
|
+
truncateAt.push( HOUR );
|
964
|
+
break;
|
965
|
+
|
966
|
+
case "H": // 0-23
|
967
|
+
value = token.value;
|
968
|
+
if ( outOfRange( value, 0, 23 ) ) {
|
969
|
+
return false;
|
970
|
+
}
|
971
|
+
hour = true;
|
972
|
+
date.setHours( value );
|
973
|
+
truncateAt.push( HOUR );
|
974
|
+
break;
|
975
|
+
|
976
|
+
// Minute
|
977
|
+
case "m":
|
978
|
+
value = token.value;
|
979
|
+
if ( outOfRange( value, 0, 59 ) ) {
|
980
|
+
return false;
|
981
|
+
}
|
982
|
+
date.setMinutes( value );
|
983
|
+
truncateAt.push( MINUTE );
|
984
|
+
break;
|
985
|
+
|
986
|
+
// Second
|
987
|
+
case "s":
|
988
|
+
value = token.value;
|
989
|
+
if ( outOfRange( value, 0, 59 ) ) {
|
990
|
+
return false;
|
991
|
+
}
|
992
|
+
date.setSeconds( value );
|
993
|
+
truncateAt.push( SECOND );
|
994
|
+
break;
|
995
|
+
|
996
|
+
case "A":
|
997
|
+
date.setHours( 0 );
|
998
|
+
date.setMinutes( 0 );
|
999
|
+
date.setSeconds( 0 );
|
1000
|
+
|
1001
|
+
/* falls through */
|
1002
|
+
case "S":
|
1003
|
+
value = Math.round( token.value * Math.pow( 10, 3 - length ) );
|
1004
|
+
date.setMilliseconds( value );
|
1005
|
+
truncateAt.push( MILLISECONDS );
|
1006
|
+
break;
|
1007
|
+
|
1008
|
+
// Zone
|
1009
|
+
case "z":
|
1010
|
+
case "Z":
|
1011
|
+
case "O":
|
1012
|
+
case "v":
|
1013
|
+
case "V":
|
1014
|
+
case "X":
|
1015
|
+
case "x":
|
1016
|
+
if ( typeof token.value === "number" ) {
|
1017
|
+
timezoneOffset = token.value;
|
1018
|
+
}
|
1019
|
+
break;
|
1020
|
+
}
|
1021
|
+
|
1022
|
+
return true;
|
1023
|
+
});
|
1024
|
+
|
1025
|
+
if ( !valid ) {
|
1026
|
+
return null;
|
1027
|
+
}
|
1028
|
+
|
1029
|
+
// 12-hour format needs AM or PM, 24-hour format doesn't, ie. return null
|
1030
|
+
// if amPm && !hour12 || !amPm && hour12.
|
1031
|
+
if ( hour && !( !amPm ^ hour12 ) ) {
|
1032
|
+
return null;
|
1033
|
+
}
|
1034
|
+
|
1035
|
+
if ( era === 0 ) {
|
1036
|
+
|
1037
|
+
// 1 BC = year 0
|
1038
|
+
date.setFullYear( date.getFullYear() * -1 + 1 );
|
1039
|
+
}
|
1040
|
+
|
1041
|
+
if ( month !== undefined ) {
|
1042
|
+
dateSetMonth( date, month - 1 );
|
1043
|
+
}
|
1044
|
+
|
1045
|
+
if ( day !== undefined ) {
|
1046
|
+
if ( outOfRange( day, 1, dateLastDayOfMonth( date ) ) ) {
|
1047
|
+
return null;
|
1048
|
+
}
|
1049
|
+
date.setDate( day );
|
1050
|
+
} else if ( daysOfYear !== undefined ) {
|
1051
|
+
if ( outOfRange( daysOfYear, 1, dateIsLeapYear( date.getFullYear() ) ? 366 : 365 ) ) {
|
1052
|
+
return null;
|
1053
|
+
}
|
1054
|
+
date.setMonth( 0 );
|
1055
|
+
date.setDate( daysOfYear );
|
1056
|
+
}
|
1057
|
+
|
1058
|
+
if ( hour12 && amPm === "pm" ) {
|
1059
|
+
date.setHours( date.getHours() + 12 );
|
1060
|
+
}
|
1061
|
+
|
1062
|
+
if ( timezoneOffset !== undefined ) {
|
1063
|
+
date.setMinutes( date.getMinutes() + timezoneOffset - date.getTimezoneOffset() );
|
1064
|
+
}
|
1065
|
+
|
1066
|
+
// Truncate date at the most precise unit defined. Eg.
|
1067
|
+
// If value is "12/31", and pattern is "MM/dd":
|
1068
|
+
// => new Date( <current Year>, 12, 31, 0, 0, 0, 0 );
|
1069
|
+
truncateAt = Math.max.apply( null, truncateAt );
|
1070
|
+
date = dateStartOf( date, units[ truncateAt ] );
|
1071
|
+
|
1072
|
+
// Get date back from globalize date.
|
1073
|
+
if ( date instanceof ZonedDateTime ) {
|
1074
|
+
date = date.toDate();
|
1075
|
+
}
|
1076
|
+
|
1077
|
+
return date;
|
1078
|
+
};
|
1079
|
+
|
1080
|
+
|
1081
|
+
/* eslint-disable no-unused-expressions */
|
1082
|
+
|
1083
|
+
|
1084
|
+
|
1085
|
+
/**
|
1086
|
+
* tokenizer( value, numberParser, properties )
|
1087
|
+
*
|
1088
|
+
* @value [String] string date.
|
1089
|
+
*
|
1090
|
+
* @numberParser [Function]
|
1091
|
+
*
|
1092
|
+
* @properties [Object] output returned by date/tokenizer-properties.
|
1093
|
+
*
|
1094
|
+
* Returns an Array of tokens, eg. value "5 o'clock PM", pattern "h 'o''clock' a":
|
1095
|
+
* [{
|
1096
|
+
* type: "h",
|
1097
|
+
* lexeme: "5"
|
1098
|
+
* }, {
|
1099
|
+
* type: "literal",
|
1100
|
+
* lexeme: " "
|
1101
|
+
* }, {
|
1102
|
+
* type: "literal",
|
1103
|
+
* lexeme: "o'clock"
|
1104
|
+
* }, {
|
1105
|
+
* type: "literal",
|
1106
|
+
* lexeme: " "
|
1107
|
+
* }, {
|
1108
|
+
* type: "a",
|
1109
|
+
* lexeme: "PM",
|
1110
|
+
* value: "pm"
|
1111
|
+
* }]
|
1112
|
+
*
|
1113
|
+
* OBS: lexeme's are always String and may return invalid ranges depending of the token type.
|
1114
|
+
* Eg. "99" for month number.
|
1115
|
+
*
|
1116
|
+
* Return an empty Array when not successfully parsed.
|
1117
|
+
*/
|
1118
|
+
var dateTokenizer = function( value, numberParser, properties ) {
|
1119
|
+
var digitsRe, valid,
|
1120
|
+
tokens = [],
|
1121
|
+
widths = [ "abbreviated", "wide", "narrow" ];
|
1122
|
+
|
1123
|
+
digitsRe = properties.digitsRe;
|
1124
|
+
value = looseMatching( value );
|
1125
|
+
|
1126
|
+
valid = properties.pattern.match( datePatternRe ).every(function( current ) {
|
1127
|
+
var aux, chr, length, numeric, tokenRe,
|
1128
|
+
token = {};
|
1129
|
+
|
1130
|
+
function hourFormatParse( tokenRe, numberParser ) {
|
1131
|
+
var aux, isPositive,
|
1132
|
+
match = value.match( tokenRe );
|
1133
|
+
numberParser = numberParser || function( value ) {
|
1134
|
+
return +value;
|
1135
|
+
};
|
1136
|
+
|
1137
|
+
if ( !match ) {
|
1138
|
+
return false;
|
1139
|
+
}
|
1140
|
+
|
1141
|
+
isPositive = match[ 1 ];
|
1142
|
+
|
1143
|
+
// hourFormat containing H only, e.g., `+H;-H`
|
1144
|
+
if ( match.length < 6 ) {
|
1145
|
+
aux = isPositive ? 1 : 3;
|
1146
|
+
token.value = numberParser( match[ aux ] ) * 60;
|
1147
|
+
|
1148
|
+
// hourFormat containing H and m, e.g., `+HHmm;-HHmm`
|
1149
|
+
} else if ( match.length < 10 ) {
|
1150
|
+
aux = isPositive ? [ 1, 3 ] : [ 5, 7 ];
|
1151
|
+
token.value = numberParser( match[ aux[ 0 ] ] ) * 60 +
|
1152
|
+
numberParser( match[ aux[ 1 ] ] );
|
1153
|
+
|
1154
|
+
// hourFormat containing H, m, and s e.g., `+HHmmss;-HHmmss`
|
1155
|
+
} else {
|
1156
|
+
aux = isPositive ? [ 1, 3, 5 ] : [ 7, 9, 11 ];
|
1157
|
+
token.value = numberParser( match[ aux[ 0 ] ] ) * 60 +
|
1158
|
+
numberParser( match[ aux[ 1 ] ] ) +
|
1159
|
+
numberParser( match[ aux[ 2 ] ] ) / 60;
|
1160
|
+
}
|
1161
|
+
|
1162
|
+
if ( isPositive ) {
|
1163
|
+
token.value *= -1;
|
1164
|
+
}
|
1165
|
+
|
1166
|
+
return true;
|
1167
|
+
}
|
1168
|
+
|
1169
|
+
function oneDigitIfLengthOne() {
|
1170
|
+
if ( length === 1 ) {
|
1171
|
+
|
1172
|
+
// Unicode equivalent to /\d/
|
1173
|
+
numeric = true;
|
1174
|
+
return tokenRe = digitsRe;
|
1175
|
+
}
|
1176
|
+
}
|
1177
|
+
|
1178
|
+
function oneOrTwoDigitsIfLengthOne() {
|
1179
|
+
if ( length === 1 ) {
|
1180
|
+
|
1181
|
+
// Unicode equivalent to /\d\d?/
|
1182
|
+
numeric = true;
|
1183
|
+
return tokenRe = new RegExp( "^(" + digitsRe.source + "){1,2}" );
|
1184
|
+
}
|
1185
|
+
}
|
1186
|
+
|
1187
|
+
function oneOrTwoDigitsIfLengthOneOrTwo() {
|
1188
|
+
if ( length === 1 || length === 2 ) {
|
1189
|
+
|
1190
|
+
// Unicode equivalent to /\d\d?/
|
1191
|
+
numeric = true;
|
1192
|
+
return tokenRe = new RegExp( "^(" + digitsRe.source + "){1,2}" );
|
1193
|
+
}
|
1194
|
+
}
|
1195
|
+
|
1196
|
+
function twoDigitsIfLengthTwo() {
|
1197
|
+
if ( length === 2 ) {
|
1198
|
+
|
1199
|
+
// Unicode equivalent to /\d\d/
|
1200
|
+
numeric = true;
|
1201
|
+
return tokenRe = new RegExp( "^(" + digitsRe.source + "){2}" );
|
1202
|
+
}
|
1203
|
+
}
|
1204
|
+
|
1205
|
+
// Brute-force test every locale entry in an attempt to match the given value.
|
1206
|
+
// Return the first found one (and set token accordingly), or null.
|
1207
|
+
function lookup( path ) {
|
1208
|
+
var array = properties[ path.join( "/" ) ];
|
1209
|
+
|
1210
|
+
if ( !array ) {
|
1211
|
+
return null;
|
1212
|
+
}
|
1213
|
+
|
1214
|
+
// array of pairs [key, value] sorted by desc value length.
|
1215
|
+
array.some(function( item ) {
|
1216
|
+
var valueRe = item[ 1 ];
|
1217
|
+
if ( valueRe.test( value ) ) {
|
1218
|
+
token.value = item[ 0 ];
|
1219
|
+
tokenRe = item[ 1 ];
|
1220
|
+
return true;
|
1221
|
+
}
|
1222
|
+
});
|
1223
|
+
return null;
|
1224
|
+
}
|
1225
|
+
|
1226
|
+
token.type = current;
|
1227
|
+
chr = current.charAt( 0 );
|
1228
|
+
length = current.length;
|
1229
|
+
|
1230
|
+
if ( chr === "Z" ) {
|
1231
|
+
|
1232
|
+
// Z..ZZZ: same as "xxxx".
|
1233
|
+
if ( length < 4 ) {
|
1234
|
+
chr = "x";
|
1235
|
+
length = 4;
|
1236
|
+
|
1237
|
+
// ZZZZ: same as "OOOO".
|
1238
|
+
} else if ( length < 5 ) {
|
1239
|
+
chr = "O";
|
1240
|
+
length = 4;
|
1241
|
+
|
1242
|
+
// ZZZZZ: same as "XXXXX"
|
1243
|
+
} else {
|
1244
|
+
chr = "X";
|
1245
|
+
length = 5;
|
1246
|
+
}
|
1247
|
+
}
|
1248
|
+
|
1249
|
+
if ( chr === "z" ) {
|
1250
|
+
if ( properties.standardOrDaylightTzName ) {
|
1251
|
+
token.value = null;
|
1252
|
+
tokenRe = properties.standardOrDaylightTzName;
|
1253
|
+
}
|
1254
|
+
}
|
1255
|
+
|
1256
|
+
// v...vvv: "{shortRegion}", eg. "PT".
|
1257
|
+
// vvvv: "{regionName} {Time}" or "{regionName} {Time}",
|
1258
|
+
// e.g., "Pacific Time"
|
1259
|
+
// http://unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns
|
1260
|
+
if ( chr === "v" ) {
|
1261
|
+
if ( properties.genericTzName ) {
|
1262
|
+
token.value = null;
|
1263
|
+
tokenRe = properties.genericTzName;
|
1264
|
+
|
1265
|
+
// Fall back to "V" format.
|
1266
|
+
} else {
|
1267
|
+
chr = "V";
|
1268
|
+
length = 4;
|
1269
|
+
}
|
1270
|
+
}
|
1271
|
+
|
1272
|
+
if ( chr === "V" && properties.timeZoneName ) {
|
1273
|
+
token.value = length === 2 ? properties.timeZoneName : null;
|
1274
|
+
tokenRe = properties.timeZoneNameRe;
|
1275
|
+
}
|
1276
|
+
|
1277
|
+
switch ( chr ) {
|
1278
|
+
|
1279
|
+
// Era
|
1280
|
+
case "G":
|
1281
|
+
lookup([
|
1282
|
+
"gregorian/eras",
|
1283
|
+
length <= 3 ? "eraAbbr" : ( length === 4 ? "eraNames" : "eraNarrow" )
|
1284
|
+
]);
|
1285
|
+
break;
|
1286
|
+
|
1287
|
+
// Year
|
1288
|
+
case "y":
|
1289
|
+
case "Y":
|
1290
|
+
numeric = true;
|
1291
|
+
|
1292
|
+
// number l=1:+, l=2:{2}, l=3:{3,}, l=4:{4,}, ...
|
1293
|
+
if ( length === 1 ) {
|
1294
|
+
|
1295
|
+
// Unicode equivalent to /\d+/.
|
1296
|
+
tokenRe = new RegExp( "^(" + digitsRe.source + ")+" );
|
1297
|
+
} else if ( length === 2 ) {
|
1298
|
+
|
1299
|
+
// Lenient parsing: there's no year pattern to indicate non-zero-padded 2-digits
|
1300
|
+
// year, so parser accepts both zero-padded and non-zero-padded for `yy`.
|
1301
|
+
//
|
1302
|
+
// Unicode equivalent to /\d\d?/
|
1303
|
+
tokenRe = new RegExp( "^(" + digitsRe.source + "){1,2}" );
|
1304
|
+
} else {
|
1305
|
+
|
1306
|
+
// Unicode equivalent to /\d{length,}/
|
1307
|
+
tokenRe = new RegExp( "^(" + digitsRe.source + "){" + length + ",}" );
|
1308
|
+
}
|
1309
|
+
break;
|
1310
|
+
|
1311
|
+
// Quarter
|
1312
|
+
case "Q":
|
1313
|
+
case "q":
|
1314
|
+
|
1315
|
+
// number l=1:{1}, l=2:{2}.
|
1316
|
+
// lookup l=3...
|
1317
|
+
oneDigitIfLengthOne() || twoDigitsIfLengthTwo() ||
|
1318
|
+
lookup([
|
1319
|
+
"gregorian/quarters",
|
1320
|
+
chr === "Q" ? "format" : "stand-alone",
|
1321
|
+
widths[ length - 3 ]
|
1322
|
+
]);
|
1323
|
+
break;
|
1324
|
+
|
1325
|
+
// Month
|
1326
|
+
case "M":
|
1327
|
+
case "L":
|
1328
|
+
|
1329
|
+
// number l=1:{1,2}, l=2:{2}.
|
1330
|
+
// lookup l=3...
|
1331
|
+
//
|
1332
|
+
// Lenient parsing: skeleton "yMd" (i.e., one M) may include MM for the pattern,
|
1333
|
+
// therefore parser accepts both zero-padded and non-zero-padded for M and MM.
|
1334
|
+
// Similar for L.
|
1335
|
+
oneOrTwoDigitsIfLengthOneOrTwo() || lookup([
|
1336
|
+
"gregorian/months",
|
1337
|
+
chr === "M" ? "format" : "stand-alone",
|
1338
|
+
widths[ length - 3 ]
|
1339
|
+
]);
|
1340
|
+
break;
|
1341
|
+
|
1342
|
+
// Day
|
1343
|
+
case "D":
|
1344
|
+
|
1345
|
+
// number {l,3}.
|
1346
|
+
if ( length <= 3 ) {
|
1347
|
+
|
1348
|
+
// Equivalent to /\d{length,3}/
|
1349
|
+
numeric = true;
|
1350
|
+
tokenRe = new RegExp( "^(" + digitsRe.source + "){" + length + ",3}" );
|
1351
|
+
}
|
1352
|
+
break;
|
1353
|
+
|
1354
|
+
case "W":
|
1355
|
+
case "F":
|
1356
|
+
|
1357
|
+
// number l=1:{1}.
|
1358
|
+
oneDigitIfLengthOne();
|
1359
|
+
break;
|
1360
|
+
|
1361
|
+
// Week day
|
1362
|
+
case "e":
|
1363
|
+
case "c":
|
1364
|
+
|
1365
|
+
// number l=1:{1}, l=2:{2}.
|
1366
|
+
// lookup for length >=3.
|
1367
|
+
if ( length <= 2 ) {
|
1368
|
+
oneDigitIfLengthOne() || twoDigitsIfLengthTwo();
|
1369
|
+
break;
|
1370
|
+
}
|
1371
|
+
|
1372
|
+
/* falls through */
|
1373
|
+
case "E":
|
1374
|
+
if ( length === 6 ) {
|
1375
|
+
|
1376
|
+
// Note: if short day names are not explicitly specified, abbreviated day
|
1377
|
+
// names are used instead http://www.unicode.org/reports/tr35/tr35-dates.html#months_days_quarters_eras
|
1378
|
+
lookup([
|
1379
|
+
"gregorian/days",
|
1380
|
+
[ chr === "c" ? "stand-alone" : "format" ],
|
1381
|
+
"short"
|
1382
|
+
]) || lookup([
|
1383
|
+
"gregorian/days",
|
1384
|
+
[ chr === "c" ? "stand-alone" : "format" ],
|
1385
|
+
"abbreviated"
|
1386
|
+
]);
|
1387
|
+
} else {
|
1388
|
+
lookup([
|
1389
|
+
"gregorian/days",
|
1390
|
+
[ chr === "c" ? "stand-alone" : "format" ],
|
1391
|
+
widths[ length < 3 ? 0 : length - 3 ]
|
1392
|
+
]);
|
1393
|
+
}
|
1394
|
+
break;
|
1395
|
+
|
1396
|
+
// Period (AM or PM)
|
1397
|
+
case "a":
|
1398
|
+
lookup([
|
1399
|
+
"gregorian/dayPeriods/format/wide"
|
1400
|
+
]);
|
1401
|
+
break;
|
1402
|
+
|
1403
|
+
// Week
|
1404
|
+
case "w":
|
1405
|
+
|
1406
|
+
// number l1:{1,2}, l2:{2}.
|
1407
|
+
oneOrTwoDigitsIfLengthOne() || twoDigitsIfLengthTwo();
|
1408
|
+
break;
|
1409
|
+
|
1410
|
+
// Day, Hour, Minute, or Second
|
1411
|
+
case "d":
|
1412
|
+
case "h":
|
1413
|
+
case "H":
|
1414
|
+
case "K":
|
1415
|
+
case "k":
|
1416
|
+
case "j":
|
1417
|
+
case "m":
|
1418
|
+
case "s":
|
1419
|
+
|
1420
|
+
// number l1:{1,2}, l2:{2}.
|
1421
|
+
//
|
1422
|
+
// Lenient parsing:
|
1423
|
+
// - skeleton "hms" (i.e., one m) always includes mm for the pattern, i.e., it's
|
1424
|
+
// impossible to use a different skeleton to parse non-zero-padded minutes,
|
1425
|
+
// therefore parser accepts both zero-padded and non-zero-padded for m. Similar
|
1426
|
+
// for seconds s.
|
1427
|
+
// - skeleton "hms" (i.e., one h) may include h or hh for the pattern, i.e., it's
|
1428
|
+
// impossible to use a different skeleton to parser non-zero-padded hours for some
|
1429
|
+
// locales, therefore parser accepts both zero-padded and non-zero-padded for h.
|
1430
|
+
// Similar for d (in skeleton yMd).
|
1431
|
+
oneOrTwoDigitsIfLengthOneOrTwo();
|
1432
|
+
break;
|
1433
|
+
|
1434
|
+
case "S":
|
1435
|
+
|
1436
|
+
// number {l}.
|
1437
|
+
|
1438
|
+
// Unicode equivalent to /\d{length}/
|
1439
|
+
numeric = true;
|
1440
|
+
tokenRe = new RegExp( "^(" + digitsRe.source + "){" + length + "}" );
|
1441
|
+
break;
|
1442
|
+
|
1443
|
+
case "A":
|
1444
|
+
|
1445
|
+
// number {l+5}.
|
1446
|
+
|
1447
|
+
// Unicode equivalent to /\d{length+5}/
|
1448
|
+
numeric = true;
|
1449
|
+
tokenRe = new RegExp( "^(" + digitsRe.source + "){" + ( length + 5 ) + "}" );
|
1450
|
+
break;
|
1451
|
+
|
1452
|
+
// Zone
|
1453
|
+
case "v":
|
1454
|
+
case "V":
|
1455
|
+
case "z":
|
1456
|
+
if ( tokenRe && tokenRe.test( value ) ) {
|
1457
|
+
break;
|
1458
|
+
}
|
1459
|
+
if ( chr === "V" && length === 2 ) {
|
1460
|
+
break;
|
1461
|
+
}
|
1462
|
+
|
1463
|
+
/* falls through */
|
1464
|
+
case "O":
|
1465
|
+
|
1466
|
+
// O: "{gmtFormat}+H;{gmtFormat}-H" or "{gmtZeroFormat}", eg. "GMT-8" or "GMT".
|
1467
|
+
// OOOO: "{gmtFormat}{hourFormat}" or "{gmtZeroFormat}", eg. "GMT-08:00" or "GMT".
|
1468
|
+
if ( value === properties[ "timeZoneNames/gmtZeroFormat" ] ) {
|
1469
|
+
token.value = 0;
|
1470
|
+
tokenRe = properties[ "timeZoneNames/gmtZeroFormatRe" ];
|
1471
|
+
} else {
|
1472
|
+
aux = properties[ "timeZoneNames/hourFormat" ].some(function( hourFormatRe ) {
|
1473
|
+
if ( hourFormatParse( hourFormatRe, numberParser ) ) {
|
1474
|
+
tokenRe = hourFormatRe;
|
1475
|
+
return true;
|
1476
|
+
}
|
1477
|
+
});
|
1478
|
+
if ( !aux ) {
|
1479
|
+
return null;
|
1480
|
+
}
|
1481
|
+
}
|
1482
|
+
break;
|
1483
|
+
|
1484
|
+
case "X":
|
1485
|
+
|
1486
|
+
// Same as x*, except it uses "Z" for zero offset.
|
1487
|
+
if ( value === "Z" ) {
|
1488
|
+
token.value = 0;
|
1489
|
+
tokenRe = /^Z/;
|
1490
|
+
break;
|
1491
|
+
}
|
1492
|
+
|
1493
|
+
/* falls through */
|
1494
|
+
case "x":
|
1495
|
+
|
1496
|
+
// x: hourFormat("+HH[mm];-HH[mm]")
|
1497
|
+
// xx: hourFormat("+HHmm;-HHmm")
|
1498
|
+
// xxx: hourFormat("+HH:mm;-HH:mm")
|
1499
|
+
// xxxx: hourFormat("+HHmm[ss];-HHmm[ss]")
|
1500
|
+
// xxxxx: hourFormat("+HH:mm[:ss];-HH:mm[:ss]")
|
1501
|
+
aux = properties.x.some(function( hourFormatRe ) {
|
1502
|
+
if ( hourFormatParse( hourFormatRe ) ) {
|
1503
|
+
tokenRe = hourFormatRe;
|
1504
|
+
return true;
|
1505
|
+
}
|
1506
|
+
});
|
1507
|
+
if ( !aux ) {
|
1508
|
+
return null;
|
1509
|
+
}
|
1510
|
+
break;
|
1511
|
+
|
1512
|
+
case "'":
|
1513
|
+
token.type = "literal";
|
1514
|
+
tokenRe = new RegExp( "^" + regexpEscape( removeLiteralQuotes( current ) ) );
|
1515
|
+
break;
|
1516
|
+
|
1517
|
+
default:
|
1518
|
+
token.type = "literal";
|
1519
|
+
tokenRe = new RegExp( "^" + regexpEscape( current ) );
|
1520
|
+
}
|
1521
|
+
|
1522
|
+
if ( !tokenRe ) {
|
1523
|
+
return false;
|
1524
|
+
}
|
1525
|
+
|
1526
|
+
// Get lexeme and consume it.
|
1527
|
+
value = value.replace( tokenRe, function( lexeme ) {
|
1528
|
+
token.lexeme = lexeme;
|
1529
|
+
if ( numeric ) {
|
1530
|
+
token.value = numberParser( lexeme );
|
1531
|
+
}
|
1532
|
+
return "";
|
1533
|
+
});
|
1534
|
+
|
1535
|
+
if ( !token.lexeme ) {
|
1536
|
+
return false;
|
1537
|
+
}
|
1538
|
+
|
1539
|
+
if ( numeric && isNaN( token.value ) ) {
|
1540
|
+
return false;
|
1541
|
+
}
|
1542
|
+
|
1543
|
+
tokens.push( token );
|
1544
|
+
return true;
|
1545
|
+
});
|
1546
|
+
|
1547
|
+
if ( value !== "" ) {
|
1548
|
+
valid = false;
|
1549
|
+
}
|
1550
|
+
|
1551
|
+
return valid ? tokens : [];
|
1552
|
+
};
|
1553
|
+
|
1554
|
+
|
1555
|
+
|
1556
|
+
|
1557
|
+
var dateParserFn = function( numberParser, parseProperties, tokenizerProperties ) {
|
1558
|
+
return function dateParser( value ) {
|
1559
|
+
var tokens;
|
1560
|
+
|
1561
|
+
validateParameterPresence( value, "value" );
|
1562
|
+
validateParameterTypeString( value, "value" );
|
1563
|
+
|
1564
|
+
tokens = dateTokenizer( value, numberParser, tokenizerProperties );
|
1565
|
+
return dateParse( value, tokens, parseProperties ) || null;
|
1566
|
+
};
|
1567
|
+
};
|
1568
|
+
|
1569
|
+
|
1570
|
+
|
1571
|
+
|
1572
|
+
var dateToPartsFormatterFn = function( numberFormatters, properties ) {
|
1573
|
+
return function dateToPartsFormatter( value ) {
|
1574
|
+
validateParameterPresence( value, "value" );
|
1575
|
+
validateParameterTypeDate( value, "value" );
|
1576
|
+
|
1577
|
+
return dateFormat( value, numberFormatters, properties );
|
1578
|
+
};
|
1579
|
+
|
1580
|
+
};
|
1581
|
+
|
1582
|
+
|
1583
|
+
|
1584
|
+
|
1585
|
+
Globalize._dateFormat = dateFormat;
|
1586
|
+
Globalize._dateFormatterFn = dateFormatterFn;
|
1587
|
+
Globalize._dateParser = dateParse;
|
1588
|
+
Globalize._dateParserFn = dateParserFn;
|
1589
|
+
Globalize._dateTokenizer = dateTokenizer;
|
1590
|
+
Globalize._dateToPartsFormatterFn = dateToPartsFormatterFn;
|
1591
|
+
Globalize._validateParameterTypeDate = validateParameterTypeDate;
|
1592
|
+
|
1593
|
+
function optionsHasStyle( options ) {
|
1594
|
+
return options.skeleton !== undefined ||
|
1595
|
+
options.date !== undefined ||
|
1596
|
+
options.time !== undefined ||
|
1597
|
+
options.datetime !== undefined ||
|
1598
|
+
options.raw !== undefined;
|
1599
|
+
}
|
1600
|
+
|
1601
|
+
Globalize.dateFormatter =
|
1602
|
+
Globalize.prototype.dateFormatter = function( options ) {
|
1603
|
+
options = options || {};
|
1604
|
+
if ( !optionsHasStyle( options ) ) {
|
1605
|
+
options.skeleton = "yMd";
|
1606
|
+
}
|
1607
|
+
return Globalize[ runtimeKey( "dateFormatter", this._locale, [ options ] ) ];
|
1608
|
+
};
|
1609
|
+
|
1610
|
+
Globalize.dateToPartsFormatter =
|
1611
|
+
Globalize.prototype.dateToPartsFormatter = function( options ) {
|
1612
|
+
options = options || {};
|
1613
|
+
if ( !optionsHasStyle( options ) ) {
|
1614
|
+
options.skeleton = "yMd";
|
1615
|
+
}
|
1616
|
+
return Globalize[ runtimeKey( "dateToPartsFormatter", this._locale, [ options ] ) ];
|
1617
|
+
};
|
1618
|
+
|
1619
|
+
Globalize.dateParser =
|
1620
|
+
Globalize.prototype.dateParser = function( options ) {
|
1621
|
+
options = options || {};
|
1622
|
+
if ( !optionsHasStyle( options ) ) {
|
1623
|
+
options.skeleton = "yMd";
|
1624
|
+
}
|
1625
|
+
return Globalize[ runtimeKey( "dateParser", this._locale, [ options ] ) ];
|
1626
|
+
};
|
1627
|
+
|
1628
|
+
Globalize.formatDate =
|
1629
|
+
Globalize.prototype.formatDate = function( value, options ) {
|
1630
|
+
validateParameterPresence( value, "value" );
|
1631
|
+
validateParameterTypeDate( value, "value" );
|
1632
|
+
|
1633
|
+
return this.dateFormatter( options )( value );
|
1634
|
+
};
|
1635
|
+
|
1636
|
+
Globalize.formatDateToParts =
|
1637
|
+
Globalize.prototype.formatDateToParts = function( value, options ) {
|
1638
|
+
validateParameterPresence( value, "value" );
|
1639
|
+
validateParameterTypeDate( value, "value" );
|
1640
|
+
|
1641
|
+
return this.dateToPartsFormatter( options )( value );
|
1642
|
+
};
|
1643
|
+
|
1644
|
+
Globalize.parseDate =
|
1645
|
+
Globalize.prototype.parseDate = function( value, options ) {
|
1646
|
+
validateParameterPresence( value, "value" );
|
1647
|
+
validateParameterTypeString( value, "value" );
|
1648
|
+
|
1649
|
+
return this.dateParser( options )( value );
|
1650
|
+
};
|
1651
|
+
|
1652
|
+
return Globalize;
|
1653
|
+
|
1654
|
+
|
1655
|
+
|
1656
|
+
|
1657
|
+
}));
|