nhb-toolbox 3.7.7 → 3.7.99

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.
@@ -1,7 +1,6 @@
1
- import { DAYS, MONTHS, sortedFormats, TIME_ZONES } from './constants';
1
+ import { DAYS, MONTHS, ORIGIN, sortedFormats, TIME_ZONES } from './constants';
2
2
  import { isValidUTCOffSet } from './guards';
3
3
  import { extractMinutesFromUTC } from './utils';
4
- const ORIGIN = Symbol('origin');
5
4
  export class Chronos {
6
5
  #date;
7
6
  [ORIGIN];
@@ -24,27 +23,13 @@ export class Chronos {
24
23
  yield ['month', this.month];
25
24
  yield ['isoMonth', this.month + 1];
26
25
  yield ['date', this.date];
27
- yield ['day', this.day];
28
- yield ['isoDay', this.day + 1];
26
+ yield ['weekDay', this.weekDay];
27
+ yield ['isoWeekDay', this.weekDay + 1];
29
28
  yield ['hour', this.hour];
30
29
  yield ['minute', this.minute];
31
30
  yield ['second', this.second];
32
31
  yield ['millisecond', this.millisecond];
33
32
  }
34
- #withOrigin(origin) {
35
- const instance = new Chronos(this.#date);
36
- instance[ORIGIN] = origin;
37
- return instance;
38
- }
39
- get [Symbol.toStringTag]() {
40
- switch (this[ORIGIN]) {
41
- case 'toUTC':
42
- case 'utc':
43
- return this.#toLocalISOString().replace(this.getUTCOffset(), 'Z');
44
- default:
45
- return this.#toLocalISOString();
46
- }
47
- }
48
33
  /**
49
34
  * * Enables primitive coercion like `console.log`, `${chronos}`, etc.
50
35
  * @param hint - The type hint provided by the JS engine.
@@ -55,144 +40,26 @@ export class Chronos {
55
40
  return this.valueOf();
56
41
  return this.toLocalISOString();
57
42
  }
58
- /** Returns a debug-friendly string for console.log or util.inspect */
59
- inspect() {
60
- return `[Chronos ${this.toLocalISOString()}]`;
61
- }
62
- /** * Clones and returns a new Chronos instance with the same date. */
63
- clone() {
64
- return new Chronos(this.#date);
65
- }
66
- /** * Enables JSON.stringify and console logging to show readable output. */
67
- toJSON() {
68
- return this.toLocalISOString();
69
- }
70
- /** * Enables arithmetic and comparison operations (e.g., +new Chronos()). */
71
- valueOf() {
72
- return this.getTimeStamp();
73
- }
74
- /** * Gets the native `Date` instance (read-only). */
75
- toDate() {
76
- return new Date(this.#date);
77
- }
78
- /** * Returns a string representation of a date. The format of the string depends on the locale. */
79
- toString() {
80
- switch (this[ORIGIN]) {
81
- case 'toUTC':
82
- case 'utc': {
83
- const mins = extractMinutesFromUTC(`UTC${this.getUTCOffset()}`);
84
- const date = this.addMinutes(mins);
85
- return date.toString();
86
- }
87
- default:
88
- return this.#date.toString();
89
- }
90
- }
91
- /** * Returns ISO string with local time zone offset */
92
- #toLocalISOString() {
93
- const pad = (n, p = 2) => String(n).padStart(p, '0');
94
- return `${this.year}-${pad(this.month + 1)}-${pad(this.date)}T${pad(this.hour)}:${pad(this.minute)}:${pad(this.second)}.${pad(this.millisecond, 3)}${this.getUTCOffset()}`;
95
- }
96
- /** * Returns ISO string with local time zone offset */
97
- toLocalISOString() {
98
- switch (this[ORIGIN]) {
99
- case 'toUTC':
100
- case 'utc': {
101
- const mins = extractMinutesFromUTC(`UTC${this.getUTCOffset()}`);
102
- const date = this.addMinutes(mins);
103
- return date.#toLocalISOString();
104
- }
105
- default:
106
- return this.#toLocalISOString();
107
- }
108
- }
109
- /** * Returns a date as a string value in ISO format. */
110
- toISOString() {
43
+ get [Symbol.toStringTag]() {
111
44
  switch (this[ORIGIN]) {
112
45
  case 'toUTC':
113
46
  case 'utc':
114
47
  return this.#toLocalISOString().replace(this.getUTCOffset(), 'Z');
115
48
  default:
116
- return this.#date.toISOString();
49
+ return this.#toLocalISOString();
117
50
  }
118
51
  }
119
- /**
120
- * * Wrapper over native `toLocaleString`
121
- * @description Converts a date and time to a string by using the current or specified locale.
122
- *
123
- * @param locales A locale string, array of locale strings, Intl.Locale object, or array of Intl.Locale objects that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.
124
- * @param options An object that contains one or more properties that specify comparison options.
125
- */
126
- toLocaleString(locale, options) {
127
- return this.#date.toLocaleString(locale, options);
128
- }
129
- /** * Returns the time value in milliseconds since midnight, January 1, 1970 UTC. */
130
- getTimeStamp() {
131
- return this.#date.getTime();
132
- }
133
- /** * Returns the time value in milliseconds since midnight, January 1, 1970 UTC. */
134
- get unix() {
135
- return this.#date.getTime();
136
- }
137
- get year() {
138
- return this.#date.getFullYear();
139
- }
140
- get month() {
141
- return this.#date.getMonth();
142
- }
143
- get date() {
144
- return this.#date.getDate();
145
- }
146
- get day() {
147
- return this.#date.getDay();
148
- }
149
- get hour() {
150
- return this.#date.getHours();
151
- }
152
- get minute() {
153
- return this.#date.getMinutes();
154
- }
155
- get second() {
156
- return this.#date.getSeconds();
157
- }
158
- get millisecond() {
159
- return this.#date.getMilliseconds();
160
- }
161
- /** * ISO weekday: 1 = Monday, 7 = Sunday */
162
- get isoWeekday() {
163
- const day = this.day;
164
- return day === 0 ? 7 : day;
165
- }
166
- /**
167
- * @instance Returns the current date and time in a specified format in local time.
168
- * * Default format is dd, `MMM DD, YYYY HH:mm:ss` = `Sun, Apr 06, 2025 16:11:55:379`
169
- * @param options - Configure format string and whether to format using utc offset.
170
- * @returns Formatted date string in desired format.
171
- */
172
- today(options) {
173
- const { format = 'dd, MMM DD, YYYY HH:mm:ss', useUTC = false } = options || {};
174
- const today = new Date();
175
- return new Chronos(today).#format(format, useUTC);
176
- }
177
- /**
178
- * @static Returns the current date and time in a specified format in local time.
179
- * * Default format is dd, `MMM DD, YYYY HH:mm:ss` = `Sun, Apr 06, 2025 16:11:55:379`
180
- * @param options - Configure format string and whether to format using utc offset.
181
- * @returns Formatted date string in desired format.
182
- */
183
- static today(options) {
184
- const { format = 'dd, MMM DD, YYYY HH:mm:ss', useUTC = false } = options || {};
185
- const today = new Date();
186
- return new Chronos(today).#format(format, useUTC);
52
+ /** @private @instance Method to tag origin of the `Chronos` instance. */
53
+ #withOrigin(origin) {
54
+ const instance = new Chronos(this.#date);
55
+ instance[ORIGIN] = origin;
56
+ return instance;
187
57
  }
188
58
  /**
189
- * * Returns the number of milliseconds elapsed since midnight, January 1, 1970 Universal Coordinated Time (UTC).
190
- * * It basically calls `Date.now()`.
191
- * @returns The number of milliseconds elapsed since the Unix epoch.
59
+ * @private @instance Method to create native `Date` instance from date-like data types.
60
+ * @param value The value to convert into `Date`.
61
+ * @returns Instance of native Date object.
192
62
  */
193
- static now() {
194
- return Date.now();
195
- }
196
63
  #toNewDate(value) {
197
64
  const date = value instanceof Chronos ?
198
65
  value.toDate()
@@ -204,7 +71,7 @@ export class Chronos {
204
71
  return date;
205
72
  }
206
73
  /**
207
- * @private Formats the current `Chronos` date using the specified template.
74
+ * @private @instance Formats the current `Chronos` date using the specified template.
208
75
  *
209
76
  * @param format - The desired date format.
210
77
  * @param useUTC - Whether to use UTC or local time.
@@ -276,8 +143,140 @@ export class Chronos {
276
143
  }
277
144
  return result;
278
145
  }
146
+ /** @private @instance Returns ISO string with local time zone offset */
147
+ #toLocalISOString() {
148
+ const pad = (n, p = 2) => String(n).padStart(p, '0');
149
+ return `${this.year}-${pad(this.month + 1)}-${pad(this.date)}T${pad(this.hour)}:${pad(this.minute)}:${pad(this.second)}.${pad(this.millisecond, 3)}${this.getUTCOffset()}`;
150
+ }
151
+ /** Gets the full year of the date. */
152
+ get year() {
153
+ return this.#date.getFullYear();
154
+ }
155
+ /** Gets the month (0-11) of the date. */
156
+ get month() {
157
+ return this.#date.getMonth();
158
+ }
159
+ /** Gets the day of the month (1-31). */
160
+ get date() {
161
+ return this.#date.getDate();
162
+ }
163
+ /** Gets the day of the week (0-6, where 0 is Sunday). */
164
+ get weekDay() {
165
+ return this.#date.getDay();
166
+ }
167
+ /** Gets the hour (0-23) of the date. */
168
+ get hour() {
169
+ return this.#date.getHours();
170
+ }
171
+ /** Gets the minute (0-59) of the date. */
172
+ get minute() {
173
+ return this.#date.getMinutes();
174
+ }
175
+ /** Gets the second (0-59) of the date. */
176
+ get second() {
177
+ return this.#date.getSeconds();
178
+ }
179
+ /** Gets the millisecond (0-999) of the date. */
180
+ get millisecond() {
181
+ return this.#date.getMilliseconds();
182
+ }
183
+ /** Gets ISO weekday: 1 = Monday, 7 = Sunday */
184
+ get isoWeekday() {
185
+ const day = this.weekDay;
186
+ return day === 0 ? 7 : day;
187
+ }
188
+ /** Gets ISO month (1–12 instead of 0–11) */
189
+ get isoMonth() {
190
+ return this.month + 1;
191
+ }
192
+ /** Gets the time value in milliseconds since midnight, January 1, 1970 UTC. */
193
+ get unix() {
194
+ return this.#date.getTime();
195
+ }
196
+ /** @public @instance Returns a debug-friendly string for console.log or util.inspect */
197
+ inspect() {
198
+ return `[Chronos ${this.toLocalISOString()}]`;
199
+ }
200
+ /** @public @instance Clones and returns a new Chronos instance with the same date. */
201
+ clone() {
202
+ return new Chronos(this.#date).#withOrigin(this[ORIGIN]);
203
+ }
204
+ /** @public @instance Enables JSON.stringify and console logging to show readable output. */
205
+ toJSON() {
206
+ return this.toLocalISOString();
207
+ }
208
+ /** @public @instance Enables arithmetic and comparison operations (e.g., +new Chronos()). */
209
+ valueOf() {
210
+ return this.getTimeStamp();
211
+ }
212
+ /** @public @instance Gets the native `Date` instance (read-only). */
213
+ toDate() {
214
+ return new Date(this.#date);
215
+ }
216
+ /** @public @instance Returns a string representation of a date. The format of the string depends on the locale. */
217
+ toString() {
218
+ switch (this[ORIGIN]) {
219
+ case 'toUTC':
220
+ case 'utc': {
221
+ const mins = extractMinutesFromUTC(`UTC${this.getUTCOffset()}`);
222
+ const date = this.addMinutes(mins);
223
+ return date.toString();
224
+ }
225
+ default:
226
+ return this.#date.toString();
227
+ }
228
+ }
229
+ /** @public @instance Returns ISO string with local time zone offset */
230
+ toLocalISOString() {
231
+ switch (this[ORIGIN]) {
232
+ case 'toUTC':
233
+ case 'utc': {
234
+ const mins = extractMinutesFromUTC(`UTC${this.getUTCOffset()}`);
235
+ const date = this.addMinutes(mins);
236
+ return date.#toLocalISOString();
237
+ }
238
+ default:
239
+ return this.#toLocalISOString();
240
+ }
241
+ }
242
+ /** @public @instance Returns a date as a string value in ISO format. */
243
+ toISOString() {
244
+ switch (this[ORIGIN]) {
245
+ case 'toUTC':
246
+ case 'utc':
247
+ return this.#toLocalISOString().replace(this.getUTCOffset(), 'Z');
248
+ default:
249
+ return this.#date.toISOString();
250
+ }
251
+ }
252
+ /**
253
+ * @public @instance Wrapper over native `toLocaleString`
254
+ * @description Converts a date and time to a string by using the current or specified locale.
255
+ *
256
+ * @param locales A locale string, array of locale strings, Intl.Locale object, or array of Intl.Locale objects that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.
257
+ * @param options An object that contains one or more properties that specify comparison options.
258
+ */
259
+ toLocaleString(locale, options) {
260
+ return this.#date.toLocaleString(locale, options);
261
+ }
262
+ /** @public @instance Returns the time value in milliseconds since midnight, January 1, 1970 UTC. */
263
+ getTimeStamp() {
264
+ return this.#date.getTime();
265
+ }
266
+ /**
267
+ * @public @instance Returns the current date and time in a specified format in local time.
268
+ * @description Default format is dd, `MMM DD, YYYY HH:mm:ss` = `Sun, Apr 06, 2025 16:11:55:379`
269
+ *
270
+ * @param options - Configure format string and whether to format using utc offset.
271
+ * @returns Formatted date string in desired format.
272
+ */
273
+ today(options) {
274
+ const { format = 'dd, MMM DD, YYYY HH:mm:ss', useUTC = false } = options || {};
275
+ const today = new Date();
276
+ return new Chronos(today).#format(format, useUTC);
277
+ }
279
278
  /**
280
- * * Formats the date into a custom string format (local time).
279
+ * @public @instance Formats the date into a custom string format (local time).
281
280
  *
282
281
  * @param format - The desired format (Default format is `dd, MMM DD, YYYY HH:mm:ss:mss` = `Sun, Apr 06, 2025 16:11:55:379`).
283
282
  * @param useUTC - Optional `useUTC` to get the formatted time using UTC Offset, defaults to `false`. Equivalent to `formatUTC()` method if set to `true`.
@@ -287,7 +286,7 @@ export class Chronos {
287
286
  return this.#format(format, useUTC);
288
287
  }
289
288
  /**
290
- * * Formats the date into a custom string format (UTC time).
289
+ * @public @instance Formats the date into a custom string format (UTC time).
291
290
  *
292
291
  * @param format - The desired format (Default format is `dd, MMM DD, YYYY HH:mm:ss:mss` = `Sun, Apr 06, 2025 16:11:55:379`).
293
292
  * @returns Formatted date string in desired format (UTC time).
@@ -302,85 +301,67 @@ export class Chronos {
302
301
  }
303
302
  }
304
303
  /**
305
- * * Adds seconds and returns a new immutable instance.
304
+ * @public @instance Adds seconds and returns a new immutable instance.
306
305
  * @param seconds - Number of seconds to add.
307
306
  * @returns A new `Chronos` instance with the updated date.
308
307
  */
309
308
  addSeconds(seconds) {
310
309
  const newDate = new Date(this.#date);
311
310
  newDate.setSeconds(newDate.getSeconds() + seconds);
312
- return new Chronos(newDate);
311
+ return new Chronos(newDate).#withOrigin('addSeconds');
313
312
  }
314
313
  /**
315
- * * Adds minutes and returns a new immutable instance.
314
+ * @public @instance Adds minutes and returns a new immutable instance.
316
315
  * @param minutes - Number of minutes to add.
317
316
  * @returns A new `Chronos` instance with the updated date.
318
317
  */
319
318
  addMinutes(minutes) {
320
319
  const newDate = new Date(this.#date);
321
320
  newDate.setMinutes(newDate.getMinutes() + minutes);
322
- return new Chronos(newDate);
321
+ return new Chronos(newDate).#withOrigin('addMinutes');
323
322
  }
324
323
  /**
325
- * * Adds hours and returns a new immutable instance.
324
+ * @public @instance Adds hours and returns a new immutable instance.
326
325
  * @param hours - Number of hours to add.
327
326
  * @returns A new `Chronos` instance with the updated date.
328
327
  */
329
328
  addHours(hours) {
330
329
  const newDate = new Date(this.#date);
331
330
  newDate.setHours(newDate.getHours() + hours);
332
- return new Chronos(newDate);
331
+ return new Chronos(newDate).#withOrigin('addHours');
333
332
  }
334
333
  /**
335
- * * Adds days and returns a new immutable instance.
334
+ * @public @instance Adds days and returns a new immutable instance.
336
335
  * @param days - Number of days to add.
337
336
  * @returns A new `Chronos` instance with the updated date.
338
337
  */
339
338
  addDays(days) {
340
339
  const newDate = new Date(this.#date);
341
340
  newDate.setDate(newDate.getDate() + days);
342
- return new Chronos(newDate);
341
+ return new Chronos(newDate).#withOrigin('addDays');
343
342
  }
344
343
  /**
345
- * * Adds months and returns a new immutable instance.
344
+ * @public @instance Adds months and returns a new immutable instance.
346
345
  * @param months - Number of months to add.
347
346
  * @returns A new `Chronos` instance with the updated date.
348
347
  */
349
348
  addMonths(months) {
350
349
  const newDate = new Date(this.#date);
351
350
  newDate.setMonth(newDate.getMonth() + months);
352
- return new Chronos(newDate);
351
+ return new Chronos(newDate).#withOrigin('addMonths');
353
352
  }
354
353
  /**
355
- * * Adds years and returns a new immutable instance.
354
+ * @public @instance Adds years and returns a new immutable instance.
356
355
  * @param years - Number of years to add.
357
356
  * @returns A new `Chronos` instance with the updated date.
358
357
  */
359
358
  addYears(years) {
360
359
  const newDate = new Date(this.#date);
361
360
  newDate.setFullYear(newDate.getFullYear() + years);
362
- return new Chronos(newDate);
363
- }
364
- /**
365
- * * Subtracts days and returns a new immutable instance.
366
- * @param days - Number of days to subtract.
367
- * @returns A new `Chronos` instance with the updated date.
368
- */
369
- subtractDays(days) {
370
- return this.addDays(-days);
361
+ return new Chronos(newDate).#withOrigin('addYears');
371
362
  }
372
363
  /**
373
- * * Checks if the year is a leap year.
374
- * - A year is a leap year if it is divisible by 4, but not divisible by 100, unless it is also divisible by 400.
375
- * - For example, 2000 and 2400 are leap years, but 1900 and 2100 are not.
376
- * @returns `true` if the year is a leap year, `false` otherwise.
377
- */
378
- isLeapYear() {
379
- const year = this.#date.getFullYear();
380
- return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
381
- }
382
- /**
383
- * * Create a new instance of `Chronos` in the specified timezone.
364
+ * @public @instance Create a new instance of `Chronos` in the specified timezone.
384
365
  *
385
366
  * @param zone - Standard timezone abbreviation (e.g., 'IST', 'UTC', 'EST') or UTC Offset in `UTC-01:30` format.
386
367
  * @returns A new instance of `Chronos` with time in the given timezone. Invalid input sets time-zone to `UTC`.
@@ -395,22 +376,97 @@ export class Chronos {
395
376
  }
396
377
  const utc = this.#date.getTime() + this.#date.getTimezoneOffset() * 60 * 1000;
397
378
  const adjusted = new Date(utc + offset * 60 * 1000);
398
- return new Chronos(adjusted);
379
+ return new Chronos(adjusted).#withOrigin('timeZone');
399
380
  }
400
- /** - Checks if the current date is today. */
381
+ /**
382
+ * @public @instance Checks if the year is a leap year.
383
+ * - A year is a leap year if it is divisible by 4, but not divisible by 100, unless it is also divisible by 400.
384
+ * - For example, 2000 and 2400 are leap years, but 1900 and 2100 are not.
385
+ * @returns `true` if the year is a leap year, `false` otherwise.
386
+ */
387
+ isLeapYear() {
388
+ const year = this.#date.getFullYear();
389
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
390
+ }
391
+ /** @public @instance Checks if the current date is today. */
401
392
  isToday() {
402
393
  return this.getRelativeDay() === 0;
403
394
  }
404
- /** - Checks if the current date is tomorrow. */
395
+ /** @public @instance Checks if the current date is tomorrow. */
405
396
  isTomorrow() {
406
397
  return this.getRelativeDay() === 1;
407
398
  }
408
- /** - Checks if the current date is yesterday. */
399
+ /** @public @instance Checks if the current date is yesterday. */
409
400
  isYesterday() {
410
401
  return this.getRelativeDay() === -1;
411
402
  }
412
403
  /**
413
- * * Returns full time difference from now (or a specified time) down to a given level.
404
+ * @public @instance Checks if another date is the same as this one in a specific unit.
405
+ * @param other The other date to compare.
406
+ * @param unit The unit to compare.
407
+ */
408
+ isSame(other, unit) {
409
+ const time = new Chronos(other);
410
+ return (this.startOf(unit).toDate().getTime() ===
411
+ time.startOf(unit).toDate().getTime());
412
+ }
413
+ /**
414
+ * @public @instance Checks if this date is before another date in a specific unit.
415
+ * @param other The other date to compare.
416
+ * @param unit The unit to compare.
417
+ */
418
+ isBefore(other, unit) {
419
+ const time = new Chronos(other);
420
+ return (this.startOf(unit).toDate().getTime() <
421
+ time.startOf(unit).toDate().getTime());
422
+ }
423
+ /**
424
+ * @public @instance Checks if this date is after another date in a specific unit.
425
+ * @param other The other date to compare.
426
+ * @param unit The unit to compare.
427
+ */
428
+ isAfter(other, unit) {
429
+ const time = new Chronos(other);
430
+ return (this.startOf(unit).toDate().getTime() >
431
+ time.startOf(unit).toDate().getTime());
432
+ }
433
+ /**
434
+ * @public @instance Checks if the current date is between the given start and end dates.
435
+ *
436
+ * @param start - The start of the range.
437
+ * @param end - The end of the range.
438
+ * @param inclusive - Specifies whether the comparison is inclusive or exclusive:
439
+ * - `'[]'`: inclusive of both start and end (≥ start and ≤ end)
440
+ * - `'[)'`: inclusive of start, exclusive of end (≥ start and < end)
441
+ * - `'(]'`: exclusive of start, inclusive of end (> start and ≤ end)
442
+ * - `'()'`: exclusive of both start and end (> start and < end)
443
+ *
444
+ * @returns `true` if the current date is within the specified range based on the `inclusive` mode.
445
+ */
446
+ isBetween(start, end, inclusive = '()') {
447
+ const s = new Chronos(start).valueOf();
448
+ const e = new Chronos(end).valueOf();
449
+ const t = this.valueOf();
450
+ switch (inclusive) {
451
+ case '[]':
452
+ return t >= s && t <= e;
453
+ case '[)':
454
+ return t >= s && t < e;
455
+ case '(]':
456
+ return t > s && t <= e;
457
+ case '()':
458
+ return t > s && t < e;
459
+ }
460
+ }
461
+ /** @public @instance Checks if currently in DST */
462
+ isDST() {
463
+ const jan = new Date(this.year, 0, 1);
464
+ const jul = new Date(this.year, 6, 1);
465
+ return (Math.min(jan.getTimezoneOffset(), jul.getTimezoneOffset()) !==
466
+ this.#date.getTimezoneOffset());
467
+ }
468
+ /**
469
+ * @public @instance Returns full time difference from now (or a specified time) down to a given level.
414
470
  *
415
471
  * @param level Determines the smallest unit to include in the output (e.g., 'minute' will show up to minutes, ignoring seconds). Defaults to `minute`.
416
472
  * @param withSuffixPrefix If `true`, adds `"in"` or `"ago"` depending on whether the time is in the future or past. Defaults to `true`.
@@ -493,7 +549,7 @@ export class Chronos {
493
549
  return `${prefix}${parts.join(' ')}${suffix}`;
494
550
  }
495
551
  /**
496
- * * Returns the number of full years between the input date and now.
552
+ * @public @instance Returns the number of full years between the input date and now.
497
553
  * @param time Optional time to compare with the `Chronos` date/time.
498
554
  * @returns The difference in number, negative is `Chronos` time is a past time else positive.
499
555
  */
@@ -509,7 +565,7 @@ export class Chronos {
509
565
  return years;
510
566
  }
511
567
  /**
512
- * * Returns the number of full months between the input date and now.
568
+ * @public @instance Returns the number of full months between the input date and now.
513
569
  * @param time Optional time to compare with the `Chronos` date/time.
514
570
  * @returns The difference in number, negative is `Chronos` time is a past time else positive.
515
571
  */
@@ -524,7 +580,7 @@ export class Chronos {
524
580
  return months;
525
581
  }
526
582
  /**
527
- * * Determines if the given date is today, tomorrow, yesterday or any relative day.
583
+ * @public @instance Determines if the given date is today, tomorrow, yesterday or any relative day.
528
584
  * @param date - The date to compare (Date object).
529
585
  * @param time Optional time to compare with the `Chronos` date/time.
530
586
  * @returns
@@ -545,7 +601,7 @@ export class Chronos {
545
601
  return diffDays;
546
602
  }
547
603
  /**
548
- * * Returns the number of full hours between the input date and now.
604
+ * @public @instance Returns the number of full hours between the input date and now.
549
605
  * @param time Optional time to compare with the `Chronos` date/time.
550
606
  * @returns The difference in number, negative is `Chronos` time is a past time else positive.
551
607
  */
@@ -554,7 +610,7 @@ export class Chronos {
554
610
  return Math.floor(diff / (1000 * 60 * 60));
555
611
  }
556
612
  /**
557
- * * Returns the number of full minutes between the input date and now.
613
+ * @public @instance Returns the number of full minutes between the input date and now.
558
614
  * @param time Optional time to compare with the `Chronos` date/time.
559
615
  * @returns The difference in number, negative is `Chronos` time is a past time else positive.
560
616
  */
@@ -563,7 +619,7 @@ export class Chronos {
563
619
  return Math.floor(diff / (1000 * 60));
564
620
  }
565
621
  /**
566
- * * Returns the number of full seconds between the input date and now.
622
+ * @public @instance Returns the number of full seconds between the input date and now.
567
623
  * @param time Optional time to compare with the `Chronos` date/time.
568
624
  * @returns The difference in number, negative is `Chronos` time is a past time else positive.
569
625
  */
@@ -572,7 +628,7 @@ export class Chronos {
572
628
  return Math.floor(diff / 1000);
573
629
  }
574
630
  /**
575
- * * Returns the number of milliseconds between the input date and now.
631
+ * @public @instance Returns the number of milliseconds between the input date and now.
576
632
  * @param time Optional time to compare with the `Chronos` date/time.
577
633
  * @returns The difference in number, negative is `Chronos` time is a past time else positive.
578
634
  */
@@ -580,7 +636,7 @@ export class Chronos {
580
636
  return this.#date.getTime() - this.#toNewDate(time).getTime();
581
637
  }
582
638
  /**
583
- * * Compares the stored date with now, returning the difference in the specified unit.
639
+ * @public @instance Compares the stored date with now, returning the difference in the specified unit.
584
640
  *
585
641
  * @param unit The time unit to compare by. Defaults to 'minute'.
586
642
  * @param time Optional time to compare with the `Chronos` date/time.
@@ -607,7 +663,7 @@ export class Chronos {
607
663
  }
608
664
  }
609
665
  /**
610
- * * Returns a new Chronos instance at the start of a given unit.
666
+ * @public @instance Returns a new Chronos instance at the start of a given unit.
611
667
  * @param unit The unit to reset (e.g., year, month, day).
612
668
  */
613
669
  startOf(unit) {
@@ -643,17 +699,20 @@ export class Chronos {
643
699
  case 'millisecond':
644
700
  break;
645
701
  }
646
- return new Chronos(d);
702
+ return new Chronos(d).#withOrigin('startOf');
647
703
  }
648
704
  /**
649
- * * Returns a new Chronos instance at the end of a given unit.
705
+ * @public @instance Returns a new Chronos instance at the end of a given unit.
650
706
  * @param unit The unit to adjust (e.g., year, month, day).
651
707
  */
652
708
  endOf(unit) {
653
- return this.startOf(unit).add(1, unit).add(-1, 'millisecond');
709
+ return this.startOf(unit)
710
+ .add(1, unit)
711
+ .add(-1, 'millisecond')
712
+ .#withOrigin('endOf');
654
713
  }
655
714
  /**
656
- * * Returns a new Chronos instance with the specified unit added.
715
+ * @public @instance Returns a new Chronos instance with the specified unit added.
657
716
  * @param amount The amount to add (can be negative).
658
717
  * @param unit The time unit to add.
659
718
  */
@@ -682,10 +741,18 @@ export class Chronos {
682
741
  d.setFullYear(d.getFullYear() + amount);
683
742
  break;
684
743
  }
685
- return new Chronos(d);
744
+ return new Chronos(d).#withOrigin('add');
745
+ }
746
+ /**
747
+ * @public @instance Returns a new Chronos instance with the specified unit subtracted.
748
+ * @param amount The amount to subtract (can be negative).
749
+ * @param unit The time unit to add.
750
+ */
751
+ subtract(amount, unit) {
752
+ return this.add(-amount, unit).#withOrigin('subtract');
686
753
  }
687
754
  /**
688
- * * Gets the value of a specific time unit from the date.
755
+ * @public @instance Gets the value of a specific time unit from the date.
689
756
  * @param unit The unit to retrieve.
690
757
  */
691
758
  get(unit) {
@@ -707,7 +774,7 @@ export class Chronos {
707
774
  }
708
775
  }
709
776
  /**
710
- * Returns a new Chronos instance with the specified unit set to the given value.
777
+ * @public @instance Returns a new Chronos instance with the specified unit set to the given value.
711
778
  * @param unit The unit to modify.
712
779
  * @param value The value to set for the unit.
713
780
  */
@@ -736,10 +803,10 @@ export class Chronos {
736
803
  d.setMilliseconds(value);
737
804
  break;
738
805
  }
739
- return new Chronos(d);
806
+ return new Chronos(d).#withOrigin('set');
740
807
  }
741
808
  /**
742
- * * Returns the difference between this and another date in the given unit.
809
+ * @public @instance Returns the difference between this and another date in the given unit.
743
810
  * @param other The other date to compare.
744
811
  * @param unit The unit in which to return the difference.
745
812
  */
@@ -765,37 +832,7 @@ export class Chronos {
765
832
  }
766
833
  }
767
834
  /**
768
- * * Checks if another date is the same as this one in a specific unit.
769
- * @param other The other date to compare.
770
- * @param unit The unit to compare.
771
- */
772
- isSame(other, unit) {
773
- const time = new Chronos(other);
774
- return (this.startOf(unit).toDate().getTime() ===
775
- time.startOf(unit).toDate().getTime());
776
- }
777
- /**
778
- * * Checks if this date is before another date in a specific unit.
779
- * @param other The other date to compare.
780
- * @param unit The unit to compare.
781
- */
782
- isBefore(other, unit) {
783
- const time = new Chronos(other);
784
- return (this.startOf(unit).toDate().getTime() <
785
- time.startOf(unit).toDate().getTime());
786
- }
787
- /**
788
- * * Checks if this date is after another date in a specific unit.
789
- * @param other The other date to compare.
790
- * @param unit The unit to compare.
791
- */
792
- isAfter(other, unit) {
793
- const time = new Chronos(other);
794
- return (this.startOf(unit).toDate().getTime() >
795
- time.startOf(unit).toDate().getTime());
796
- }
797
- /**
798
- * * Returns a human-readable relative calendar time like "Today at 3:00 PM"
835
+ * @public @instance Returns a human-readable relative calendar time like "Today at 3:00 PM"
799
836
  * @param baseDate Optional base date to compare with.
800
837
  */
801
838
  calendar(baseDate) {
@@ -822,7 +859,7 @@ export class Chronos {
822
859
  minute: '2-digit',
823
860
  });
824
861
  }
825
- /** * Returns a short human-readable string like "2h ago", "in 5m" */
862
+ /** @public @instance Returns a short human-readable string like "2h ago", "in 5m" */
826
863
  fromNowShort() {
827
864
  const now = new Chronos();
828
865
  const diffInSeconds = this.diff(now, 'second');
@@ -848,7 +885,7 @@ export class Chronos {
848
885
  return `${suffix}${Math.floor(abs / 31536000)}y${postfix}`;
849
886
  }
850
887
  }
851
- /** * Returns ISO week number */
888
+ /** @public @instance Returns ISO week number */
852
889
  getWeek() {
853
890
  // ISO week starts on Monday
854
891
  const target = this.startOf('week').add(3, 'day');
@@ -859,84 +896,68 @@ export class Chronos {
859
896
  const week = Math.floor(daysDiff / 7) + 1;
860
897
  return week;
861
898
  }
862
- /** * Returns ISO week year */
899
+ /** @public @instance Returns ISO week year */
863
900
  getWeekYear() {
864
901
  const d = this.startOf('week').add(3, 'day'); // Thursday of current ISO week
865
902
  return d.year;
866
903
  }
867
- /** * Returns day of year (1 - 366) */
904
+ /** @public @instance Returns day of year (1 - 366) */
868
905
  getDayOfYear() {
869
906
  const start = new Date(this.year, 0, 1);
870
907
  const diff = this.#date.getTime() - start.getTime();
871
908
  return Math.floor(diff / 86400000) + 1;
872
909
  }
873
- /**
874
- * * Checks if the current date is between the given start and end dates.
875
- *
876
- * @param start - The start of the range.
877
- * @param end - The end of the range.
878
- * @param inclusive - Specifies whether the comparison is inclusive or exclusive:
879
- * - `'[]'`: inclusive of both start and end (≥ start and ≤ end)
880
- * - `'[)'`: inclusive of start, exclusive of end (≥ start and < end)
881
- * - `'(]'`: exclusive of start, inclusive of end (> start and ≤ end)
882
- * - `'()'`: exclusive of both start and end (> start and < end)
883
- *
884
- * @returns `true` if the current date is within the specified range based on the `inclusive` mode.
885
- */
886
- isBetween(start, end, inclusive = '()') {
887
- const s = new Chronos(start).valueOf();
888
- const e = new Chronos(end).valueOf();
889
- const t = this.valueOf();
890
- switch (inclusive) {
891
- case '[]':
892
- return t >= s && t <= e;
893
- case '[)':
894
- return t >= s && t < e;
895
- case '(]':
896
- return t > s && t <= e;
897
- case '()':
898
- return t > s && t < e;
899
- }
900
- }
901
- /** * Returns number of days in current month */
910
+ /** @public @instance Returns number of days in current month */
902
911
  daysInMonth() {
903
912
  return new Date(this.year, this.month + 1, 0).getDate();
904
913
  }
905
- /** * Converts to object with all date unit parts */
914
+ /** @public @instance Converts to object with all date unit parts */
906
915
  toObject() {
907
916
  return Object.fromEntries([...this]);
908
917
  }
909
- /** * Converts to array with all date unit parts */
918
+ /** @public @instance Converts to array with all date unit parts */
910
919
  toArray() {
911
920
  return Object.values(this.toObject());
912
921
  }
913
- /** * Returns offset like +06:00 */
922
+ /** @public @instance Returns offset like +06:00 */
914
923
  getUTCOffset() {
915
924
  const offset = -this.#date.getTimezoneOffset();
916
925
  const sign = offset >= 0 ? '+' : '-';
917
926
  const pad = (n) => String(Math.floor(Math.abs(n))).padStart(2, '0');
918
927
  return `${sign}${pad(offset / 60)}:${pad(offset % 60)}`;
919
928
  }
920
- /** * Checks if currently in DST */
921
- isDST() {
922
- const jan = new Date(this.year, 0, 1);
923
- const jul = new Date(this.year, 6, 1);
924
- return (Math.min(jan.getTimezoneOffset(), jul.getTimezoneOffset()) !==
925
- this.#date.getTimezoneOffset());
926
- }
927
- /** * Returns new Chronos instance in UTC */
929
+ /** @public @instance Returns new Chronos instance in UTC */
928
930
  toUTC() {
929
931
  const date = this.#date;
930
932
  const utc = new Date(date.getTime() + date.getTimezoneOffset() * 60000);
931
933
  return new Chronos(utc).#withOrigin('toUTC');
932
934
  }
933
- /** * Returns new Chronos instance in local time */
935
+ /** @public @instance Returns new Chronos instance in local time */
934
936
  toLocal() {
935
937
  const date = this.#date;
936
938
  const utc = new Date(date.getTime() - date.getTimezoneOffset() * 60000);
937
939
  return new Chronos(utc).#withOrigin('toLocal');
938
940
  }
939
- /** @static Parses a date string with a given format (partial support) */
941
+ /**
942
+ * @public @static Returns the current date and time in a specified format in local time.
943
+ * * Default format is dd, `MMM DD, YYYY HH:mm:ss` = `Sun, Apr 06, 2025 16:11:55:379`
944
+ * @param options - Configure format string and whether to format using utc offset.
945
+ * @returns Formatted date string in desired format.
946
+ */
947
+ static today(options) {
948
+ const { format = 'dd, MMM DD, YYYY HH:mm:ss', useUTC = false } = options || {};
949
+ const today = new Date();
950
+ return new Chronos(today).#format(format, useUTC);
951
+ }
952
+ /**
953
+ * @public @static Returns the number of milliseconds elapsed since midnight, January 1, 1970 Universal Coordinated Time (UTC).
954
+ * * It basically calls `Date.now()`.
955
+ * @returns The number of milliseconds elapsed since the Unix epoch.
956
+ */
957
+ static now() {
958
+ return Date.now();
959
+ }
960
+ /** @public @static Parses a date string with a given format (partial support) */
940
961
  static parse(dateStr, format) {
941
962
  const formatMap = {
942
963
  YYYY: 'year',
@@ -960,10 +981,10 @@ export class Chronos {
960
981
  }
961
982
  return acc;
962
983
  }, {});
963
- return new Chronos(new Date(values.year ?? 1970, (values.month ?? 1) - 1, values.date ?? 1, values.hour ?? 0, values.minute ?? 0, values.second ?? 0));
984
+ return new Chronos(new Date(values.year ?? 1970, (values.month ?? 1) - 1, values.date ?? 1, values.hour ?? 0, values.minute ?? 0, values.second ?? 0)).#withOrigin('parse');
964
985
  }
965
986
  /**
966
- * @static Creates UTC Chronos
987
+ * @public @static Creates UTC Chronos
967
988
  * @param dateLike Date input to create utc time.
968
989
  */
969
990
  static utc(dateLike) {
@@ -972,17 +993,17 @@ export class Chronos {
972
993
  return new Chronos(utc).#withOrigin('utc');
973
994
  }
974
995
  /**
975
- * @static Returns earliest Chronos
996
+ * @public @static Returns earliest Chronos
976
997
  * @param dates Date inputs.
977
998
  */
978
999
  static min(...dates) {
979
- return new Chronos(Math.min(...dates.map((d) => new Chronos(d).valueOf())));
1000
+ return new Chronos(Math.min(...dates.map((d) => new Chronos(d).valueOf()))).#withOrigin('min');
980
1001
  }
981
1002
  /**
982
- * @static Returns latest Chronos
1003
+ * @public @static Returns latest Chronos
983
1004
  * @param dates Date inputs.
984
1005
  */
985
1006
  static max(...dates) {
986
- return new Chronos(Math.max(...dates.map((d) => new Chronos(d).valueOf())));
1007
+ return new Chronos(Math.max(...dates.map((d) => new Chronos(d).valueOf()))).#withOrigin('max');
987
1008
  }
988
1009
  }