1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
/* -*- Mode: js; js-indent-level: 2; indent-tabs-mode: nil -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
'use strict';
/**
* This lib relies on `l10n.js' to implement localizable date/time strings.
*
* The proposed `DateTimeFormat' object should provide all the features that are
* planned for the `Intl.DateTimeFormat' constructor, but the API does not match
* exactly the ES-i18n draft.
* - https://bugzilla.mozilla.org/show_bug.cgi?id=769872
* - http://wiki.ecmascript.org/doku.php?id=globalization:specification_drafts
*
* Besides, this `DateTimeFormat' object provides two features that aren't
* planned in the ES-i18n spec:
* - a `toLocaleFormat()' that really works (i.e. fully translated);
* - a `fromNow()' method to handle relative dates ("pretty dates").
*
* WARNING: this library relies on the non-standard `toLocaleFormat()' method,
* which is specific to Firefox -- no other browser is supported.
*/
navigator.mozL10n.DateTimeFormat = function(locales, options) {
var _ = navigator.mozL10n.get;
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date/toLocaleFormat
function localeFormat(d, format) {
var tokens = format.match(/(%E.|%O.|%.)/g);
for (var i = 0; tokens && i < tokens.length; i++) {
var value = '';
// http://pubs.opengroup.org/onlinepubs/007908799/xsh/strftime.html
switch (tokens[i]) {
// localized day/month names
case '%a':
value = _('weekday-' + d.getDay() + '-short');
break;
case '%A':
value = _('weekday-' + d.getDay() + '-long');
break;
case '%b':
case '%h':
value = _('month-' + d.getMonth() + '-short');
break;
case '%B':
value = _('month-' + d.getMonth() + '-long');
break;
// like %H, but in 12-hour format and without any leading zero
case '%I':
value = d.getHours() % 12 || 12;
break;
// like %d, without any leading zero
case '%e':
value = d.getDate();
break;
// localized date/time strings
case '%c':
case '%x':
case '%X':
// ensure the localized format string doesn't contain any %c|%x|%X
var tmp = _('dateTimeFormat_' + tokens[i]);
if (tmp && !(/(%c|%x|%X)/).test(tmp)) {
value = localeFormat(d, tmp);
}
break;
// other tokens don't require any localization
}
format = format.replace(tokens[i], value || d.toLocaleFormat(tokens[i]));
}
return format;
}
// variant of John Resig's PrettyDate.js
function prettyDate(time, useCompactFormat) {
switch (time.constructor) {
case String: // timestamp
time = parseInt(time);
break;
case Date:
time = time.getTime();
break;
}
var secDiff = (Date.now() - time) / 1000;
if (isNaN(secDiff)) {
return _('incorrectDate');
}
var f = useCompactFormat ? '-short' : '-long';
if (secDiff >= 0) { // past
var dayDiff = Math.floor(secDiff / 86400);
if (secDiff < 3600) {
return _('minutesAgo' + f, { m: Math.floor(secDiff / 60) });
} else if (dayDiff === 0) {
return _('hoursAgo' + f, { h: Math.floor(secDiff / 3600) });
} else if (dayDiff < 10) {
return _('daysAgo' + f, { d: dayDiff });
}
}
if (secDiff < 0) { // future
secDiff = -secDiff;
dayDiff = Math.floor(secDiff / 86400);
if (secDiff < 3600) {
return _('inMinutes' + f, { m: Math.floor(secDiff / 60) });
} else if (dayDiff === 0) {
return _('inHours' + f, { h: Math.floor(secDiff / 3600) });
} else if (dayDiff < 10) {
return _('inDays' + f, { d: dayDiff });
}
}
// too far: return an absolute date
return localeFormat(new Date(time), '%x');
}
// API
return {
localeDateString: function localeDateString(d) {
return localeFormat(d, '%x');
},
localeTimeString: function localeTimeString(d) {
return localeFormat(d, '%X');
},
localeString: function localeString(d) {
return localeFormat(d, '%c');
},
localeFormat: localeFormat,
fromNow: prettyDate
};
};
|