nhb-toolbox 3.7.5 → 3.7.9

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,9 +1,9 @@
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
4
  export class Chronos {
5
5
  #date;
6
- // readonly preview: string;
6
+ [ORIGIN];
7
7
  /**
8
8
  * * Creates a new immutable `Chronos` instance.
9
9
  *
@@ -16,10 +16,19 @@ export class Chronos {
16
16
  constructor(value) {
17
17
  const date = this.#toNewDate(value);
18
18
  this.#date = date;
19
- // this.preview = this.toISOString();
19
+ this[ORIGIN] = 'root';
20
20
  }
21
- get [Symbol.toStringTag]() {
22
- return this.toLocalISOString();
21
+ *[Symbol.iterator]() {
22
+ yield ['year', this.year];
23
+ yield ['month', this.month];
24
+ yield ['isoMonth', this.month + 1];
25
+ yield ['date', this.date];
26
+ yield ['weekDay', this.weekDay];
27
+ yield ['isoWeekDay', this.weekDay + 1];
28
+ yield ['hour', this.hour];
29
+ yield ['minute', this.minute];
30
+ yield ['second', this.second];
31
+ yield ['millisecond', this.millisecond];
23
32
  }
24
33
  /**
25
34
  * * Enables primitive coercion like `console.log`, `${chronos}`, etc.
@@ -31,112 +40,26 @@ export class Chronos {
31
40
  return this.valueOf();
32
41
  return this.toLocalISOString();
33
42
  }
34
- /** * Clones and returns a new Chronos instance with the same date. */
35
- clone() {
36
- return new Chronos(this.#date);
37
- }
38
- /** * Enables JSON.stringify and console logging to show readable output. */
39
- toJSON() {
40
- return this.toLocalISOString();
41
- }
42
- /** * Enables arithmetic and comparison operations (e.g., +new Chronos()). */
43
- valueOf() {
44
- return this.getTimeStamp();
45
- }
46
- /** * Gets the native `Date` instance (read-only). */
47
- toDate() {
48
- return new Date(this.#date);
49
- }
50
- /** * Returns a string representation of a date. The format of the string depends on the locale. */
51
- toString() {
52
- return this.#date.toString();
53
- }
54
- /** * Returns ISO string with local time zone offset */
55
- toLocalISOString() {
56
- const pad = (n, p = 2) => String(n).padStart(p, '0');
57
- 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()}`;
58
- }
59
- /**
60
- * * Wrapper over native `toLocaleString`
61
- * @description Converts a date and time to a string by using the current or specified locale.
62
- *
63
- * @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.
64
- * @param options An object that contains one or more properties that specify comparison options.
65
- */
66
- toLocaleString(locale, options) {
67
- return this.#date.toLocaleString(locale, options);
68
- }
69
- /** * Returns a date as a string value in ISO format. */
70
- toISOString() {
71
- return this.#date.toISOString();
72
- }
73
- /** * Returns the time value in milliseconds since midnight, January 1, 1970 UTC. */
74
- getTimeStamp() {
75
- return this.#date.getTime();
76
- }
77
- /** * Returns the time value in milliseconds since midnight, January 1, 1970 UTC. */
78
- get unix() {
79
- return this.#date.getTime();
80
- }
81
- get year() {
82
- return this.#date.getFullYear();
83
- }
84
- get month() {
85
- return this.#date.getMonth();
86
- }
87
- get date() {
88
- return this.#date.getDate();
89
- }
90
- get day() {
91
- return this.#date.getDay();
92
- }
93
- get hour() {
94
- return this.#date.getHours();
95
- }
96
- get minute() {
97
- return this.#date.getMinutes();
98
- }
99
- get second() {
100
- return this.#date.getSeconds();
101
- }
102
- get millisecond() {
103
- return this.#date.getMilliseconds();
104
- }
105
- /** * ISO weekday: 1 = Monday, 7 = Sunday */
106
- get isoWeekday() {
107
- const day = this.day;
108
- return day === 0 ? 7 : day;
109
- }
110
- /**
111
- * @instance Returns the current date and time in a specified format in local time.
112
- * * Default format is dd, `MMM DD, YYYY HH:mm:ss` = `Sun, Apr 06, 2025 16:11:55:379`
113
- * @param options - Configure format string and whether to format using utc offset.
114
- * @returns Formatted date string in desired format.
115
- */
116
- today(options) {
117
- const { format = 'dd, MMM DD, YYYY HH:mm:ss', useUTC = false } = options || {};
118
- const today = new Date();
119
- return new Chronos(today).#format(format, useUTC);
43
+ get [Symbol.toStringTag]() {
44
+ switch (this[ORIGIN]) {
45
+ case 'toUTC':
46
+ case 'utc':
47
+ return this.#toLocalISOString().replace(this.getUTCOffset(), 'Z');
48
+ default:
49
+ return this.#toLocalISOString();
50
+ }
120
51
  }
121
- /**
122
- * @static Returns the current date and time in a specified format in local time.
123
- * * Default format is dd, `MMM DD, YYYY HH:mm:ss` = `Sun, Apr 06, 2025 16:11:55:379`
124
- * @param options - Configure format string and whether to format using utc offset.
125
- * @returns Formatted date string in desired format.
126
- */
127
- static today(options) {
128
- const { format = 'dd, MMM DD, YYYY HH:mm:ss', useUTC = false } = options || {};
129
- const today = new Date();
130
- 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;
131
57
  }
132
58
  /**
133
- * * Returns the number of milliseconds elapsed since midnight, January 1, 1970 Universal Coordinated Time (UTC).
134
- * * It basically calls `Date.now()`.
135
- * @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.
136
62
  */
137
- static now() {
138
- return Date.now();
139
- }
140
63
  #toNewDate(value) {
141
64
  const date = value instanceof Chronos ?
142
65
  value.toDate()
@@ -148,7 +71,7 @@ export class Chronos {
148
71
  return date;
149
72
  }
150
73
  /**
151
- * @private Formats the current `Chronos` date using the specified template.
74
+ * @private @instance Formats the current `Chronos` date using the specified template.
152
75
  *
153
76
  * @param format - The desired date format.
154
77
  * @param useUTC - Whether to use UTC or local time.
@@ -220,8 +143,140 @@ export class Chronos {
220
143
  }
221
144
  return result;
222
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
+ }
223
266
  /**
224
- * * Formats the date into a custom string format (local time).
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
+ }
278
+ /**
279
+ * @public @instance Formats the date into a custom string format (local time).
225
280
  *
226
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`).
227
282
  * @param useUTC - Optional `useUTC` to get the formatted time using UTC Offset, defaults to `false`. Equivalent to `formatUTC()` method if set to `true`.
@@ -231,94 +286,82 @@ export class Chronos {
231
286
  return this.#format(format, useUTC);
232
287
  }
233
288
  /**
234
- * * Formats the date into a custom string format (UTC time).
289
+ * @public @instance Formats the date into a custom string format (UTC time).
235
290
  *
236
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`).
237
292
  * @returns Formatted date string in desired format (UTC time).
238
293
  */
239
294
  formatUTC(format = 'dd, MMM DD, YYYY HH:mm:ss:mss') {
240
- return this.#format(format, true);
295
+ switch (this[ORIGIN]) {
296
+ case 'toUTC':
297
+ case 'utc':
298
+ return this.#format(format, false);
299
+ default:
300
+ return this.#format(format, true);
301
+ }
241
302
  }
242
303
  /**
243
- * * Adds seconds and returns a new immutable instance.
304
+ * @public @instance Adds seconds and returns a new immutable instance.
244
305
  * @param seconds - Number of seconds to add.
245
306
  * @returns A new `Chronos` instance with the updated date.
246
307
  */
247
308
  addSeconds(seconds) {
248
309
  const newDate = new Date(this.#date);
249
310
  newDate.setSeconds(newDate.getSeconds() + seconds);
250
- return new Chronos(newDate);
311
+ return new Chronos(newDate).#withOrigin('addSeconds');
251
312
  }
252
313
  /**
253
- * * Adds minutes and returns a new immutable instance.
314
+ * @public @instance Adds minutes and returns a new immutable instance.
254
315
  * @param minutes - Number of minutes to add.
255
316
  * @returns A new `Chronos` instance with the updated date.
256
317
  */
257
318
  addMinutes(minutes) {
258
319
  const newDate = new Date(this.#date);
259
320
  newDate.setMinutes(newDate.getMinutes() + minutes);
260
- return new Chronos(newDate);
321
+ return new Chronos(newDate).#withOrigin('addMinutes');
261
322
  }
262
323
  /**
263
- * * Adds hours and returns a new immutable instance.
324
+ * @public @instance Adds hours and returns a new immutable instance.
264
325
  * @param hours - Number of hours to add.
265
326
  * @returns A new `Chronos` instance with the updated date.
266
327
  */
267
328
  addHours(hours) {
268
329
  const newDate = new Date(this.#date);
269
330
  newDate.setHours(newDate.getHours() + hours);
270
- return new Chronos(newDate);
331
+ return new Chronos(newDate).#withOrigin('addHours');
271
332
  }
272
333
  /**
273
- * * Adds days and returns a new immutable instance.
334
+ * @public @instance Adds days and returns a new immutable instance.
274
335
  * @param days - Number of days to add.
275
336
  * @returns A new `Chronos` instance with the updated date.
276
337
  */
277
338
  addDays(days) {
278
339
  const newDate = new Date(this.#date);
279
340
  newDate.setDate(newDate.getDate() + days);
280
- return new Chronos(newDate);
341
+ return new Chronos(newDate).#withOrigin('addDays');
281
342
  }
282
343
  /**
283
- * * Adds months and returns a new immutable instance.
344
+ * @public @instance Adds months and returns a new immutable instance.
284
345
  * @param months - Number of months to add.
285
346
  * @returns A new `Chronos` instance with the updated date.
286
347
  */
287
348
  addMonths(months) {
288
349
  const newDate = new Date(this.#date);
289
350
  newDate.setMonth(newDate.getMonth() + months);
290
- return new Chronos(newDate);
351
+ return new Chronos(newDate).#withOrigin('addMonths');
291
352
  }
292
353
  /**
293
- * * Adds years and returns a new immutable instance.
354
+ * @public @instance Adds years and returns a new immutable instance.
294
355
  * @param years - Number of years to add.
295
356
  * @returns A new `Chronos` instance with the updated date.
296
357
  */
297
358
  addYears(years) {
298
359
  const newDate = new Date(this.#date);
299
360
  newDate.setFullYear(newDate.getFullYear() + years);
300
- return new Chronos(newDate);
361
+ return new Chronos(newDate).#withOrigin('addYears');
301
362
  }
302
363
  /**
303
- * * Subtracts days and returns a new immutable instance.
304
- * @param days - Number of days to subtract.
305
- * @returns A new `Chronos` instance with the updated date.
306
- */
307
- subtractDays(days) {
308
- return this.addDays(-days);
309
- }
310
- /**
311
- * * Checks if the year is a leap year.
312
- * - A year is a leap year if it is divisible by 4, but not divisible by 100, unless it is also divisible by 400.
313
- * - For example, 2000 and 2400 are leap years, but 1900 and 2100 are not.
314
- * @returns `true` if the year is a leap year, `false` otherwise.
315
- */
316
- isLeapYear() {
317
- const year = this.#date.getFullYear();
318
- return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
319
- }
320
- /**
321
- * * Create a new instance of `Chronos` in the specified timezone.
364
+ * @public @instance Create a new instance of `Chronos` in the specified timezone.
322
365
  *
323
366
  * @param zone - Standard timezone abbreviation (e.g., 'IST', 'UTC', 'EST') or UTC Offset in `UTC-01:30` format.
324
367
  * @returns A new instance of `Chronos` with time in the given timezone. Invalid input sets time-zone to `UTC`.
@@ -333,22 +376,97 @@ export class Chronos {
333
376
  }
334
377
  const utc = this.#date.getTime() + this.#date.getTimezoneOffset() * 60 * 1000;
335
378
  const adjusted = new Date(utc + offset * 60 * 1000);
336
- return new Chronos(adjusted);
379
+ return new Chronos(adjusted).#withOrigin('timeZone');
380
+ }
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;
337
390
  }
338
- /** - Checks if the current date is today. */
391
+ /** @public @instance Checks if the current date is today. */
339
392
  isToday() {
340
393
  return this.getRelativeDay() === 0;
341
394
  }
342
- /** - Checks if the current date is tomorrow. */
395
+ /** @public @instance Checks if the current date is tomorrow. */
343
396
  isTomorrow() {
344
397
  return this.getRelativeDay() === 1;
345
398
  }
346
- /** - Checks if the current date is yesterday. */
399
+ /** @public @instance Checks if the current date is yesterday. */
347
400
  isYesterday() {
348
401
  return this.getRelativeDay() === -1;
349
402
  }
350
403
  /**
351
- * * 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.
352
470
  *
353
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`.
354
472
  * @param withSuffixPrefix If `true`, adds `"in"` or `"ago"` depending on whether the time is in the future or past. Defaults to `true`.
@@ -431,7 +549,7 @@ export class Chronos {
431
549
  return `${prefix}${parts.join(' ')}${suffix}`;
432
550
  }
433
551
  /**
434
- * * 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.
435
553
  * @param time Optional time to compare with the `Chronos` date/time.
436
554
  * @returns The difference in number, negative is `Chronos` time is a past time else positive.
437
555
  */
@@ -447,7 +565,7 @@ export class Chronos {
447
565
  return years;
448
566
  }
449
567
  /**
450
- * * 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.
451
569
  * @param time Optional time to compare with the `Chronos` date/time.
452
570
  * @returns The difference in number, negative is `Chronos` time is a past time else positive.
453
571
  */
@@ -462,7 +580,7 @@ export class Chronos {
462
580
  return months;
463
581
  }
464
582
  /**
465
- * * 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.
466
584
  * @param date - The date to compare (Date object).
467
585
  * @param time Optional time to compare with the `Chronos` date/time.
468
586
  * @returns
@@ -483,7 +601,7 @@ export class Chronos {
483
601
  return diffDays;
484
602
  }
485
603
  /**
486
- * * 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.
487
605
  * @param time Optional time to compare with the `Chronos` date/time.
488
606
  * @returns The difference in number, negative is `Chronos` time is a past time else positive.
489
607
  */
@@ -492,7 +610,7 @@ export class Chronos {
492
610
  return Math.floor(diff / (1000 * 60 * 60));
493
611
  }
494
612
  /**
495
- * * 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.
496
614
  * @param time Optional time to compare with the `Chronos` date/time.
497
615
  * @returns The difference in number, negative is `Chronos` time is a past time else positive.
498
616
  */
@@ -501,7 +619,7 @@ export class Chronos {
501
619
  return Math.floor(diff / (1000 * 60));
502
620
  }
503
621
  /**
504
- * * 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.
505
623
  * @param time Optional time to compare with the `Chronos` date/time.
506
624
  * @returns The difference in number, negative is `Chronos` time is a past time else positive.
507
625
  */
@@ -510,7 +628,7 @@ export class Chronos {
510
628
  return Math.floor(diff / 1000);
511
629
  }
512
630
  /**
513
- * * 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.
514
632
  * @param time Optional time to compare with the `Chronos` date/time.
515
633
  * @returns The difference in number, negative is `Chronos` time is a past time else positive.
516
634
  */
@@ -518,7 +636,7 @@ export class Chronos {
518
636
  return this.#date.getTime() - this.#toNewDate(time).getTime();
519
637
  }
520
638
  /**
521
- * * 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.
522
640
  *
523
641
  * @param unit The time unit to compare by. Defaults to 'minute'.
524
642
  * @param time Optional time to compare with the `Chronos` date/time.
@@ -545,7 +663,7 @@ export class Chronos {
545
663
  }
546
664
  }
547
665
  /**
548
- * * 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.
549
667
  * @param unit The unit to reset (e.g., year, month, day).
550
668
  */
551
669
  startOf(unit) {
@@ -581,17 +699,20 @@ export class Chronos {
581
699
  case 'millisecond':
582
700
  break;
583
701
  }
584
- return new Chronos(d);
702
+ return new Chronos(d).#withOrigin('startOf');
585
703
  }
586
704
  /**
587
- * * 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.
588
706
  * @param unit The unit to adjust (e.g., year, month, day).
589
707
  */
590
708
  endOf(unit) {
591
- 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');
592
713
  }
593
714
  /**
594
- * * Returns a new Chronos instance with the specified unit added.
715
+ * @public @instance Returns a new Chronos instance with the specified unit added.
595
716
  * @param amount The amount to add (can be negative).
596
717
  * @param unit The time unit to add.
597
718
  */
@@ -620,10 +741,18 @@ export class Chronos {
620
741
  d.setFullYear(d.getFullYear() + amount);
621
742
  break;
622
743
  }
623
- 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');
624
753
  }
625
754
  /**
626
- * * 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.
627
756
  * @param unit The unit to retrieve.
628
757
  */
629
758
  get(unit) {
@@ -645,7 +774,7 @@ export class Chronos {
645
774
  }
646
775
  }
647
776
  /**
648
- * 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.
649
778
  * @param unit The unit to modify.
650
779
  * @param value The value to set for the unit.
651
780
  */
@@ -674,10 +803,10 @@ export class Chronos {
674
803
  d.setMilliseconds(value);
675
804
  break;
676
805
  }
677
- return new Chronos(d);
806
+ return new Chronos(d).#withOrigin('set');
678
807
  }
679
808
  /**
680
- * * 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.
681
810
  * @param other The other date to compare.
682
811
  * @param unit The unit in which to return the difference.
683
812
  */
@@ -703,37 +832,7 @@ export class Chronos {
703
832
  }
704
833
  }
705
834
  /**
706
- * * Checks if another date is the same as this one in a specific unit.
707
- * @param other The other date to compare.
708
- * @param unit The unit to compare.
709
- */
710
- isSame(other, unit) {
711
- const time = new Chronos(other);
712
- return (this.startOf(unit).toDate().getTime() ===
713
- time.startOf(unit).toDate().getTime());
714
- }
715
- /**
716
- * * Checks if this date is before another date in a specific unit.
717
- * @param other The other date to compare.
718
- * @param unit The unit to compare.
719
- */
720
- isBefore(other, unit) {
721
- const time = new Chronos(other);
722
- return (this.startOf(unit).toDate().getTime() <
723
- time.startOf(unit).toDate().getTime());
724
- }
725
- /**
726
- * * Checks if this date is after another date in a specific unit.
727
- * @param other The other date to compare.
728
- * @param unit The unit to compare.
729
- */
730
- isAfter(other, unit) {
731
- const time = new Chronos(other);
732
- return (this.startOf(unit).toDate().getTime() >
733
- time.startOf(unit).toDate().getTime());
734
- }
735
- /**
736
- * * 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"
737
836
  * @param baseDate Optional base date to compare with.
738
837
  */
739
838
  calendar(baseDate) {
@@ -760,7 +859,7 @@ export class Chronos {
760
859
  minute: '2-digit',
761
860
  });
762
861
  }
763
- /** * 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" */
764
863
  fromNowShort() {
765
864
  const now = new Chronos();
766
865
  const diffInSeconds = this.diff(now, 'second');
@@ -786,7 +885,7 @@ export class Chronos {
786
885
  return `${suffix}${Math.floor(abs / 31536000)}y${postfix}`;
787
886
  }
788
887
  }
789
- /** * Returns ISO week number */
888
+ /** @public @instance Returns ISO week number */
790
889
  getWeek() {
791
890
  // ISO week starts on Monday
792
891
  const target = this.startOf('week').add(3, 'day');
@@ -797,115 +896,68 @@ export class Chronos {
797
896
  const week = Math.floor(daysDiff / 7) + 1;
798
897
  return week;
799
898
  }
800
- /** * Returns ISO week year */
899
+ /** @public @instance Returns ISO week year */
801
900
  getWeekYear() {
802
901
  const d = this.startOf('week').add(3, 'day'); // Thursday of current ISO week
803
902
  return d.year;
804
903
  }
805
- /** * Returns day of year (1 - 366) */
904
+ /** @public @instance Returns day of year (1 - 366) */
806
905
  getDayOfYear() {
807
906
  const start = new Date(this.year, 0, 1);
808
907
  const diff = this.#date.getTime() - start.getTime();
809
908
  return Math.floor(diff / 86400000) + 1;
810
909
  }
811
- /**
812
- * * Checks if the current date is between the given start and end dates.
813
- *
814
- * @param start - The start of the range.
815
- * @param end - The end of the range.
816
- * @param inclusive - Specifies whether the comparison is inclusive or exclusive:
817
- * - `'[]'`: inclusive of both start and end (≥ start and ≤ end)
818
- * - `'[)'`: inclusive of start, exclusive of end (≥ start and < end)
819
- * - `'(]'`: exclusive of start, inclusive of end (> start and ≤ end)
820
- * - `'()'`: exclusive of both start and end (> start and < end)
821
- *
822
- * @returns `true` if the current date is within the specified range based on the `inclusive` mode.
823
- */
824
- isBetween(start, end, inclusive = '()') {
825
- const s = new Chronos(start).valueOf();
826
- const e = new Chronos(end).valueOf();
827
- const t = this.valueOf();
828
- switch (inclusive) {
829
- case '[]':
830
- return t >= s && t <= e;
831
- case '[)':
832
- return t >= s && t < e;
833
- case '(]':
834
- return t > s && t <= e;
835
- case '()':
836
- return t > s && t < e;
837
- }
838
- }
839
- /** * Returns number of days in current month */
910
+ /** @public @instance Returns number of days in current month */
840
911
  daysInMonth() {
841
912
  return new Date(this.year, this.month + 1, 0).getDate();
842
913
  }
843
- /** * Converts to object with all date unit parts */
914
+ /** @public @instance Converts to object with all date unit parts */
844
915
  toObject() {
845
- return {
846
- year: this.year,
847
- month: this.month,
848
- isoMonth: this.month + 1,
849
- date: this.date,
850
- day: this.day,
851
- isoDay: this.day + 1,
852
- hour: this.hour,
853
- minute: this.minute,
854
- second: this.second,
855
- millisecond: this.millisecond,
856
- };
916
+ return Object.fromEntries([...this]);
857
917
  }
858
- /** * Converts to array with all date unit parts */
918
+ /** @public @instance Converts to array with all date unit parts */
859
919
  toArray() {
860
- return [
861
- this.year,
862
- this.month,
863
- this.date,
864
- this.hour,
865
- this.minute,
866
- this.second,
867
- this.millisecond,
868
- ];
920
+ return Object.values(this.toObject());
869
921
  }
870
- /** * Returns offset like +06:00 */
922
+ /** @public @instance Returns offset like +06:00 */
871
923
  getUTCOffset() {
872
924
  const offset = -this.#date.getTimezoneOffset();
873
925
  const sign = offset >= 0 ? '+' : '-';
874
926
  const pad = (n) => String(Math.floor(Math.abs(n))).padStart(2, '0');
875
927
  return `${sign}${pad(offset / 60)}:${pad(offset % 60)}`;
876
928
  }
877
- /** * Checks if currently in DST */
878
- isDST() {
879
- const jan = new Date(this.year, 0, 1);
880
- const jul = new Date(this.year, 6, 1);
881
- return (Math.min(jan.getTimezoneOffset(), jul.getTimezoneOffset()) !==
882
- this.#date.getTimezoneOffset());
929
+ /** @public @instance Returns new Chronos instance in UTC */
930
+ toUTC() {
931
+ const date = this.#date;
932
+ const utc = new Date(date.getTime() + date.getTimezoneOffset() * 60000);
933
+ return new Chronos(utc).#withOrigin('toUTC');
934
+ }
935
+ /** @public @instance Returns new Chronos instance in local time */
936
+ toLocal() {
937
+ const date = this.#date;
938
+ const utc = new Date(date.getTime() - date.getTimezoneOffset() * 60000);
939
+ return new Chronos(utc).#withOrigin('toLocal');
940
+ }
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);
883
951
  }
884
- /** * Returns new Chronos instance in UTC */
885
- // toUTC(): Chronos {
886
- // // const utcDate = new Date(
887
- // // Date.UTC(
888
- // // this.#date.getFullYear(),
889
- // // this.#date.getMonth(),
890
- // // this.#date.getDate(),
891
- // // this.#date.getHours(),
892
- // // this.#date.getMinutes(),
893
- // // this.#date.getSeconds(),
894
- // // this.#date.getMilliseconds(),
895
- // // ),
896
- // // );
897
- // // return new Chronos(utcDate);
898
- // const date = this.#date;
899
- // const utc = new Date(date.getTime() + date.getTimezoneOffset() * 60000);
900
- // return new Chronos(utc);
901
- // }
902
- /** * Returns new Chronos instance in local time */
903
- // toLocal(): Chronos {
904
- // const date = new Date(this.#date.getTime());
905
- // date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
906
- // return new Chronos(date);
907
- // }
908
- /** @static Parses a date string with a given format (partial support) */
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) */
909
961
  static parse(dateStr, format) {
910
962
  const formatMap = {
911
963
  YYYY: 'year',
@@ -929,29 +981,29 @@ export class Chronos {
929
981
  }
930
982
  return acc;
931
983
  }, {});
932
- return new Chronos(new Date(values.year ?? 1970, (values.month ?? 1) - 1, values.date ?? 1, values.hour ?? 0, values.minute ?? 0, values.second ?? 0));
933
- }
934
- // /**
935
- // * @static Creates UTC Chronos
936
- // * @param dateLike Date input to create utc time.
937
- // */
938
- // static utc(dateLike: number | string | Date | Chronos): Chronos {
939
- // const date = new Chronos(dateLike).toDate();
940
- // const utc = new Date(date.getTime() + date.getTimezoneOffset() * 60000);
941
- // return new Chronos(utc);
942
- // }
943
- /**
944
- * @static Returns earliest Chronos
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');
985
+ }
986
+ /**
987
+ * @public @static Creates UTC Chronos
988
+ * @param dateLike Date input to create utc time.
989
+ */
990
+ static utc(dateLike) {
991
+ const date = new Chronos(dateLike).#date;
992
+ const utc = new Date(date.getTime() + date.getTimezoneOffset() * 60000);
993
+ return new Chronos(utc).#withOrigin('utc');
994
+ }
995
+ /**
996
+ * @public @static Returns earliest Chronos
945
997
  * @param dates Date inputs.
946
998
  */
947
999
  static min(...dates) {
948
- 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');
949
1001
  }
950
1002
  /**
951
- * @static Returns latest Chronos
1003
+ * @public @static Returns latest Chronos
952
1004
  * @param dates Date inputs.
953
1005
  */
954
1006
  static max(...dates) {
955
- 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');
956
1008
  }
957
1009
  }