@simplysm/core-common 13.0.69 → 13.0.71

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 (151) hide show
  1. package/README.md +66 -267
  2. package/dist/common.types.d.ts +14 -14
  3. package/dist/errors/argument-error.d.ts +10 -10
  4. package/dist/errors/argument-error.d.ts.map +1 -1
  5. package/dist/errors/argument-error.js +2 -2
  6. package/dist/errors/argument-error.js.map +1 -1
  7. package/dist/errors/not-implemented-error.d.ts +8 -8
  8. package/dist/errors/not-implemented-error.js +2 -2
  9. package/dist/errors/not-implemented-error.js.map +1 -1
  10. package/dist/errors/sd-error.d.ts +10 -10
  11. package/dist/errors/sd-error.d.ts.map +1 -1
  12. package/dist/errors/timeout-error.d.ts +10 -10
  13. package/dist/errors/timeout-error.js +3 -3
  14. package/dist/errors/timeout-error.js.map +1 -1
  15. package/dist/extensions/arr-ext.d.ts +2 -2
  16. package/dist/extensions/arr-ext.helpers.d.ts +8 -8
  17. package/dist/extensions/arr-ext.helpers.js +1 -1
  18. package/dist/extensions/arr-ext.helpers.js.map +1 -1
  19. package/dist/extensions/arr-ext.js +13 -13
  20. package/dist/extensions/arr-ext.js.map +1 -1
  21. package/dist/extensions/arr-ext.types.d.ts +57 -57
  22. package/dist/extensions/arr-ext.types.d.ts.map +1 -1
  23. package/dist/extensions/map-ext.d.ts +16 -16
  24. package/dist/extensions/set-ext.d.ts +11 -11
  25. package/dist/features/debounce-queue.d.ts +17 -15
  26. package/dist/features/debounce-queue.d.ts.map +1 -1
  27. package/dist/features/debounce-queue.js +6 -6
  28. package/dist/features/debounce-queue.js.map +1 -1
  29. package/dist/features/event-emitter.d.ts +20 -20
  30. package/dist/features/event-emitter.js +17 -17
  31. package/dist/features/serial-queue.d.ts +11 -11
  32. package/dist/features/serial-queue.js +5 -5
  33. package/dist/features/serial-queue.js.map +1 -1
  34. package/dist/globals.d.ts +4 -4
  35. package/dist/types/date-only.d.ts +64 -64
  36. package/dist/types/date-only.d.ts.map +1 -1
  37. package/dist/types/date-only.js +63 -63
  38. package/dist/types/date-time.d.ts +37 -37
  39. package/dist/types/date-time.d.ts.map +1 -1
  40. package/dist/types/date-time.js +54 -37
  41. package/dist/types/date-time.js.map +1 -1
  42. package/dist/types/lazy-gc-map.d.ts +26 -26
  43. package/dist/types/lazy-gc-map.d.ts.map +1 -1
  44. package/dist/types/lazy-gc-map.js +26 -26
  45. package/dist/types/lazy-gc-map.js.map +1 -1
  46. package/dist/types/time.d.ts +25 -25
  47. package/dist/types/time.d.ts.map +1 -1
  48. package/dist/types/time.js +25 -25
  49. package/dist/types/time.js.map +1 -1
  50. package/dist/types/uuid.d.ts +11 -11
  51. package/dist/types/uuid.d.ts.map +1 -1
  52. package/dist/types/uuid.js +12 -12
  53. package/dist/types/uuid.js.map +1 -1
  54. package/dist/utils/bytes.d.ts +17 -17
  55. package/dist/utils/bytes.js +4 -4
  56. package/dist/utils/bytes.js.map +1 -1
  57. package/dist/utils/date-format.d.ts +45 -45
  58. package/dist/utils/date-format.js +1 -1
  59. package/dist/utils/date-format.js.map +1 -1
  60. package/dist/utils/error.d.ts +4 -4
  61. package/dist/utils/json.d.ts +17 -17
  62. package/dist/utils/json.js +3 -3
  63. package/dist/utils/json.js.map +1 -1
  64. package/dist/utils/num.d.ts +23 -23
  65. package/dist/utils/obj.d.ts +111 -111
  66. package/dist/utils/obj.d.ts.map +1 -1
  67. package/dist/utils/obj.js +3 -3
  68. package/dist/utils/obj.js.map +1 -1
  69. package/dist/utils/path.d.ts +10 -10
  70. package/dist/utils/primitive.d.ts +5 -5
  71. package/dist/utils/primitive.js +1 -1
  72. package/dist/utils/primitive.js.map +1 -1
  73. package/dist/utils/str.d.ts +46 -46
  74. package/dist/utils/str.d.ts.map +1 -1
  75. package/dist/utils/str.js +5 -5
  76. package/dist/utils/str.js.map +1 -1
  77. package/dist/utils/template-strings.d.ts +26 -26
  78. package/dist/utils/transferable.d.ts +18 -18
  79. package/dist/utils/transferable.js +1 -1
  80. package/dist/utils/transferable.js.map +1 -1
  81. package/dist/utils/wait.d.ts +9 -9
  82. package/dist/utils/xml.d.ts +13 -13
  83. package/dist/utils/xml.d.ts.map +1 -1
  84. package/dist/utils/xml.js +1 -0
  85. package/dist/utils/xml.js.map +1 -1
  86. package/dist/zip/sd-zip.d.ts +22 -22
  87. package/dist/zip/sd-zip.js +16 -16
  88. package/package.json +4 -4
  89. package/src/common.types.ts +17 -17
  90. package/src/errors/argument-error.ts +15 -15
  91. package/src/errors/not-implemented-error.ts +9 -9
  92. package/src/errors/sd-error.ts +12 -12
  93. package/src/errors/timeout-error.ts +12 -12
  94. package/src/extensions/arr-ext.helpers.ts +10 -10
  95. package/src/extensions/arr-ext.ts +57 -57
  96. package/src/extensions/arr-ext.types.ts +59 -59
  97. package/src/extensions/map-ext.ts +16 -16
  98. package/src/extensions/set-ext.ts +11 -11
  99. package/src/features/debounce-queue.ts +21 -19
  100. package/src/features/event-emitter.ts +25 -25
  101. package/src/features/serial-queue.ts +13 -13
  102. package/src/globals.ts +4 -4
  103. package/src/index.ts +1 -1
  104. package/src/types/date-only.ts +83 -83
  105. package/src/types/date-time.ts +64 -44
  106. package/src/types/lazy-gc-map.ts +45 -45
  107. package/src/types/time.ts +34 -34
  108. package/src/types/uuid.ts +17 -17
  109. package/src/utils/bytes.ts +35 -35
  110. package/src/utils/date-format.ts +65 -65
  111. package/src/utils/error.ts +4 -4
  112. package/src/utils/json.ts +39 -39
  113. package/src/utils/num.ts +23 -23
  114. package/src/utils/obj.ts +138 -138
  115. package/src/utils/path.ts +10 -10
  116. package/src/utils/primitive.ts +6 -6
  117. package/src/utils/str.ts +260 -261
  118. package/src/utils/template-strings.ts +29 -29
  119. package/src/utils/transferable.ts +284 -284
  120. package/src/utils/wait.ts +10 -10
  121. package/src/utils/xml.ts +20 -19
  122. package/src/zip/sd-zip.ts +25 -25
  123. package/tests/errors/errors.spec.ts +80 -0
  124. package/tests/extensions/array-extension.spec.ts +796 -0
  125. package/tests/extensions/map-extension.spec.ts +147 -0
  126. package/tests/extensions/set-extension.spec.ts +74 -0
  127. package/tests/types/date-only.spec.ts +638 -0
  128. package/tests/types/date-time.spec.ts +391 -0
  129. package/tests/types/lazy-gc-map.spec.ts +692 -0
  130. package/tests/types/time.spec.ts +559 -0
  131. package/tests/types/uuid.spec.ts +74 -0
  132. package/tests/utils/bytes-utils.spec.ts +230 -0
  133. package/tests/utils/date-format.spec.ts +373 -0
  134. package/tests/utils/debounce-queue.spec.ts +272 -0
  135. package/tests/utils/json.spec.ts +486 -0
  136. package/tests/utils/number.spec.ts +157 -0
  137. package/tests/utils/object.spec.ts +829 -0
  138. package/tests/utils/path.spec.ts +78 -0
  139. package/tests/utils/primitive.spec.ts +43 -0
  140. package/tests/utils/sd-event-emitter.spec.ts +216 -0
  141. package/tests/utils/serial-queue.spec.ts +365 -0
  142. package/tests/utils/string.spec.ts +281 -0
  143. package/tests/utils/template-strings.spec.ts +57 -0
  144. package/tests/utils/transferable.spec.ts +703 -0
  145. package/tests/utils/wait.spec.ts +145 -0
  146. package/tests/utils/xml.spec.ts +146 -0
  147. package/tests/zip/sd-zip.spec.ts +238 -0
  148. package/docs/extensions.md +0 -503
  149. package/docs/features.md +0 -109
  150. package/docs/types.md +0 -486
  151. package/docs/utils.md +0 -780
@@ -2,10 +2,10 @@ import { ArgumentError } from "../errors/argument-error";
2
2
  import { formatDate, normalizeMonth } from "../utils/date-format";
3
3
 
4
4
  /**
5
- * 날짜 클래스 (시간제외: yyyy-MM-dd, 불변)
5
+ * Date class (without time: yyyy-MM-dd, immutable)
6
6
  *
7
- * 시간 정보 없이 날짜만 저장하는 불변 클래스이다.
8
- * 로컬 타임존을 기준으로 동작한다.
7
+ * An immutable class that stores only the date without time information.
8
+ * Operates based on local timezone.
9
9
  *
10
10
  * @example
11
11
  * const today = new DateOnly();
@@ -17,13 +17,13 @@ export class DateOnly {
17
17
 
18
18
  readonly date: Date;
19
19
 
20
- /** 현재시간 */
20
+ /** Current time */
21
21
  constructor();
22
- /** 연월일로 초기화 */
22
+ /** Initialize with year, month, day */
23
23
  constructor(year: number, month: number, day: number);
24
- /** tick (millisecond)으로 생성 */
24
+ /** Create from tick (millisecond) */
25
25
  constructor(tick: number);
26
- /** Date 타입으로 생성 */
26
+ /** Create from Date type */
27
27
  constructor(date: Date);
28
28
  constructor(arg1?: number | Date, arg2?: number, arg3?: number) {
29
29
  if (arg1 === undefined) {
@@ -42,26 +42,26 @@ export class DateOnly {
42
42
  }
43
43
 
44
44
  /**
45
- * 문자열을 DateOnly로 파싱
46
- * @param str 날짜 문자열
47
- * @returns DateOnly 인스턴스
45
+ * Parse a string into DateOnly
46
+ * @param str Date string
47
+ * @returns DateOnly instance
48
48
  *
49
- * 지원 형식:
50
- * - `yyyy-MM-dd` (예: '2024-01-15') - 문자열에서 직접 추출, 타임존 영향 없음
51
- * - `yyyyMMdd` (예: '20240115') - 문자열에서 직접 추출, 타임존 영향 없음
52
- * - ISO 8601 (예: '2024-01-15T00:00:00Z') - UTC 해석 로컬 타임존 변환
49
+ * Supported formats:
50
+ * - `yyyy-MM-dd` (e.g., '2024-01-15') - Extracted directly from string, timezone-independent
51
+ * - `yyyyMMdd` (e.g., '20240115') - Extracted directly from string, timezone-independent
52
+ * - ISO 8601 (e.g., '2024-01-15T00:00:00Z') - Interpreted as UTC, then converted to local timezone
53
53
  *
54
- * @note 서버/클라이언트 타임존이 다른 경우 `yyyy-MM-dd` 형식 사용 권장
55
- * @note DST(일광절약시간) 지역에서 ISO 8601 형식 파싱 시, 파싱 대상 날짜의 오프셋을 사용합니다.
54
+ * @note For different server/client timezones, `yyyy-MM-dd` format is recommended
55
+ * @note For DST regions when parsing ISO 8601 format, the offset of the parsing target date is used.
56
56
  */
57
57
  static parse(str: string): DateOnly {
58
- // yyyy-MM-dd 형식 (타임존 영향 없음)
58
+ // yyyy-MM-dd format (timezone-independent)
59
59
  const matchYMD = /^(\d{4})-(\d{2})-(\d{2})$/.exec(str);
60
60
  if (matchYMD != null) {
61
61
  return new DateOnly(Number(matchYMD[1]), Number(matchYMD[2]), Number(matchYMD[3]));
62
62
  }
63
63
 
64
- // yyyyMMdd 형식 (타임존 영향 없음)
64
+ // yyyyMMdd format (timezone-independent)
65
65
  const matchCompact = /^(\d{4})(\d{2})(\d{2})$/.exec(str);
66
66
  if (matchCompact != null) {
67
67
  return new DateOnly(
@@ -71,11 +71,11 @@ export class DateOnly {
71
71
  );
72
72
  }
73
73
 
74
- // ISO 8601 기타 형식 (Date.parse 사용, 타임존 변환 적용)
75
- // Date.parse() 'Z' 접미사가 있는 ISO 8601 UTC tick으로 반환
76
- // getTimezoneOffset() "로컬에서 UTC로 변환할 더할 " 반환 (KST -540 = UTC+9)
77
- // 여기서는 "UTC → 로컬" 변환이므로 부호를 반대로 적용 (뺄셈)
78
- // 파싱 대상 날짜의 오프셋을 사용하여 DST 지역에서도 정확한 변환
74
+ // ISO 8601 and other formats (using Date.parse, timezone conversion applied)
75
+ // Date.parse() returns UTC tick for ISO 8601 with 'Z' suffix
76
+ // getTimezoneOffset() returns "minutes to add when converting from local to UTC" (KST is -540 = UTC+9)
77
+ // Here we do "UTC → local" conversion, so apply opposite sign (subtraction)
78
+ // Use the offset of the parsing target date for accurate conversion in DST regions
79
79
  const utcTick = Date.parse(str);
80
80
  if (!Number.isNaN(utcTick)) {
81
81
  const tempDate = new Date(utcTick);
@@ -85,45 +85,45 @@ export class DateOnly {
85
85
  }
86
86
 
87
87
  throw new ArgumentError(
88
- `날짜 형식을 파싱할 없습니다. 지원 형식: 'yyyy-MM-dd', 'yyyyMMdd', ISO 8601 날짜`,
88
+ `Failed to parse date format. Supported formats: 'yyyy-MM-dd', 'yyyyMMdd', ISO 8601 date`,
89
89
  {
90
90
  input: str,
91
91
  },
92
92
  );
93
93
  }
94
94
 
95
- //#region 주차 계산
95
+ //#region Week calculation
96
96
 
97
97
  /**
98
- * 기준 연도와 월을 주차 정보를 기반으로 반환
99
- * @param weekStartDay 주의 시작 요일 (0=일요일, 1=월요일, ..., 6=토요일). 기본값: 1(월요일)
100
- * @param minDaysInFirstWeek 주로 간주할 최소 일수 (1~7). 기본값: 4 (ISO 8601 표준)
101
- * @returns 해당 날짜가 속한 주차의 기준 연도와
98
+ * Return the base year and month based on week information
99
+ * @param weekStartDay Week start day (0=Sunday, 1=Monday, ..., 6=Saturday). Default: 1(Monday)
100
+ * @param minDaysInFirstWeek Minimum days to be considered the first week (1~7). Default: 4 (ISO 8601 standard)
101
+ * @returns Base year and month of the week containing this date
102
102
  *
103
103
  * @example
104
- * // ISO 8601 표준 (월요일 시작, 최소 4)
104
+ * // ISO 8601 standard (Monday start, first week minimum 4 days)
105
105
  * new DateOnly(2024, 1, 1).getBaseYearMonthSeqForWeekSeq(1, 4)
106
- * // 미국식 (일요일 시작, 최소 1)
106
+ * // US style (Sunday start, first week minimum 1 day)
107
107
  * new DateOnly(2024, 1, 1).getBaseYearMonthSeqForWeekSeq(0, 1)
108
108
  */
109
109
  getBaseYearMonthSeqForWeekSeq(weekStartDay: number = 1, minDaysInFirstWeek: number = 4) {
110
- // 주의 시작 요일 기준으로 현재 날짜의 요일 인덱스 계산 (0 = 시작일)
110
+ // Calculate day of week index based on week start day (0 = week start day)
111
111
  const dayOfWeek = (this.dayOfWeek + 7 - weekStartDay) % 7;
112
- // 현재 주의 남은 일수 (현재 날짜 포함)
112
+ // Remaining days in the current week (including current date)
113
113
  const daysInWeek = 7 - dayOfWeek;
114
114
 
115
- // 현재 주의 남은 일수가 최소 일수 미만이면 이전 주로 간주
115
+ // If remaining days in current week is less than minimum, consider as previous week
116
116
  if (daysInWeek < minDaysInFirstWeek) {
117
117
  const prevWeek = this.addDays(-7);
118
118
  return { year: prevWeek.year, monthSeq: prevWeek.month };
119
119
  } else {
120
- // 경계를 고려한 실제 주의 남은 일수 계산
120
+ // Calculate actual remaining days of the week considering month boundary
121
121
  const nextMonthDate = this.addMonths(1).setDay(1);
122
122
  const remainedDays = (nextMonthDate.tick - this.tick) / DateOnly.MS_PER_DAY;
123
123
 
124
- // 경계까지의 실제 일수와 주의 남은 일수 작은
124
+ // Take the smaller of actual days to month boundary and week remaining days
125
125
  const realDaysInWeek = Math.min(daysInWeek, remainedDays);
126
- // 경계 고려 시에도 최소 일수 미만이면 다음 주로 간주
126
+ // If still less than minimum when considering month boundary, consider as next week
127
127
  if (realDaysInWeek < minDaysInFirstWeek) {
128
128
  const nextWeek = this.addDays(7);
129
129
  return { year: nextWeek.year, monthSeq: nextWeek.month };
@@ -134,10 +134,10 @@ export class DateOnly {
134
134
  }
135
135
 
136
136
  /**
137
- * 주차 정보를 기반으로 해당 주의 시작 날짜 계산
138
- * @param weekStartDay 주의 시작 요일 (0=일요일, 1=월요일, ..., 6=토요일). 기본값: 1(월요일)
139
- * @param minDaysInFirstWeek 주로 간주할 최소 일수 (1~7). 기본값: 4 (ISO 8601 표준)
140
- * @returns 해당 날짜가 속한 주의 시작 날짜
137
+ * Calculate the start date of the week based on week information
138
+ * @param weekStartDay Week start day (0=Sunday, 1=Monday, ..., 6=Saturday). Default: 1(Monday)
139
+ * @param minDaysInFirstWeek Minimum days to be considered the first week (1~7). Default: 4 (ISO 8601 standard)
140
+ * @returns Start date of the week containing this date
141
141
  */
142
142
  getWeekSeqStartDate(weekStartDay: number = 1, minDaysInFirstWeek: number = 4) {
143
143
  const dayOfWeek = (this.dayOfWeek + 7 - weekStartDay) % 7;
@@ -151,16 +151,16 @@ export class DateOnly {
151
151
  }
152
152
 
153
153
  /**
154
- * 연도 주차 순서 정보를 반환
155
- * @param weekStartDay 주의 시작 요일 (0=일요일, 1=월요일, ..., 6=토요일). 기본값: 1(월요일)
156
- * @param minDaysInFirstWeek 주로 간주할 최소 일수 (1~7). 기본값: 4 (ISO 8601 표준)
157
- * @returns 연도와 해당 연도 기준 주차 번호
154
+ * Return year and week sequence information
155
+ * @param weekStartDay Week start day (0=Sunday, 1=Monday, ..., 6=Saturday). Default: 1(Monday)
156
+ * @param minDaysInFirstWeek Minimum days to be considered the first week (1~7). Default: 4 (ISO 8601 standard)
157
+ * @returns Year and week number within that year
158
158
  *
159
159
  * @example
160
- * // ISO 8601 표준 (월요일 시작, 4 이상)
160
+ * // ISO 8601 standard (Monday start, first week minimum 4 days)
161
161
  * new DateOnly(2025, 1, 6).getWeekSeqOfYear(); // { year: 2025, weekSeq: 2 }
162
162
  *
163
- * // 미국식 (일요일 시작, 1 이상)
163
+ * // US style (Sunday start, first week minimum 1 day)
164
164
  * new DateOnly(2025, 1, 1).getWeekSeqOfYear(0, 1); // { year: 2025, weekSeq: 1 }
165
165
  */
166
166
  getWeekSeqOfYear(
@@ -182,16 +182,16 @@ export class DateOnly {
182
182
  }
183
183
 
184
184
  /**
185
- * 해당 날짜의 연도, 주차(weekSeq) 정보를 반환
186
- * @param weekStartDay 주의 시작 요일 (0=일요일, 1=월요일, ..., 6=토요일). 기본값: 1(월요일)
187
- * @param minDaysInFirstWeek 주로 간주할 최소 일수 (1~7). 기본값: 4 (ISO 8601 표준)
188
- * @returns 연도, 해당 기준 주차 번호
185
+ * Return year, month and week sequence information for the given date
186
+ * @param weekStartDay Week start day (0=Sunday, 1=Monday, ..., 6=Saturday). Default: 1(Monday)
187
+ * @param minDaysInFirstWeek Minimum days to be considered the first week (1~7). Default: 4 (ISO 8601 standard)
188
+ * @returns Year, month and week number within that month
189
189
  *
190
190
  * @example
191
- * // ISO 8601 표준 (월요일 시작, 4 이상)
191
+ * // ISO 8601 standard (Monday start, first week minimum 4 days)
192
192
  * new DateOnly(2025, 1, 15).getWeekSeqOfMonth(); // { year: 2025, monthSeq: 1, weekSeq: 3 }
193
193
  *
194
- * // 미국식 (일요일 시작, 1 이상)
194
+ * // US style (Sunday start, first week minimum 1 day)
195
195
  * new DateOnly(2025, 1, 15).getWeekSeqOfMonth(0, 1); // { year: 2025, monthSeq: 1, weekSeq: 3 }
196
196
  */
197
197
  getWeekSeqOfMonth(
@@ -214,18 +214,18 @@ export class DateOnly {
214
214
  }
215
215
 
216
216
  /**
217
- * 주차 정보를 기반으로 해당 주의 시작 날짜 가져오기
218
- * @param arg 연도, 선택적 월, 주차 번호
219
- * @param weekStartDay 주의 시작 요일 (0=일요일, 1=월요일, ..., 6=토요일). 기본값: 1(월요일)
220
- * @param minDaysInFirstWeek 주로 간주할 최소 일수 (1~7). 기본값: 4 (ISO 8601 표준)
221
- * @returns 해당 주차의 시작 날짜
217
+ * Get the start date of a week based on week information
218
+ * @param arg Year, optional month, and week number
219
+ * @param weekStartDay Week start day (0=Sunday, 1=Monday, ..., 6=Saturday). Default: 1(Monday)
220
+ * @param minDaysInFirstWeek Minimum days to be considered the first week (1~7). Default: 4 (ISO 8601 standard)
221
+ * @returns Start date of the specified week
222
222
  *
223
223
  * @example
224
- * // 2025년 2주차의 시작일 (ISO 8601 표준)
225
- * DateOnly.getDateByYearWeekSeq({ year: 2025, weekSeq: 2 }); // 2025-01-06 (월요일)
224
+ * // Start date of week 2 in 2025 (ISO 8601 standard)
225
+ * DateOnly.getDateByYearWeekSeq({ year: 2025, weekSeq: 2 }); // 2025-01-06 (Monday)
226
226
  *
227
- * // 2025년 1월 3주차의 시작일
228
- * DateOnly.getDateByYearWeekSeq({ year: 2025, month: 1, weekSeq: 3 }); // 2025-01-13 (월요일)
227
+ * // Start date of week 3 in January 2025
228
+ * DateOnly.getDateByYearWeekSeq({ year: 2025, month: 1, weekSeq: 3 }); // 2025-01-13 (Monday)
229
229
  */
230
230
  static getDateByYearWeekSeq(
231
231
  arg: { year: number; month?: number; weekSeq: number },
@@ -240,9 +240,9 @@ export class DateOnly {
240
240
 
241
241
  //#endregion
242
242
 
243
- //#region Getters (읽기 전용)
243
+ //#region Getters (read-only)
244
244
 
245
- /** 날짜 세팅이 제대로 되었는지 여부 */
245
+ /** Whether the date is set correctly */
246
246
  get isValid(): boolean {
247
247
  return this.date instanceof Date && !Number.isNaN(this.date.getTime());
248
248
  }
@@ -263,25 +263,25 @@ export class DateOnly {
263
263
  return this.date.getTime();
264
264
  }
265
265
 
266
- /** 요일 (일~토: 0~6) */
266
+ /** Day of week (Sunday~Saturday: 0~6) */
267
267
  get dayOfWeek(): number {
268
268
  return this.date.getDay();
269
269
  }
270
270
 
271
271
  //#endregion
272
272
 
273
- //#region 불변 변환 메서드 ( 인스턴스 반환)
273
+ //#region Immutable transformation methods (returns new instance)
274
274
 
275
- /** 지정된 연도로 인스턴스 반환 */
275
+ /** Return new instance with specified year */
276
276
  setYear(year: number): DateOnly {
277
277
  return new DateOnly(year, this.month, this.day);
278
278
  }
279
279
 
280
280
  /**
281
- * 지정된 월로 DateOnly 인스턴스를 반환
282
- * @param month 설정할 (1-12, 범위 값은 연도 조정)
283
- * @note 대상 월의 일수보다 현재 일자가 크면 해당 월의 마지막 날로 조정됨
284
- * (예: 1월 31일에서 setMonth(2) → 2월 28 또는 29)
281
+ * Return new DateOnly instance with specified month
282
+ * @param month Month to set (1-12, out-of-range values are adjusted in year)
283
+ * @note If current day is greater than target month's day count, it will be adjusted to last day of month
284
+ * (e.g., setMonth(2) on Jan 31 Feb 28 or 29)
285
285
  */
286
286
  setMonth(month: number): DateOnly {
287
287
  const normalized = normalizeMonth(this.year, month, this.day);
@@ -289,10 +289,10 @@ export class DateOnly {
289
289
  }
290
290
 
291
291
  /**
292
- * 지정된 일자로 DateOnly 인스턴스를 반환
293
- * @param day 설정할 일자
294
- * @note 해당 월의 유효 범위를 벗어나는 일자는 JavaScript Date 기본 동작에 따라
295
- * 자동으로 다음/이전 달로 조정됨 (예: 1월에 day=32 → 2월 1)
292
+ * Return new DateOnly instance with specified day
293
+ * @param day Day to set
294
+ * @note Days outside valid month range are automatically adjusted to next/previous month per JavaScript Date behavior
295
+ * (e.g., day=32 in January February 1)
296
296
  */
297
297
  setDay(day: number): DateOnly {
298
298
  return new DateOnly(this.year, this.month, day);
@@ -300,31 +300,31 @@ export class DateOnly {
300
300
 
301
301
  //#endregion
302
302
 
303
- //#region 산술 메서드 ( 인스턴스 반환)
303
+ //#region Arithmetic methods (returns new instance)
304
304
 
305
- /** 지정된 연수를 더한 인스턴스 반환 */
305
+ /** Return new instance with specified years added */
306
306
  addYears(years: number): DateOnly {
307
307
  return this.setYear(this.year + years);
308
308
  }
309
309
 
310
- /** 지정된 월수를 더한 인스턴스 반환 */
310
+ /** Return new instance with specified months added */
311
311
  addMonths(months: number): DateOnly {
312
312
  return this.setMonth(this.month + months);
313
313
  }
314
314
 
315
- /** 지정된 일수를 더한 인스턴스 반환 */
315
+ /** Return new instance with specified days added */
316
316
  addDays(days: number): DateOnly {
317
317
  return new DateOnly(this.tick + days * DateOnly.MS_PER_DAY);
318
318
  }
319
319
 
320
320
  //#endregion
321
321
 
322
- //#region 포맷팅
322
+ //#region Formatting
323
323
 
324
324
  /**
325
- * 지정된 포맷으로 문자열 변환
326
- * @param format 포맷 문자열
327
- * @see dtFormat 지원 포맷 문자열 참조
325
+ * Convert to string with specified format
326
+ * @param format Format string
327
+ * @see dtFormat for supported format strings
328
328
  */
329
329
  toFormatString(formatStr: string): string {
330
330
  return formatDate(formatStr, {
@@ -2,10 +2,10 @@ import { ArgumentError } from "../errors/argument-error";
2
2
  import { convert12To24, formatDate, normalizeMonth } from "../utils/date-format";
3
3
 
4
4
  /**
5
- * 날짜시간 클래스 (불변)
5
+ * DateTime class (immutable)
6
6
  *
7
- * JavaScript Date 객체를 래핑하여 불변성과 편리한 API를 제공한다.
8
- * 밀리초 단위까지 지원하며, 로컬 타임존을 기준으로 동작한다.
7
+ * Wraps JavaScript Date object to provide immutability and convenient API.
8
+ * Supports millisecond precision and operates based on local timezone.
9
9
  *
10
10
  * @example
11
11
  * const now = new DateTime();
@@ -15,9 +15,9 @@ import { convert12To24, formatDate, normalizeMonth } from "../utils/date-format"
15
15
  export class DateTime {
16
16
  readonly date: Date;
17
17
 
18
- /** 현재 시간으로 생성 */
18
+ /** Create with current time */
19
19
  constructor();
20
- /** 연월일시분초밀리초로 생성 */
20
+ /** Create with year, month, day, hour, minute, second, millisecond */
21
21
  constructor(
22
22
  year: number,
23
23
  month: number,
@@ -27,9 +27,9 @@ export class DateTime {
27
27
  second?: number,
28
28
  millisecond?: number,
29
29
  );
30
- /** tick (밀리초)으로 생성 */
30
+ /** Create from tick (millisecond) */
31
31
  constructor(tick: number);
32
- /** Date 객체로 생성 */
32
+ /** Create from Date object */
33
33
  constructor(date: Date);
34
34
  constructor(
35
35
  arg1?: number | Date,
@@ -60,17 +60,17 @@ export class DateTime {
60
60
  }
61
61
 
62
62
  /**
63
- * 문자열을 파싱하여 DateTime 인스턴스를 생성
63
+ * Parse a string to create DateTime instance
64
64
  *
65
- * @param str 날짜시간 문자열
66
- * @returns 파싱된 DateTime 인스턴스
67
- * @throws ArgumentError 지원하지 않는 형식인 경우
65
+ * @param str DateTime string
66
+ * @returns Parsed DateTime instance
67
+ * @throws ArgumentError If unsupported format
68
68
  *
69
69
  * @example
70
70
  * DateTime.parse("2025-01-15 10:30:00") // yyyy-MM-dd HH:mm:ss
71
71
  * DateTime.parse("2025-01-15 10:30:00.123") // yyyy-MM-dd HH:mm:ss.fff
72
72
  * DateTime.parse("20250115103000") // yyyyMMddHHmmss
73
- * DateTime.parse("2025-01-15 오전 10:30:00") // yyyy-MM-dd 오전/오후 HH:mm:ss
73
+ * DateTime.parse("2025-01-15 AM 10:30:00") // yyyy-MM-dd AM/PM HH:mm:ss
74
74
  * DateTime.parse("2025-01-15T10:30:00Z") // ISO 8601
75
75
  */
76
76
  static parse(str: string): DateTime {
@@ -80,12 +80,12 @@ export class DateTime {
80
80
  }
81
81
 
82
82
  const match1 =
83
- /^([0-9]{4})-([0-9]{2})-([0-9]{2}) (오전|오후) ([0-9]{1,2}):([0-9]{2}):([0-9]{2})(\.([0-9]{1,3}))?$/.exec(
83
+ /^([0-9]{4})-([0-9]{2})-([0-9]{2}) (AM|PM) ([0-9]{1,2}):([0-9]{2}):([0-9]{2})(\.([0-9]{1,3}))?$/i.exec(
84
84
  str,
85
85
  );
86
86
  if (match1 != null) {
87
87
  const rawHour = Number(match1[5]);
88
- const isPM = match1[4] === "오후";
88
+ const isPM = match1[4].toUpperCase() === "PM";
89
89
  const hour = convert12To24(rawHour, isPM);
90
90
  return new DateTime(
91
91
  Number(match1[1]),
@@ -98,6 +98,26 @@ export class DateTime {
98
98
  );
99
99
  }
100
100
 
101
+ // Korean AM/PM format (오전/오후)
102
+ const matchKorean =
103
+ /^([0-9]{4})-([0-9]{2})-([0-9]{2}) (오전|오후) ([0-9]{1,2}):([0-9]{2}):([0-9]{2})(\.([0-9]{1,3}))?$/.exec(
104
+ str,
105
+ );
106
+ if (matchKorean != null) {
107
+ const rawHour = Number(matchKorean[5]);
108
+ const isPM = matchKorean[4] === "오후";
109
+ const hour = convert12To24(rawHour, isPM);
110
+ return new DateTime(
111
+ Number(matchKorean[1]),
112
+ Number(matchKorean[2]),
113
+ Number(matchKorean[3]),
114
+ hour,
115
+ Number(matchKorean[6]),
116
+ Number(matchKorean[7]),
117
+ matchKorean[9] ? Number(matchKorean[9].padEnd(3, "0")) : undefined,
118
+ );
119
+ }
120
+
101
121
  const match2 = /^[0-9]{14}$/.exec(str);
102
122
  if (match2 != null) {
103
123
  return new DateTime(
@@ -127,12 +147,12 @@ export class DateTime {
127
147
  }
128
148
 
129
149
  throw new ArgumentError(
130
- `날짜시간 형식을 파싱할 없습니다. 지원 형식: 'yyyy-MM-dd HH:mm:ss', 'yyyyMMddHHmmss', 'yyyy-MM-dd 오전/오후 HH:mm:ss', ISO 8601`,
150
+ `Failed to parse datetime format. Supported formats: 'yyyy-MM-dd HH:mm:ss', 'yyyyMMddHHmmss', 'yyyy-MM-dd AM/PM HH:mm:ss', ISO 8601`,
131
151
  { input: str },
132
152
  );
133
153
  }
134
154
 
135
- //#region Getters (읽기 전용)
155
+ //#region Getters (read-only)
136
156
 
137
157
  get year(): number {
138
158
  return this.date.getFullYear();
@@ -166,7 +186,7 @@ export class DateTime {
166
186
  return this.date.getTime();
167
187
  }
168
188
 
169
- /** 요일 (일~토: 0~6) */
189
+ /** Day of week (Sunday~Saturday: 0~6) */
170
190
  get dayOfWeek(): number {
171
191
  return this.date.getDay();
172
192
  }
@@ -175,16 +195,16 @@ export class DateTime {
175
195
  return -this.date.getTimezoneOffset();
176
196
  }
177
197
 
178
- /** 날짜시간 세팅이 제대로 되었는지 여부 */
198
+ /** Whether the datetime is set correctly */
179
199
  get isValid(): boolean {
180
200
  return this.date instanceof Date && !Number.isNaN(this.date.getTime());
181
201
  }
182
202
 
183
203
  //#endregion
184
204
 
185
- //#region 불변 변환 메서드 ( 인스턴스 반환)
205
+ //#region Immutable transformation methods (returns new instance)
186
206
 
187
- /** 지정된 연도로 인스턴스 반환 */
207
+ /** Return new instance with specified year */
188
208
  setYear(year: number): DateTime {
189
209
  return new DateTime(
190
210
  year,
@@ -198,10 +218,10 @@ export class DateTime {
198
218
  }
199
219
 
200
220
  /**
201
- * 지정된 월로 DateTime 인스턴스를 반환
202
- * @param month 설정할 (1-12, 범위 값은 연도 조정)
203
- * @note 대상 월의 일수보다 현재 일자가 크면 해당 월의 마지막 날로 조정됨
204
- * (예: 1월 31일에서 setMonth(2) → 2월 28 또는 29)
221
+ * Return new DateTime instance with specified month
222
+ * @param month Month to set (1-12, out-of-range values are adjusted in year)
223
+ * @note If current day is greater than target month's day count, it will be adjusted to last day of month
224
+ * (e.g., setMonth(2) on Jan 31 Feb 28 or 29)
205
225
  */
206
226
  setMonth(month: number): DateTime {
207
227
  const normalized = normalizeMonth(this.year, month, this.day);
@@ -217,10 +237,10 @@ export class DateTime {
217
237
  }
218
238
 
219
239
  /**
220
- * 지정된 일자로 DateTime 인스턴스를 반환
221
- * @param day 설정할 일자
222
- * @note 해당 월의 유효 범위를 벗어나는 일자는 JavaScript Date 기본 동작에 따라
223
- * 자동으로 다음/이전 달로 조정됨 (예: 1월에 day=32 → 2월 1)
240
+ * Return new DateTime instance with specified day
241
+ * @param day Day to set
242
+ * @note Days outside valid month range are automatically adjusted to next/previous month per JavaScript Date behavior
243
+ * (e.g., day=32 in January February 1)
224
244
  */
225
245
  setDay(day: number): DateTime {
226
246
  return new DateTime(
@@ -234,7 +254,7 @@ export class DateTime {
234
254
  );
235
255
  }
236
256
 
237
- /** 지정된 시로 인스턴스 반환 */
257
+ /** Return new instance with specified hour */
238
258
  setHour(hour: number): DateTime {
239
259
  return new DateTime(
240
260
  this.year,
@@ -247,7 +267,7 @@ export class DateTime {
247
267
  );
248
268
  }
249
269
 
250
- /** 지정된 분으로 인스턴스 반환 */
270
+ /** Return new instance with specified minute */
251
271
  setMinute(minute: number): DateTime {
252
272
  return new DateTime(
253
273
  this.year,
@@ -260,7 +280,7 @@ export class DateTime {
260
280
  );
261
281
  }
262
282
 
263
- /** 지정된 초로 인스턴스 반환 */
283
+ /** Return new instance with specified second */
264
284
  setSecond(second: number): DateTime {
265
285
  return new DateTime(
266
286
  this.year,
@@ -273,7 +293,7 @@ export class DateTime {
273
293
  );
274
294
  }
275
295
 
276
- /** 지정된 밀리초로 인스턴스 반환 */
296
+ /** Return new instance with specified millisecond */
277
297
  setMillisecond(millisecond: number): DateTime {
278
298
  return new DateTime(
279
299
  this.year,
@@ -288,51 +308,51 @@ export class DateTime {
288
308
 
289
309
  //#endregion
290
310
 
291
- //#region 산술 메서드 ( 인스턴스 반환)
311
+ //#region Arithmetic methods (returns new instance)
292
312
 
293
- /** 지정된 연수를 더한 인스턴스 반환 */
313
+ /** Return new instance with specified years added */
294
314
  addYears(years: number): DateTime {
295
315
  return this.setYear(this.year + years);
296
316
  }
297
317
 
298
- /** 지정된 월수를 더한 인스턴스 반환 */
318
+ /** Return new instance with specified months added */
299
319
  addMonths(months: number): DateTime {
300
320
  return this.setMonth(this.month + months);
301
321
  }
302
322
 
303
- /** 지정된 일수를 더한 인스턴스 반환 */
323
+ /** Return new instance with specified days added */
304
324
  addDays(days: number): DateTime {
305
325
  return new DateTime(this.tick + days * 24 * 60 * 60 * 1000);
306
326
  }
307
327
 
308
- /** 지정된 시간을 더한 인스턴스 반환 */
328
+ /** Return new instance with specified hours added */
309
329
  addHours(hours: number): DateTime {
310
330
  return new DateTime(this.tick + hours * 60 * 60 * 1000);
311
331
  }
312
332
 
313
- /** 지정된 분을 더한 인스턴스 반환 */
333
+ /** Return new instance with specified minutes added */
314
334
  addMinutes(minutes: number): DateTime {
315
335
  return new DateTime(this.tick + minutes * 60 * 1000);
316
336
  }
317
337
 
318
- /** 지정된 초를 더한 인스턴스 반환 */
338
+ /** Return new instance with specified seconds added */
319
339
  addSeconds(seconds: number): DateTime {
320
340
  return new DateTime(this.tick + seconds * 1000);
321
341
  }
322
342
 
323
- /** 지정된 밀리초를 더한 인스턴스 반환 */
343
+ /** Return new instance with specified milliseconds added */
324
344
  addMilliseconds(milliseconds: number): DateTime {
325
345
  return new DateTime(this.tick + milliseconds);
326
346
  }
327
347
 
328
348
  //#endregion
329
349
 
330
- //#region 포맷팅
350
+ //#region Formatting
331
351
 
332
352
  /**
333
- * 지정된 포맷으로 문자열 변환
334
- * @param format 포맷 문자열
335
- * @see dtFormat 지원 포맷 문자열 참조
353
+ * Convert to string with specified format
354
+ * @param format Format string
355
+ * @see dtFormat for supported format strings
336
356
  */
337
357
  toFormatString(formatStr: string): string {
338
358
  return formatDate(formatStr, {