@yangsaiyam/helper 1.11.3 → 1.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addressess/index.d.ts +137 -0
- package/dist/addressess/index.js +24 -0
- package/dist/addressess/index.test.d.ts +1 -0
- package/dist/addressess/index.test.js +16 -0
- package/dist/assessment-question/index.d.ts +19 -0
- package/dist/assessment-question/index.js +22 -0
- package/dist/assessment-question/index.test.d.ts +1 -0
- package/dist/assessment-question/index.test.js +27 -0
- package/dist/career/index.d.ts +132 -0
- package/dist/career/index.js +40 -0
- package/dist/contact-form/index.d.ts +13 -0
- package/dist/contact-form/index.js +13 -0
- package/dist/email-template/index.d.ts +13 -0
- package/dist/email-template/index.js +5 -0
- package/dist/files/index.d.ts +18 -0
- package/dist/files/index.js +8 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +16 -0
- package/dist/job-applications/index.d.ts +33 -0
- package/dist/job-applications/index.js +10 -0
- package/dist/locale/index.d.ts +9 -0
- package/dist/locale/index.js +4 -0
- package/dist/roles/index.d.ts +61 -0
- package/dist/roles/index.js +170 -0
- package/dist/roles/index.test.d.ts +1 -0
- package/dist/roles/index.test.js +80 -0
- package/dist/routes/index.d.ts +80 -0
- package/dist/routes/index.js +106 -0
- package/dist/routes/index.test.d.ts +1 -0
- package/dist/routes/index.test.js +92 -0
- package/dist/shared/helpers.d.ts +5 -0
- package/dist/shared/helpers.js +15 -0
- package/dist/shared/types.d.ts +5 -0
- package/dist/shared/types.js +1 -0
- package/dist/src/addressess/index.d.ts +137 -0
- package/dist/src/addressess/index.js +24 -0
- package/dist/src/addressess/index.test.d.ts +1 -0
- package/dist/src/addressess/index.test.js +16 -0
- package/dist/src/assessment-question/index.d.ts +19 -0
- package/dist/src/assessment-question/index.js +22 -0
- package/dist/src/assessment-question/index.test.d.ts +1 -0
- package/dist/src/assessment-question/index.test.js +27 -0
- package/dist/src/career/index.d.ts +132 -0
- package/dist/src/career/index.js +40 -0
- package/dist/src/contact-form/index.d.ts +13 -0
- package/dist/src/contact-form/index.js +13 -0
- package/dist/src/email-template/index.d.ts +13 -0
- package/dist/src/email-template/index.js +5 -0
- package/dist/src/files/index.d.ts +18 -0
- package/dist/src/files/index.js +8 -0
- package/dist/src/index.d.ts +16 -0
- package/dist/src/index.js +16 -0
- package/dist/src/job-applications/index.d.ts +33 -0
- package/dist/src/job-applications/index.js +10 -0
- package/dist/src/locale/index.d.ts +9 -0
- package/dist/src/locale/index.js +4 -0
- package/dist/src/roles/index.d.ts +61 -0
- package/dist/src/roles/index.js +170 -0
- package/dist/src/roles/index.test.d.ts +1 -0
- package/dist/src/roles/index.test.js +80 -0
- package/dist/src/routes/index.d.ts +80 -0
- package/dist/src/routes/index.js +106 -0
- package/dist/src/routes/index.test.d.ts +1 -0
- package/dist/src/routes/index.test.js +92 -0
- package/dist/src/shared/helpers.d.ts +5 -0
- package/dist/src/shared/helpers.js +15 -0
- package/dist/src/shared/types.d.ts +5 -0
- package/dist/src/shared/types.js +1 -0
- package/dist/src/time/index.d.ts +73 -0
- package/dist/src/time/index.js +161 -0
- package/dist/src/time/index.test.d.ts +1 -0
- package/dist/src/time/index.test.js +35 -0
- package/dist/src/track/index.d.ts +17 -0
- package/dist/src/track/index.js +14 -0
- package/dist/src/track/index.test.d.ts +1 -0
- package/dist/src/track/index.test.js +7 -0
- package/dist/src/url-prefix/index.d.ts +8 -0
- package/dist/src/url-prefix/index.js +9 -0
- package/dist/src/website/index.d.ts +16 -0
- package/dist/src/website/index.js +17 -0
- package/dist/time/index.d.ts +73 -0
- package/dist/time/index.js +161 -0
- package/dist/time/index.test.d.ts +1 -0
- package/dist/time/index.test.js +35 -0
- package/dist/track/index.d.ts +17 -0
- package/dist/track/index.js +14 -0
- package/dist/track/index.test.d.ts +1 -0
- package/dist/track/index.test.js +7 -0
- package/dist/url-prefix/index.d.ts +8 -0
- package/dist/url-prefix/index.js +9 -0
- package/dist/website/index.d.ts +16 -0
- package/dist/website/index.js +17 -0
- package/package.json +1 -1
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import dayjs from "dayjs";
|
|
2
|
+
import timezone from "dayjs/plugin/timezone.js";
|
|
3
|
+
import utc from "dayjs/plugin/utc.js";
|
|
4
|
+
dayjs.extend(utc);
|
|
5
|
+
dayjs.extend(timezone);
|
|
6
|
+
export const TIMEZONE = [
|
|
7
|
+
{ key: 1, value: "UTC", i18nKey: "time.timezone.utc" },
|
|
8
|
+
{
|
|
9
|
+
key: 2,
|
|
10
|
+
value: "Asia/Kuala_Lumpur",
|
|
11
|
+
i18nKey: "time.timezone.asiaKualaLumpur",
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
key: 3,
|
|
15
|
+
value: "Asia/Singapore",
|
|
16
|
+
i18nKey: "time.timezone.asiaSingapore",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
key: 4,
|
|
20
|
+
value: "Asia/Bangkok",
|
|
21
|
+
i18nKey: "time.timezone.asiaBangkok",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
key: 5,
|
|
25
|
+
value: "Asia/Jakarta",
|
|
26
|
+
i18nKey: "time.timezone.asiaJakarta",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
key: 6,
|
|
30
|
+
value: "Asia/Manila",
|
|
31
|
+
i18nKey: "time.timezone.asiaManila",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
key: 7,
|
|
35
|
+
value: "Asia/Hong_Kong",
|
|
36
|
+
i18nKey: "time.timezone.asiaHongKong",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
key: 8,
|
|
40
|
+
value: "Asia/Shanghai",
|
|
41
|
+
i18nKey: "time.timezone.asiaShanghai",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
key: 9,
|
|
45
|
+
value: "Asia/Tokyo",
|
|
46
|
+
i18nKey: "time.timezone.asiaTokyo",
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
key: 10,
|
|
50
|
+
value: "Australia/Sydney",
|
|
51
|
+
i18nKey: "time.timezone.australiaSydney",
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
key: 11,
|
|
55
|
+
value: "Europe/London",
|
|
56
|
+
i18nKey: "time.timezone.europeLondon",
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
key: 12,
|
|
60
|
+
value: "Europe/Berlin",
|
|
61
|
+
i18nKey: "time.timezone.europeBerlin",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
key: 13,
|
|
65
|
+
value: "America/New_York",
|
|
66
|
+
i18nKey: "time.timezone.americaNewYork",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
key: 14,
|
|
70
|
+
value: "America/Chicago",
|
|
71
|
+
i18nKey: "time.timezone.americaChicago",
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
key: 15,
|
|
75
|
+
value: "America/Denver",
|
|
76
|
+
i18nKey: "time.timezone.americaDenver",
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
key: 16,
|
|
80
|
+
value: "America/Los_Angeles",
|
|
81
|
+
i18nKey: "time.timezone.americaLosAngeles",
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
const TIMEZONE_ALIAS_TO_CANONICAL = {
|
|
85
|
+
utc: "UTC",
|
|
86
|
+
"etc/utc": "UTC",
|
|
87
|
+
"asia/kuala_lumpur": "Asia/Kuala_Lumpur",
|
|
88
|
+
"asia/kuala lumpur": "Asia/Kuala_Lumpur",
|
|
89
|
+
"kuala_lumpur": "Asia/Kuala_Lumpur",
|
|
90
|
+
"kuala lumpur": "Asia/Kuala_Lumpur",
|
|
91
|
+
"asia/singapore": "Asia/Singapore",
|
|
92
|
+
singapore: "Asia/Singapore",
|
|
93
|
+
"asia/bangkok": "Asia/Bangkok",
|
|
94
|
+
bangkok: "Asia/Bangkok",
|
|
95
|
+
"asia/jakarta": "Asia/Jakarta",
|
|
96
|
+
jakarta: "Asia/Jakarta",
|
|
97
|
+
"asia/manila": "Asia/Manila",
|
|
98
|
+
manila: "Asia/Manila",
|
|
99
|
+
"asia/hong_kong": "Asia/Hong_Kong",
|
|
100
|
+
"asia/hong kong": "Asia/Hong_Kong",
|
|
101
|
+
"hong_kong": "Asia/Hong_Kong",
|
|
102
|
+
"hong kong": "Asia/Hong_Kong",
|
|
103
|
+
"asia/shanghai": "Asia/Shanghai",
|
|
104
|
+
shanghai: "Asia/Shanghai",
|
|
105
|
+
"asia/tokyo": "Asia/Tokyo",
|
|
106
|
+
tokyo: "Asia/Tokyo",
|
|
107
|
+
"australia/sydney": "Australia/Sydney",
|
|
108
|
+
sydney: "Australia/Sydney",
|
|
109
|
+
"europe/london": "Europe/London",
|
|
110
|
+
london: "Europe/London",
|
|
111
|
+
"europe/berlin": "Europe/Berlin",
|
|
112
|
+
berlin: "Europe/Berlin",
|
|
113
|
+
"america/new_york": "America/New_York",
|
|
114
|
+
"america/new york": "America/New_York",
|
|
115
|
+
"new_york": "America/New_York",
|
|
116
|
+
"new york": "America/New_York",
|
|
117
|
+
"america/chicago": "America/Chicago",
|
|
118
|
+
chicago: "America/Chicago",
|
|
119
|
+
"america/denver": "America/Denver",
|
|
120
|
+
denver: "America/Denver",
|
|
121
|
+
"america/los_angeles": "America/Los_Angeles",
|
|
122
|
+
"america/los angeles": "America/Los_Angeles",
|
|
123
|
+
"los_angeles": "America/Los_Angeles",
|
|
124
|
+
"los angeles": "America/Los_Angeles",
|
|
125
|
+
};
|
|
126
|
+
const TIMEZONE_I18N_KEY = Object.fromEntries(TIMEZONE.map(({ value, i18nKey }) => [value, i18nKey]));
|
|
127
|
+
function toTimezoneAlias(timezone) {
|
|
128
|
+
return timezone.trim().toLowerCase().replace(/-/g, "_");
|
|
129
|
+
}
|
|
130
|
+
export function normalizeTimezone(timezone) {
|
|
131
|
+
if (!timezone) {
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
return TIMEZONE_ALIAS_TO_CANONICAL[toTimezoneAlias(timezone)];
|
|
135
|
+
}
|
|
136
|
+
export function timezoneToUtc(timezone, timestamp = Date.now()) {
|
|
137
|
+
const normalizedTimezone = normalizeTimezone(timezone);
|
|
138
|
+
if (!normalizedTimezone) {
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
return `UTC${dayjs(timestamp).tz(normalizedTimezone).format("Z")}`;
|
|
142
|
+
}
|
|
143
|
+
export const TIMEZONE_CURRENT_UTC_OFFSET = Object.fromEntries(TIMEZONE.map(({ value }) => [value, timezoneToUtc(value)]));
|
|
144
|
+
export const TIMEZONE_TO_UTC = TIMEZONE_CURRENT_UTC_OFFSET;
|
|
145
|
+
export function timezoneLabelKey(timezone) {
|
|
146
|
+
const normalizedTimezone = normalizeTimezone(timezone);
|
|
147
|
+
if (!normalizedTimezone) {
|
|
148
|
+
return "time.timezone.utc";
|
|
149
|
+
}
|
|
150
|
+
return TIMEZONE_I18N_KEY[normalizedTimezone];
|
|
151
|
+
}
|
|
152
|
+
export function convertTimestampToTimezone(timestamp, sourceTimezone, targetTimezone) {
|
|
153
|
+
const normalizedSourceTimezone = normalizeTimezone(sourceTimezone);
|
|
154
|
+
const normalizedTargetTimezone = normalizeTimezone(targetTimezone);
|
|
155
|
+
if (!normalizedSourceTimezone || !normalizedTargetTimezone) {
|
|
156
|
+
return undefined;
|
|
157
|
+
}
|
|
158
|
+
const sourceDateTime = dayjs(timestamp).tz(normalizedSourceTimezone);
|
|
159
|
+
const preservedWallClock = sourceDateTime.format("YYYY-MM-DDTHH:mm:ss.SSS");
|
|
160
|
+
return dayjs.tz(preservedWallClock, normalizedTargetTimezone).valueOf();
|
|
161
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { convertTimestampToTimezone, TIMEZONE, TIMEZONE_CURRENT_UTC_OFFSET, TIMEZONE_TO_UTC, normalizeTimezone, timezoneLabelKey, timezoneToUtc, } from "./index";
|
|
3
|
+
assert.equal(normalizeTimezone("UTC"), "UTC");
|
|
4
|
+
assert.equal(normalizeTimezone("utc"), "UTC");
|
|
5
|
+
assert.equal(normalizeTimezone("Etc/UTC"), "UTC");
|
|
6
|
+
assert.equal(normalizeTimezone("Asia/Kuala_Lumpur"), "Asia/Kuala_Lumpur");
|
|
7
|
+
assert.equal(normalizeTimezone("asia/kuala lumpur"), "Asia/Kuala_Lumpur");
|
|
8
|
+
assert.equal(normalizeTimezone("singapore"), "Asia/Singapore");
|
|
9
|
+
assert.equal(normalizeTimezone("unknown"), undefined);
|
|
10
|
+
assert.equal(normalizeTimezone(undefined), undefined);
|
|
11
|
+
assert.equal(timezoneToUtc("UTC"), "UTC+00:00");
|
|
12
|
+
assert.equal(timezoneToUtc("Etc/UTC"), "UTC+00:00");
|
|
13
|
+
assert.equal(timezoneToUtc("Asia/Kuala_Lumpur"), "UTC+08:00");
|
|
14
|
+
assert.equal(timezoneToUtc("kuala lumpur"), "UTC+08:00");
|
|
15
|
+
assert.equal(timezoneToUtc("America/New_York", Date.UTC(2024, 0, 1, 12, 0, 0)), "UTC-05:00");
|
|
16
|
+
assert.equal(timezoneToUtc("America/New_York", Date.UTC(2024, 6, 1, 12, 0, 0)), "UTC-04:00");
|
|
17
|
+
assert.equal(timezoneToUtc("unknown"), undefined);
|
|
18
|
+
assert.equal(timezoneLabelKey("UTC"), "time.timezone.utc");
|
|
19
|
+
assert.equal(timezoneLabelKey("Asia/Singapore"), "time.timezone.asiaSingapore");
|
|
20
|
+
assert.equal(timezoneLabelKey(undefined), "time.timezone.utc");
|
|
21
|
+
assert.deepEqual(TIMEZONE[0], {
|
|
22
|
+
key: 1,
|
|
23
|
+
value: "UTC",
|
|
24
|
+
i18nKey: "time.timezone.utc",
|
|
25
|
+
});
|
|
26
|
+
assert.equal(TIMEZONE[2]?.value, "Asia/Singapore");
|
|
27
|
+
assert.equal(TIMEZONE_CURRENT_UTC_OFFSET.UTC, "UTC+00:00");
|
|
28
|
+
assert.equal(TIMEZONE_CURRENT_UTC_OFFSET["Asia/Kuala_Lumpur"], "UTC+08:00");
|
|
29
|
+
assert.equal(TIMEZONE_TO_UTC, TIMEZONE_CURRENT_UTC_OFFSET);
|
|
30
|
+
const utcNineAm = Date.UTC(2024, 0, 1, 9, 0, 0);
|
|
31
|
+
const klNineAm = Date.UTC(2024, 0, 1, 1, 0, 0);
|
|
32
|
+
assert.equal(convertTimestampToTimezone(utcNineAm, "UTC", "Asia/Kuala_Lumpur"), Date.UTC(2024, 0, 1, 1, 0, 0));
|
|
33
|
+
assert.equal(convertTimestampToTimezone(klNineAm, "Asia/Kuala_Lumpur", "America/New_York"), Date.UTC(2024, 0, 1, 14, 0, 0));
|
|
34
|
+
assert.equal(convertTimestampToTimezone(utcNineAm, "unknown", "Asia/Kuala_Lumpur"), undefined);
|
|
35
|
+
assert.equal(convertTimestampToTimezone(utcNineAm, "UTC", "unknown"), undefined);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const ORIGIN: readonly [{
|
|
2
|
+
readonly key: 0;
|
|
3
|
+
readonly value: "Website";
|
|
4
|
+
readonly i18nKey: "track.origin.0";
|
|
5
|
+
}, {
|
|
6
|
+
readonly key: 1;
|
|
7
|
+
readonly value: "Linkedin";
|
|
8
|
+
readonly i18nKey: "track.origin.1";
|
|
9
|
+
}, {
|
|
10
|
+
readonly key: 2;
|
|
11
|
+
readonly value: "Jobstreet";
|
|
12
|
+
readonly i18nKey: "track.origin.2";
|
|
13
|
+
}, {
|
|
14
|
+
readonly key: 3;
|
|
15
|
+
readonly value: "Maukerja";
|
|
16
|
+
readonly i18nKey: "track.origin.3";
|
|
17
|
+
}];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const ORIGIN = [
|
|
2
|
+
{
|
|
3
|
+
key: 0,
|
|
4
|
+
value: "Website",
|
|
5
|
+
i18nKey: "track.origin.0",
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
key: 1,
|
|
9
|
+
value: "Linkedin",
|
|
10
|
+
i18nKey: "track.origin.1",
|
|
11
|
+
},
|
|
12
|
+
{ key: 2, value: "Jobstreet", i18nKey: "track.origin.2" },
|
|
13
|
+
{ key: 3, value: "Maukerja", i18nKey: "track.origin.3" },
|
|
14
|
+
];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Website } from "../website";
|
|
2
|
+
export const URL_PREFIXES = {
|
|
3
|
+
[Website.KORRE]: {
|
|
4
|
+
contact: "https://www.korre.site/contact",
|
|
5
|
+
careerDetail: "https://www.korre.site/career/[id]",
|
|
6
|
+
careerApply: "https://www.korre.site/career/[id]/apply",
|
|
7
|
+
},
|
|
8
|
+
[Website.KORRE_LABS]: {},
|
|
9
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export var Website;
|
|
2
|
+
(function (Website) {
|
|
3
|
+
Website[Website["KORRE"] = 1] = "KORRE";
|
|
4
|
+
Website[Website["KORRE_LABS"] = 2] = "KORRE_LABS";
|
|
5
|
+
})(Website || (Website = {}));
|
|
6
|
+
export const WEBSITES = {
|
|
7
|
+
[Website.KORRE]: {
|
|
8
|
+
id: Website.KORRE,
|
|
9
|
+
name: "Korre Evolution",
|
|
10
|
+
url: "https://public.korre.site/images/korre-evo.png",
|
|
11
|
+
},
|
|
12
|
+
[Website.KORRE_LABS]: {
|
|
13
|
+
id: Website.KORRE_LABS,
|
|
14
|
+
name: "Korre Labs",
|
|
15
|
+
url: "https://public.korre.site/images/korre-labs.png",
|
|
16
|
+
},
|
|
17
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export declare const TIMEZONE: readonly [{
|
|
2
|
+
readonly key: 1;
|
|
3
|
+
readonly value: "UTC";
|
|
4
|
+
readonly i18nKey: "time.timezone.utc";
|
|
5
|
+
}, {
|
|
6
|
+
readonly key: 2;
|
|
7
|
+
readonly value: "Asia/Kuala_Lumpur";
|
|
8
|
+
readonly i18nKey: "time.timezone.asiaKualaLumpur";
|
|
9
|
+
}, {
|
|
10
|
+
readonly key: 3;
|
|
11
|
+
readonly value: "Asia/Singapore";
|
|
12
|
+
readonly i18nKey: "time.timezone.asiaSingapore";
|
|
13
|
+
}, {
|
|
14
|
+
readonly key: 4;
|
|
15
|
+
readonly value: "Asia/Bangkok";
|
|
16
|
+
readonly i18nKey: "time.timezone.asiaBangkok";
|
|
17
|
+
}, {
|
|
18
|
+
readonly key: 5;
|
|
19
|
+
readonly value: "Asia/Jakarta";
|
|
20
|
+
readonly i18nKey: "time.timezone.asiaJakarta";
|
|
21
|
+
}, {
|
|
22
|
+
readonly key: 6;
|
|
23
|
+
readonly value: "Asia/Manila";
|
|
24
|
+
readonly i18nKey: "time.timezone.asiaManila";
|
|
25
|
+
}, {
|
|
26
|
+
readonly key: 7;
|
|
27
|
+
readonly value: "Asia/Hong_Kong";
|
|
28
|
+
readonly i18nKey: "time.timezone.asiaHongKong";
|
|
29
|
+
}, {
|
|
30
|
+
readonly key: 8;
|
|
31
|
+
readonly value: "Asia/Shanghai";
|
|
32
|
+
readonly i18nKey: "time.timezone.asiaShanghai";
|
|
33
|
+
}, {
|
|
34
|
+
readonly key: 9;
|
|
35
|
+
readonly value: "Asia/Tokyo";
|
|
36
|
+
readonly i18nKey: "time.timezone.asiaTokyo";
|
|
37
|
+
}, {
|
|
38
|
+
readonly key: 10;
|
|
39
|
+
readonly value: "Australia/Sydney";
|
|
40
|
+
readonly i18nKey: "time.timezone.australiaSydney";
|
|
41
|
+
}, {
|
|
42
|
+
readonly key: 11;
|
|
43
|
+
readonly value: "Europe/London";
|
|
44
|
+
readonly i18nKey: "time.timezone.europeLondon";
|
|
45
|
+
}, {
|
|
46
|
+
readonly key: 12;
|
|
47
|
+
readonly value: "Europe/Berlin";
|
|
48
|
+
readonly i18nKey: "time.timezone.europeBerlin";
|
|
49
|
+
}, {
|
|
50
|
+
readonly key: 13;
|
|
51
|
+
readonly value: "America/New_York";
|
|
52
|
+
readonly i18nKey: "time.timezone.americaNewYork";
|
|
53
|
+
}, {
|
|
54
|
+
readonly key: 14;
|
|
55
|
+
readonly value: "America/Chicago";
|
|
56
|
+
readonly i18nKey: "time.timezone.americaChicago";
|
|
57
|
+
}, {
|
|
58
|
+
readonly key: 15;
|
|
59
|
+
readonly value: "America/Denver";
|
|
60
|
+
readonly i18nKey: "time.timezone.americaDenver";
|
|
61
|
+
}, {
|
|
62
|
+
readonly key: 16;
|
|
63
|
+
readonly value: "America/Los_Angeles";
|
|
64
|
+
readonly i18nKey: "time.timezone.americaLosAngeles";
|
|
65
|
+
}];
|
|
66
|
+
export type CanonicalTimezone = (typeof TIMEZONE)[number]["value"];
|
|
67
|
+
export type TimezoneInput = CanonicalTimezone | string;
|
|
68
|
+
export declare function normalizeTimezone(timezone: TimezoneInput | undefined): CanonicalTimezone | undefined;
|
|
69
|
+
export declare function timezoneToUtc(timezone: TimezoneInput | undefined, timestamp?: number): string | undefined;
|
|
70
|
+
export declare const TIMEZONE_CURRENT_UTC_OFFSET: Record<CanonicalTimezone, string>;
|
|
71
|
+
export declare const TIMEZONE_TO_UTC: Record<"UTC" | "Asia/Kuala_Lumpur" | "Asia/Singapore" | "Asia/Bangkok" | "Asia/Jakarta" | "Asia/Manila" | "Asia/Hong_Kong" | "Asia/Shanghai" | "Asia/Tokyo" | "Australia/Sydney" | "Europe/London" | "Europe/Berlin" | "America/New_York" | "America/Chicago" | "America/Denver" | "America/Los_Angeles", string>;
|
|
72
|
+
export declare function timezoneLabelKey(timezone: TimezoneInput | undefined): string;
|
|
73
|
+
export declare function convertTimestampToTimezone(timestamp: number, sourceTimezone: TimezoneInput | undefined, targetTimezone: TimezoneInput | undefined): number | undefined;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import dayjs from "dayjs";
|
|
2
|
+
import timezone from "dayjs/plugin/timezone.js";
|
|
3
|
+
import utc from "dayjs/plugin/utc.js";
|
|
4
|
+
dayjs.extend(utc);
|
|
5
|
+
dayjs.extend(timezone);
|
|
6
|
+
export const TIMEZONE = [
|
|
7
|
+
{ key: 1, value: "UTC", i18nKey: "time.timezone.utc" },
|
|
8
|
+
{
|
|
9
|
+
key: 2,
|
|
10
|
+
value: "Asia/Kuala_Lumpur",
|
|
11
|
+
i18nKey: "time.timezone.asiaKualaLumpur",
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
key: 3,
|
|
15
|
+
value: "Asia/Singapore",
|
|
16
|
+
i18nKey: "time.timezone.asiaSingapore",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
key: 4,
|
|
20
|
+
value: "Asia/Bangkok",
|
|
21
|
+
i18nKey: "time.timezone.asiaBangkok",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
key: 5,
|
|
25
|
+
value: "Asia/Jakarta",
|
|
26
|
+
i18nKey: "time.timezone.asiaJakarta",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
key: 6,
|
|
30
|
+
value: "Asia/Manila",
|
|
31
|
+
i18nKey: "time.timezone.asiaManila",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
key: 7,
|
|
35
|
+
value: "Asia/Hong_Kong",
|
|
36
|
+
i18nKey: "time.timezone.asiaHongKong",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
key: 8,
|
|
40
|
+
value: "Asia/Shanghai",
|
|
41
|
+
i18nKey: "time.timezone.asiaShanghai",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
key: 9,
|
|
45
|
+
value: "Asia/Tokyo",
|
|
46
|
+
i18nKey: "time.timezone.asiaTokyo",
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
key: 10,
|
|
50
|
+
value: "Australia/Sydney",
|
|
51
|
+
i18nKey: "time.timezone.australiaSydney",
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
key: 11,
|
|
55
|
+
value: "Europe/London",
|
|
56
|
+
i18nKey: "time.timezone.europeLondon",
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
key: 12,
|
|
60
|
+
value: "Europe/Berlin",
|
|
61
|
+
i18nKey: "time.timezone.europeBerlin",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
key: 13,
|
|
65
|
+
value: "America/New_York",
|
|
66
|
+
i18nKey: "time.timezone.americaNewYork",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
key: 14,
|
|
70
|
+
value: "America/Chicago",
|
|
71
|
+
i18nKey: "time.timezone.americaChicago",
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
key: 15,
|
|
75
|
+
value: "America/Denver",
|
|
76
|
+
i18nKey: "time.timezone.americaDenver",
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
key: 16,
|
|
80
|
+
value: "America/Los_Angeles",
|
|
81
|
+
i18nKey: "time.timezone.americaLosAngeles",
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
const TIMEZONE_ALIAS_TO_CANONICAL = {
|
|
85
|
+
utc: "UTC",
|
|
86
|
+
"etc/utc": "UTC",
|
|
87
|
+
"asia/kuala_lumpur": "Asia/Kuala_Lumpur",
|
|
88
|
+
"asia/kuala lumpur": "Asia/Kuala_Lumpur",
|
|
89
|
+
"kuala_lumpur": "Asia/Kuala_Lumpur",
|
|
90
|
+
"kuala lumpur": "Asia/Kuala_Lumpur",
|
|
91
|
+
"asia/singapore": "Asia/Singapore",
|
|
92
|
+
singapore: "Asia/Singapore",
|
|
93
|
+
"asia/bangkok": "Asia/Bangkok",
|
|
94
|
+
bangkok: "Asia/Bangkok",
|
|
95
|
+
"asia/jakarta": "Asia/Jakarta",
|
|
96
|
+
jakarta: "Asia/Jakarta",
|
|
97
|
+
"asia/manila": "Asia/Manila",
|
|
98
|
+
manila: "Asia/Manila",
|
|
99
|
+
"asia/hong_kong": "Asia/Hong_Kong",
|
|
100
|
+
"asia/hong kong": "Asia/Hong_Kong",
|
|
101
|
+
"hong_kong": "Asia/Hong_Kong",
|
|
102
|
+
"hong kong": "Asia/Hong_Kong",
|
|
103
|
+
"asia/shanghai": "Asia/Shanghai",
|
|
104
|
+
shanghai: "Asia/Shanghai",
|
|
105
|
+
"asia/tokyo": "Asia/Tokyo",
|
|
106
|
+
tokyo: "Asia/Tokyo",
|
|
107
|
+
"australia/sydney": "Australia/Sydney",
|
|
108
|
+
sydney: "Australia/Sydney",
|
|
109
|
+
"europe/london": "Europe/London",
|
|
110
|
+
london: "Europe/London",
|
|
111
|
+
"europe/berlin": "Europe/Berlin",
|
|
112
|
+
berlin: "Europe/Berlin",
|
|
113
|
+
"america/new_york": "America/New_York",
|
|
114
|
+
"america/new york": "America/New_York",
|
|
115
|
+
"new_york": "America/New_York",
|
|
116
|
+
"new york": "America/New_York",
|
|
117
|
+
"america/chicago": "America/Chicago",
|
|
118
|
+
chicago: "America/Chicago",
|
|
119
|
+
"america/denver": "America/Denver",
|
|
120
|
+
denver: "America/Denver",
|
|
121
|
+
"america/los_angeles": "America/Los_Angeles",
|
|
122
|
+
"america/los angeles": "America/Los_Angeles",
|
|
123
|
+
"los_angeles": "America/Los_Angeles",
|
|
124
|
+
"los angeles": "America/Los_Angeles",
|
|
125
|
+
};
|
|
126
|
+
const TIMEZONE_I18N_KEY = Object.fromEntries(TIMEZONE.map(({ value, i18nKey }) => [value, i18nKey]));
|
|
127
|
+
function toTimezoneAlias(timezone) {
|
|
128
|
+
return timezone.trim().toLowerCase().replace(/-/g, "_");
|
|
129
|
+
}
|
|
130
|
+
export function normalizeTimezone(timezone) {
|
|
131
|
+
if (!timezone) {
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
return TIMEZONE_ALIAS_TO_CANONICAL[toTimezoneAlias(timezone)];
|
|
135
|
+
}
|
|
136
|
+
export function timezoneToUtc(timezone, timestamp = Date.now()) {
|
|
137
|
+
const normalizedTimezone = normalizeTimezone(timezone);
|
|
138
|
+
if (!normalizedTimezone) {
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
return `UTC${dayjs(timestamp).tz(normalizedTimezone).format("Z")}`;
|
|
142
|
+
}
|
|
143
|
+
export const TIMEZONE_CURRENT_UTC_OFFSET = Object.fromEntries(TIMEZONE.map(({ value }) => [value, timezoneToUtc(value)]));
|
|
144
|
+
export const TIMEZONE_TO_UTC = TIMEZONE_CURRENT_UTC_OFFSET;
|
|
145
|
+
export function timezoneLabelKey(timezone) {
|
|
146
|
+
const normalizedTimezone = normalizeTimezone(timezone);
|
|
147
|
+
if (!normalizedTimezone) {
|
|
148
|
+
return "time.timezone.utc";
|
|
149
|
+
}
|
|
150
|
+
return TIMEZONE_I18N_KEY[normalizedTimezone];
|
|
151
|
+
}
|
|
152
|
+
export function convertTimestampToTimezone(timestamp, sourceTimezone, targetTimezone) {
|
|
153
|
+
const normalizedSourceTimezone = normalizeTimezone(sourceTimezone);
|
|
154
|
+
const normalizedTargetTimezone = normalizeTimezone(targetTimezone);
|
|
155
|
+
if (!normalizedSourceTimezone || !normalizedTargetTimezone) {
|
|
156
|
+
return undefined;
|
|
157
|
+
}
|
|
158
|
+
const sourceDateTime = dayjs(timestamp).tz(normalizedSourceTimezone);
|
|
159
|
+
const preservedWallClock = sourceDateTime.format("YYYY-MM-DDTHH:mm:ss.SSS");
|
|
160
|
+
return dayjs.tz(preservedWallClock, normalizedTargetTimezone).valueOf();
|
|
161
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { convertTimestampToTimezone, TIMEZONE, TIMEZONE_CURRENT_UTC_OFFSET, TIMEZONE_TO_UTC, normalizeTimezone, timezoneLabelKey, timezoneToUtc, } from "./index";
|
|
3
|
+
assert.equal(normalizeTimezone("UTC"), "UTC");
|
|
4
|
+
assert.equal(normalizeTimezone("utc"), "UTC");
|
|
5
|
+
assert.equal(normalizeTimezone("Etc/UTC"), "UTC");
|
|
6
|
+
assert.equal(normalizeTimezone("Asia/Kuala_Lumpur"), "Asia/Kuala_Lumpur");
|
|
7
|
+
assert.equal(normalizeTimezone("asia/kuala lumpur"), "Asia/Kuala_Lumpur");
|
|
8
|
+
assert.equal(normalizeTimezone("singapore"), "Asia/Singapore");
|
|
9
|
+
assert.equal(normalizeTimezone("unknown"), undefined);
|
|
10
|
+
assert.equal(normalizeTimezone(undefined), undefined);
|
|
11
|
+
assert.equal(timezoneToUtc("UTC"), "UTC+00:00");
|
|
12
|
+
assert.equal(timezoneToUtc("Etc/UTC"), "UTC+00:00");
|
|
13
|
+
assert.equal(timezoneToUtc("Asia/Kuala_Lumpur"), "UTC+08:00");
|
|
14
|
+
assert.equal(timezoneToUtc("kuala lumpur"), "UTC+08:00");
|
|
15
|
+
assert.equal(timezoneToUtc("America/New_York", Date.UTC(2024, 0, 1, 12, 0, 0)), "UTC-05:00");
|
|
16
|
+
assert.equal(timezoneToUtc("America/New_York", Date.UTC(2024, 6, 1, 12, 0, 0)), "UTC-04:00");
|
|
17
|
+
assert.equal(timezoneToUtc("unknown"), undefined);
|
|
18
|
+
assert.equal(timezoneLabelKey("UTC"), "time.timezone.utc");
|
|
19
|
+
assert.equal(timezoneLabelKey("Asia/Singapore"), "time.timezone.asiaSingapore");
|
|
20
|
+
assert.equal(timezoneLabelKey(undefined), "time.timezone.utc");
|
|
21
|
+
assert.deepEqual(TIMEZONE[0], {
|
|
22
|
+
key: 1,
|
|
23
|
+
value: "UTC",
|
|
24
|
+
i18nKey: "time.timezone.utc",
|
|
25
|
+
});
|
|
26
|
+
assert.equal(TIMEZONE[2]?.value, "Asia/Singapore");
|
|
27
|
+
assert.equal(TIMEZONE_CURRENT_UTC_OFFSET.UTC, "UTC+00:00");
|
|
28
|
+
assert.equal(TIMEZONE_CURRENT_UTC_OFFSET["Asia/Kuala_Lumpur"], "UTC+08:00");
|
|
29
|
+
assert.equal(TIMEZONE_TO_UTC, TIMEZONE_CURRENT_UTC_OFFSET);
|
|
30
|
+
const utcNineAm = Date.UTC(2024, 0, 1, 9, 0, 0);
|
|
31
|
+
const klNineAm = Date.UTC(2024, 0, 1, 1, 0, 0);
|
|
32
|
+
assert.equal(convertTimestampToTimezone(utcNineAm, "UTC", "Asia/Kuala_Lumpur"), Date.UTC(2024, 0, 1, 1, 0, 0));
|
|
33
|
+
assert.equal(convertTimestampToTimezone(klNineAm, "Asia/Kuala_Lumpur", "America/New_York"), Date.UTC(2024, 0, 1, 14, 0, 0));
|
|
34
|
+
assert.equal(convertTimestampToTimezone(utcNineAm, "unknown", "Asia/Kuala_Lumpur"), undefined);
|
|
35
|
+
assert.equal(convertTimestampToTimezone(utcNineAm, "UTC", "unknown"), undefined);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const ORIGIN: readonly [{
|
|
2
|
+
readonly key: 0;
|
|
3
|
+
readonly value: "Website";
|
|
4
|
+
readonly i18nKey: "track.origin.0";
|
|
5
|
+
}, {
|
|
6
|
+
readonly key: 1;
|
|
7
|
+
readonly value: "Linkedin";
|
|
8
|
+
readonly i18nKey: "track.origin.1";
|
|
9
|
+
}, {
|
|
10
|
+
readonly key: 2;
|
|
11
|
+
readonly value: "Jobstreet";
|
|
12
|
+
readonly i18nKey: "track.origin.2";
|
|
13
|
+
}, {
|
|
14
|
+
readonly key: 3;
|
|
15
|
+
readonly value: "Maukerja";
|
|
16
|
+
readonly i18nKey: "track.origin.3";
|
|
17
|
+
}];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const ORIGIN = [
|
|
2
|
+
{
|
|
3
|
+
key: 0,
|
|
4
|
+
value: "Website",
|
|
5
|
+
i18nKey: "track.origin.0",
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
key: 1,
|
|
9
|
+
value: "Linkedin",
|
|
10
|
+
i18nKey: "track.origin.1",
|
|
11
|
+
},
|
|
12
|
+
{ key: 2, value: "Jobstreet", i18nKey: "track.origin.2" },
|
|
13
|
+
{ key: 3, value: "Maukerja", i18nKey: "track.origin.3" },
|
|
14
|
+
];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Website } from "../website";
|
|
2
|
+
export const URL_PREFIXES = {
|
|
3
|
+
[Website.KORRE]: {
|
|
4
|
+
contact: "https://www.korre.site/contact",
|
|
5
|
+
careerDetail: "https://www.korre.site/career/[id]",
|
|
6
|
+
careerApply: "https://www.korre.site/career/[id]/apply",
|
|
7
|
+
},
|
|
8
|
+
[Website.KORRE_LABS]: {},
|
|
9
|
+
};
|