Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/base/common/date.ts
3292 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { localize } from '../../nls.js';
7
import { Lazy } from './lazy.js';
8
import { LANGUAGE_DEFAULT } from './platform.js';
9
10
const minute = 60;
11
const hour = minute * 60;
12
const day = hour * 24;
13
const week = day * 7;
14
const month = day * 30;
15
const year = day * 365;
16
17
/**
18
* Create a localized difference of the time between now and the specified date.
19
* @param date The date to generate the difference from.
20
* @param appendAgoLabel Whether to append the " ago" to the end.
21
* @param useFullTimeWords Whether to use full words (eg. seconds) instead of
22
* shortened (eg. secs).
23
* @param disallowNow Whether to disallow the string "now" when the difference
24
* is less than 30 seconds.
25
*/
26
export function fromNow(date: number | Date, appendAgoLabel?: boolean, useFullTimeWords?: boolean, disallowNow?: boolean): string {
27
if (typeof date !== 'number') {
28
date = date.getTime();
29
}
30
31
const seconds = Math.round((new Date().getTime() - date) / 1000);
32
if (seconds < -30) {
33
return localize('date.fromNow.in', 'in {0}', fromNow(new Date().getTime() + seconds * 1000, false));
34
}
35
36
if (!disallowNow && seconds < 30) {
37
return localize('date.fromNow.now', 'now');
38
}
39
40
let value: number;
41
if (seconds < minute) {
42
value = seconds;
43
44
if (appendAgoLabel) {
45
if (value === 1) {
46
return useFullTimeWords
47
? localize('date.fromNow.seconds.singular.ago.fullWord', '{0} second ago', value)
48
: localize('date.fromNow.seconds.singular.ago', '{0} sec ago', value);
49
} else {
50
return useFullTimeWords
51
? localize('date.fromNow.seconds.plural.ago.fullWord', '{0} seconds ago', value)
52
: localize('date.fromNow.seconds.plural.ago', '{0} secs ago', value);
53
}
54
} else {
55
if (value === 1) {
56
return useFullTimeWords
57
? localize('date.fromNow.seconds.singular.fullWord', '{0} second', value)
58
: localize('date.fromNow.seconds.singular', '{0} sec', value);
59
} else {
60
return useFullTimeWords
61
? localize('date.fromNow.seconds.plural.fullWord', '{0} seconds', value)
62
: localize('date.fromNow.seconds.plural', '{0} secs', value);
63
}
64
}
65
}
66
67
if (seconds < hour) {
68
value = Math.floor(seconds / minute);
69
if (appendAgoLabel) {
70
if (value === 1) {
71
return useFullTimeWords
72
? localize('date.fromNow.minutes.singular.ago.fullWord', '{0} minute ago', value)
73
: localize('date.fromNow.minutes.singular.ago', '{0} min ago', value);
74
} else {
75
return useFullTimeWords
76
? localize('date.fromNow.minutes.plural.ago.fullWord', '{0} minutes ago', value)
77
: localize('date.fromNow.minutes.plural.ago', '{0} mins ago', value);
78
}
79
} else {
80
if (value === 1) {
81
return useFullTimeWords
82
? localize('date.fromNow.minutes.singular.fullWord', '{0} minute', value)
83
: localize('date.fromNow.minutes.singular', '{0} min', value);
84
} else {
85
return useFullTimeWords
86
? localize('date.fromNow.minutes.plural.fullWord', '{0} minutes', value)
87
: localize('date.fromNow.minutes.plural', '{0} mins', value);
88
}
89
}
90
}
91
92
if (seconds < day) {
93
value = Math.floor(seconds / hour);
94
if (appendAgoLabel) {
95
if (value === 1) {
96
return useFullTimeWords
97
? localize('date.fromNow.hours.singular.ago.fullWord', '{0} hour ago', value)
98
: localize('date.fromNow.hours.singular.ago', '{0} hr ago', value);
99
} else {
100
return useFullTimeWords
101
? localize('date.fromNow.hours.plural.ago.fullWord', '{0} hours ago', value)
102
: localize('date.fromNow.hours.plural.ago', '{0} hrs ago', value);
103
}
104
} else {
105
if (value === 1) {
106
return useFullTimeWords
107
? localize('date.fromNow.hours.singular.fullWord', '{0} hour', value)
108
: localize('date.fromNow.hours.singular', '{0} hr', value);
109
} else {
110
return useFullTimeWords
111
? localize('date.fromNow.hours.plural.fullWord', '{0} hours', value)
112
: localize('date.fromNow.hours.plural', '{0} hrs', value);
113
}
114
}
115
}
116
117
if (seconds < week) {
118
value = Math.floor(seconds / day);
119
if (appendAgoLabel) {
120
return value === 1
121
? localize('date.fromNow.days.singular.ago', '{0} day ago', value)
122
: localize('date.fromNow.days.plural.ago', '{0} days ago', value);
123
} else {
124
return value === 1
125
? localize('date.fromNow.days.singular', '{0} day', value)
126
: localize('date.fromNow.days.plural', '{0} days', value);
127
}
128
}
129
130
if (seconds < month) {
131
value = Math.floor(seconds / week);
132
if (appendAgoLabel) {
133
if (value === 1) {
134
return useFullTimeWords
135
? localize('date.fromNow.weeks.singular.ago.fullWord', '{0} week ago', value)
136
: localize('date.fromNow.weeks.singular.ago', '{0} wk ago', value);
137
} else {
138
return useFullTimeWords
139
? localize('date.fromNow.weeks.plural.ago.fullWord', '{0} weeks ago', value)
140
: localize('date.fromNow.weeks.plural.ago', '{0} wks ago', value);
141
}
142
} else {
143
if (value === 1) {
144
return useFullTimeWords
145
? localize('date.fromNow.weeks.singular.fullWord', '{0} week', value)
146
: localize('date.fromNow.weeks.singular', '{0} wk', value);
147
} else {
148
return useFullTimeWords
149
? localize('date.fromNow.weeks.plural.fullWord', '{0} weeks', value)
150
: localize('date.fromNow.weeks.plural', '{0} wks', value);
151
}
152
}
153
}
154
155
if (seconds < year) {
156
value = Math.floor(seconds / month);
157
if (appendAgoLabel) {
158
if (value === 1) {
159
return useFullTimeWords
160
? localize('date.fromNow.months.singular.ago.fullWord', '{0} month ago', value)
161
: localize('date.fromNow.months.singular.ago', '{0} mo ago', value);
162
} else {
163
return useFullTimeWords
164
? localize('date.fromNow.months.plural.ago.fullWord', '{0} months ago', value)
165
: localize('date.fromNow.months.plural.ago', '{0} mos ago', value);
166
}
167
} else {
168
if (value === 1) {
169
return useFullTimeWords
170
? localize('date.fromNow.months.singular.fullWord', '{0} month', value)
171
: localize('date.fromNow.months.singular', '{0} mo', value);
172
} else {
173
return useFullTimeWords
174
? localize('date.fromNow.months.plural.fullWord', '{0} months', value)
175
: localize('date.fromNow.months.plural', '{0} mos', value);
176
}
177
}
178
}
179
180
value = Math.floor(seconds / year);
181
if (appendAgoLabel) {
182
if (value === 1) {
183
return useFullTimeWords
184
? localize('date.fromNow.years.singular.ago.fullWord', '{0} year ago', value)
185
: localize('date.fromNow.years.singular.ago', '{0} yr ago', value);
186
} else {
187
return useFullTimeWords
188
? localize('date.fromNow.years.plural.ago.fullWord', '{0} years ago', value)
189
: localize('date.fromNow.years.plural.ago', '{0} yrs ago', value);
190
}
191
} else {
192
if (value === 1) {
193
return useFullTimeWords
194
? localize('date.fromNow.years.singular.fullWord', '{0} year', value)
195
: localize('date.fromNow.years.singular', '{0} yr', value);
196
} else {
197
return useFullTimeWords
198
? localize('date.fromNow.years.plural.fullWord', '{0} years', value)
199
: localize('date.fromNow.years.plural', '{0} yrs', value);
200
}
201
}
202
}
203
204
export function fromNowByDay(date: number | Date, appendAgoLabel?: boolean, useFullTimeWords?: boolean): string {
205
if (typeof date !== 'number') {
206
date = date.getTime();
207
}
208
209
const todayMidnightTime = new Date();
210
todayMidnightTime.setHours(0, 0, 0, 0);
211
const yesterdayMidnightTime = new Date(todayMidnightTime.getTime());
212
yesterdayMidnightTime.setDate(yesterdayMidnightTime.getDate() - 1);
213
214
if (date > todayMidnightTime.getTime()) {
215
return localize('today', 'Today');
216
}
217
218
if (date > yesterdayMidnightTime.getTime()) {
219
return localize('yesterday', 'Yesterday');
220
}
221
222
return fromNow(date, appendAgoLabel, useFullTimeWords);
223
}
224
225
/**
226
* Gets a readable duration with intelligent/lossy precision. For example "40ms" or "3.040s")
227
* @param ms The duration to get in milliseconds.
228
* @param useFullTimeWords Whether to use full words (eg. seconds) instead of
229
* shortened (eg. secs).
230
*/
231
export function getDurationString(ms: number, useFullTimeWords?: boolean) {
232
const seconds = Math.abs(ms / 1000);
233
if (seconds < 1) {
234
return useFullTimeWords
235
? localize('duration.ms.full', '{0} milliseconds', ms)
236
: localize('duration.ms', '{0}ms', ms);
237
}
238
if (seconds < minute) {
239
return useFullTimeWords
240
? localize('duration.s.full', '{0} seconds', Math.round(ms) / 1000)
241
: localize('duration.s', '{0}s', Math.round(ms) / 1000);
242
}
243
if (seconds < hour) {
244
return useFullTimeWords
245
? localize('duration.m.full', '{0} minutes', Math.round(ms / (1000 * minute)))
246
: localize('duration.m', '{0} mins', Math.round(ms / (1000 * minute)));
247
}
248
if (seconds < day) {
249
return useFullTimeWords
250
? localize('duration.h.full', '{0} hours', Math.round(ms / (1000 * hour)))
251
: localize('duration.h', '{0} hrs', Math.round(ms / (1000 * hour)));
252
}
253
return localize('duration.d', '{0} days', Math.round(ms / (1000 * day)));
254
}
255
256
export function toLocalISOString(date: Date): string {
257
return date.getFullYear() +
258
'-' + String(date.getMonth() + 1).padStart(2, '0') +
259
'-' + String(date.getDate()).padStart(2, '0') +
260
'T' + String(date.getHours()).padStart(2, '0') +
261
':' + String(date.getMinutes()).padStart(2, '0') +
262
':' + String(date.getSeconds()).padStart(2, '0') +
263
'.' + (date.getMilliseconds() / 1000).toFixed(3).slice(2, 5) +
264
'Z';
265
}
266
267
export const safeIntl = {
268
DateTimeFormat(locales?: Intl.LocalesArgument, options?: Intl.DateTimeFormatOptions): Lazy<Intl.DateTimeFormat> {
269
return new Lazy(() => {
270
try {
271
return new Intl.DateTimeFormat(locales, options);
272
} catch {
273
return new Intl.DateTimeFormat(undefined, options);
274
}
275
});
276
},
277
Collator(locales?: Intl.LocalesArgument, options?: Intl.CollatorOptions): Lazy<Intl.Collator> {
278
return new Lazy(() => {
279
try {
280
return new Intl.Collator(locales, options);
281
} catch {
282
return new Intl.Collator(undefined, options);
283
}
284
});
285
},
286
Segmenter(locales?: Intl.LocalesArgument, options?: Intl.SegmenterOptions): Lazy<Intl.Segmenter> {
287
return new Lazy(() => {
288
try {
289
return new Intl.Segmenter(locales, options);
290
} catch {
291
return new Intl.Segmenter(undefined, options);
292
}
293
});
294
},
295
Locale(tag: Intl.Locale | string, options?: Intl.LocaleOptions): Lazy<Intl.Locale> {
296
return new Lazy(() => {
297
try {
298
return new Intl.Locale(tag, options);
299
} catch {
300
return new Intl.Locale(LANGUAGE_DEFAULT, options);
301
}
302
});
303
},
304
NumberFormat(locales?: Intl.LocalesArgument, options?: Intl.NumberFormatOptions): Lazy<Intl.NumberFormat> {
305
return new Lazy(() => {
306
try {
307
return new Intl.NumberFormat(locales, options);
308
} catch {
309
return new Intl.NumberFormat(undefined, options);
310
}
311
});
312
}
313
};
314
315