@alexstukovnikov/oz-time 1.0.0 → 1.0.1
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/package.json +45 -48
- package/src/core/core.js +353 -0
- package/src/core/factory.js +194 -0
- package/src/index.js +22 -0
- package/src/modules/arithmetic.js +100 -0
- package/src/modules/compare.js +197 -0
- package/src/modules/duration.js +165 -0
- package/src/modules/format.js +162 -0
- package/src/modules/interval.js +190 -0
- package/src/modules/timezone.js +112 -0
- package/src/utils/calendar.js +277 -0
- package/src/utils/units.js +135 -0
- package/dist/oz-time.cjs +0 -1
- package/dist/oz-time.esm.js +0 -426
package/package.json
CHANGED
|
@@ -1,48 +1,45 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@alexstukovnikov/oz-time",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Lightweight JavaScript date-time library",
|
|
5
|
-
"repository": {
|
|
6
|
-
"type": "git",
|
|
7
|
-
"url": "https://github.com/AlexStukovnikov/oz-time.git"
|
|
8
|
-
},
|
|
9
|
-
"type": "module",
|
|
10
|
-
"main": "./
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"vitest": "^4.1.7"
|
|
47
|
-
}
|
|
48
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@alexstukovnikov/oz-time",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Lightweight JavaScript date-time library",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/AlexStukovnikov/oz-time.git"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"main": "./src/index.js",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": "./src/index.js"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"src",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"scripts": {
|
|
20
|
+
"dev": "vite",
|
|
21
|
+
"build": "vite build",
|
|
22
|
+
"test": "vitest",
|
|
23
|
+
"test:run": "vitest run",
|
|
24
|
+
"test:coverage": "vitest run --coverage",
|
|
25
|
+
"docs": "jsdoc -c jsdoc.json",
|
|
26
|
+
"docs:clean": "rimraf docs",
|
|
27
|
+
"docs:build": "npm run docs:clean && npm run docs",
|
|
28
|
+
"prepublishOnly": "npm run build"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"date",
|
|
32
|
+
"time",
|
|
33
|
+
"datetime"
|
|
34
|
+
],
|
|
35
|
+
"author": "",
|
|
36
|
+
"license": "ISC",
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@vitest/coverage-v8": "^4.1.7",
|
|
39
|
+
"@vitest/ui": "^4.1.7",
|
|
40
|
+
"docdash": "^2.0.2",
|
|
41
|
+
"jsdoc": "^4.0.5",
|
|
42
|
+
"vite": "^8.0.14",
|
|
43
|
+
"vitest": "^4.1.7"
|
|
44
|
+
}
|
|
45
|
+
}
|
package/src/core/core.js
ADDED
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import { add, subtract } from '../modules/arithmetic.js';
|
|
2
|
+
import { format } from '../modules/format.js';
|
|
3
|
+
import { isSame, isBefore, isAfter, isBetween } from '../modules/compare.js';
|
|
4
|
+
import { setTimezone, getTimezoneOffset } from '../modules/timezone.js';
|
|
5
|
+
import { diff } from '../utils/calendar.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Основной модуль, содержащий класс {@link OzTime}.
|
|
9
|
+
*
|
|
10
|
+
* @module core/core
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Строка с идентификатором часового пояса в формате IANA.
|
|
15
|
+
*
|
|
16
|
+
* @typedef {string} TimezoneString
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Строка локали, совместимая с Intl API.
|
|
21
|
+
*
|
|
22
|
+
* @typedef {string} LocaleString
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Формат включённости границ диапазона.
|
|
27
|
+
*
|
|
28
|
+
* @typedef {'[]'|'[)'|'(]'|'()'} Inclusivity
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Поддерживаемая единица времени.
|
|
33
|
+
*
|
|
34
|
+
* @typedef {'millisecond'|'second'|'minute'|'hour'|'day'|'month'|'year'} TimeUnit
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Проверяет корректность timestamp.
|
|
39
|
+
*
|
|
40
|
+
* @private
|
|
41
|
+
* @param {number} timestamp - Unix timestamp в миллисекундах.
|
|
42
|
+
* @throws {TypeError} Выбрасывается, если timestamp не является корректным числом.
|
|
43
|
+
* @returns {void}
|
|
44
|
+
*/
|
|
45
|
+
function assertValidTimestamp(timestamp) {
|
|
46
|
+
if (typeof timestamp !== 'number' || Number.isNaN(timestamp)) {
|
|
47
|
+
throw new TypeError('OzTime: timestamp must be a valid number');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Проверяет корректность строки часового пояса.
|
|
53
|
+
*
|
|
54
|
+
* @private
|
|
55
|
+
* @param {TimezoneString} timezone - Идентификатор часового пояса.
|
|
56
|
+
* @throws {TypeError} Выбрасывается, если timezone пустой или не является строкой.
|
|
57
|
+
* @returns {void}
|
|
58
|
+
*/
|
|
59
|
+
function assertValidTimezone(timezone) {
|
|
60
|
+
if (typeof timezone !== 'string' || timezone.trim() === '') {
|
|
61
|
+
throw new TypeError('OzTime: timezone must be a non-empty string');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Проверяет корректность строки локали.
|
|
67
|
+
*
|
|
68
|
+
* @private
|
|
69
|
+
* @param {LocaleString} locale - Локаль форматирования.
|
|
70
|
+
* @throws {TypeError} Выбрасывается, если locale пустая или не является строкой.
|
|
71
|
+
* @returns {void}
|
|
72
|
+
*/
|
|
73
|
+
function assertValidLocale(locale) {
|
|
74
|
+
if (typeof locale !== 'string' || locale.trim() === '') {
|
|
75
|
+
throw new TypeError('OzTime: locale must be a non-empty string');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Неизменяемый объект даты и времени на основе UTC timestamp
|
|
81
|
+
* с дополнительными метаданными о часовом поясе и локали.
|
|
82
|
+
*
|
|
83
|
+
* @class
|
|
84
|
+
*/
|
|
85
|
+
export class OzTime {
|
|
86
|
+
/**
|
|
87
|
+
* Создаёт новый экземпляр OzTime.
|
|
88
|
+
*
|
|
89
|
+
* @param {number} timestamp - Unix timestamp в миллисекундах.
|
|
90
|
+
* @param {TimezoneString} [timezone='UTC'] - Часовой пояс в формате IANA.
|
|
91
|
+
* @param {LocaleString} [locale='en-US'] - Локаль, используемая для форматирования.
|
|
92
|
+
* @throws {TypeError} Выбрасывается, если timestamp, timezone или locale некорректны.
|
|
93
|
+
*/
|
|
94
|
+
constructor(timestamp, timezone = 'UTC', locale = 'en-US') {
|
|
95
|
+
assertValidTimestamp(timestamp);
|
|
96
|
+
assertValidTimezone(timezone);
|
|
97
|
+
assertValidLocale(locale);
|
|
98
|
+
|
|
99
|
+
this._timestamp = timestamp;
|
|
100
|
+
this._timezone = timezone;
|
|
101
|
+
this._locale = locale;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Возвращает внутренний Unix timestamp экземпляра в миллисекундах.
|
|
106
|
+
*
|
|
107
|
+
* @returns {number} Unix timestamp в миллисекундах.
|
|
108
|
+
* @example
|
|
109
|
+
* import { fromISO } from '@alexstukovnikov/oz-time';
|
|
110
|
+
*
|
|
111
|
+
* const time = fromISO('2024-05-25T12:00:00Z', 'UTC', 'ru-RU');
|
|
112
|
+
* console.log(time.getTimestamp()); // ожидаемый результат: 1716638400000
|
|
113
|
+
*/
|
|
114
|
+
getTimestamp() {
|
|
115
|
+
return this._timestamp;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Возвращает текущий часовой пояс экземпляра.
|
|
120
|
+
*
|
|
121
|
+
* @returns {TimezoneString} Идентификатор часового пояса.
|
|
122
|
+
* @example
|
|
123
|
+
* import { fromISO } from '@alexstukovnikov/oz-time';
|
|
124
|
+
*
|
|
125
|
+
* const time = fromISO('2024-05-25T12:00:00Z', 'Europe/Moscow', 'ru-RU');
|
|
126
|
+
* console.log(time.getTimezone()); // ожидаемый результат: Europe/Moscow
|
|
127
|
+
*/
|
|
128
|
+
getTimezone() {
|
|
129
|
+
return this._timezone;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Возвращает текущую локаль экземпляра.
|
|
134
|
+
*
|
|
135
|
+
* @returns {LocaleString} Строка локали.
|
|
136
|
+
* @example
|
|
137
|
+
* import { fromISO } from '@alexstukovnikov/oz-time';
|
|
138
|
+
*
|
|
139
|
+
* const time = fromISO('2024-05-25T12:00:00Z', 'UTC', 'ru-RU');
|
|
140
|
+
* console.log(time.getLocale()); // ожидаемый результат: ru-RU
|
|
141
|
+
*/
|
|
142
|
+
getLocale() {
|
|
143
|
+
return this._locale;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Преобразует экземпляр в числовой timestamp.
|
|
148
|
+
*
|
|
149
|
+
* @returns {number} Unix timestamp в миллисекундах.
|
|
150
|
+
* @example
|
|
151
|
+
* const time = fromISO('2024-05-25T12:00:00Z', 'UTC', 'ru-RU');
|
|
152
|
+
console.log(time.toTimestamp()); // ожидаемый результат: 1716638400000
|
|
153
|
+
*/
|
|
154
|
+
toTimestamp() {
|
|
155
|
+
return this._timestamp;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Преобразует текущее значение времени в строку формата ISO 8601.
|
|
160
|
+
*
|
|
161
|
+
* @returns {string} Строковое представление даты и времени в формате ISO 8601.
|
|
162
|
+
* @example
|
|
163
|
+
* import { fromComponents } from '@alexstukovnikov/oz-time';
|
|
164
|
+
*
|
|
165
|
+
* const time = fromComponents(2024, 5, 25, 12, 0, 0, 0, 'UTC', 'ru-RU');
|
|
166
|
+
* console.log(time.toISOString()); // ожидаемый результат: 2024-05-25T12:00:00.000Z
|
|
167
|
+
*/
|
|
168
|
+
toISOString() {
|
|
169
|
+
return new Date(this._timestamp).toISOString();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Возвращает новый экземпляр OzTime, у которого timestamp увеличен
|
|
174
|
+
* на указанное количество единиц времени.
|
|
175
|
+
*
|
|
176
|
+
* Исходный экземпляр не изменяется.
|
|
177
|
+
*
|
|
178
|
+
* @param {number} amount - Количество единиц времени.
|
|
179
|
+
* @param {TimeUnit|string} unit - Единица времени.
|
|
180
|
+
* @returns {OzTime} Новый экземпляр OzTime с timestamp, сдвинутым вперёд.
|
|
181
|
+
* @example
|
|
182
|
+
* import { fromISO } from '@alexstukovnikov/oz-time';
|
|
183
|
+
*
|
|
184
|
+
* const time = fromISO('2024-05-25T12:00:00Z', 'UTC', 'ru-RU');
|
|
185
|
+
* const nextDay = time.add(1, 'day');
|
|
186
|
+
* console.log(nextDay.toISOString()); // ожидаемый результат: 2024-05-26T12:00:00.000Z
|
|
187
|
+
*/
|
|
188
|
+
add(amount, unit) {
|
|
189
|
+
return add(this, amount, unit);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Возвращает новый экземпляр OzTime, у которого timestamp уменьшен
|
|
194
|
+
* на указанное количество единиц времени.
|
|
195
|
+
*
|
|
196
|
+
* Исходный экземпляр не изменяется.
|
|
197
|
+
*
|
|
198
|
+
* @param {number} amount - Количество единиц времени.
|
|
199
|
+
* @param {TimeUnit|string} unit - Единица времени.
|
|
200
|
+
* @returns {OzTime} Новый экземпляр OzTime с timestamp, сдвинутым назад.
|
|
201
|
+
* @example
|
|
202
|
+
* import { fromISO } from '@alexstukovnikov/oz-time';
|
|
203
|
+
*
|
|
204
|
+
* const time = fromISO('2024-05-25T12:00:00Z', 'UTC', 'ru-RU');
|
|
205
|
+
* const prevHour = time.subtract(1, 'hour');
|
|
206
|
+
* console.log(prevHour.toISOString()); // ожидаемый результат: 2024-05-25T11:00:00.000Z
|
|
207
|
+
*/
|
|
208
|
+
subtract(amount, unit) {
|
|
209
|
+
return subtract(this, amount, unit);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Возвращает строковое представление текущего значения времени по заданному шаблону.
|
|
214
|
+
*
|
|
215
|
+
* @param {string} template - Строка шаблона форматирования.
|
|
216
|
+
* @param {LocaleString} [locale] - Локаль, которая переопределяет локаль экземпляра.
|
|
217
|
+
* @returns {string} Отформатированная строка.
|
|
218
|
+
* @example
|
|
219
|
+
* import { fromISO } from '@alexstukovnikov/oz-time';
|
|
220
|
+
*
|
|
221
|
+
* const time = fromISO('2024-05-25T12:00:00Z', 'UTC', 'ru-RU');
|
|
222
|
+
* console.log(time.format('DD.MM.YYYY HH:mm')); // ожидаемый результат: 25.05.2024 12:00
|
|
223
|
+
*/
|
|
224
|
+
format(template, locale) {
|
|
225
|
+
return format(this, template, locale);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Проверяет, совпадает ли текущее значение с другим значением времени
|
|
230
|
+
* на заданной точности.
|
|
231
|
+
*
|
|
232
|
+
* @param {OzTime} other - Второе значение для сравнения.
|
|
233
|
+
* @param {TimeUnit|string} [unit='millisecond'] - Точность сравнения.
|
|
234
|
+
* @returns {boolean} `true`, если значения совпадают на указанной точности.
|
|
235
|
+
* @example
|
|
236
|
+
* import { fromISO } from '@alexstukovnikov/oz-time';
|
|
237
|
+
*
|
|
238
|
+
* const a = fromISO('2024-05-25T12:00:00.100Z');
|
|
239
|
+
* const b = fromISO('2024-05-25T12:00:00.900Z');
|
|
240
|
+
* console.log(a.isSame(b, 'second')); // ожидаемый результат: true
|
|
241
|
+
*/
|
|
242
|
+
isSame(other, unit = 'millisecond') {
|
|
243
|
+
return isSame(this, other, unit);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Проверяет, находится ли текущее значение раньше другого значения времени
|
|
248
|
+
* на заданной точности.
|
|
249
|
+
*
|
|
250
|
+
* @param {OzTime} other - Второе значение для сравнения.
|
|
251
|
+
* @param {TimeUnit|string} [unit='millisecond'] - Точность сравнения.
|
|
252
|
+
* @returns {boolean} `true`, если текущее значение раньше.
|
|
253
|
+
* @example
|
|
254
|
+
* import { fromISO } from '@alexstukovnikov/oz-time';
|
|
255
|
+
*
|
|
256
|
+
* const a = fromISO('2024-05-25T12:00:00Z');
|
|
257
|
+
* const b = fromISO('2024-05-26T12:00:00Z');
|
|
258
|
+
* console.log(a.isBefore(b)); // ожидаемый результат: true
|
|
259
|
+
*/
|
|
260
|
+
isBefore(other, unit = 'millisecond') {
|
|
261
|
+
return isBefore(this, other, unit);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Проверяет, находится ли текущее значение позже другого значения времени
|
|
266
|
+
* на заданной точности.
|
|
267
|
+
*
|
|
268
|
+
* @param {OzTime} other - Второе значение для сравнения.
|
|
269
|
+
* @param {TimeUnit|string} [unit='millisecond'] - Точность сравнения.
|
|
270
|
+
* @returns {boolean} `true`, если текущее значение позже.
|
|
271
|
+
* @example
|
|
272
|
+
* import { fromISO } from '@alexstukovnikov/oz-time';
|
|
273
|
+
*
|
|
274
|
+
* const a = fromISO('2024-05-26T12:00:00Z');
|
|
275
|
+
* const b = fromISO('2024-05-25T12:00:00Z');
|
|
276
|
+
* console.log(a.isAfter(b)); // ожидаемый результат: true
|
|
277
|
+
*/
|
|
278
|
+
isAfter(other, unit = 'millisecond') {
|
|
279
|
+
return isAfter(this, other, unit);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Проверяет, попадает ли текущее значение времени в диапазон между двумя границами
|
|
284
|
+
* на заданной точности.
|
|
285
|
+
*
|
|
286
|
+
* @param {OzTime} start - Левая граница диапазона.
|
|
287
|
+
* @param {OzTime} end - Правая граница диапазона.
|
|
288
|
+
* @param {TimeUnit|string} [unit='millisecond'] - Точность сравнения.
|
|
289
|
+
* @param {Inclusivity} [inclusivity='[]'] - Формат включённости границ.
|
|
290
|
+
* @returns {boolean} `true`, если значение находится внутри диапазона.
|
|
291
|
+
* @example
|
|
292
|
+
* import { fromISO } from '@alexstukovnikov/oz-time';
|
|
293
|
+
*
|
|
294
|
+
* const current = fromISO('2024-05-25T12:00:00Z');
|
|
295
|
+
* const start = fromISO('2024-05-25T10:00:00Z');
|
|
296
|
+
* const end = fromISO('2024-05-25T14:00:00Z');
|
|
297
|
+
* console.log(current.isBetween(start, end)); // ожидаемый результат: true
|
|
298
|
+
*/
|
|
299
|
+
isBetween(start, end, unit = 'millisecond', inclusivity = '[]') {
|
|
300
|
+
return isBetween(this, start, end, unit, inclusivity);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Возвращает новый экземпляр OzTime с тем же timestamp и locale,
|
|
305
|
+
* но с другим часовым поясом.
|
|
306
|
+
*
|
|
307
|
+
* Абсолютный момент времени при этом не изменяется.
|
|
308
|
+
*
|
|
309
|
+
* @param {TimezoneString} timezone - Новый часовой пояс.
|
|
310
|
+
* @returns {OzTime} Новый экземпляр OzTime с обновлённым часовым поясом.
|
|
311
|
+
* @example
|
|
312
|
+
* import { fromISO } from '@alexstukovnikov/oz-time';
|
|
313
|
+
*
|
|
314
|
+
* const time = fromISO('2024-05-25T12:00:00Z', 'UTC', 'ru-RU');
|
|
315
|
+
* const moscowTime = time.setTimezone('Europe/Moscow');
|
|
316
|
+
* console.log(moscowTime.getTimezone()); // ожидаемый результат: Europe/Moscow
|
|
317
|
+
*/
|
|
318
|
+
setTimezone(timezone) {
|
|
319
|
+
return setTimezone(this, timezone);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Возвращает смещение текущего часового пояса относительно UTC в минутах.
|
|
324
|
+
*
|
|
325
|
+
* @returns {number} Смещение в минутах относительно UTC.
|
|
326
|
+
* @example
|
|
327
|
+
* import { fromISO } from '@alexstukovnikov/oz-time';
|
|
328
|
+
*
|
|
329
|
+
* const time = fromISO('2024-05-25T12:00:00Z', 'Europe/Moscow', 'ru-RU');
|
|
330
|
+
* console.log(time.getTimezoneOffset()); // ожидаемый результат: 180
|
|
331
|
+
*/
|
|
332
|
+
getTimezoneOffset() {
|
|
333
|
+
return getTimezoneOffset(this);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Возвращает числовую разницу между текущим экземпляром и другим значением времени
|
|
338
|
+
* в указанной единице измерения.
|
|
339
|
+
*
|
|
340
|
+
* @param {OzTime} other - Второе значение для сравнения.
|
|
341
|
+
* @param {TimeUnit|string} [unit='millisecond'] - Единица измерения разницы.
|
|
342
|
+
* @returns {number} Разница между двумя значениями времени.
|
|
343
|
+
* @example
|
|
344
|
+
* import { fromISO } from '@alexstukovnikov/oz-time';
|
|
345
|
+
*
|
|
346
|
+
* const start = fromISO('2024-05-25T12:00:00Z');
|
|
347
|
+
* const end = fromISO('2024-05-25T14:00:00Z');
|
|
348
|
+
* console.log(end.diff(start, 'hour')); // ожидаемый результат: 2
|
|
349
|
+
*/
|
|
350
|
+
diff(other, unit = 'millisecond') {
|
|
351
|
+
return diff(this, other, unit);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { OzTime } from './core.js';
|
|
2
|
+
import { daysInMonth } from '../utils/calendar.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Фабричные функции для создания экземпляров {@link OzTime}.
|
|
6
|
+
*
|
|
7
|
+
* @module core/factory
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Проверяет корректность timestamp.
|
|
12
|
+
*
|
|
13
|
+
* @private
|
|
14
|
+
* @param {number} timestamp - Unix timestamp в миллисекундах.
|
|
15
|
+
* @throws {TypeError} Выбрасывается, если timestamp некорректен.
|
|
16
|
+
* @returns {void}
|
|
17
|
+
*/
|
|
18
|
+
function assertValidTimestamp(timestamp) {
|
|
19
|
+
if (typeof timestamp !== 'number' || Number.isNaN(timestamp)) {
|
|
20
|
+
throw new TypeError('fromTimestamp: timestamp must be a valid number');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Проверяет корректность объекта Date.
|
|
26
|
+
*
|
|
27
|
+
* @private
|
|
28
|
+
* @param {Date} date - Проверяемый объект Date.
|
|
29
|
+
* @throws {TypeError} Выбрасывается, если date некорректен.
|
|
30
|
+
* @returns {void}
|
|
31
|
+
*/
|
|
32
|
+
function assertValidDate(date) {
|
|
33
|
+
if (!(date instanceof Date) || Number.isNaN(date.getTime())) {
|
|
34
|
+
throw new TypeError('fromDate: date must be a valid Date');
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Проверяет, что значение является целым числом.
|
|
40
|
+
*
|
|
41
|
+
* @private
|
|
42
|
+
* @param {number} value - Проверяемое значение.
|
|
43
|
+
* @param {string} name - Имя параметра.
|
|
44
|
+
* @throws {TypeError} Выбрасывается, если значение не является целым числом.
|
|
45
|
+
* @returns {void}
|
|
46
|
+
*/
|
|
47
|
+
function assertInteger(value, name) {
|
|
48
|
+
if (!Number.isInteger(value)) {
|
|
49
|
+
throw new TypeError(`${name} must be an integer`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Создаёт и возвращает экземпляр {@link OzTime} для текущего момента времени.
|
|
55
|
+
*
|
|
56
|
+
* @param {string} [timezone='UTC'] - Часовой пояс в формате IANA.
|
|
57
|
+
* @param {string} [locale='en-US'] - Локаль форматирования.
|
|
58
|
+
* @returns {OzTime} Экземпляр с текущим временем.
|
|
59
|
+
* @example
|
|
60
|
+
* import { now } from '@alexstukovnikov/oz-time';
|
|
61
|
+
*
|
|
62
|
+
* const current = now('Europe/Moscow', 'ru-RU');
|
|
63
|
+
* console.log(current.getTimezone()); // ожидаемый результат: Europe/Moscow
|
|
64
|
+
*/
|
|
65
|
+
export function now(timezone = 'UTC', locale = 'en-US') {
|
|
66
|
+
return new OzTime(Date.now(), timezone, locale);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Создаёт и возвращает экземпляр {@link OzTime} на основе Unix timestamp.
|
|
71
|
+
*
|
|
72
|
+
* @param {number} timestamp - Unix timestamp в миллисекундах.
|
|
73
|
+
* @param {string} [timezone='UTC'] - Часовой пояс в формате IANA.
|
|
74
|
+
* @param {string} [locale='en-US'] - Локаль форматирования.
|
|
75
|
+
* @throws {TypeError} Выбрасывается, если timestamp некорректен.
|
|
76
|
+
* @returns {OzTime} Экземпляр времени.
|
|
77
|
+
* @example
|
|
78
|
+
* import { fromTimestamp } from '@alexstukovnikov/oz-time';
|
|
79
|
+
*
|
|
80
|
+
* const time = fromTimestamp(1716638400000, 'UTC', 'ru-RU');
|
|
81
|
+
* console.log(time.toISOString()); // ожидаемый результат: 2024-05-25T12:00:00.000Z
|
|
82
|
+
*/
|
|
83
|
+
export function fromTimestamp(timestamp, timezone = 'UTC', locale = 'en-US') {
|
|
84
|
+
assertValidTimestamp(timestamp);
|
|
85
|
+
return new OzTime(timestamp, timezone, locale);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Создаёт и возвращает экземпляр {@link OzTime} на основе объекта {@link Date}.
|
|
90
|
+
*
|
|
91
|
+
* @param {Date} date - Нативный объект Date.
|
|
92
|
+
* @param {string} [timezone='UTC'] - Часовой пояс в формате IANA.
|
|
93
|
+
* @param {string} [locale='en-US'] - Локаль форматирования.
|
|
94
|
+
* @throws {TypeError} Выбрасывается, если date некорректен.
|
|
95
|
+
* @returns {OzTime} Экземпляр времени.
|
|
96
|
+
* @example
|
|
97
|
+
* import { fromDate } from '@alexstukovnikov/oz-time';
|
|
98
|
+
*
|
|
99
|
+
* const time = fromDate(new Date('2024-05-25T12:00:00Z'), 'UTC', 'ru-RU');
|
|
100
|
+
* console.log(time.toTimestamp()); // ожидаемый результат: 1716638400000
|
|
101
|
+
*/
|
|
102
|
+
export function fromDate(date, timezone = 'UTC', locale = 'en-US') {
|
|
103
|
+
assertValidDate(date);
|
|
104
|
+
return new OzTime(date.getTime(), timezone, locale);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Создаёт и возвращает экземпляр {@link OzTime} на основе ISO-строки.
|
|
109
|
+
*
|
|
110
|
+
* @param {string} isoString - Строка даты и времени в формате ISO 8601.
|
|
111
|
+
* @param {string} [timezone='UTC'] - Часовой пояс в формате IANA.
|
|
112
|
+
* @param {string} [locale='en-US'] - Локаль форматирования.
|
|
113
|
+
* @throws {TypeError} Выбрасывается, если строка пустая или не является строкой.
|
|
114
|
+
* @throws {Error} Выбрасывается, если строку не удалось распарсить.
|
|
115
|
+
* @returns {OzTime} Экземпляр времени.
|
|
116
|
+
* @example
|
|
117
|
+
* import { fromISO } from '@alexstukovnikov/oz-time';
|
|
118
|
+
*
|
|
119
|
+
* const time = fromISO('2024-05-25T12:00:00Z', 'UTC', 'ru-RU');
|
|
120
|
+
* console.log(time.format('DD.MM.YYYY HH:mm')); // ожидаемый результат: 25.05.2024 12:00
|
|
121
|
+
*/
|
|
122
|
+
export function fromISO(isoString, timezone = 'UTC', locale = 'en-US') {
|
|
123
|
+
if (typeof isoString !== 'string' || isoString.trim() === '') {
|
|
124
|
+
throw new TypeError('fromISO: isoString must be a non-empty string');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const ts = Date.parse(isoString);
|
|
128
|
+
|
|
129
|
+
if (Number.isNaN(ts)) {
|
|
130
|
+
throw new Error(`Invalid ISO date string: ${isoString}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return new OzTime(ts, timezone, locale);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Создаёт и возвращает экземпляр {@link OzTime} на основе отдельных компонентов даты и времени.
|
|
138
|
+
*
|
|
139
|
+
* @param {number} year - Год.
|
|
140
|
+
* @param {number} month - Месяц от 1 до 12.
|
|
141
|
+
* @param {number} day - День месяца.
|
|
142
|
+
* @param {number} [hour=0] - Час от 0 до 23.
|
|
143
|
+
* @param {number} [minute=0] - Минута от 0 до 59.
|
|
144
|
+
* @param {number} [second=0] - Секунда от 0 до 59.
|
|
145
|
+
* @param {number} [ms=0] - Миллисекунда от 0 до 999.
|
|
146
|
+
* @param {string} [timezone='UTC'] - Часовой пояс в формате IANA.
|
|
147
|
+
* @param {string} [locale='en-US'] - Локаль форматирования.
|
|
148
|
+
* @throws {TypeError} Выбрасывается, если любой числовой параметр не является целым числом.
|
|
149
|
+
* @throws {RangeError} Выбрасывается, если любой компонент даты или времени вне допустимого диапазона.
|
|
150
|
+
* @returns {OzTime} Экземпляр времени.
|
|
151
|
+
* @example
|
|
152
|
+
* import { fromComponents } from '@alexstukovnikov/oz-time';
|
|
153
|
+
*
|
|
154
|
+
* const time = fromComponents(2024, 5, 25, 12, 0, 0, 0, 'UTC', 'ru-RU');
|
|
155
|
+
* console.log(time.toISOString()); // ожидаемый результат: 2024-05-25T12:00:00.000Z
|
|
156
|
+
*/
|
|
157
|
+
export function fromComponents(year, month, day, hour = 0, minute = 0, second = 0, ms = 0, timezone = 'UTC', locale = 'en-US') {
|
|
158
|
+
assertInteger(year, 'year');
|
|
159
|
+
assertInteger(month, 'month');
|
|
160
|
+
assertInteger(day, 'day');
|
|
161
|
+
assertInteger(hour, 'hour');
|
|
162
|
+
assertInteger(minute, 'minute');
|
|
163
|
+
assertInteger(second, 'second');
|
|
164
|
+
assertInteger(ms, 'millisecond');
|
|
165
|
+
|
|
166
|
+
if (month < 1 || month > 12) {
|
|
167
|
+
throw new RangeError('month must be between 1 and 12');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (hour < 0 || hour > 23) {
|
|
171
|
+
throw new RangeError('hour must be between 0 and 23');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (minute < 0 || minute > 59) {
|
|
175
|
+
throw new RangeError('minute must be between 0 and 59');
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (second < 0 || second > 59) {
|
|
179
|
+
throw new RangeError('second must be between 0 and 59');
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (ms < 0 || ms > 999) {
|
|
183
|
+
throw new RangeError('millisecond must be between 0 and 999');
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const maxDay = daysInMonth(year, month);
|
|
187
|
+
|
|
188
|
+
if (day < 1 || day > maxDay) {
|
|
189
|
+
throw new RangeError(`day must be between 1 and ${maxDay} for ${year}-${month}`);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const ts = Date.UTC(year, month - 1, day, hour, minute, second, ms);
|
|
193
|
+
return new OzTime(ts, timezone, locale);
|
|
194
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Публичная точка входа библиотеки OzTime.
|
|
3
|
+
*
|
|
4
|
+
* @module index
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export { OzTime } from './core/core.js';
|
|
8
|
+
export { now, fromTimestamp, fromDate, fromISO, fromComponents } from './core/factory.js';
|
|
9
|
+
|
|
10
|
+
export { add, subtract } from './modules/arithmetic.js';
|
|
11
|
+
|
|
12
|
+
export { isSame, isBefore, isAfter, isBetween } from './modules/compare.js';
|
|
13
|
+
|
|
14
|
+
export { setTimezone, getTimezoneOffset } from './modules/timezone.js';
|
|
15
|
+
|
|
16
|
+
export { Interval, interval } from './modules/interval.js';
|
|
17
|
+
|
|
18
|
+
export { Duration, duration } from './modules/duration.js';
|
|
19
|
+
|
|
20
|
+
export { format } from './modules/format.js';
|
|
21
|
+
|
|
22
|
+
export { isLeapYear, daysInMonth } from './utils/calendar.js';
|