Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/i18n/datetimeformat.js
2868 views
1
// Copyright 2006 The Closure Library Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
* @fileoverview Functions for dealing with date/time formatting.
17
*/
18
19
20
/**
21
* Namespace for i18n date/time formatting functions
22
*/
23
goog.provide('goog.i18n.DateTimeFormat');
24
goog.provide('goog.i18n.DateTimeFormat.Format');
25
26
goog.require('goog.asserts');
27
goog.require('goog.date');
28
goog.require('goog.i18n.DateTimeSymbols');
29
goog.require('goog.i18n.TimeZone');
30
goog.require('goog.string');
31
32
33
/**
34
* Datetime formatting functions following the pattern specification as defined
35
* in JDK, ICU and CLDR, with minor modification for typical usage in JS.
36
* Pattern specification:
37
* {@link http://userguide.icu-project.org/formatparse/datetime}
38
* <pre>
39
* Symbol Meaning Presentation Example
40
* ------ ------- ------------ -------
41
* G# era designator (Text) AD
42
* y# year (Number) 1996
43
* Y* year (week of year) (Number) 1997
44
* u* extended year (Number) 4601
45
* Q# quarter (Text) Q3 & 3rd quarter
46
* M month in year (Text & Number) July & 07
47
* L month in year (standalone) (Text & Number) July & 07
48
* d day in month (Number) 10
49
* h hour in am/pm (1~12) (Number) 12
50
* H hour in day (0~23) (Number) 0
51
* m minute in hour (Number) 30
52
* s second in minute (Number) 55
53
* S fractional second (Number) 978
54
* E# day of week (Text) Tue & Tuesday
55
* e* day of week (local 1~7) (Number) 2
56
* c# day of week (standalone) (Text & Number) 2 & Tues & Tuesday & T
57
* D* day in year (Number) 189
58
* F* day of week in month (Number) 2 (2nd Wed in July)
59
* w week in year (Number) 27
60
* W* week in month (Number) 2
61
* a am/pm marker (Text) PM
62
* k hour in day (1~24) (Number) 24
63
* K hour in am/pm (0~11) (Number) 0
64
* z time zone (Text) Pacific Standard Time
65
* Z# time zone (RFC 822) (Number) -0800
66
* v# time zone (generic) (Text) America/Los_Angeles
67
* V# time zone (Text) Los Angeles Time
68
* g* Julian day (Number) 2451334
69
* A* milliseconds in day (Number) 69540000
70
* ' escape for text (Delimiter) 'Date='
71
* '' single quote (Literal) 'o''clock'
72
*
73
* Item marked with '*' are not supported yet.
74
* Item marked with '#' works different than java
75
*
76
* The count of pattern letters determine the format.
77
* (Text): 4 or more, use full form, <4, use short or abbreviated form if it
78
* exists. (e.g., "EEEE" produces "Monday", "EEE" produces "Mon")
79
*
80
* (Number): the minimum number of digits. Shorter numbers are zero-padded to
81
* this amount (e.g. if "m" produces "6", "mm" produces "06"). Year is handled
82
* specially; that is, if the count of 'y' is 2, the Year will be truncated to
83
* 2 digits. (e.g., if "yyyy" produces "1997", "yy" produces "97".) Unlike other
84
* fields, fractional seconds are padded on the right with zero.
85
*
86
* :(Text & Number) 3 or over, use text, otherwise use number. (e.g., "M"
87
* produces "1", "MM" produces "01", "MMM" produces "Jan", and "MMMM" produces
88
* "January".)
89
*
90
* Any characters in the pattern that are not in the ranges of ['a'..'z'] and
91
* ['A'..'Z'] will be treated as quoted text. For instance, characters like ':',
92
* '.', ' ', '#' and '@' will appear in the resulting time text even they are
93
* not embraced within single quotes.
94
* </pre>
95
*/
96
97
/**
98
* Construct a DateTimeFormat object based on current locale.
99
* @constructor
100
* @param {string|number} pattern pattern specification or pattern type.
101
* @param {!Object=} opt_dateTimeSymbols Optional symbols to use for this
102
* instance rather than the global symbols.
103
* @final
104
*/
105
goog.i18n.DateTimeFormat = function(pattern, opt_dateTimeSymbols) {
106
goog.asserts.assert(goog.isDef(pattern), 'Pattern must be defined');
107
goog.asserts.assert(
108
goog.isDef(opt_dateTimeSymbols) || goog.isDef(goog.i18n.DateTimeSymbols),
109
'goog.i18n.DateTimeSymbols or explicit symbols must be defined');
110
111
this.patternParts_ = [];
112
113
/**
114
* Data structure that with all the locale info needed for date formatting.
115
* (day/month names, most common patterns, rules for week-end, etc.)
116
* @private {!goog.i18n.DateTimeSymbolsType}
117
*/
118
this.dateTimeSymbols_ = /** @type {!goog.i18n.DateTimeSymbolsType} */ (
119
opt_dateTimeSymbols || goog.i18n.DateTimeSymbols);
120
if (typeof pattern == 'number') {
121
this.applyStandardPattern_(pattern);
122
} else {
123
this.applyPattern_(pattern);
124
}
125
};
126
127
128
/**
129
* Enum to identify predefined Date/Time format pattern.
130
* @enum {number}
131
*/
132
goog.i18n.DateTimeFormat.Format = {
133
FULL_DATE: 0,
134
LONG_DATE: 1,
135
MEDIUM_DATE: 2,
136
SHORT_DATE: 3,
137
FULL_TIME: 4,
138
LONG_TIME: 5,
139
MEDIUM_TIME: 6,
140
SHORT_TIME: 7,
141
FULL_DATETIME: 8,
142
LONG_DATETIME: 9,
143
MEDIUM_DATETIME: 10,
144
SHORT_DATETIME: 11
145
};
146
147
148
/**
149
* regular expression pattern for parsing pattern string
150
* @type {Array<RegExp>}
151
* @private
152
*/
153
goog.i18n.DateTimeFormat.TOKENS_ = [
154
// quote string
155
/^\'(?:[^\']|\'\')*(\'|$)/,
156
// pattern chars
157
/^(?:G+|y+|M+|k+|S+|E+|a+|h+|K+|H+|c+|L+|Q+|d+|m+|s+|v+|V+|w+|z+|Z+)/,
158
// and all the other chars
159
/^[^\'GyMkSEahKHcLQdmsvVwzZ]+/ // and all the other chars
160
];
161
162
163
/**
164
* These are token types, corresponding to above token definitions.
165
* @enum {number}
166
* @private
167
*/
168
goog.i18n.DateTimeFormat.PartTypes_ = {
169
QUOTED_STRING: 0,
170
FIELD: 1,
171
LITERAL: 2
172
};
173
174
175
/**
176
* @param {!goog.date.DateLike} date
177
* @return {number}
178
* @private
179
*/
180
goog.i18n.DateTimeFormat.getHours_ = function(date) {
181
return date.getHours ? date.getHours() : 0;
182
};
183
184
185
/**
186
* Apply specified pattern to this formatter object.
187
* @param {string} pattern String specifying how the date should be formatted.
188
* @private
189
*/
190
goog.i18n.DateTimeFormat.prototype.applyPattern_ = function(pattern) {
191
if (goog.i18n.DateTimeFormat.removeRlmInPatterns_) {
192
// Remove RLM unicode control character from pattern.
193
pattern = pattern.replace(/\u200f/g, '');
194
}
195
// lex the pattern, once for all uses
196
while (pattern) {
197
var previousPattern = pattern;
198
for (var i = 0; i < goog.i18n.DateTimeFormat.TOKENS_.length; ++i) {
199
var m = pattern.match(goog.i18n.DateTimeFormat.TOKENS_[i]);
200
if (m) {
201
var part = m[0];
202
pattern = pattern.substring(part.length);
203
if (i == goog.i18n.DateTimeFormat.PartTypes_.QUOTED_STRING) {
204
if (part == "''") {
205
part = "'"; // '' -> '
206
} else {
207
part = part.substring(
208
1,
209
m[1] == '\'' ? part.length - 1 : part.length); // strip quotes
210
part = part.replace(/\'\'/g, '\'');
211
}
212
}
213
this.patternParts_.push({text: part, type: i});
214
break;
215
}
216
}
217
if (previousPattern === pattern) {
218
// On every iteration, part of the pattern string must be consumed.
219
throw new Error('Malformed pattern part: ' + pattern);
220
}
221
}
222
};
223
224
225
/**
226
* Format the given date object according to preset pattern and current locale.
227
* @param {goog.date.DateLike} date The Date object that is being formatted.
228
* @param {goog.i18n.TimeZone=} opt_timeZone optional, if specified, time
229
* related fields will be formatted based on its setting. When this field
230
* is not specified, "undefined" will be pass around and those function
231
* that really need time zone service will create a default one.
232
* @return {string} Formatted string for the given date.
233
* Throws an error if the date is null or if one tries to format a date-only
234
* object (for instance goog.date.Date) using a pattern with time fields.
235
*/
236
goog.i18n.DateTimeFormat.prototype.format = function(date, opt_timeZone) {
237
if (!date) throw Error('The date to format must be non-null.');
238
239
// We don't want to write code to calculate each date field because we
240
// want to maximize performance and minimize code size.
241
// JavaScript only provide API to render local time.
242
// Suppose target date is: 16:00 GMT-0400
243
// OS local time is: 12:00 GMT-0800
244
// We want to create a Local Date Object : 16:00 GMT-0800, and fix the
245
// time zone display ourselves.
246
// Thing get a little bit tricky when daylight time transition happens. For
247
// example, suppose OS timeZone is America/Los_Angeles, it is impossible to
248
// represent "2006/4/2 02:30" even for those timeZone that has no transition
249
// at this time. Because 2:00 to 3:00 on that day does not exist in
250
// America/Los_Angeles time zone. To avoid calculating date field through
251
// our own code, we uses 3 Date object instead, one for "Year, month, day",
252
// one for time within that day, and one for timeZone object since it need
253
// the real time to figure out actual time zone offset.
254
var diff = opt_timeZone ?
255
(date.getTimezoneOffset() - opt_timeZone.getOffset(date)) * 60000 :
256
0;
257
var dateForDate = diff ? new Date(date.getTime() + diff) : date;
258
var dateForTime = dateForDate;
259
// When the time manipulation applied above spans the DST on/off hour, this
260
// could alter the time incorrectly by adding or subtracting an additional
261
// hour.
262
// We can mitigate this by:
263
// - Adding the difference in timezone offset to the date. This ensures that
264
// the dateForDate is still within the right day if the extra DST hour
265
// affected the date.
266
// - Move the time one day forward if we applied a timezone offset backwards,
267
// or vice versa. This trick ensures that the time is in the same offset
268
// as the original date, so we remove the additional hour added or
269
// subtracted by the DST switch.
270
if (opt_timeZone &&
271
dateForDate.getTimezoneOffset() != date.getTimezoneOffset()) {
272
var dstDiff =
273
(dateForDate.getTimezoneOffset() - date.getTimezoneOffset()) * 60000;
274
dateForDate = new Date(dateForDate.getTime() + dstDiff);
275
276
diff += diff > 0 ? -goog.date.MS_PER_DAY : goog.date.MS_PER_DAY;
277
dateForTime = new Date(date.getTime() + diff);
278
}
279
280
var out = [];
281
for (var i = 0; i < this.patternParts_.length; ++i) {
282
var text = this.patternParts_[i].text;
283
if (goog.i18n.DateTimeFormat.PartTypes_.FIELD ==
284
this.patternParts_[i].type) {
285
out.push(
286
this.formatField_(
287
text, date, dateForDate, dateForTime, opt_timeZone));
288
} else {
289
out.push(text);
290
}
291
}
292
return out.join('');
293
};
294
295
296
/**
297
* Apply a predefined pattern as identified by formatType, which is stored in
298
* locale specific repository.
299
* @param {number} formatType A number that identified the predefined pattern.
300
* @private
301
*/
302
goog.i18n.DateTimeFormat.prototype.applyStandardPattern_ = function(
303
formatType) {
304
var pattern;
305
if (formatType < 4) {
306
pattern = this.dateTimeSymbols_.DATEFORMATS[formatType];
307
} else if (formatType < 8) {
308
pattern = this.dateTimeSymbols_.TIMEFORMATS[formatType - 4];
309
} else if (formatType < 12) {
310
pattern = this.dateTimeSymbols_.DATETIMEFORMATS[formatType - 8];
311
pattern = pattern.replace(
312
'{1}', this.dateTimeSymbols_.DATEFORMATS[formatType - 8]);
313
pattern = pattern.replace(
314
'{0}', this.dateTimeSymbols_.TIMEFORMATS[formatType - 8]);
315
} else {
316
this.applyStandardPattern_(goog.i18n.DateTimeFormat.Format.MEDIUM_DATETIME);
317
return;
318
}
319
this.applyPattern_(pattern);
320
};
321
322
323
/**
324
* Localizes a string potentially containing numbers, replacing ASCII digits
325
* with native digits if specified so by the locale. Leaves other characters.
326
* @param {string} input the string to be localized, using ASCII digits.
327
* @return {string} localized string, potentially using native digits.
328
* @private
329
*/
330
goog.i18n.DateTimeFormat.prototype.localizeNumbers_ = function(input) {
331
return goog.i18n.DateTimeFormat.localizeNumbers(input, this.dateTimeSymbols_);
332
};
333
334
335
/**
336
* If the usage of Ascii digits should be enforced regardless of locale.
337
* @type {boolean}
338
* @private
339
*/
340
goog.i18n.DateTimeFormat.enforceAsciiDigits_ = false;
341
342
343
/**
344
* If RLM unicode characters should be removed from date/time patterns (useful
345
* when enforcing ASCII digits for Arabic). See {@code #setEnforceAsciiDigits}.
346
* @type {boolean}
347
* @private
348
*/
349
goog.i18n.DateTimeFormat.removeRlmInPatterns_ = false;
350
351
352
/**
353
* Sets if the usage of Ascii digits in formatting should be enforced in
354
* formatted date/time even for locales where native digits are indicated.
355
* Also sets whether to remove RLM unicode control characters when using
356
* standard enumerated patterns (they exist e.g. in standard d/M/y for Arabic).
357
* Production code should call this once before any {@code DateTimeFormat}
358
* object is instantiated.
359
* Caveats:
360
* * Enforcing ASCII digits affects all future formatting by new or existing
361
* {@code DateTimeFormat} objects.
362
* * Removal of RLM characters only applies to {@code DateTimeFormat} objects
363
* instantiated after this call.
364
* @param {boolean} enforceAsciiDigits Whether Ascii digits should be enforced.
365
*/
366
goog.i18n.DateTimeFormat.setEnforceAsciiDigits = function(enforceAsciiDigits) {
367
goog.i18n.DateTimeFormat.enforceAsciiDigits_ = enforceAsciiDigits;
368
369
// Also setting removal of RLM chracters when forcing ASCII digits since it's
370
// the right thing to do for Arabic standard patterns. One could add an
371
// optional argument here or to the {@code DateTimeFormat} constructor to
372
// enable an alternative behavior.
373
goog.i18n.DateTimeFormat.removeRlmInPatterns_ = enforceAsciiDigits;
374
};
375
376
377
/**
378
* @return {boolean} Whether enforcing ASCII digits for all locales. See
379
* {@code #setEnforceAsciiDigits} for more details.
380
*/
381
goog.i18n.DateTimeFormat.isEnforceAsciiDigits = function() {
382
return goog.i18n.DateTimeFormat.enforceAsciiDigits_;
383
};
384
385
386
/**
387
* Localizes a string potentially containing numbers, replacing ASCII digits
388
* with native digits if specified so by the locale. Leaves other characters.
389
* @param {number|string} input the string to be localized, using ASCII digits.
390
* @param {!Object=} opt_dateTimeSymbols Optional symbols to use rather than
391
* the global symbols.
392
* @return {string} localized string, potentially using native digits.
393
*/
394
goog.i18n.DateTimeFormat.localizeNumbers = function(
395
input, opt_dateTimeSymbols) {
396
input = String(input);
397
var dateTimeSymbols = opt_dateTimeSymbols || goog.i18n.DateTimeSymbols;
398
if (dateTimeSymbols.ZERODIGIT === undefined ||
399
goog.i18n.DateTimeFormat.enforceAsciiDigits_) {
400
return input;
401
}
402
403
var parts = [];
404
for (var i = 0; i < input.length; i++) {
405
var c = input.charCodeAt(i);
406
parts.push(
407
(0x30 <= c && c <= 0x39) ? // '0' <= c <= '9'
408
String.fromCharCode(dateTimeSymbols.ZERODIGIT + c - 0x30) :
409
input.charAt(i));
410
}
411
return parts.join('');
412
};
413
414
415
/**
416
* Formats Era field according to pattern specified.
417
*
418
* @param {number} count Number of time pattern char repeats, it controls
419
* how a field should be formatted.
420
* @param {!goog.date.DateLike} date It holds the date object to be formatted.
421
* @return {string} Formatted string that represent this field.
422
* @private
423
*/
424
goog.i18n.DateTimeFormat.prototype.formatEra_ = function(count, date) {
425
var value = date.getFullYear() > 0 ? 1 : 0;
426
return count >= 4 ? this.dateTimeSymbols_.ERANAMES[value] :
427
this.dateTimeSymbols_.ERAS[value];
428
};
429
430
431
/**
432
* Formats Year field according to pattern specified
433
* Javascript Date object seems incapable handling 1BC and
434
* year before. It can show you year 0 which does not exists.
435
* following we just keep consistent with javascript's
436
* toString method. But keep in mind those things should be
437
* unsupported.
438
* @param {number} count Number of time pattern char repeats, it controls
439
* how a field should be formatted.
440
* @param {!goog.date.DateLike} date It holds the date object to be formatted.
441
* @return {string} Formatted string that represent this field.
442
* @private
443
*/
444
goog.i18n.DateTimeFormat.prototype.formatYear_ = function(count, date) {
445
var value = date.getFullYear();
446
if (value < 0) {
447
value = -value;
448
}
449
if (count == 2) {
450
// See comment about special casing 'yy' at the start of the file, this
451
// matches ICU and CLDR behaviour. See also:
452
// http://icu-project.org/apiref/icu4j/com/ibm/icu/text/SimpleDateFormat.html
453
// http://www.unicode.org/reports/tr35/tr35-dates.html
454
value = value % 100;
455
}
456
return this.localizeNumbers_(goog.string.padNumber(value, count));
457
};
458
459
460
/**
461
* Formats Month field according to pattern specified
462
*
463
* @param {number} count Number of time pattern char repeats, it controls
464
* how a field should be formatted.
465
* @param {!goog.date.DateLike} date It holds the date object to be formatted.
466
* @return {string} Formatted string that represent this field.
467
* @private
468
*/
469
goog.i18n.DateTimeFormat.prototype.formatMonth_ = function(count, date) {
470
var value = date.getMonth();
471
switch (count) {
472
case 5:
473
return this.dateTimeSymbols_.NARROWMONTHS[value];
474
case 4:
475
return this.dateTimeSymbols_.MONTHS[value];
476
case 3:
477
return this.dateTimeSymbols_.SHORTMONTHS[value];
478
default:
479
return this.localizeNumbers_(goog.string.padNumber(value + 1, count));
480
}
481
};
482
483
484
/**
485
* Validates is the goog.date.DateLike object to format has a time.
486
* DateLike means Date|goog.date.Date, and goog.date.DateTime inherits
487
* from goog.date.Date. But goog.date.Date does not have time related
488
* members (getHours, getMinutes, getSeconds).
489
* Formatting can be done, if there are no time placeholders in the pattern.
490
*
491
* @param {!goog.date.DateLike} date the object to validate.
492
* @private
493
*/
494
goog.i18n.DateTimeFormat.validateDateHasTime_ = function(date) {
495
if (date.getHours && date.getSeconds && date.getMinutes) return;
496
// if (date instanceof Date || date instanceof goog.date.DateTime)
497
throw Error(
498
'The date to format has no time (probably a goog.date.Date). ' +
499
'Use Date or goog.date.DateTime, or use a pattern without time fields.');
500
};
501
502
503
/**
504
* Formats (1..24) Hours field according to pattern specified
505
*
506
* @param {number} count Number of time pattern char repeats. This controls
507
* how a field should be formatted.
508
* @param {!goog.date.DateLike} date It holds the date object to be formatted.
509
* @return {string} Formatted string that represent this field.
510
* @private
511
*/
512
goog.i18n.DateTimeFormat.prototype.format24Hours_ = function(count, date) {
513
goog.i18n.DateTimeFormat.validateDateHasTime_(date);
514
var hours = goog.i18n.DateTimeFormat.getHours_(date) || 24;
515
return this.localizeNumbers_(goog.string.padNumber(hours, count));
516
};
517
518
519
/**
520
* Formats Fractional seconds field according to pattern
521
* specified
522
*
523
* @param {number} count Number of time pattern char repeats, it controls
524
* how a field should be formatted.
525
* @param {!goog.date.DateLike} date It holds the date object to be formatted.
526
*
527
* @return {string} Formatted string that represent this field.
528
* @private
529
*/
530
goog.i18n.DateTimeFormat.prototype.formatFractionalSeconds_ = function(
531
count, date) {
532
// Fractional seconds left-justify, append 0 for precision beyond 3
533
var value = date.getTime() % 1000 / 1000;
534
return this.localizeNumbers_(
535
value.toFixed(Math.min(3, count)).substr(2) +
536
(count > 3 ? goog.string.padNumber(0, count - 3) : ''));
537
};
538
539
540
/**
541
* Formats Day of week field according to pattern specified
542
*
543
* @param {number} count Number of time pattern char repeats, it controls
544
* how a field should be formatted.
545
* @param {!goog.date.DateLike} date It holds the date object to be formatted.
546
* @return {string} Formatted string that represent this field.
547
* @private
548
*/
549
goog.i18n.DateTimeFormat.prototype.formatDayOfWeek_ = function(count, date) {
550
var value = date.getDay();
551
return count >= 4 ? this.dateTimeSymbols_.WEEKDAYS[value] :
552
this.dateTimeSymbols_.SHORTWEEKDAYS[value];
553
};
554
555
556
/**
557
* Formats Am/Pm field according to pattern specified
558
*
559
* @param {number} count Number of time pattern char repeats, it controls
560
* how a field should be formatted.
561
* @param {!goog.date.DateLike} date It holds the date object to be formatted.
562
* @return {string} Formatted string that represent this field.
563
* @private
564
*/
565
goog.i18n.DateTimeFormat.prototype.formatAmPm_ = function(count, date) {
566
goog.i18n.DateTimeFormat.validateDateHasTime_(date);
567
var hours = goog.i18n.DateTimeFormat.getHours_(date);
568
return this.dateTimeSymbols_.AMPMS[hours >= 12 && hours < 24 ? 1 : 0];
569
};
570
571
572
/**
573
* Formats (1..12) Hours field according to pattern specified
574
*
575
* @param {number} count Number of time pattern char repeats, it controls
576
* how a field should be formatted.
577
* @param {!goog.date.DateLike} date It holds the date object to be formatted.
578
* @return {string} formatted string that represent this field.
579
* @private
580
*/
581
goog.i18n.DateTimeFormat.prototype.format1To12Hours_ = function(count, date) {
582
goog.i18n.DateTimeFormat.validateDateHasTime_(date);
583
var hours = goog.i18n.DateTimeFormat.getHours_(date) % 12 || 12;
584
return this.localizeNumbers_(goog.string.padNumber(hours, count));
585
};
586
587
588
/**
589
* Formats (0..11) Hours field according to pattern specified
590
*
591
* @param {number} count Number of time pattern char repeats, it controls
592
* how a field should be formatted.
593
* @param {!goog.date.DateLike} date It holds the date object to be formatted.
594
* @return {string} formatted string that represent this field.
595
* @private
596
*/
597
goog.i18n.DateTimeFormat.prototype.format0To11Hours_ = function(count, date) {
598
goog.i18n.DateTimeFormat.validateDateHasTime_(date);
599
var hours = goog.i18n.DateTimeFormat.getHours_(date) % 12;
600
return this.localizeNumbers_(goog.string.padNumber(hours, count));
601
};
602
603
604
/**
605
* Formats (0..23) Hours field according to pattern specified
606
*
607
* @param {number} count Number of time pattern char repeats, it controls
608
* how a field should be formatted.
609
* @param {!goog.date.DateLike} date It holds the date object to be formatted.
610
* @return {string} formatted string that represent this field.
611
* @private
612
*/
613
goog.i18n.DateTimeFormat.prototype.format0To23Hours_ = function(count, date) {
614
goog.i18n.DateTimeFormat.validateDateHasTime_(date);
615
var hours = goog.i18n.DateTimeFormat.getHours_(date);
616
return this.localizeNumbers_(goog.string.padNumber(hours, count));
617
};
618
619
620
/**
621
* Formats Standalone weekday field according to pattern specified
622
*
623
* @param {number} count Number of time pattern char repeats, it controls
624
* how a field should be formatted.
625
* @param {!goog.date.DateLike} date It holds the date object to be formatted.
626
* @return {string} formatted string that represent this field.
627
* @private
628
*/
629
goog.i18n.DateTimeFormat.prototype.formatStandaloneDay_ = function(
630
count, date) {
631
var value = date.getDay();
632
switch (count) {
633
case 5:
634
return this.dateTimeSymbols_.STANDALONENARROWWEEKDAYS[value];
635
case 4:
636
return this.dateTimeSymbols_.STANDALONEWEEKDAYS[value];
637
case 3:
638
return this.dateTimeSymbols_.STANDALONESHORTWEEKDAYS[value];
639
default:
640
return this.localizeNumbers_(goog.string.padNumber(value, 1));
641
}
642
};
643
644
645
/**
646
* Formats Standalone Month field according to pattern specified
647
*
648
* @param {number} count Number of time pattern char repeats, it controls
649
* how a field should be formatted.
650
* @param {!goog.date.DateLike} date It holds the date object to be formatted.
651
* @return {string} formatted string that represent this field.
652
* @private
653
*/
654
goog.i18n.DateTimeFormat.prototype.formatStandaloneMonth_ = function(
655
count, date) {
656
var value = date.getMonth();
657
switch (count) {
658
case 5:
659
return this.dateTimeSymbols_.STANDALONENARROWMONTHS[value];
660
case 4:
661
return this.dateTimeSymbols_.STANDALONEMONTHS[value];
662
case 3:
663
return this.dateTimeSymbols_.STANDALONESHORTMONTHS[value];
664
default:
665
return this.localizeNumbers_(goog.string.padNumber(value + 1, count));
666
}
667
};
668
669
670
/**
671
* Formats Quarter field according to pattern specified
672
*
673
* @param {number} count Number of time pattern char repeats, it controls
674
* how a field should be formatted.
675
* @param {!goog.date.DateLike} date It holds the date object to be formatted.
676
* @return {string} Formatted string that represent this field.
677
* @private
678
*/
679
goog.i18n.DateTimeFormat.prototype.formatQuarter_ = function(count, date) {
680
var value = Math.floor(date.getMonth() / 3);
681
return count < 4 ? this.dateTimeSymbols_.SHORTQUARTERS[value] :
682
this.dateTimeSymbols_.QUARTERS[value];
683
};
684
685
686
/**
687
* Formats Date field according to pattern specified
688
*
689
* @param {number} count Number of time pattern char repeats, it controls
690
* how a field should be formatted.
691
* @param {!goog.date.DateLike} date It holds the date object to be formatted.
692
* @return {string} Formatted string that represent this field.
693
* @private
694
*/
695
goog.i18n.DateTimeFormat.prototype.formatDate_ = function(count, date) {
696
return this.localizeNumbers_(goog.string.padNumber(date.getDate(), count));
697
};
698
699
700
/**
701
* Formats Minutes field according to pattern specified
702
*
703
* @param {number} count Number of time pattern char repeats, it controls
704
* how a field should be formatted.
705
* @param {!goog.date.DateLike} date It holds the date object to be formatted.
706
* @return {string} Formatted string that represent this field.
707
* @private
708
*/
709
goog.i18n.DateTimeFormat.prototype.formatMinutes_ = function(count, date) {
710
goog.i18n.DateTimeFormat.validateDateHasTime_(date);
711
return this.localizeNumbers_(
712
goog.string.padNumber(
713
/** @type {!goog.date.DateTime} */ (date).getMinutes(), count));
714
};
715
716
717
/**
718
* Formats Seconds field according to pattern specified
719
*
720
* @param {number} count Number of time pattern char repeats, it controls
721
* how a field should be formatted.
722
* @param {!goog.date.DateLike} date It holds the date object to be formatted.
723
* @return {string} Formatted string that represent this field.
724
* @private
725
*/
726
goog.i18n.DateTimeFormat.prototype.formatSeconds_ = function(count, date) {
727
goog.i18n.DateTimeFormat.validateDateHasTime_(date);
728
return this.localizeNumbers_(
729
goog.string.padNumber(
730
/** @type {!goog.date.DateTime} */ (date).getSeconds(), count));
731
};
732
733
734
/**
735
* Formats the week of year field according to pattern specified
736
*
737
* @param {number} count Number of time pattern char repeats, it controls
738
* how a field should be formatted.
739
* @param {!goog.date.DateLike} date It holds the date object to be formatted.
740
* @return {string} Formatted string that represent this field.
741
* @private
742
*/
743
goog.i18n.DateTimeFormat.prototype.formatWeekOfYear_ = function(count, date) {
744
745
746
var weekNum = goog.date.getWeekNumber(
747
date.getFullYear(), date.getMonth(), date.getDate(),
748
this.dateTimeSymbols_.FIRSTWEEKCUTOFFDAY,
749
this.dateTimeSymbols_.FIRSTDAYOFWEEK);
750
751
return this.localizeNumbers_(goog.string.padNumber(weekNum, count));
752
};
753
754
755
/**
756
* Formats TimeZone field following RFC
757
*
758
* @param {number} count Number of time pattern char repeats, it controls
759
* how a field should be formatted.
760
* @param {!goog.date.DateLike} date It holds the date object to be formatted.
761
* @param {goog.i18n.TimeZone=} opt_timeZone This holds current time zone info.
762
* @return {string} Formatted string that represent this field.
763
* @private
764
*/
765
goog.i18n.DateTimeFormat.prototype.formatTimeZoneRFC_ = function(
766
count, date, opt_timeZone) {
767
opt_timeZone = opt_timeZone ||
768
goog.i18n.TimeZone.createTimeZone(date.getTimezoneOffset());
769
770
// RFC 822 formats should be kept in ASCII, but localized GMT formats may need
771
// to use native digits.
772
return count < 4 ? opt_timeZone.getRFCTimeZoneString(date) :
773
this.localizeNumbers_(opt_timeZone.getGMTString(date));
774
};
775
776
777
/**
778
* Generate GMT timeZone string for given date
779
* @param {number} count Number of time pattern char repeats, it controls
780
* how a field should be formatted.
781
* @param {!goog.date.DateLike} date Whose value being evaluated.
782
* @param {goog.i18n.TimeZone=} opt_timeZone This holds current time zone info.
783
* @return {string} GMT timeZone string.
784
* @private
785
*/
786
goog.i18n.DateTimeFormat.prototype.formatTimeZone_ = function(
787
count, date, opt_timeZone) {
788
opt_timeZone = opt_timeZone ||
789
goog.i18n.TimeZone.createTimeZone(date.getTimezoneOffset());
790
return count < 4 ? opt_timeZone.getShortName(date) :
791
opt_timeZone.getLongName(date);
792
};
793
794
795
/**
796
* Generate GMT timeZone string for given date
797
* @param {!goog.date.DateLike} date Whose value being evaluated.
798
* @param {goog.i18n.TimeZone=} opt_timeZone This holds current time zone info.
799
* @return {string} GMT timeZone string.
800
* @private
801
*/
802
goog.i18n.DateTimeFormat.prototype.formatTimeZoneId_ = function(
803
date, opt_timeZone) {
804
opt_timeZone = opt_timeZone ||
805
goog.i18n.TimeZone.createTimeZone(date.getTimezoneOffset());
806
return opt_timeZone.getTimeZoneId();
807
};
808
809
810
/**
811
* Generate localized, location dependent time zone id
812
* @param {number} count Number of time pattern char repeats, it controls
813
* how a field should be formatted.
814
* @param {!goog.date.DateLike} date Whose value being evaluated.
815
* @param {goog.i18n.TimeZone=} opt_timeZone This holds current time zone info.
816
* @return {string} GMT timeZone string.
817
* @private
818
*/
819
goog.i18n.DateTimeFormat.prototype.formatTimeZoneLocationId_ = function(
820
count, date, opt_timeZone) {
821
opt_timeZone = opt_timeZone ||
822
goog.i18n.TimeZone.createTimeZone(date.getTimezoneOffset());
823
return count <= 2 ? opt_timeZone.getTimeZoneId() :
824
opt_timeZone.getGenericLocation(date);
825
};
826
827
828
/**
829
* Formatting one date field.
830
* @param {string} patternStr The pattern string for the field being formatted.
831
* @param {!goog.date.DateLike} date represents the real date to be formatted.
832
* @param {!goog.date.DateLike} dateForDate used to resolve date fields
833
* for formatting.
834
* @param {!goog.date.DateLike} dateForTime used to resolve time fields
835
* for formatting.
836
* @param {goog.i18n.TimeZone=} opt_timeZone This holds current time zone info.
837
* @return {string} string representation for the given field.
838
* @private
839
*/
840
goog.i18n.DateTimeFormat.prototype.formatField_ = function(
841
patternStr, date, dateForDate, dateForTime, opt_timeZone) {
842
var count = patternStr.length;
843
switch (patternStr.charAt(0)) {
844
case 'G':
845
return this.formatEra_(count, dateForDate);
846
case 'y':
847
return this.formatYear_(count, dateForDate);
848
case 'M':
849
return this.formatMonth_(count, dateForDate);
850
case 'k':
851
return this.format24Hours_(count, dateForTime);
852
case 'S':
853
return this.formatFractionalSeconds_(count, dateForTime);
854
case 'E':
855
return this.formatDayOfWeek_(count, dateForDate);
856
case 'a':
857
return this.formatAmPm_(count, dateForTime);
858
case 'h':
859
return this.format1To12Hours_(count, dateForTime);
860
case 'K':
861
return this.format0To11Hours_(count, dateForTime);
862
case 'H':
863
return this.format0To23Hours_(count, dateForTime);
864
case 'c':
865
return this.formatStandaloneDay_(count, dateForDate);
866
case 'L':
867
return this.formatStandaloneMonth_(count, dateForDate);
868
case 'Q':
869
return this.formatQuarter_(count, dateForDate);
870
case 'd':
871
return this.formatDate_(count, dateForDate);
872
case 'm':
873
return this.formatMinutes_(count, dateForTime);
874
case 's':
875
return this.formatSeconds_(count, dateForTime);
876
case 'v':
877
return this.formatTimeZoneId_(date, opt_timeZone);
878
case 'V':
879
return this.formatTimeZoneLocationId_(count, date, opt_timeZone);
880
case 'w':
881
return this.formatWeekOfYear_(count, dateForTime);
882
case 'z':
883
return this.formatTimeZone_(count, date, opt_timeZone);
884
case 'Z':
885
return this.formatTimeZoneRFC_(count, date, opt_timeZone);
886
default:
887
return '';
888
}
889
};
890
891