Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/date/relative.js
2868 views
1
// Copyright 2009 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 formatting relative dates. Such as "3 days ago"
17
* "3 hours ago", "14 minutes ago", "12 days ago", "Today", "Yesterday".
18
*
19
* For better quality localization of plurals ("hours"/"minutes"/"days") and
20
* to use local digits, goog.date.relativeWithPlurals can be loaded in addition
21
* to this namespace.
22
*
23
*/
24
25
goog.provide('goog.date.relative');
26
goog.provide('goog.date.relative.TimeDeltaFormatter');
27
goog.provide('goog.date.relative.Unit');
28
29
goog.require('goog.i18n.DateTimeFormat');
30
goog.require('goog.i18n.DateTimePatterns');
31
32
33
/**
34
* Number of milliseconds in a minute.
35
* @type {number}
36
* @private
37
*/
38
goog.date.relative.MINUTE_MS_ = 60000;
39
40
41
/**
42
* Number of milliseconds in a day.
43
* @type {number}
44
* @private
45
*/
46
goog.date.relative.DAY_MS_ = 86400000;
47
48
49
/**
50
* Enumeration used to identify time units internally.
51
* @enum {number}
52
*/
53
goog.date.relative.Unit = {
54
MINUTES: 0,
55
HOURS: 1,
56
DAYS: 2
57
};
58
59
60
/**
61
* Full date formatter.
62
* @type {goog.i18n.DateTimeFormat}
63
* @private
64
*/
65
goog.date.relative.fullDateFormatter_;
66
67
68
/**
69
* Short time formatter.
70
* @type {goog.i18n.DateTimeFormat}
71
* @private
72
*/
73
goog.date.relative.shortTimeFormatter_;
74
75
76
/**
77
* Month-date formatter.
78
* @type {goog.i18n.DateTimeFormat}
79
* @private
80
*/
81
goog.date.relative.monthDateFormatter_;
82
83
84
/**
85
* @typedef {function(number, boolean, goog.date.relative.Unit): string}
86
*/
87
goog.date.relative.TimeDeltaFormatter;
88
89
90
/**
91
* Handles formatting of time deltas.
92
* @private {goog.date.relative.TimeDeltaFormatter}
93
*/
94
goog.date.relative.formatTimeDelta_;
95
96
97
/**
98
* Sets a different formatting function for time deltas ("3 days ago").
99
* While its visibility is public, this function is Closure-internal and should
100
* not be used in application code.
101
* @param {goog.date.relative.TimeDeltaFormatter} formatter The function to use
102
* for formatting time deltas (i.e. relative times).
103
*/
104
goog.date.relative.setTimeDeltaFormatter = function(formatter) {
105
goog.date.relative.formatTimeDelta_ = formatter;
106
};
107
108
109
/**
110
* Returns a date in month format, e.g. Mar 15.
111
* @param {Date} date The date object.
112
* @return {string} The formatted string.
113
* @private
114
*/
115
goog.date.relative.formatMonth_ = function(date) {
116
if (!goog.date.relative.monthDateFormatter_) {
117
goog.date.relative.monthDateFormatter_ =
118
new goog.i18n.DateTimeFormat(goog.i18n.DateTimePatterns.MONTH_DAY_ABBR);
119
}
120
return goog.date.relative.monthDateFormatter_.format(date);
121
};
122
123
124
/**
125
* Returns a date in short-time format, e.g. 2:50 PM.
126
* @param {Date|goog.date.DateTime} date The date object.
127
* @return {string} The formatted string.
128
* @private
129
*/
130
goog.date.relative.formatShortTime_ = function(date) {
131
if (!goog.date.relative.shortTimeFormatter_) {
132
goog.date.relative.shortTimeFormatter_ = new goog.i18n.DateTimeFormat(
133
goog.i18n.DateTimeFormat.Format.SHORT_TIME);
134
}
135
return goog.date.relative.shortTimeFormatter_.format(date);
136
};
137
138
139
/**
140
* Returns a date in full date format, e.g. Tuesday, March 24, 2009.
141
* @param {Date|goog.date.DateTime} date The date object.
142
* @return {string} The formatted string.
143
* @private
144
*/
145
goog.date.relative.formatFullDate_ = function(date) {
146
if (!goog.date.relative.fullDateFormatter_) {
147
goog.date.relative.fullDateFormatter_ =
148
new goog.i18n.DateTimeFormat(goog.i18n.DateTimeFormat.Format.FULL_DATE);
149
}
150
return goog.date.relative.fullDateFormatter_.format(date);
151
};
152
153
154
/**
155
* Accepts a timestamp in milliseconds and outputs a relative time in the form
156
* of "1 hour ago", "1 day ago", "in 1 hour", "in 2 days" etc. If the date
157
* delta is over 2 weeks, then the output string will be empty.
158
* @param {number} dateMs Date in milliseconds.
159
* @return {string} The formatted date.
160
*/
161
goog.date.relative.format = function(dateMs) {
162
var now = goog.now();
163
var delta = Math.floor((now - dateMs) / goog.date.relative.MINUTE_MS_);
164
165
var future = false;
166
167
if (delta < 0) {
168
future = true;
169
delta *= -1;
170
}
171
172
if (delta < 60) { // Minutes.
173
return goog.date.relative.formatTimeDelta_(
174
delta, future, goog.date.relative.Unit.MINUTES);
175
176
} else {
177
delta = Math.floor(delta / 60);
178
if (delta < 24) { // Hours.
179
return goog.date.relative.formatTimeDelta_(
180
delta, future, goog.date.relative.Unit.HOURS);
181
182
} else {
183
// We can be more than 24 hours apart but still only 1 day apart, so we
184
// compare the closest time from today against the target time to find
185
// the number of days in the delta.
186
var midnight = new Date(goog.now());
187
midnight.setHours(0);
188
midnight.setMinutes(0);
189
midnight.setSeconds(0);
190
midnight.setMilliseconds(0);
191
192
// Convert to days ago.
193
delta =
194
Math.ceil((midnight.getTime() - dateMs) / goog.date.relative.DAY_MS_);
195
196
if (future) {
197
delta *= -1;
198
}
199
200
// Uses days for less than 2-weeks.
201
if (delta < 14) {
202
return goog.date.relative.formatTimeDelta_(
203
delta, future, goog.date.relative.Unit.DAYS);
204
205
} else {
206
// For messages older than 2 weeks do not show anything. The client
207
// should decide the date format to show.
208
return '';
209
}
210
}
211
}
212
};
213
214
215
/**
216
* Accepts a timestamp in milliseconds and outputs a relative time in the form
217
* of "1 hour ago", "1 day ago". All future times will be returned as 0 minutes
218
* ago.
219
*
220
* This is provided for compatibility with users of the previous incarnation of
221
* the above {@see #format} method who relied on it protecting against
222
* future dates.
223
*
224
* @param {number} dateMs Date in milliseconds.
225
* @return {string} The formatted date.
226
*/
227
goog.date.relative.formatPast = function(dateMs) {
228
var now = goog.now();
229
if (now < dateMs) {
230
dateMs = now;
231
}
232
return goog.date.relative.format(dateMs);
233
};
234
235
236
/**
237
* Accepts a timestamp in milliseconds and outputs a relative day. i.e. "Today",
238
* "Yesterday", "Tomorrow", or "Sept 15".
239
*
240
* @param {number} dateMs Date in milliseconds.
241
* @param {function(!Date):string=} opt_formatter Formatter for the date.
242
* Defaults to form 'MMM dd'.
243
* @return {string} The formatted date.
244
*/
245
goog.date.relative.formatDay = function(dateMs, opt_formatter) {
246
var today = new Date(goog.now());
247
248
today.setHours(0);
249
today.setMinutes(0);
250
today.setSeconds(0);
251
today.setMilliseconds(0);
252
253
var yesterday = new Date(today.getTime() - goog.date.relative.DAY_MS_);
254
var tomorrow = new Date(today.getTime() + goog.date.relative.DAY_MS_);
255
var dayAfterTomorrow =
256
new Date(today.getTime() + 2 * goog.date.relative.DAY_MS_);
257
258
var message;
259
if (dateMs >= tomorrow.getTime() && dateMs < dayAfterTomorrow.getTime()) {
260
/** @desc Tomorrow. */
261
var MSG_TOMORROW = goog.getMsg('Tomorrow');
262
message = MSG_TOMORROW;
263
} else if (dateMs >= today.getTime() && dateMs < tomorrow.getTime()) {
264
/** @desc Today. */
265
var MSG_TODAY = goog.getMsg('Today');
266
message = MSG_TODAY;
267
} else if (dateMs >= yesterday.getTime() && dateMs < today.getTime()) {
268
/** @desc Yesterday. */
269
var MSG_YESTERDAY = goog.getMsg('Yesterday');
270
message = MSG_YESTERDAY;
271
} else {
272
// If we don't have a special relative term for this date, then return the
273
// short date format (or a custom-formatted date).
274
var formatFunction = opt_formatter || goog.date.relative.formatMonth_;
275
message = formatFunction(new Date(dateMs));
276
}
277
return message;
278
};
279
280
281
/**
282
* Formats a date, adding the relative date in parenthesis. If the date is less
283
* than 24 hours then the time will be printed, otherwise the full-date will be
284
* used. Examples:
285
* 2:20 PM (1 minute ago)
286
* Monday, February 27, 2009 (4 days ago)
287
* Tuesday, March 20, 2005 // Too long ago for a relative date.
288
*
289
* @param {Date|goog.date.DateTime} date A date object.
290
* @param {string=} opt_shortTimeMsg An optional short time message can be
291
* provided if available, so that it's not recalculated in this function.
292
* @param {string=} opt_fullDateMsg An optional date message can be
293
* provided if available, so that it's not recalculated in this function.
294
* @return {string} The date string in the above form.
295
*/
296
goog.date.relative.getDateString = function(
297
date, opt_shortTimeMsg, opt_fullDateMsg) {
298
return goog.date.relative.getDateString_(
299
date, goog.date.relative.format, opt_shortTimeMsg, opt_fullDateMsg);
300
};
301
302
303
/**
304
* Formats a date, adding the relative date in parenthesis. Functions the same
305
* as #getDateString but ensures that the date is always seen to be in the past.
306
* If the date is in the future, it will be shown as 0 minutes ago.
307
*
308
* This is provided for compatibility with users of the previous incarnation of
309
* the above {@see #getDateString} method who relied on it protecting against
310
* future dates.
311
*
312
* @param {Date|goog.date.DateTime} date A date object.
313
* @param {string=} opt_shortTimeMsg An optional short time message can be
314
* provided if available, so that it's not recalculated in this function.
315
* @param {string=} opt_fullDateMsg An optional date message can be
316
* provided if available, so that it's not recalculated in this function.
317
* @return {string} The date string in the above form.
318
*/
319
goog.date.relative.getPastDateString = function(
320
date, opt_shortTimeMsg, opt_fullDateMsg) {
321
return goog.date.relative.getDateString_(
322
date, goog.date.relative.formatPast, opt_shortTimeMsg, opt_fullDateMsg);
323
};
324
325
326
/**
327
* Formats a date, adding the relative date in parenthesis. If the date is less
328
* than 24 hours then the time will be printed, otherwise the full-date will be
329
* used. Examples:
330
* 2:20 PM (1 minute ago)
331
* Monday, February 27, 2009 (4 days ago)
332
* Tuesday, March 20, 2005 // Too long ago for a relative date.
333
*
334
* @param {Date|goog.date.DateTime} date A date object.
335
* @param {function(number) : string} relativeFormatter Function to use when
336
* formatting the relative date.
337
* @param {string=} opt_shortTimeMsg An optional short time message can be
338
* provided if available, so that it's not recalculated in this function.
339
* @param {string=} opt_fullDateMsg An optional date message can be
340
* provided if available, so that it's not recalculated in this function.
341
* @return {string} The date string in the above form.
342
* @private
343
*/
344
goog.date.relative.getDateString_ = function(
345
date, relativeFormatter, opt_shortTimeMsg, opt_fullDateMsg) {
346
var dateMs = date.getTime();
347
348
var relativeDate = relativeFormatter(dateMs);
349
350
if (relativeDate) {
351
relativeDate = ' (' + relativeDate + ')';
352
}
353
354
var delta = Math.floor((goog.now() - dateMs) / goog.date.relative.MINUTE_MS_);
355
if (delta < 60 * 24) {
356
// TODO(user): this call raises an exception if date is a goog.date.Date.
357
return (opt_shortTimeMsg || goog.date.relative.formatShortTime_(date)) +
358
relativeDate;
359
} else {
360
return (opt_fullDateMsg || goog.date.relative.formatFullDate_(date)) +
361
relativeDate;
362
}
363
};
364
365
366
/*
367
* TODO(user):
368
*
369
* I think that this whole relative formatting should move to DateTimeFormat.
370
* But we would have to wait for the next version of CLDR, which is cleaning
371
* the data for relative dates (even ICU has incomplete support for this).
372
*/
373
/**
374
* Gets a localized relative date string for a given delta and unit.
375
* @param {number} delta Number of minutes/hours/days.
376
* @param {boolean} future Whether the delta is in the future.
377
* @param {goog.date.relative.Unit} unit The units the delta is in.
378
* @return {string} The message.
379
* @private
380
*/
381
goog.date.relative.getMessage_ = function(delta, future, unit) {
382
var deltaFormatted = goog.i18n.DateTimeFormat.localizeNumbers(delta);
383
if (!future && unit == goog.date.relative.Unit.MINUTES) {
384
/**
385
* @desc Relative date indicating how many minutes ago something happened
386
* (singular).
387
*/
388
var MSG_MINUTES_AGO_SINGULAR =
389
goog.getMsg('{$num} minute ago', {'num': deltaFormatted});
390
391
/**
392
* @desc Relative date indicating how many minutes ago something happened
393
* (plural).
394
*/
395
var MSG_MINUTES_AGO_PLURAL =
396
goog.getMsg('{$num} minutes ago', {'num': deltaFormatted});
397
398
return delta == 1 ? MSG_MINUTES_AGO_SINGULAR : MSG_MINUTES_AGO_PLURAL;
399
400
} else if (future && unit == goog.date.relative.Unit.MINUTES) {
401
/**
402
* @desc Relative date indicating in how many minutes something happens
403
* (singular).
404
*/
405
var MSG_IN_MINUTES_SINGULAR =
406
goog.getMsg('in {$num} minute', {'num': deltaFormatted});
407
408
/**
409
* @desc Relative date indicating in how many minutes something happens
410
* (plural).
411
*/
412
var MSG_IN_MINUTES_PLURAL =
413
goog.getMsg('in {$num} minutes', {'num': deltaFormatted});
414
415
return delta == 1 ? MSG_IN_MINUTES_SINGULAR : MSG_IN_MINUTES_PLURAL;
416
417
} else if (!future && unit == goog.date.relative.Unit.HOURS) {
418
/**
419
* @desc Relative date indicating how many hours ago something happened
420
* (singular).
421
*/
422
var MSG_HOURS_AGO_SINGULAR =
423
goog.getMsg('{$num} hour ago', {'num': deltaFormatted});
424
425
/**
426
* @desc Relative date indicating how many hours ago something happened
427
* (plural).
428
*/
429
var MSG_HOURS_AGO_PLURAL =
430
goog.getMsg('{$num} hours ago', {'num': deltaFormatted});
431
432
return delta == 1 ? MSG_HOURS_AGO_SINGULAR : MSG_HOURS_AGO_PLURAL;
433
434
} else if (future && unit == goog.date.relative.Unit.HOURS) {
435
/**
436
* @desc Relative date indicating in how many hours something happens
437
* (singular).
438
*/
439
var MSG_IN_HOURS_SINGULAR =
440
goog.getMsg('in {$num} hour', {'num': deltaFormatted});
441
442
/**
443
* @desc Relative date indicating in how many hours something happens
444
* (plural).
445
*/
446
var MSG_IN_HOURS_PLURAL =
447
goog.getMsg('in {$num} hours', {'num': deltaFormatted});
448
449
return delta == 1 ? MSG_IN_HOURS_SINGULAR : MSG_IN_HOURS_PLURAL;
450
451
} else if (!future && unit == goog.date.relative.Unit.DAYS) {
452
/**
453
* @desc Relative date indicating how many days ago something happened
454
* (singular).
455
*/
456
var MSG_DAYS_AGO_SINGULAR =
457
goog.getMsg('{$num} day ago', {'num': deltaFormatted});
458
459
/**
460
* @desc Relative date indicating how many days ago something happened
461
* (plural).
462
*/
463
var MSG_DAYS_AGO_PLURAL =
464
goog.getMsg('{$num} days ago', {'num': deltaFormatted});
465
466
return delta == 1 ? MSG_DAYS_AGO_SINGULAR : MSG_DAYS_AGO_PLURAL;
467
468
} else if (future && unit == goog.date.relative.Unit.DAYS) {
469
/**
470
* @desc Relative date indicating in how many days something happens
471
* (singular).
472
*/
473
var MSG_IN_DAYS_SINGULAR =
474
goog.getMsg('in {$num} day', {'num': deltaFormatted});
475
476
/**
477
* @desc Relative date indicating in how many days something happens
478
* (plural).
479
*/
480
var MSG_IN_DAYS_PLURAL =
481
goog.getMsg('in {$num} days', {'num': deltaFormatted});
482
483
return delta == 1 ? MSG_IN_DAYS_SINGULAR : MSG_IN_DAYS_PLURAL;
484
485
} else {
486
return '';
487
}
488
};
489
490
goog.date.relative.setTimeDeltaFormatter(goog.date.relative.getMessage_);
491
492