[READ-ONLY] Mirror of https://github.com/flo-bit/skywatched. review movies and tv shows, based on at proto
skywatched.app
2.1 kB
75 lines
1export type Callback = (result: {
2 seconds: number;
3 count: number;
4 units: Intl.RelativeTimeFormatUnit;
5 text: string;
6}) => void;
7
8export interface RenderState {
9 date: Date | number;
10 callback: Callback;
11 formatter: Intl.RelativeTimeFormat;
12}
13
14// Array reprsenting one minute, hour, day, week, month, etc in seconds
15const cutoffs = [60, 3600, 86400, 86400 * 7, 86400 * 30, 86400 * 365, Infinity];
16
17// Array equivalent to the above but in the string representation of the units
18const formatUnits: Intl.RelativeTimeFormatUnit[] = [
19 'seconds',
20 'minutes',
21 'hours',
22 'days',
23 'weeks',
24 'months',
25 'years'
26];
27
28// function to render relative time into
29export function render(state: RenderState, now: number) {
30 const { date, callback, formatter } = state;
31
32 // Allow dates or times to be passed
33 const timeMs = typeof date === 'number' ? date : date.getTime();
34
35 // Get the amount of seconds between the given date and now
36 const delta = timeMs - now;
37 const seconds = Math.round(delta / 1000);
38
39 // Grab the ideal cutoff unit
40 const unitIndex = cutoffs.findIndex((cutoff) => cutoff > Math.abs(seconds));
41
42 // units
43 const units = formatUnits[unitIndex];
44
45 // Get the divisor to divide from the seconds. E.g. if our unit is 'day' our divisor
46 // is one day in seconds, so we can divide our seconds by this to get the # of days
47 const divisor = unitIndex ? cutoffs[unitIndex - 1] : 1;
48
49 // count of units
50 const count = Math.round(seconds / divisor);
51
52 // Intl.RelativeTimeFormat do its magic
53 callback({ seconds: seconds, count, units, text: formatter.format(count, units) });
54
55 // calculate time to next update, taking account rounding (e.g. it goes from 2 minutes to 1 minute at 90 seconds)
56 // and also the changeover from units (59 seconds shouldn't show as 1 minute, so at 61 seconds we schedule the next
57 // update for 1 second time)
58
59 const divisorMs = divisor * 1000;
60
61 let updateIn;
62
63 if (unitIndex) {
64 updateIn = divisorMs / 2 - (Math.abs(delta) % divisorMs);
65 if (updateIn < 0) {
66 updateIn += divisorMs;
67 }
68 } else {
69 updateIn = divisorMs - (Math.abs(delta) % divisorMs);
70 }
71
72 const updateAt = now + updateIn;
73
74 return updateAt;
75}