@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.
Files changed (84) hide show
  1. package/dist/common.types.js +4 -4
  2. package/dist/errors/argument-error.js +1 -1
  3. package/dist/errors/not-implemented-error.js +1 -1
  4. package/dist/errors/timeout-error.js +1 -1
  5. package/dist/extensions/arr-ext.helpers.js +4 -4
  6. package/dist/extensions/arr-ext.js +9 -9
  7. package/dist/features/debounce-queue.js +2 -2
  8. package/dist/features/serial-queue.js +3 -3
  9. package/dist/index.js +30 -30
  10. package/dist/types/date-only.js +2 -2
  11. package/dist/types/date-time.js +2 -2
  12. package/dist/types/time.js +2 -2
  13. package/dist/types/uuid.js +1 -1
  14. package/dist/utils/bytes.js +1 -1
  15. package/dist/utils/json.js +8 -8
  16. package/dist/utils/obj.js +5 -5
  17. package/dist/utils/primitive.js +5 -5
  18. package/dist/utils/transferable.js +4 -4
  19. package/dist/utils/wait.js +1 -1
  20. package/package.json +7 -4
  21. package/.cache/typecheck-browser.tsbuildinfo +0 -1
  22. package/.cache/typecheck-node.tsbuildinfo +0 -1
  23. package/.cache/typecheck-tests-browser.tsbuildinfo +0 -1
  24. package/.cache/typecheck-tests-node.tsbuildinfo +0 -1
  25. package/src/common.types.ts +0 -91
  26. package/src/env.ts +0 -11
  27. package/src/errors/argument-error.ts +0 -40
  28. package/src/errors/not-implemented-error.ts +0 -32
  29. package/src/errors/sd-error.ts +0 -53
  30. package/src/errors/timeout-error.ts +0 -36
  31. package/src/extensions/arr-ext.helpers.ts +0 -53
  32. package/src/extensions/arr-ext.ts +0 -777
  33. package/src/extensions/arr-ext.types.ts +0 -258
  34. package/src/extensions/map-ext.ts +0 -86
  35. package/src/extensions/set-ext.ts +0 -68
  36. package/src/features/debounce-queue.ts +0 -116
  37. package/src/features/event-emitter.ts +0 -112
  38. package/src/features/serial-queue.ts +0 -94
  39. package/src/globals.ts +0 -12
  40. package/src/index.ts +0 -55
  41. package/src/types/date-only.ts +0 -329
  42. package/src/types/date-time.ts +0 -294
  43. package/src/types/lazy-gc-map.ts +0 -244
  44. package/src/types/time.ts +0 -210
  45. package/src/types/uuid.ts +0 -113
  46. package/src/utils/bytes.ts +0 -160
  47. package/src/utils/date-format.ts +0 -239
  48. package/src/utils/json.ts +0 -230
  49. package/src/utils/num.ts +0 -97
  50. package/src/utils/obj.ts +0 -956
  51. package/src/utils/path.ts +0 -40
  52. package/src/utils/primitive.ts +0 -33
  53. package/src/utils/str.ts +0 -252
  54. package/src/utils/template-strings.ts +0 -132
  55. package/src/utils/transferable.ts +0 -269
  56. package/src/utils/wait.ts +0 -40
  57. package/src/utils/xml.ts +0 -105
  58. package/src/zip/sd-zip.ts +0 -218
  59. package/tests/errors/errors.spec.ts +0 -196
  60. package/tests/extensions/array-extension.spec.ts +0 -790
  61. package/tests/extensions/map-extension.spec.ts +0 -147
  62. package/tests/extensions/set-extension.spec.ts +0 -74
  63. package/tests/types/date-only.spec.ts +0 -636
  64. package/tests/types/date-time.spec.ts +0 -391
  65. package/tests/types/lazy-gc-map.spec.ts +0 -692
  66. package/tests/types/time.spec.ts +0 -559
  67. package/tests/types/types.spec.ts +0 -55
  68. package/tests/types/uuid.spec.ts +0 -91
  69. package/tests/utils/bytes-utils.spec.ts +0 -230
  70. package/tests/utils/date-format.spec.ts +0 -371
  71. package/tests/utils/debounce-queue.spec.ts +0 -272
  72. package/tests/utils/json.spec.ts +0 -475
  73. package/tests/utils/number.spec.ts +0 -184
  74. package/tests/utils/object.spec.ts +0 -827
  75. package/tests/utils/path.spec.ts +0 -78
  76. package/tests/utils/primitive.spec.ts +0 -55
  77. package/tests/utils/sd-event-emitter.spec.ts +0 -216
  78. package/tests/utils/serial-queue.spec.ts +0 -365
  79. package/tests/utils/string.spec.ts +0 -294
  80. package/tests/utils/template-strings.spec.ts +0 -96
  81. package/tests/utils/transferable.spec.ts +0 -698
  82. package/tests/utils/wait.spec.ts +0 -145
  83. package/tests/utils/xml.spec.ts +0 -146
  84. 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
- });