@simplysm/core-common 13.0.0-beta.2 → 13.0.0-beta.21
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/common.types.js +4 -4
- package/dist/errors/argument-error.js +1 -1
- package/dist/errors/not-implemented-error.js +1 -1
- package/dist/errors/timeout-error.js +1 -1
- package/dist/extensions/arr-ext.helpers.js +4 -4
- package/dist/extensions/arr-ext.js +9 -9
- package/dist/features/debounce-queue.js +2 -2
- package/dist/features/serial-queue.js +3 -3
- package/dist/index.js +30 -30
- package/dist/types/date-only.js +2 -2
- package/dist/types/date-time.js +2 -2
- package/dist/types/time.js +2 -2
- package/dist/types/uuid.js +1 -1
- package/dist/utils/bytes.js +1 -1
- package/dist/utils/json.js +8 -8
- package/dist/utils/obj.js +5 -5
- package/dist/utils/primitive.js +5 -5
- package/dist/utils/transferable.js +4 -4
- package/dist/utils/wait.js +1 -1
- package/package.json +7 -4
- package/.cache/typecheck-browser.tsbuildinfo +0 -1
- package/.cache/typecheck-node.tsbuildinfo +0 -1
- package/.cache/typecheck-tests-browser.tsbuildinfo +0 -1
- package/.cache/typecheck-tests-node.tsbuildinfo +0 -1
- package/src/common.types.ts +0 -91
- package/src/env.ts +0 -11
- package/src/errors/argument-error.ts +0 -40
- package/src/errors/not-implemented-error.ts +0 -32
- package/src/errors/sd-error.ts +0 -53
- package/src/errors/timeout-error.ts +0 -36
- package/src/extensions/arr-ext.helpers.ts +0 -53
- package/src/extensions/arr-ext.ts +0 -777
- package/src/extensions/arr-ext.types.ts +0 -258
- package/src/extensions/map-ext.ts +0 -86
- package/src/extensions/set-ext.ts +0 -68
- package/src/features/debounce-queue.ts +0 -116
- package/src/features/event-emitter.ts +0 -112
- package/src/features/serial-queue.ts +0 -94
- package/src/globals.ts +0 -12
- package/src/index.ts +0 -55
- package/src/types/date-only.ts +0 -329
- package/src/types/date-time.ts +0 -294
- package/src/types/lazy-gc-map.ts +0 -244
- package/src/types/time.ts +0 -210
- package/src/types/uuid.ts +0 -113
- package/src/utils/bytes.ts +0 -160
- package/src/utils/date-format.ts +0 -239
- package/src/utils/json.ts +0 -230
- package/src/utils/num.ts +0 -97
- package/src/utils/obj.ts +0 -956
- package/src/utils/path.ts +0 -40
- package/src/utils/primitive.ts +0 -33
- package/src/utils/str.ts +0 -252
- package/src/utils/template-strings.ts +0 -132
- package/src/utils/transferable.ts +0 -269
- package/src/utils/wait.ts +0 -40
- package/src/utils/xml.ts +0 -105
- package/src/zip/sd-zip.ts +0 -218
- package/tests/errors/errors.spec.ts +0 -196
- package/tests/extensions/array-extension.spec.ts +0 -790
- package/tests/extensions/map-extension.spec.ts +0 -147
- package/tests/extensions/set-extension.spec.ts +0 -74
- package/tests/types/date-only.spec.ts +0 -636
- package/tests/types/date-time.spec.ts +0 -391
- package/tests/types/lazy-gc-map.spec.ts +0 -692
- package/tests/types/time.spec.ts +0 -559
- package/tests/types/types.spec.ts +0 -55
- package/tests/types/uuid.spec.ts +0 -91
- package/tests/utils/bytes-utils.spec.ts +0 -230
- package/tests/utils/date-format.spec.ts +0 -371
- package/tests/utils/debounce-queue.spec.ts +0 -272
- package/tests/utils/json.spec.ts +0 -475
- package/tests/utils/number.spec.ts +0 -184
- package/tests/utils/object.spec.ts +0 -827
- package/tests/utils/path.spec.ts +0 -78
- package/tests/utils/primitive.spec.ts +0 -55
- package/tests/utils/sd-event-emitter.spec.ts +0 -216
- package/tests/utils/serial-queue.spec.ts +0 -365
- package/tests/utils/string.spec.ts +0 -294
- package/tests/utils/template-strings.spec.ts +0 -96
- package/tests/utils/transferable.spec.ts +0 -698
- package/tests/utils/wait.spec.ts +0 -145
- package/tests/utils/xml.spec.ts +0 -146
- package/tests/zip/sd-zip.spec.ts +0 -234
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
ArgumentError,
|
|
4
|
-
bytesConcat as concat,
|
|
5
|
-
bytesToHex as toHex,
|
|
6
|
-
bytesFromHex as fromHex,
|
|
7
|
-
bytesToBase64 as toBase64,
|
|
8
|
-
bytesFromBase64 as fromBase64,
|
|
9
|
-
} from "@simplysm/core-common";
|
|
10
|
-
|
|
11
|
-
describe("BytesUtils", () => {
|
|
12
|
-
//#region concat
|
|
13
|
-
|
|
14
|
-
describe("concat()", () => {
|
|
15
|
-
it("여러 Uint8Array를 연결한다", () => {
|
|
16
|
-
const arr1 = new Uint8Array([1, 2, 3]);
|
|
17
|
-
const arr2 = new Uint8Array([4, 5]);
|
|
18
|
-
const arr3 = new Uint8Array([6, 7, 8, 9]);
|
|
19
|
-
|
|
20
|
-
const result = concat([arr1, arr2, arr3]);
|
|
21
|
-
|
|
22
|
-
expect(result).toEqual(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9]));
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it("빈 배열을 처리한다", () => {
|
|
26
|
-
const result = concat([]);
|
|
27
|
-
|
|
28
|
-
expect(result).toEqual(new Uint8Array([]));
|
|
29
|
-
expect(result.length).toBe(0);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it("단일 배열을 처리한다", () => {
|
|
33
|
-
const arr = new Uint8Array([1, 2, 3]);
|
|
34
|
-
|
|
35
|
-
const result = concat([arr]);
|
|
36
|
-
|
|
37
|
-
expect(result).toEqual(new Uint8Array([1, 2, 3]));
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it("빈 Uint8Array가 포함된 경우 처리한다", () => {
|
|
41
|
-
const arr1 = new Uint8Array([1, 2]);
|
|
42
|
-
const arr2 = new Uint8Array([]);
|
|
43
|
-
const arr3 = new Uint8Array([3, 4]);
|
|
44
|
-
|
|
45
|
-
const result = concat([arr1, arr2, arr3]);
|
|
46
|
-
|
|
47
|
-
expect(result).toEqual(new Uint8Array([1, 2, 3, 4]));
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
//#endregion
|
|
52
|
-
|
|
53
|
-
//#region toHex/fromHex
|
|
54
|
-
|
|
55
|
-
describe("toHex()", () => {
|
|
56
|
-
it("Uint8Array를 hex 문자열로 변환한다", () => {
|
|
57
|
-
const bytes = new Uint8Array([0, 1, 15, 16, 255]);
|
|
58
|
-
|
|
59
|
-
const result = toHex(bytes);
|
|
60
|
-
|
|
61
|
-
expect(result).toBe("00010f10ff");
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it("빈 배열을 처리한다", () => {
|
|
65
|
-
const result = toHex(new Uint8Array([]));
|
|
66
|
-
|
|
67
|
-
expect(result).toBe("");
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it("단일 바이트를 처리한다", () => {
|
|
71
|
-
expect(toHex(new Uint8Array([0]))).toBe("00");
|
|
72
|
-
expect(toHex(new Uint8Array([255]))).toBe("ff");
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
describe("fromHex()", () => {
|
|
77
|
-
it("hex 문자열을 Uint8Array로 변환한다", () => {
|
|
78
|
-
const result = fromHex("00010f10ff");
|
|
79
|
-
|
|
80
|
-
expect(result).toEqual(new Uint8Array([0, 1, 15, 16, 255]));
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it("빈 문자열을 처리한다", () => {
|
|
84
|
-
const result = fromHex("");
|
|
85
|
-
|
|
86
|
-
expect(result).toEqual(new Uint8Array([]));
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it("대문자 hex도 처리한다", () => {
|
|
90
|
-
const result = fromHex("FF0A");
|
|
91
|
-
|
|
92
|
-
expect(result).toEqual(new Uint8Array([255, 10]));
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it("홀수 길이 문자열은 에러를 발생시킨다", () => {
|
|
96
|
-
expect(() => fromHex("abc")).toThrow(ArgumentError);
|
|
97
|
-
expect(() => fromHex("a")).toThrow(ArgumentError);
|
|
98
|
-
expect(() => fromHex("12345")).toThrow(ArgumentError);
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it("유효하지 않은 hex 문자가 포함되면 에러를 발생시킨다", () => {
|
|
102
|
-
expect(() => fromHex("zz")).toThrow(ArgumentError);
|
|
103
|
-
expect(() => fromHex("gh")).toThrow(ArgumentError);
|
|
104
|
-
expect(() => fromHex("12g4")).toThrow(ArgumentError);
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
describe("toHex/fromHex 왕복 변환", () => {
|
|
109
|
-
it("왕복 변환이 일치한다", () => {
|
|
110
|
-
const original = new Uint8Array([0, 127, 128, 255, 1, 2, 3]);
|
|
111
|
-
|
|
112
|
-
const hex = toHex(original);
|
|
113
|
-
const restored = fromHex(hex);
|
|
114
|
-
|
|
115
|
-
expect(restored).toEqual(original);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it("모든 바이트 값(0-255)에 대해 왕복 변환이 일치한다", () => {
|
|
119
|
-
const original = new Uint8Array(256);
|
|
120
|
-
for (let i = 0; i < 256; i++) {
|
|
121
|
-
original[i] = i;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const hex = toHex(original);
|
|
125
|
-
const restored = fromHex(hex);
|
|
126
|
-
|
|
127
|
-
expect(restored).toEqual(original);
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
//#endregion
|
|
132
|
-
|
|
133
|
-
//#region toBase64/fromBase64
|
|
134
|
-
|
|
135
|
-
describe("toBase64()", () => {
|
|
136
|
-
it("빈 배열을 처리한다", () => {
|
|
137
|
-
expect(toBase64(new Uint8Array([]))).toBe("");
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it("일반 데이터를 변환한다", () => {
|
|
141
|
-
expect(toBase64(new Uint8Array([72, 101, 108, 108, 111]))).toBe("SGVsbG8=");
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
it("대용량 데이터 (1MB)를 스택 오버플로우 없이 처리한다", () => {
|
|
145
|
-
const data = new Uint8Array(1024 * 1024);
|
|
146
|
-
expect(() => toBase64(data)).not.toThrow();
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it("패딩이 필요없는 경우를 처리한다", () => {
|
|
150
|
-
// 3의 배수 길이 - 패딩 없음
|
|
151
|
-
expect(toBase64(new Uint8Array([1, 2, 3]))).toBe("AQID");
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
it("단일 패딩이 필요한 경우를 처리한다", () => {
|
|
155
|
-
// 3으로 나눠 나머지 2 - = 1개
|
|
156
|
-
expect(toBase64(new Uint8Array([1, 2]))).toBe("AQI=");
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it("이중 패딩이 필요한 경우를 처리한다", () => {
|
|
160
|
-
// 3으로 나눠 나머지 1 - == 2개
|
|
161
|
-
expect(toBase64(new Uint8Array([1]))).toBe("AQ==");
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
describe("fromBase64()", () => {
|
|
166
|
-
it("빈 문자열을 처리한다", () => {
|
|
167
|
-
expect(fromBase64("")).toEqual(new Uint8Array([]));
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
it("일반 데이터를 변환한다", () => {
|
|
171
|
-
expect(fromBase64("SGVsbG8=")).toEqual(new Uint8Array([72, 101, 108, 108, 111]));
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
it("유효하지 않은 base64 문자가 포함되면 에러를 발생시킨다", () => {
|
|
175
|
-
expect(() => fromBase64("!!invalid!!")).toThrow(ArgumentError);
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
it("유효하지 않은 base64 길이(나머지 1)면 에러를 발생시킨다", () => {
|
|
179
|
-
expect(() => fromBase64("A")).toThrow(ArgumentError);
|
|
180
|
-
expect(() => fromBase64("AAAAA")).toThrow(ArgumentError);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
it("패딩 없는 base64를 처리한다", () => {
|
|
184
|
-
expect(fromBase64("AQID")).toEqual(new Uint8Array([1, 2, 3]));
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
it("공백이 포함된 base64를 처리한다", () => {
|
|
188
|
-
expect(fromBase64("SGVs bG8=")).toEqual(new Uint8Array([72, 101, 108, 108, 111]));
|
|
189
|
-
});
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
describe("toBase64/fromBase64 왕복 변환", () => {
|
|
193
|
-
it("왕복 변환이 일치한다", () => {
|
|
194
|
-
const original = new Uint8Array([0, 127, 128, 255, 1, 2, 3]);
|
|
195
|
-
|
|
196
|
-
const base64 = toBase64(original);
|
|
197
|
-
const restored = fromBase64(base64);
|
|
198
|
-
|
|
199
|
-
expect(restored).toEqual(original);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
it("모든 바이트 값(0-255)에 대해 왕복 변환이 일치한다", () => {
|
|
203
|
-
const original = new Uint8Array(256);
|
|
204
|
-
for (let i = 0; i < 256; i++) {
|
|
205
|
-
original[i] = i;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
const base64 = toBase64(original);
|
|
209
|
-
const restored = fromBase64(base64);
|
|
210
|
-
|
|
211
|
-
expect(restored).toEqual(original);
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
it("다양한 길이(1~10바이트)에 대해 왕복 변환이 일치한다", () => {
|
|
215
|
-
for (let len = 1; len <= 10; len++) {
|
|
216
|
-
const original = new Uint8Array(len);
|
|
217
|
-
for (let i = 0; i < len; i++) {
|
|
218
|
-
original[i] = (i * 37 + 13) % 256;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
const base64 = toBase64(original);
|
|
222
|
-
const restored = fromBase64(base64);
|
|
223
|
-
|
|
224
|
-
expect(restored).toEqual(original);
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
//#endregion
|
|
230
|
-
});
|
|
@@ -1,371 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { formatDate, normalizeMonth } from "@simplysm/core-common";
|
|
3
|
-
|
|
4
|
-
describe("formatDateTime", () => {
|
|
5
|
-
//#region 연도 패턴
|
|
6
|
-
|
|
7
|
-
describe("연도 패턴", () => {
|
|
8
|
-
it("yyyy - 4자리 연도를 출력한다", () => {
|
|
9
|
-
expect(formatDate("yyyy", { year: 2025 })).toBe("2025");
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it("yy - 2자리 연도를 출력한다", () => {
|
|
13
|
-
expect(formatDate("yy", { year: 2025 })).toBe("25");
|
|
14
|
-
expect(formatDate("yy", { year: 2000 })).toBe("00");
|
|
15
|
-
expect(formatDate("yy", { year: 1999 })).toBe("99");
|
|
16
|
-
});
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
//#endregion
|
|
20
|
-
|
|
21
|
-
//#region 월 패턴
|
|
22
|
-
|
|
23
|
-
describe("월 패턴", () => {
|
|
24
|
-
it("MM - 2자리 월을 출력한다", () => {
|
|
25
|
-
expect(formatDate("MM", { month: 1 })).toBe("01");
|
|
26
|
-
expect(formatDate("MM", { month: 9 })).toBe("09");
|
|
27
|
-
expect(formatDate("MM", { month: 12 })).toBe("12");
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("M - 패딩 없이 월을 출력한다", () => {
|
|
31
|
-
expect(formatDate("M", { month: 1 })).toBe("1");
|
|
32
|
-
expect(formatDate("M", { month: 9 })).toBe("9");
|
|
33
|
-
expect(formatDate("M", { month: 12 })).toBe("12");
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
//#endregion
|
|
38
|
-
|
|
39
|
-
//#region 일 패턴
|
|
40
|
-
|
|
41
|
-
describe("일 패턴", () => {
|
|
42
|
-
it("dd - 2자리 일을 출력한다", () => {
|
|
43
|
-
expect(formatDate("dd", { day: 1 })).toBe("01");
|
|
44
|
-
expect(formatDate("dd", { day: 9 })).toBe("09");
|
|
45
|
-
expect(formatDate("dd", { day: 31 })).toBe("31");
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it("d - 패딩 없이 일을 출력한다", () => {
|
|
49
|
-
expect(formatDate("d", { day: 1 })).toBe("1");
|
|
50
|
-
expect(formatDate("d", { day: 9 })).toBe("9");
|
|
51
|
-
expect(formatDate("d", { day: 31 })).toBe("31");
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
//#endregion
|
|
56
|
-
|
|
57
|
-
//#region 요일 패턴
|
|
58
|
-
|
|
59
|
-
describe("요일 패턴", () => {
|
|
60
|
-
it("ddd - 요일을 한글로 출력한다", () => {
|
|
61
|
-
// 2025-01-18은 토요일
|
|
62
|
-
expect(formatDate("ddd", { year: 2025, month: 1, day: 18 })).toBe("토");
|
|
63
|
-
// 2025-01-19는 일요일
|
|
64
|
-
expect(formatDate("ddd", { year: 2025, month: 1, day: 19 })).toBe("일");
|
|
65
|
-
// 2025-01-20은 월요일
|
|
66
|
-
expect(formatDate("ddd", { year: 2025, month: 1, day: 20 })).toBe("월");
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
//#endregion
|
|
71
|
-
|
|
72
|
-
//#region 시간 패턴
|
|
73
|
-
|
|
74
|
-
describe("시간 패턴", () => {
|
|
75
|
-
it("hh - 12시간 형식으로 패딩하여 출력한다", () => {
|
|
76
|
-
expect(formatDate("hh", { hour: 0 })).toBe("12");
|
|
77
|
-
expect(formatDate("hh", { hour: 1 })).toBe("01");
|
|
78
|
-
expect(formatDate("hh", { hour: 12 })).toBe("12");
|
|
79
|
-
expect(formatDate("hh", { hour: 13 })).toBe("01");
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it("h - 12시간 형식으로 패딩 없이 출력한다", () => {
|
|
83
|
-
expect(formatDate("h", { hour: 0 })).toBe("12");
|
|
84
|
-
expect(formatDate("h", { hour: 1 })).toBe("1");
|
|
85
|
-
expect(formatDate("h", { hour: 9 })).toBe("9");
|
|
86
|
-
expect(formatDate("h", { hour: 10 })).toBe("10");
|
|
87
|
-
expect(formatDate("h", { hour: 12 })).toBe("12");
|
|
88
|
-
expect(formatDate("h", { hour: 13 })).toBe("1");
|
|
89
|
-
expect(formatDate("h", { hour: 23 })).toBe("11");
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it("HH - 24시간 형식으로 패딩하여 출력한다", () => {
|
|
93
|
-
expect(formatDate("HH", { hour: 0 })).toBe("00");
|
|
94
|
-
expect(formatDate("HH", { hour: 9 })).toBe("09");
|
|
95
|
-
expect(formatDate("HH", { hour: 23 })).toBe("23");
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it("H - 24시간 형식으로 패딩 없이 출력한다", () => {
|
|
99
|
-
expect(formatDate("H", { hour: 0 })).toBe("0");
|
|
100
|
-
expect(formatDate("H", { hour: 9 })).toBe("9");
|
|
101
|
-
expect(formatDate("H", { hour: 23 })).toBe("23");
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it("tt - 오전/오후를 출력한다", () => {
|
|
105
|
-
expect(formatDate("tt", { hour: 0 })).toBe("오전");
|
|
106
|
-
expect(formatDate("tt", { hour: 11 })).toBe("오전");
|
|
107
|
-
expect(formatDate("tt", { hour: 12 })).toBe("오후");
|
|
108
|
-
expect(formatDate("tt", { hour: 23 })).toBe("오후");
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
//#endregion
|
|
113
|
-
|
|
114
|
-
//#region 분 패턴
|
|
115
|
-
|
|
116
|
-
describe("분 패턴", () => {
|
|
117
|
-
it("mm - 2자리 분을 출력한다", () => {
|
|
118
|
-
expect(formatDate("mm", { minute: 0 })).toBe("00");
|
|
119
|
-
expect(formatDate("mm", { minute: 5 })).toBe("05");
|
|
120
|
-
expect(formatDate("mm", { minute: 59 })).toBe("59");
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it("m - 패딩 없이 분을 출력한다", () => {
|
|
124
|
-
expect(formatDate("m", { minute: 0 })).toBe("0");
|
|
125
|
-
expect(formatDate("m", { minute: 5 })).toBe("5");
|
|
126
|
-
expect(formatDate("m", { minute: 59 })).toBe("59");
|
|
127
|
-
});
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
//#endregion
|
|
131
|
-
|
|
132
|
-
//#region 초 패턴
|
|
133
|
-
|
|
134
|
-
describe("초 패턴", () => {
|
|
135
|
-
it("ss - 2자리 초를 출력한다", () => {
|
|
136
|
-
expect(formatDate("ss", { second: 0 })).toBe("00");
|
|
137
|
-
expect(formatDate("ss", { second: 5 })).toBe("05");
|
|
138
|
-
expect(formatDate("ss", { second: 59 })).toBe("59");
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
it("s - 패딩 없이 초를 출력한다", () => {
|
|
142
|
-
expect(formatDate("s", { second: 0 })).toBe("0");
|
|
143
|
-
expect(formatDate("s", { second: 5 })).toBe("5");
|
|
144
|
-
expect(formatDate("s", { second: 59 })).toBe("59");
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
//#endregion
|
|
149
|
-
|
|
150
|
-
//#region 밀리초 패턴
|
|
151
|
-
|
|
152
|
-
describe("밀리초 패턴", () => {
|
|
153
|
-
it("fff - 3자리 밀리초를 출력한다", () => {
|
|
154
|
-
expect(formatDate("fff", { millisecond: 0 })).toBe("000");
|
|
155
|
-
expect(formatDate("fff", { millisecond: 5 })).toBe("005");
|
|
156
|
-
expect(formatDate("fff", { millisecond: 50 })).toBe("050");
|
|
157
|
-
expect(formatDate("fff", { millisecond: 500 })).toBe("500");
|
|
158
|
-
expect(formatDate("fff", { millisecond: 999 })).toBe("999");
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it("ff - 2자리 밀리초를 출력한다", () => {
|
|
162
|
-
expect(formatDate("ff", { millisecond: 0 })).toBe("00");
|
|
163
|
-
expect(formatDate("ff", { millisecond: 5 })).toBe("00");
|
|
164
|
-
expect(formatDate("ff", { millisecond: 50 })).toBe("05");
|
|
165
|
-
expect(formatDate("ff", { millisecond: 500 })).toBe("50");
|
|
166
|
-
expect(formatDate("ff", { millisecond: 999 })).toBe("99");
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
it("f - 1자리 밀리초를 출력한다", () => {
|
|
170
|
-
expect(formatDate("f", { millisecond: 0 })).toBe("0");
|
|
171
|
-
expect(formatDate("f", { millisecond: 5 })).toBe("0");
|
|
172
|
-
expect(formatDate("f", { millisecond: 100 })).toBe("1");
|
|
173
|
-
expect(formatDate("f", { millisecond: 500 })).toBe("5");
|
|
174
|
-
expect(formatDate("f", { millisecond: 999 })).toBe("9");
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
//#endregion
|
|
179
|
-
|
|
180
|
-
//#region 타임존 패턴
|
|
181
|
-
|
|
182
|
-
describe("타임존 패턴", () => {
|
|
183
|
-
describe("양수 오프셋 (동쪽)", () => {
|
|
184
|
-
it("zzz - +HH:mm 형식으로 출력한다", () => {
|
|
185
|
-
// UTC+9 (540분)
|
|
186
|
-
expect(formatDate("zzz", { timezoneOffsetMinutes: 540 })).toBe("+09:00");
|
|
187
|
-
// UTC+5:30 (330분)
|
|
188
|
-
expect(formatDate("zzz", { timezoneOffsetMinutes: 330 })).toBe("+05:30");
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
it("zz - +HH 형식으로 출력한다", () => {
|
|
192
|
-
expect(formatDate("zz", { timezoneOffsetMinutes: 540 })).toBe("+09");
|
|
193
|
-
expect(formatDate("zz", { timezoneOffsetMinutes: 60 })).toBe("+01");
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
it("z - +H 형식으로 출력한다 (패딩 없음)", () => {
|
|
197
|
-
expect(formatDate("z", { timezoneOffsetMinutes: 540 })).toBe("+9");
|
|
198
|
-
expect(formatDate("z", { timezoneOffsetMinutes: 60 })).toBe("+1");
|
|
199
|
-
expect(formatDate("z", { timezoneOffsetMinutes: 600 })).toBe("+10");
|
|
200
|
-
});
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
describe("음수 오프셋 (서쪽)", () => {
|
|
204
|
-
it("zzz - -HH:mm 형식으로 출력한다", () => {
|
|
205
|
-
// UTC-5 (-300분) - 정수 시간대
|
|
206
|
-
expect(formatDate("zzz", { timezoneOffsetMinutes: -300 })).toBe("-05:00");
|
|
207
|
-
// UTC-8 (-480분) - 정수 시간대
|
|
208
|
-
expect(formatDate("zzz", { timezoneOffsetMinutes: -480 })).toBe("-08:00");
|
|
209
|
-
// UTC-3:30 (-210분) - Newfoundland Standard Time
|
|
210
|
-
expect(formatDate("zzz", { timezoneOffsetMinutes: -210 })).toBe("-03:30");
|
|
211
|
-
// UTC-9:30 (-570분) - Marquesas Islands
|
|
212
|
-
expect(formatDate("zzz", { timezoneOffsetMinutes: -570 })).toBe("-09:30");
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
it("zz - -HH 형식으로 출력한다", () => {
|
|
216
|
-
expect(formatDate("zz", { timezoneOffsetMinutes: -300 })).toBe("-05");
|
|
217
|
-
expect(formatDate("zz", { timezoneOffsetMinutes: -60 })).toBe("-01");
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
it("z - -H 형식으로 출력한다 (패딩 없음)", () => {
|
|
221
|
-
expect(formatDate("z", { timezoneOffsetMinutes: -300 })).toBe("-5");
|
|
222
|
-
expect(formatDate("z", { timezoneOffsetMinutes: -60 })).toBe("-1");
|
|
223
|
-
expect(formatDate("z", { timezoneOffsetMinutes: -720 })).toBe("-12");
|
|
224
|
-
});
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
describe("UTC (0 오프셋)", () => {
|
|
228
|
-
it("zzz - +00:00으로 출력한다", () => {
|
|
229
|
-
expect(formatDate("zzz", { timezoneOffsetMinutes: 0 })).toBe("+00:00");
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
it("zz - +00으로 출력한다", () => {
|
|
233
|
-
expect(formatDate("zz", { timezoneOffsetMinutes: 0 })).toBe("+00");
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
it("z - +0으로 출력한다", () => {
|
|
237
|
-
expect(formatDate("z", { timezoneOffsetMinutes: 0 })).toBe("+0");
|
|
238
|
-
});
|
|
239
|
-
});
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
//#endregion
|
|
243
|
-
|
|
244
|
-
//#region 복합 포맷
|
|
245
|
-
|
|
246
|
-
describe("복합 포맷", () => {
|
|
247
|
-
it("전체 날짜/시간 포맷을 처리한다", () => {
|
|
248
|
-
const result = formatDate("yyyy-MM-dd HH:mm:ss.fff", {
|
|
249
|
-
year: 2025,
|
|
250
|
-
month: 1,
|
|
251
|
-
day: 18,
|
|
252
|
-
hour: 14,
|
|
253
|
-
minute: 30,
|
|
254
|
-
second: 45,
|
|
255
|
-
millisecond: 123,
|
|
256
|
-
});
|
|
257
|
-
expect(result).toBe("2025-01-18 14:30:45.123");
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
it("12시간 형식 포맷을 처리한다", () => {
|
|
261
|
-
const result = formatDate("yyyy-MM-dd tt h:mm:ss", {
|
|
262
|
-
year: 2025,
|
|
263
|
-
month: 1,
|
|
264
|
-
day: 18,
|
|
265
|
-
hour: 14,
|
|
266
|
-
minute: 5,
|
|
267
|
-
second: 9,
|
|
268
|
-
});
|
|
269
|
-
expect(result).toBe("2025-01-18 오후 2:05:09");
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
it("타임존 포함 포맷을 처리한다", () => {
|
|
273
|
-
const result = formatDate("yyyy-MM-ddTHH:mm:sszzz", {
|
|
274
|
-
year: 2025,
|
|
275
|
-
month: 1,
|
|
276
|
-
day: 18,
|
|
277
|
-
hour: 14,
|
|
278
|
-
minute: 30,
|
|
279
|
-
second: 0,
|
|
280
|
-
timezoneOffsetMinutes: 540,
|
|
281
|
-
});
|
|
282
|
-
expect(result).toBe("2025-01-18T14:30:00+09:00");
|
|
283
|
-
});
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
//#endregion
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
describe("normalizeMonth", () => {
|
|
290
|
-
//#region 정상 범위
|
|
291
|
-
|
|
292
|
-
describe("정상 범위 (1-12)", () => {
|
|
293
|
-
it("월이 1-12 범위 내면 그대로 반환한다", () => {
|
|
294
|
-
expect(normalizeMonth(2025, 1, 15)).toEqual({ year: 2025, month: 1, day: 15 });
|
|
295
|
-
expect(normalizeMonth(2025, 6, 15)).toEqual({ year: 2025, month: 6, day: 15 });
|
|
296
|
-
expect(normalizeMonth(2025, 12, 15)).toEqual({ year: 2025, month: 12, day: 15 });
|
|
297
|
-
});
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
//#endregion
|
|
301
|
-
|
|
302
|
-
//#region 월 오버플로우
|
|
303
|
-
|
|
304
|
-
describe("월 오버플로우 (13 이상)", () => {
|
|
305
|
-
it("13월은 다음 해 1월이 된다", () => {
|
|
306
|
-
expect(normalizeMonth(2025, 13, 15)).toEqual({ year: 2026, month: 1, day: 15 });
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
it("14월은 다음 해 2월이 된다", () => {
|
|
310
|
-
expect(normalizeMonth(2025, 14, 15)).toEqual({ year: 2026, month: 2, day: 15 });
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
it("25월은 2년 후 1월이 된다", () => {
|
|
314
|
-
expect(normalizeMonth(2025, 25, 15)).toEqual({ year: 2027, month: 1, day: 15 });
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
it("24월은 다음 해 12월이 된다", () => {
|
|
318
|
-
expect(normalizeMonth(2025, 24, 15)).toEqual({ year: 2026, month: 12, day: 15 });
|
|
319
|
-
});
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
//#endregion
|
|
323
|
-
|
|
324
|
-
//#region 월 언더플로우
|
|
325
|
-
|
|
326
|
-
describe("월 언더플로우 (0 이하)", () => {
|
|
327
|
-
it("0월은 이전 해 12월이 된다", () => {
|
|
328
|
-
expect(normalizeMonth(2025, 0, 15)).toEqual({ year: 2024, month: 12, day: 15 });
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
it("-1월은 이전 해 11월이 된다", () => {
|
|
332
|
-
expect(normalizeMonth(2025, -1, 15)).toEqual({ year: 2024, month: 11, day: 15 });
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
it("-11월은 이전 해 1월이 된다", () => {
|
|
336
|
-
expect(normalizeMonth(2025, -11, 15)).toEqual({ year: 2024, month: 1, day: 15 });
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
it("-12월은 2년 전 12월이 된다", () => {
|
|
340
|
-
expect(normalizeMonth(2025, -12, 15)).toEqual({ year: 2023, month: 12, day: 15 });
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
it("-13월은 2년 전 11월이 된다", () => {
|
|
344
|
-
expect(normalizeMonth(2025, -13, 15)).toEqual({ year: 2023, month: 11, day: 15 });
|
|
345
|
-
});
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
//#endregion
|
|
349
|
-
|
|
350
|
-
//#region 일 조정
|
|
351
|
-
|
|
352
|
-
describe("일 조정 (대상 월의 마지막 날)", () => {
|
|
353
|
-
it("31일에서 2월로 변경하면 28일로 조정된다 (평년)", () => {
|
|
354
|
-
expect(normalizeMonth(2025, 2, 31)).toEqual({ year: 2025, month: 2, day: 28 });
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
it("31일에서 2월로 변경하면 29일로 조정된다 (윤년)", () => {
|
|
358
|
-
expect(normalizeMonth(2024, 2, 31)).toEqual({ year: 2024, month: 2, day: 29 });
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
it("31일에서 4월로 변경하면 30일로 조정된다", () => {
|
|
362
|
-
expect(normalizeMonth(2025, 4, 31)).toEqual({ year: 2025, month: 4, day: 30 });
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
it("대상 월의 일수보다 작으면 그대로 유지된다", () => {
|
|
366
|
-
expect(normalizeMonth(2025, 3, 15)).toEqual({ year: 2025, month: 3, day: 15 });
|
|
367
|
-
});
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
//#endregion
|
|
371
|
-
});
|