-
Notifications
You must be signed in to change notification settings - Fork 594
/
datetime.ts
150 lines (124 loc) · 4.29 KB
/
datetime.ts
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
142
143
144
145
146
147
148
149
150
import * as _ from 'lodash-es';
import i18n from 'i18next';
import { getLastLanguage } from '@console/app/src/components/user-preferences/language/getLastLanguage';
// The maximum allowed clock skew in milliseconds where we show a date as "Just now" even if it is from the future.
export const maxClockSkewMS = -60000;
// https://tc39.es/ecma402/#datetimeformat-objects
export const timeFormatter = new Intl.DateTimeFormat(getLastLanguage() || undefined, {
hour: 'numeric',
minute: 'numeric',
});
export const timeFormatterWithSeconds = new Intl.DateTimeFormat(getLastLanguage() || undefined, {
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
});
export const dateFormatter = new Intl.DateTimeFormat(getLastLanguage() || undefined, {
month: 'short',
day: 'numeric',
year: 'numeric',
});
export const dateFormatterNoYear = new Intl.DateTimeFormat(getLastLanguage() || undefined, {
month: 'short',
day: 'numeric',
});
export const dateTimeFormatter = new Intl.DateTimeFormat(getLastLanguage() || undefined, {
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
year: 'numeric',
});
export const dateTimeFormatterWithSeconds = new Intl.DateTimeFormat(
getLastLanguage() || undefined,
{
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
year: 'numeric',
},
);
export const utcDateTimeFormatter = new Intl.DateTimeFormat(getLastLanguage() || undefined, {
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
year: 'numeric',
timeZone: 'UTC',
timeZoneName: 'short',
});
export const relativeTimeFormatter = Intl.RelativeTimeFormat
? new Intl.RelativeTimeFormat(getLastLanguage() || undefined)
: null;
export const getDuration = (ms: number) => {
if (!ms || ms < 0) {
ms = 0;
}
let seconds = Math.floor(ms / 1000);
let minutes = Math.floor(seconds / 60);
seconds = seconds % 60;
let hours = Math.floor(minutes / 60);
minutes = minutes % 60;
const days = Math.floor(hours / 24);
hours = hours % 24;
return { days, hours, minutes, seconds };
};
export const fromNow = (dateTime: string | Date, now?: Date, options?) => {
// Check for null. If dateTime is null, it returns incorrect date Jan 1 1970.
if (!dateTime) {
return '-';
}
if (!now) {
now = new Date();
}
const d = new Date(dateTime);
const ms = now.getTime() - d.getTime();
const justNow = i18n.t('public~Just now');
// If the event occurred less than one minute in the future, assume it's clock drift and show "Just now."
if (!options?.omitSuffix && ms < 60000 && ms > maxClockSkewMS) {
return justNow;
}
// Do not attempt to handle other dates in the future.
if (ms < 0) {
return '-';
}
const { days, hours, minutes } = getDuration(ms);
if (options?.omitSuffix) {
if (days) {
return i18n.t('public~{{count}} day', { count: days });
}
if (hours) {
return i18n.t('public~{{count}} hour', { count: hours });
}
return i18n.t('public~{{count}} minute', { count: minutes });
}
// Fallback to normal date/time formatting if Intl.RelativeTimeFormat is not
// available. This is the case for older Safari versions.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat#browser_compatibility
if (!relativeTimeFormatter) {
return dateTimeFormatter.format(d);
}
if (!days && !hours && !minutes) {
return justNow;
}
if (days) {
return relativeTimeFormatter.format(-days, 'day');
}
if (hours) {
return relativeTimeFormatter.format(-hours, 'hour');
}
return relativeTimeFormatter.format(-minutes, 'minute');
};
export const isValid = (dateTime: Date) => dateTime instanceof Date && !_.isNaN(dateTime.valueOf());
const zeroPad = (number: number) => (number < 10 ? `0${number}` : number);
// Get YYYY-MM-DD date string for a date object
export const toISODateString = (date: Date): string =>
`${date.getFullYear()}-${zeroPad(date.getMonth() + 1)}-${zeroPad(date.getDate())}`;
export const twentyFourHourTime = (date: Date, showSeconds?: boolean): string => {
const hours = zeroPad(date.getHours() ?? 0);
const minutes = `:${zeroPad(date.getMinutes() ?? 0)}`;
const seconds = showSeconds ? `:${zeroPad(date.getSeconds() ?? 0)}` : '';
return `${hours}${minutes}${seconds}`;
};