-
-
Notifications
You must be signed in to change notification settings - Fork 92
Expand file tree
/
Copy pathdeadline.ts
More file actions
101 lines (87 loc) · 2.57 KB
/
deadline.ts
File metadata and controls
101 lines (87 loc) · 2.57 KB
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
import { type CalendarDate, parseDate } from "@internationalized/date";
import type { Deadline as ApiDeadline } from "@/api/domain/task";
import { t } from "@/i18n";
import { locale } from "@/infra/locale";
import { timezone, today } from "@/infra/time";
export type DeadlineInfo = {
raw: Date;
isOverdue: boolean;
isCurrentYear: boolean;
flag: "today" | "tomorrow" | "nextWeek" | "yesterday" | "lastWeek" | undefined;
};
const parseDeadline = (deadline: ApiDeadline): DeadlineInfo => {
const date = parseDate(deadline.date);
return calculateDeadlineInfo(date);
};
const calculateDeadlineInfo = (date: CalendarDate): DeadlineInfo => {
let flag: DeadlineInfo["flag"];
if (date.compare(today()) === 0) {
flag = "today";
} else if (date.compare(today().add({ days: 1 })) === 0) {
flag = "tomorrow";
} else if (date.compare(today().add({ days: -1 })) === 0) {
flag = "yesterday";
} else if (date.compare(today().add({ days: -7 })) >= 0 && date.compare(today()) < 0) {
flag = "lastWeek";
} else if (date.compare(today().add({ days: 7 })) <= 0 && date.compare(today()) > 0) {
flag = "nextWeek";
}
return {
raw: date.toDate(timezone()),
isOverdue: date.compare(today()) < 0,
isCurrentYear: date.year === today().year,
flag,
};
};
const getFormatter: (style: string) => Intl.DateTimeFormat = (() => {
const styles: Record<string, Intl.DateTimeFormatOptions> = {
weekday: {
weekday: "long",
},
date: {
month: "short",
day: "numeric",
},
dateWithYear: {
month: "short",
day: "numeric",
year: "numeric",
},
};
const cache: Record<string, Intl.DateTimeFormat> = {};
return (style: string): Intl.DateTimeFormat => {
if (cache[style]) {
return cache[style];
}
cache[style] = new Intl.DateTimeFormat(locale(), {
timeZone: timezone(),
...styles[style],
});
return cache[style];
};
})();
const formatDeadline = (info: DeadlineInfo): string => {
const i18n = t().dates;
switch (info.flag) {
case "today":
return i18n.today;
case "tomorrow":
return i18n.tomorrow;
case "yesterday":
return i18n.yesterday;
case "lastWeek":
return i18n.lastWeekday(getFormatter("weekday").format(info.raw));
case "nextWeek":
return getFormatter("weekday").format(info.raw);
default:
break;
}
if (!info.isCurrentYear) {
return getFormatter("dateWithYear").format(info.raw);
}
return getFormatter("date").format(info.raw);
};
export const Deadline = {
parse: parseDeadline,
format: formatDeadline,
};