src/vs/base/common/date.ts

317 LOC · 156 covered · 161 uncovered · 53 ranges · 3570 concepts · 18 introducers · 1919 tests

File neighbourhood

The centred file is linked to every concept that introduces one of its ranges, every test that runs code from the file, and the gray connector concepts standing between those tests and the file's own introducer concepts. Undirected links join concepts to every file where they introduce source and concepts to the tests they introduce; arrows show specialization between the displayed concepts and bridge only concepts omitted from this view. Concept colors match the source ranges below; connector concepts have no source color and are shown in gray.

Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the file

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the related-file, concept, and source links on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the related-file, concept, and source links on this page while the interactive map is unavailable.

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