-
Notifications
You must be signed in to change notification settings - Fork 22
/
time.ts
88 lines (78 loc) · 3.01 KB
/
time.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
import { DateTime } from 'luxon'
const secPerDay = 24 * 60 * 60
export const secondsToWdhms = (
seconds: string | number,
// Set to 5 or more to display all units.
numUnits = 2
): string => {
const secondsInt = Math.ceil(Number(seconds))
if (secondsInt === 0) {
return '0 seconds'
}
const w = Math.floor(secondsInt / (secPerDay * 7))
const d = Math.floor((secondsInt % (secPerDay * 7)) / secPerDay)
const h = Math.floor((secondsInt % secPerDay) / 3600)
const m = Math.floor((secondsInt % 3600) / 60)
const s = Math.floor(secondsInt % 60)
const wDisplay = w ? w + ' ' + 'week' + (w === 1 ? '' : 's') : null
const dDisplay = d ? d + ' day' + (d === 1 ? '' : 's') : null
const hDisplay = h ? h + ' ' + 'hour' + (h === 1 ? '' : 's') : null
const mDisplay = m ? m + ' ' + 'minute' + (m === 1 ? '' : 's') : null
const sDisplay = s ? s + ' ' + 'second' + (s === 1 ? '' : 's') : null
return (
[wDisplay, dDisplay, hDisplay, mDisplay, sDisplay]
// Ignore empty values.
.filter(Boolean)
// Only keep certain precision of units.
.slice(0, numUnits)
// Separate with commas.
.join(', ')
)
}
// Converts Date to string from the current point with no sign.
// Example: dateToWdhms(new Date(Date.now() + 1000)) === '1 second'
// dateToWdhms(new Date(Date.now() - 1000)) === '1 second'
export const dateToWdhms = (date: Date, numUnits = 2) =>
secondsToWdhms(Math.abs(date.getTime() - Date.now()) / 1000, numUnits)
// Converts number in seconds to time format mm:ss. Clock format.
export const secondsToMmSs = (seconds: number) =>
`${Math.floor(seconds / 60)}:${`0${Math.floor(seconds % 60)}`.slice(-2)}`
/**
* Get the most recent value at or before the given timestamp.
*
* @param data An array of values sorted by timestamp in ascending order.
* @param timestamp The timestamp to find the value at or before.
* @returns The most recent value at or before the given timestamp.
*/
export const findValueAtTimestamp = <Value extends { timestamp: number }>(
data: Value[],
timestamp: number
): Value | undefined => {
// Find the most recent value at or before this timestamp. Since they are
// ascending, get the first one after the timestamp, and then choose the one
// before.
const nextIndex = data.findIndex(
({ timestamp: dataTimestamp }) => dataTimestamp > timestamp
)
// If there is no value after this timestamp, use the last value.
return nextIndex === -1
? data[data.length - 1]
: // If the first value is after this timestamp, there is no matching item.
nextIndex === 0
? undefined
: // Otherwise just use the previous value.
data[nextIndex - 1]
}
/**
* Check whether or not the browser uses 12-hour time with AM/PM.
*/
export const browserIs12Hour = () =>
new Intl.DateTimeFormat(navigator.language, {
hour: 'numeric',
})
.formatToParts()
.some((part) => part.type === 'dayPeriod')
/**
* Get current browser's time zone abbreviation.
*/
export const browserTimeZone = () => DateTime.local().toFormat('ZZZZ')