@arkv/temporal 0.2.0

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.
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startOfHelper = startOfHelper;
4
+ exports.endOfHelper = endOfHelper;
5
+ const ZERO_TIME = {
6
+ hour: 0,
7
+ minute: 0,
8
+ second: 0,
9
+ millisecond: 0,
10
+ microsecond: 0,
11
+ nanosecond: 0,
12
+ };
13
+ const MAX_TIME = {
14
+ hour: 23,
15
+ minute: 59,
16
+ second: 59,
17
+ millisecond: 999,
18
+ microsecond: 999,
19
+ nanosecond: 999,
20
+ };
21
+ function startWeek(zdt, weekStart) {
22
+ // dayOfWeek: 1=Mon...7=Sun → convert to 0=Sun..6=Sat
23
+ const dow = zdt.dayOfWeek % 7;
24
+ const diff = (dow - weekStart + 7) % 7;
25
+ return zdt.subtract({ days: diff }).with(ZERO_TIME);
26
+ }
27
+ function endWeek(zdt, weekStart) {
28
+ const dow = zdt.dayOfWeek % 7;
29
+ const diff = (dow - weekStart + 7) % 7;
30
+ return zdt
31
+ .subtract({ days: diff })
32
+ .add({ days: 6 })
33
+ .with(MAX_TIME);
34
+ }
35
+ function startOfHelper(zdt, unit, locale) {
36
+ const weekStart = locale.weekStart ?? 0;
37
+ switch (unit) {
38
+ case 'year':
39
+ return zdt.with({ month: 1, day: 1, ...ZERO_TIME });
40
+ case 'month':
41
+ return zdt.with({ day: 1, ...ZERO_TIME });
42
+ case 'week':
43
+ return startWeek(zdt, weekStart);
44
+ case 'day':
45
+ case 'date':
46
+ return zdt.with(ZERO_TIME);
47
+ case 'hour':
48
+ return zdt.with({
49
+ minute: 0,
50
+ second: 0,
51
+ millisecond: 0,
52
+ microsecond: 0,
53
+ nanosecond: 0,
54
+ });
55
+ case 'minute':
56
+ return zdt.with({
57
+ second: 0,
58
+ millisecond: 0,
59
+ microsecond: 0,
60
+ nanosecond: 0,
61
+ });
62
+ case 'second':
63
+ return zdt.with({
64
+ millisecond: 0,
65
+ microsecond: 0,
66
+ nanosecond: 0,
67
+ });
68
+ default:
69
+ return zdt;
70
+ }
71
+ }
72
+ function endOfHelper(zdt, unit, locale) {
73
+ const weekStart = locale.weekStart ?? 0;
74
+ switch (unit) {
75
+ case 'year':
76
+ return zdt.with({ month: 12, day: 31, ...MAX_TIME });
77
+ case 'month':
78
+ return zdt.with({
79
+ day: zdt.daysInMonth,
80
+ ...MAX_TIME,
81
+ });
82
+ case 'week':
83
+ return endWeek(zdt, weekStart);
84
+ case 'day':
85
+ case 'date':
86
+ return zdt.with(MAX_TIME);
87
+ case 'hour':
88
+ return zdt.with({
89
+ minute: 59,
90
+ second: 59,
91
+ millisecond: 999,
92
+ microsecond: 999,
93
+ nanosecond: 999,
94
+ });
95
+ case 'minute':
96
+ return zdt.with({
97
+ second: 59,
98
+ millisecond: 999,
99
+ microsecond: 999,
100
+ nanosecond: 999,
101
+ });
102
+ case 'second':
103
+ return zdt.with({
104
+ millisecond: 999,
105
+ microsecond: 999,
106
+ nanosecond: 999,
107
+ });
108
+ default:
109
+ return zdt;
110
+ }
111
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DURATION_KEY = void 0;
4
+ exports.normalizeUnit = normalizeUnit;
5
+ const UNIT_MAP = {
6
+ y: 'year',
7
+ yr: 'year',
8
+ year: 'year',
9
+ years: 'year',
10
+ M: 'month',
11
+ month: 'month',
12
+ months: 'month',
13
+ Q: 'quarter',
14
+ quarter: 'quarter',
15
+ quarters: 'quarter',
16
+ w: 'week',
17
+ week: 'week',
18
+ weeks: 'week',
19
+ d: 'day',
20
+ day: 'day',
21
+ days: 'day',
22
+ D: 'date',
23
+ date: 'date',
24
+ dates: 'date',
25
+ h: 'hour',
26
+ hour: 'hour',
27
+ hours: 'hour',
28
+ m: 'minute',
29
+ min: 'minute',
30
+ minute: 'minute',
31
+ minutes: 'minute',
32
+ s: 'second',
33
+ sec: 'second',
34
+ second: 'second',
35
+ seconds: 'second',
36
+ ms: 'millisecond',
37
+ millisecond: 'millisecond',
38
+ milliseconds: 'millisecond',
39
+ };
40
+ function normalizeUnit(u) {
41
+ return (UNIT_MAP[u] ??
42
+ UNIT_MAP[u.toLowerCase()] ??
43
+ 'millisecond');
44
+ }
45
+ exports.DURATION_KEY = {
46
+ year: 'years',
47
+ month: 'months',
48
+ quarter: null,
49
+ week: 'weeks',
50
+ day: 'days',
51
+ date: 'days',
52
+ hour: 'hours',
53
+ minute: 'minutes',
54
+ second: 'seconds',
55
+ millisecond: 'milliseconds',
56
+ };
@@ -0,0 +1,4 @@
1
+ export const FORMAT_DEFAULT = 'YYYY-MM-DDTHH:mm:ssZ';
2
+ export const INVALID_DATE = 'Invalid Date';
3
+ // Matches format tokens and [escaped] text
4
+ export const REGEX_FORMAT = /\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g;
@@ -0,0 +1,315 @@
1
+ import { FORMAT_DEFAULT, INVALID_DATE, } from './constants.js';
2
+ import { diffHelper } from './diff.js';
3
+ import { formatDate } from './format.js';
4
+ import { getGlobalLocale, getLocaleObj, registerLocale, } from './locale.js';
5
+ import { parseInput } from './parse.js';
6
+ import { endOfHelper, startOfHelper } from './start-end.js';
7
+ import { DURATION_KEY, normalizeUnit, } from './units.js';
8
+ function addToZdt(zdt, n, key) {
9
+ switch (key) {
10
+ case 'years':
11
+ return zdt.add({ years: n });
12
+ case 'months':
13
+ return zdt.add({ months: n });
14
+ case 'weeks':
15
+ return zdt.add({ weeks: n });
16
+ case 'days':
17
+ return zdt.add({ days: n });
18
+ case 'hours':
19
+ return zdt.add({ hours: n });
20
+ case 'minutes':
21
+ return zdt.add({ minutes: n });
22
+ case 'seconds':
23
+ return zdt.add({ seconds: n });
24
+ case 'milliseconds':
25
+ return zdt.add({ milliseconds: n });
26
+ }
27
+ }
28
+ export const DEFAULT_TZ = Temporal.Now.timeZoneId();
29
+ export class TDayjs {
30
+ $zdt;
31
+ $L;
32
+ $tz;
33
+ constructor(cfg) {
34
+ this.$L = cfg.locale ?? getGlobalLocale();
35
+ this.$tz = cfg.tz ?? DEFAULT_TZ;
36
+ this.$zdt =
37
+ cfg.zdt !== undefined
38
+ ? cfg.zdt
39
+ : parseInput(cfg.date, this.$tz);
40
+ }
41
+ _clone(zdt) {
42
+ return new TDayjs({
43
+ zdt,
44
+ locale: this.$L,
45
+ tz: this.$tz,
46
+ });
47
+ }
48
+ isValid() {
49
+ return this.$zdt !== null;
50
+ }
51
+ clone() {
52
+ return this._clone(this.$zdt);
53
+ }
54
+ year(value) {
55
+ if (value === undefined) {
56
+ return this.$zdt?.year ?? NaN;
57
+ }
58
+ if (!this.$zdt)
59
+ return this._clone(null);
60
+ return this.add(value - this.$zdt.year, 'year');
61
+ }
62
+ month(value) {
63
+ if (value === undefined) {
64
+ return (this.$zdt?.month ?? 1) - 1;
65
+ }
66
+ if (!this.$zdt)
67
+ return this._clone(null);
68
+ // value is 0-indexed; $zdt.month is 1-indexed
69
+ return this.add(value - (this.$zdt.month - 1), 'month');
70
+ }
71
+ date(value) {
72
+ if (value === undefined) {
73
+ return this.$zdt?.day ?? NaN;
74
+ }
75
+ if (!this.$zdt)
76
+ return this._clone(null);
77
+ return this.add(value - this.$zdt.day, 'day');
78
+ }
79
+ day(value) {
80
+ if (value === undefined) {
81
+ return (this.$zdt?.dayOfWeek ?? 0) % 7;
82
+ }
83
+ if (!this.$zdt)
84
+ return this._clone(null);
85
+ const current = this.$zdt.dayOfWeek % 7;
86
+ return this._clone(this.$zdt.add({ days: value - current }));
87
+ }
88
+ hour(value) {
89
+ if (value === undefined) {
90
+ return this.$zdt?.hour ?? NaN;
91
+ }
92
+ if (!this.$zdt)
93
+ return this._clone(null);
94
+ return this.add(value - this.$zdt.hour, 'hour');
95
+ }
96
+ minute(value) {
97
+ if (value === undefined) {
98
+ return this.$zdt?.minute ?? NaN;
99
+ }
100
+ if (!this.$zdt)
101
+ return this._clone(null);
102
+ return this.add(value - this.$zdt.minute, 'minute');
103
+ }
104
+ second(value) {
105
+ if (value === undefined) {
106
+ return this.$zdt?.second ?? NaN;
107
+ }
108
+ if (!this.$zdt)
109
+ return this._clone(null);
110
+ return this.add(value - this.$zdt.second, 'second');
111
+ }
112
+ millisecond(value) {
113
+ if (value === undefined) {
114
+ return this.$zdt?.millisecond ?? NaN;
115
+ }
116
+ if (!this.$zdt)
117
+ return this._clone(null);
118
+ return this.add(value - this.$zdt.millisecond, 'millisecond');
119
+ }
120
+ get(unit) {
121
+ const u = normalizeUnit(unit);
122
+ return this._getByUnit(u);
123
+ }
124
+ _getByUnit(u) {
125
+ switch (u) {
126
+ case 'year':
127
+ return this.year();
128
+ case 'month':
129
+ return this.month();
130
+ case 'date':
131
+ return this.date();
132
+ case 'day':
133
+ return this.day();
134
+ case 'hour':
135
+ return this.hour();
136
+ case 'minute':
137
+ return this.minute();
138
+ case 'second':
139
+ return this.second();
140
+ case 'millisecond':
141
+ return this.millisecond();
142
+ case 'week':
143
+ return this.day();
144
+ case 'quarter':
145
+ return Math.ceil((this.month() + 1) / 3);
146
+ }
147
+ }
148
+ set(unit, value) {
149
+ const u = normalizeUnit(unit);
150
+ return this._setByUnit(u, value);
151
+ }
152
+ _setByUnit(u, value) {
153
+ switch (u) {
154
+ case 'year':
155
+ return this.year(value);
156
+ case 'month':
157
+ return this.month(value);
158
+ case 'date':
159
+ return this.date(value);
160
+ case 'day':
161
+ return this.day(value);
162
+ case 'hour':
163
+ return this.hour(value);
164
+ case 'minute':
165
+ return this.minute(value);
166
+ case 'second':
167
+ return this.second(value);
168
+ case 'millisecond':
169
+ return this.millisecond(value);
170
+ default:
171
+ return this.clone();
172
+ }
173
+ }
174
+ // --- Manipulation ---
175
+ add(value, unit) {
176
+ if (!this.$zdt)
177
+ return this._clone(null);
178
+ const n = Number(value);
179
+ const u = normalizeUnit(unit ?? 'millisecond');
180
+ if (u === 'quarter') {
181
+ return this.add(n * 3, 'month');
182
+ }
183
+ const key = DURATION_KEY[u];
184
+ if (!key)
185
+ return this._clone(this.$zdt);
186
+ return this._clone(addToZdt(this.$zdt, n, key));
187
+ }
188
+ subtract(value, unit) {
189
+ return this.add(-Number(value), unit);
190
+ }
191
+ startOf(unit) {
192
+ if (!this.$zdt)
193
+ return this._clone(null);
194
+ const u = normalizeUnit(unit);
195
+ return this._clone(startOfHelper(this.$zdt, u, getLocaleObj(this.$L)));
196
+ }
197
+ endOf(unit) {
198
+ if (!this.$zdt)
199
+ return this._clone(null);
200
+ const u = normalizeUnit(unit);
201
+ return this._clone(endOfHelper(this.$zdt, u, getLocaleObj(this.$L)));
202
+ }
203
+ // --- Comparison ---
204
+ _toZdt(d) {
205
+ if (d instanceof TDayjs)
206
+ return d;
207
+ return new TDayjs({ date: d, tz: this.$tz });
208
+ }
209
+ isBefore(date, unit) {
210
+ if (!this.$zdt)
211
+ return false;
212
+ const other = this._toZdt(date);
213
+ if (!other.isValid())
214
+ return false;
215
+ if (!unit) {
216
+ return (Temporal.ZonedDateTime.compare(this.$zdt, other.$zdt) < 0);
217
+ }
218
+ return this.endOf(unit).valueOf() < other.valueOf();
219
+ }
220
+ isAfter(date, unit) {
221
+ if (!this.$zdt)
222
+ return false;
223
+ const other = this._toZdt(date);
224
+ if (!other.isValid())
225
+ return false;
226
+ if (!unit) {
227
+ return (Temporal.ZonedDateTime.compare(this.$zdt, other.$zdt) > 0);
228
+ }
229
+ return other.valueOf() < this.startOf(unit).valueOf();
230
+ }
231
+ isSame(date, unit) {
232
+ if (!this.$zdt)
233
+ return false;
234
+ const other = this._toZdt(date);
235
+ if (!other.isValid())
236
+ return false;
237
+ if (!unit) {
238
+ return (Temporal.ZonedDateTime.compare(this.$zdt, other.$zdt) === 0);
239
+ }
240
+ const start = this.startOf(unit).valueOf();
241
+ const end = this.endOf(unit).valueOf();
242
+ const v = other.valueOf();
243
+ return start <= v && v <= end;
244
+ }
245
+ // --- Display ---
246
+ format(template) {
247
+ if (!this.$zdt)
248
+ return INVALID_DATE;
249
+ const loc = getLocaleObj(this.$L);
250
+ return formatDate(this.$zdt, template ?? FORMAT_DEFAULT, loc);
251
+ }
252
+ diff(date, unit, float = false) {
253
+ if (!this.$zdt)
254
+ return NaN;
255
+ const other = this._toZdt(date ?? undefined);
256
+ if (!other.$zdt)
257
+ return NaN;
258
+ const u = normalizeUnit(unit ?? 'millisecond');
259
+ // dayjs: this.diff(other) = this - other
260
+ // diffHelper(from, to) = from.until(to) = to - from
261
+ // so pass (other, this) to get this - other
262
+ return diffHelper(other.$zdt, this.$zdt, u, float);
263
+ }
264
+ valueOf() {
265
+ return this.$zdt?.epochMilliseconds ?? NaN;
266
+ }
267
+ unix() {
268
+ return Math.floor(this.valueOf() / 1_000);
269
+ }
270
+ daysInMonth() {
271
+ return this.$zdt?.daysInMonth ?? NaN;
272
+ }
273
+ utcOffset() {
274
+ if (!this.$zdt)
275
+ return 0;
276
+ return this.$zdt.offsetNanoseconds / 60_000_000_000;
277
+ }
278
+ // --- Conversion ---
279
+ toDate() {
280
+ return new Date(this.valueOf());
281
+ }
282
+ toISOString() {
283
+ if (!this.$zdt)
284
+ return INVALID_DATE;
285
+ return this.$zdt.toInstant().toString();
286
+ }
287
+ toJSON() {
288
+ return this.isValid() ? this.toISOString() : null;
289
+ }
290
+ toString() {
291
+ return this.isValid()
292
+ ? this.toDate().toUTCString()
293
+ : INVALID_DATE;
294
+ }
295
+ locale(preset, object) {
296
+ if (preset === undefined)
297
+ return this.$L;
298
+ let name;
299
+ if (typeof preset === 'string') {
300
+ name = preset.toLowerCase();
301
+ if (object) {
302
+ registerLocale({ ...object, name });
303
+ }
304
+ }
305
+ else {
306
+ registerLocale(preset);
307
+ name = preset.name;
308
+ }
309
+ return new TDayjs({
310
+ zdt: this.$zdt,
311
+ locale: name,
312
+ tz: this.$tz,
313
+ });
314
+ }
315
+ }
@@ -0,0 +1,57 @@
1
+ function monthDiff(from, to, float) {
2
+ const dur = from.until(to, {
3
+ largestUnit: 'months',
4
+ });
5
+ const whole = dur.months;
6
+ if (!float)
7
+ return whole;
8
+ const anchor = from.add({ months: whole });
9
+ const remaining = to.epochMilliseconds - anchor.epochMilliseconds;
10
+ const nextMs = anchor.add({ months: 1 }).epochMilliseconds -
11
+ anchor.epochMilliseconds;
12
+ return whole + remaining / nextMs;
13
+ }
14
+ function dayDiff(from, to, float) {
15
+ const dur = from.until(to, { largestUnit: 'days' });
16
+ const total = dur.days +
17
+ dur.hours / 24 +
18
+ dur.minutes / 1440 +
19
+ dur.seconds / 86_400 +
20
+ dur.milliseconds / 86_400_000;
21
+ return float ? total : Math.trunc(total);
22
+ }
23
+ function msDiff(from, to, unit, float) {
24
+ const ms = to.epochMilliseconds - from.epochMilliseconds;
25
+ const divisors = {
26
+ hour: 3_600_000,
27
+ minute: 60_000,
28
+ second: 1_000,
29
+ millisecond: 1,
30
+ };
31
+ const result = ms / (divisors[unit] ?? 1);
32
+ return float ? result : Math.trunc(result);
33
+ }
34
+ export function diffHelper(from, to, unit, float) {
35
+ switch (unit) {
36
+ case 'year': {
37
+ const months = monthDiff(from, to, float);
38
+ return float ? months / 12 : Math.trunc(months / 12);
39
+ }
40
+ case 'quarter': {
41
+ const months = monthDiff(from, to, float);
42
+ return float ? months / 3 : Math.trunc(months / 3);
43
+ }
44
+ case 'month':
45
+ return monthDiff(from, to, float);
46
+ case 'week': {
47
+ const days = dayDiff(from, to, true);
48
+ const result = days / 7;
49
+ return float ? result : Math.trunc(result);
50
+ }
51
+ case 'day':
52
+ case 'date':
53
+ return dayDiff(from, to, float);
54
+ default:
55
+ return msDiff(from, to, unit, float);
56
+ }
57
+ }
@@ -0,0 +1,81 @@
1
+ import { REGEX_FORMAT } from './constants.js';
2
+ function pad(n, len = 2) {
3
+ return String(n).padStart(len, '0');
4
+ }
5
+ function offsetStr(ns, sep) {
6
+ const totalMin = Math.round(ns / 60_000_000_000);
7
+ const sign = totalMin >= 0 ? '+' : '-';
8
+ const absMin = Math.abs(totalMin);
9
+ const h = pad(Math.floor(absMin / 60));
10
+ const m = pad(absMin % 60);
11
+ return sep ? `${sign}${h}:${m}` : `${sign}${h}${m}`;
12
+ }
13
+ // Temporal: 1=Mon...7=Sun → dayjs: 0=Sun...6=Sat
14
+ function toDayjsDay(dow) {
15
+ return dow % 7;
16
+ }
17
+ function matchToken(zdt, locale, token) {
18
+ const { year, month, day, hour, minute, second, millisecond, dayOfWeek, offsetNanoseconds, } = zdt;
19
+ const djDay = toDayjsDay(dayOfWeek);
20
+ switch (token) {
21
+ case 'YYYY':
22
+ return pad(year, 4);
23
+ case 'YY':
24
+ return String(year).slice(-2);
25
+ case 'M':
26
+ return String(month);
27
+ case 'MM':
28
+ return pad(month);
29
+ case 'MMM':
30
+ return locale.monthsShort[month - 1];
31
+ case 'MMMM':
32
+ return locale.months[month - 1];
33
+ case 'D':
34
+ return String(day);
35
+ case 'DD':
36
+ return pad(day);
37
+ case 'd':
38
+ return String(djDay);
39
+ case 'dd':
40
+ return locale.weekdaysMin[djDay];
41
+ case 'ddd':
42
+ return locale.weekdaysShort[djDay];
43
+ case 'dddd':
44
+ return locale.weekdays[djDay];
45
+ case 'H':
46
+ return String(hour);
47
+ case 'HH':
48
+ return pad(hour);
49
+ case 'h':
50
+ return String(hour % 12 || 12);
51
+ case 'hh':
52
+ return pad(hour % 12 || 12);
53
+ case 'a':
54
+ return hour < 12 ? 'am' : 'pm';
55
+ case 'A':
56
+ return hour < 12 ? 'AM' : 'PM';
57
+ case 'm':
58
+ return String(minute);
59
+ case 'mm':
60
+ return pad(minute);
61
+ case 's':
62
+ return String(second);
63
+ case 'ss':
64
+ return pad(second);
65
+ case 'SSS':
66
+ return pad(millisecond, 3);
67
+ case 'Z':
68
+ return offsetStr(offsetNanoseconds, ':');
69
+ case 'ZZ':
70
+ return offsetStr(offsetNanoseconds, '');
71
+ default:
72
+ return null;
73
+ }
74
+ }
75
+ export function formatDate(zdt, template, locale) {
76
+ return template.replace(REGEX_FORMAT, (match, escaped) => {
77
+ if (escaped != null)
78
+ return escaped;
79
+ return matchToken(zdt, locale, match) ?? match;
80
+ });
81
+ }
@@ -0,0 +1,45 @@
1
+ import 'temporal-polyfill/global';
2
+ import { DEFAULT_TZ, TDayjs } from './dayjs.js';
3
+ import { getGlobalLocale, registerLocale, setGlobalLocale, } from './locale.js';
4
+ export { TDayjs } from './dayjs.js';
5
+ const installed = new Set();
6
+ function tdayjs(date) {
7
+ if (date instanceof TDayjs)
8
+ return date.clone();
9
+ return new TDayjs({ date });
10
+ }
11
+ tdayjs.extend = (plugin, option) => {
12
+ if (!installed.has(plugin)) {
13
+ plugin(option, TDayjs, tdayjs);
14
+ installed.add(plugin);
15
+ }
16
+ return tdayjs;
17
+ };
18
+ tdayjs.isDayjs = (d) => {
19
+ return d instanceof TDayjs;
20
+ };
21
+ tdayjs.unix = (t) => {
22
+ return new TDayjs({
23
+ date: t * 1_000,
24
+ tz: DEFAULT_TZ,
25
+ });
26
+ };
27
+ tdayjs.locale = (preset, object) => {
28
+ if (preset === undefined)
29
+ return getGlobalLocale();
30
+ let name;
31
+ if (typeof preset === 'string') {
32
+ name = preset.toLowerCase();
33
+ if (object) {
34
+ registerLocale({ ...object, name });
35
+ }
36
+ setGlobalLocale(name);
37
+ }
38
+ else {
39
+ registerLocale(preset);
40
+ name = preset.name;
41
+ setGlobalLocale(name);
42
+ }
43
+ return name;
44
+ };
45
+ export default tdayjs;