@org-quicko/core 2.0.3 → 2.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,8 +1,33 @@
1
1
  # core
2
- Foundational Node.js library built with TypeScript used across Quicko
3
2
 
4
- ## 📦 Installation
3
+ Foundational Node.js library built with TypeScript used across Quicko.
4
+
5
+ ## Installation
5
6
 
6
7
  ```bash
7
8
  npm install @org-quicko/core
8
- ```
9
+ ```
10
+
11
+ ## Release Flow
12
+
13
+ This repository uses GitHub Actions to separate pull request validation, release drafting, and npm publishing.
14
+
15
+ - Pull requests run install, date util tests, and build validation.
16
+ - Pushes to `main` update the next draft release using Release Drafter.
17
+ - Publishing happens only when a GitHub release is published.
18
+ - PR titles are used directly in the drafted release notes, so keep them clear and specific.
19
+ - PR labels influence both release note grouping and version bump resolution.
20
+
21
+ ### Publishing A New Version
22
+
23
+ 1. Update the version in `package.json`.
24
+ 2. Merge the change into `main`.
25
+ 3. Review the drafted GitHub release.
26
+ 4. Publish the release with a tag that matches the package version, for example `v2.0.4`.
27
+
28
+ When the release is published, GitHub Actions will:
29
+
30
+ - verify the release tag matches `package.json`
31
+ - run install, tests, and build
32
+ - skip publish if that version already exists on npm
33
+ - publish the package to npm using the configured `NPM_TOKEN`
@@ -1,5 +1,5 @@
1
1
  import { TZDate } from '@date-fns/tz';
2
- import { parse, isValid, format, startOfDay, endOfDay, differenceInCalendarDays, differenceInCalendarMonths, differenceInCalendarYears, compareAsc, add, isLeapYear } from 'date-fns';
2
+ import { parse, isValid, format, startOfDay, endOfDay, differenceInCalendarDays, differenceInCalendarMonths, differenceInCalendarYears, differenceInHours, differenceInSeconds, compareAsc, add, isLeapYear } from 'date-fns';
3
3
  import { IllegalArgumentException } from '../../exceptions/IllegalArgumentException.js';
4
4
 
5
5
  /**
@@ -8,6 +8,7 @@ import { IllegalArgumentException } from '../../exceptions/IllegalArgumentExcept
8
8
  */
9
9
  class DateUtil {
10
10
  static { this.ISO_8601_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSxxx"; }
11
+ static { this.TIMEZONE = "UTC"; }
11
12
  /**
12
13
  * Gets the current date and time in the specified time zone.
13
14
  * @param timeZone The IANA time zone identifier.
@@ -39,15 +40,15 @@ class DateUtil {
39
40
  return date;
40
41
  }
41
42
  static printDate(date, timeZone, dateFormat = this.ISO_8601_FORMAT) {
42
- const normalizedDate = typeof date === 'number' ? new Date(date) : date;
43
+ const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;
43
44
  return format(new TZDate(normalizedDate, timeZone), dateFormat);
44
45
  }
45
46
  static getStartOfDay(date, timeZone) {
46
- const normalizedDate = typeof date === 'number' ? new Date(date) : date;
47
+ const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;
47
48
  return startOfDay(new TZDate(normalizedDate, timeZone));
48
49
  }
49
50
  static getEndOfDay(date, timeZone) {
50
- const normalizedDate = typeof date === 'number' ? new Date(date) : date;
51
+ const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;
51
52
  return endOfDay(new TZDate(normalizedDate, timeZone));
52
53
  }
53
54
  /**
@@ -60,35 +61,48 @@ class DateUtil {
60
61
  try {
61
62
  DateUtil.readDate(dateString, dateFormat, "UTC");
62
63
  return true;
63
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
64
64
  }
65
65
  catch (error) {
66
66
  return false;
67
67
  }
68
68
  }
69
- static daysInBetween(firstDate, secondDate) {
70
- const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;
71
- const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;
72
- return Math.abs(differenceInCalendarDays(first, second));
69
+ static daysInBetween(firstDate, secondDate, timeZone) {
70
+ const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;
71
+ const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;
72
+ const effectiveTimeZone = timeZone || this.TIMEZONE;
73
+ return Math.abs(differenceInCalendarDays(new TZDate(first, effectiveTimeZone), new TZDate(second, effectiveTimeZone)));
73
74
  }
74
- static monthsInBetween(firstDate, secondDate) {
75
- const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;
76
- const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;
77
- return Math.abs(differenceInCalendarMonths(first, second));
75
+ static monthsInBetween(firstDate, secondDate, timeZone) {
76
+ const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;
77
+ const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;
78
+ const effectiveTimeZone = timeZone || this.TIMEZONE;
79
+ return Math.abs(differenceInCalendarMonths(new TZDate(first, effectiveTimeZone), new TZDate(second, effectiveTimeZone)));
78
80
  }
79
- static yearsInBetween(firstDate, secondDate) {
80
- const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;
81
- const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;
82
- return Math.abs(differenceInCalendarYears(first, second));
81
+ static yearsInBetween(firstDate, secondDate, timeZone) {
82
+ const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;
83
+ const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;
84
+ const effectiveTimeZone = timeZone || this.TIMEZONE;
85
+ return Math.abs(differenceInCalendarYears(new TZDate(first, effectiveTimeZone), new TZDate(second, effectiveTimeZone)));
86
+ }
87
+ static hoursInBetween(firstDate, secondDate) {
88
+ const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;
89
+ const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;
90
+ return Math.abs(differenceInHours(first, second));
91
+ }
92
+ static secondsInBetween(firstDate, secondDate) {
93
+ const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;
94
+ const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;
95
+ return Math.abs(differenceInSeconds(first, second));
83
96
  }
84
97
  static compareDates(firstDate, secondDate) {
85
- const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;
86
- const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;
98
+ const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;
99
+ const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;
87
100
  return compareAsc(first, second);
88
101
  }
89
- static addDuration(date, duration) {
90
- const normalizedDate = typeof date === 'number' ? new Date(date) : date;
91
- return add(normalizedDate, duration);
102
+ static addDuration(date, duration, timeZone) {
103
+ const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;
104
+ const effectiveTimeZone = timeZone || this.TIMEZONE;
105
+ return add(new TZDate(normalizedDate, effectiveTimeZone), duration);
92
106
  }
93
107
  /**
94
108
  * Determines whether a given year is a leap year.
@@ -1 +1 @@
1
- {"version":3,"file":"DateUtil.js","sources":["../../../../src/utils/date/DateUtil.ts"],"sourcesContent":["import { TZDate } from '@date-fns/tz';\nimport { add, compareAsc, differenceInCalendarDays, differenceInCalendarMonths, differenceInCalendarYears, Duration, endOfDay, format, isLeapYear, isValid, parse, startOfDay } from 'date-fns';\nimport { IllegalArgumentException } from '../../exceptions';\n\n/**\n * Utility class for date and time operations. Provides methods for parsing,\n * formatting, and performing calculations with dates and times.\n */\nexport class DateUtil {\n\n static readonly ISO_8601_FORMAT = \"yyyy-MM-dd'T'HH:mm:ss.SSSxxx\"\n\n /**\n * Gets the current date and time in the specified time zone.\n * @param timeZone The IANA time zone identifier.\n * @returns Current date and time in the specified time zone.\n */\n static now(timeZone: string): Date {\n return new TZDate(new Date(), timeZone);\n }\n\n /**\n * Gets the current time in milliseconds since the Unix epoch.\n * @returns Current time in milliseconds.\n */\n static nowInMillis(): number {\n return Date.now();\n }\n\n /**\n * Parses a date string into a Date object.\n * @param dateString The date string to parse.\n * @param dateFormat The format of the date string (default: ISO_8601_FORMAT).\n * @param timeZone The IANA time zone identifier.\n * @throws {IllegalArgumentException} If the date string is invalid.\n * @returns Parsed Date object.\n */\n static readDate(dateString: string, dateFormat = this.ISO_8601_FORMAT, timeZone: string): Date {\n const date = parse(dateString, dateFormat, TZDate.tz(timeZone));\n if (!isValid(date)) {\n throw new IllegalArgumentException('Invalid date string or date format');\n }\n return date;\n }\n\n /**\n * Formats a Date or timestamp into a string.\n * @param date The date or timestamp to format.\n * @param timeZone The IANA time zone identifier.\n * @param dateFormat The desired output format (default: ISO_8601_FORMAT).\n * @returns Formatted date string.\n */\n static printDate(date: Date, timeZone: string, dateFormat?: string): string;\n static printDate(date: number, timeZone: string, dateFormat?: string): string;\n static printDate(date: Date | number, timeZone: string, dateFormat: string = this.ISO_8601_FORMAT): string {\n const normalizedDate = typeof date === 'number' ? new Date(date) : date;\n return format(new TZDate(normalizedDate, timeZone), dateFormat);\n }\n\n /**\n * Gets the start of the day for a given date or timestamp.\n * @param date The date or timestamp to calculate from.\n * @param timeZone The IANA time zone identifier.\n * @returns The start of the day as a Date object.\n */\n static getStartOfDay(date: Date, timeZone: string): Date;\n static getStartOfDay(date: number, timeZone: string): Date;\n static getStartOfDay(date: Date | number, timeZone: string): Date {\n const normalizedDate = typeof date === 'number' ? new Date(date) : date;\n return startOfDay(new TZDate(normalizedDate, timeZone));\n }\n\n /**\n * Gets the end of the day for a given date or timestamp.\n * @param date The date or timestamp to calculate from.\n * @param timeZone The IANA time zone identifier.\n * @returns The end of the day as a Date object.\n */\n static getEndOfDay(date: Date, timeZone: string): Date;\n static getEndOfDay(date: number, timeZone: string): Date;\n static getEndOfDay(date: Date | number, timeZone: string): Date {\n const normalizedDate = typeof date === 'number' ? new Date(date) : date;\n return endOfDay(new TZDate(normalizedDate, timeZone));\n }\n\n /**\n * Checks if a date string is valid according to the specified format.\n * @param dateString The date string to validate.\n * @param dateFormat Optional date format (default: ISO_8601_FORMAT).\n * @returns True if the date is valid, false otherwise.\n */\n static isValidDate(dateString: string, dateFormat?: string): boolean {\n try {\n DateUtil.readDate(dateString, dateFormat, \"UTC\");\n return true;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Calculates the absolute number of days between two dates or timestamps.\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns Number of days between the two dates.\n */\n static daysInBetween(firstDate: Date, secondDate: Date): number;\n static daysInBetween(firstDate: number, secondDate: number): number;\n static daysInBetween(firstDate: Date | number, secondDate: Date | number): number {\n const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;\n return Math.abs(differenceInCalendarDays(first, second));\n }\n\n /**\n * Calculates the absolute number of months between two dates or timestamps.\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns The number of months between the two dates.\n */\n static monthsInBetween(firstDate: Date, secondDate: Date): number;\n static monthsInBetween(firstDate: number, secondDate: number): number;\n static monthsInBetween(firstDate: Date | number, secondDate: Date | number): number {\n const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;\n return Math.abs(differenceInCalendarMonths(first, second));\n }\n\n /**\n * Calculates the absolute number of years between two dates or timestamps.\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns The number of years between the two dates.\n */\n static yearsInBetween(firstDate: Date, secondDate: Date): number;\n static yearsInBetween(firstDate: number, secondDate: number): number;\n static yearsInBetween(firstDate: Date | number, secondDate: Date | number): number {\n const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;\n return Math.abs(differenceInCalendarYears(first, second));\n }\n\n /**\n * Compares two dates or timestamps.\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns `-1` if the first date is earlier, `1` if it is later, or `0` if the two dates are equal.\n */\n static compareDates(firstDate: Date, secondDate: Date): -1 | 0 | 1;\n static compareDates(firstDate: number, secondDate: number): -1 | 0 | 1;\n static compareDates(firstDate: Date | number, secondDate: Date | number): -1 | 0 | 1 {\n const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;\n\n return compareAsc(first, second) as -1 | 0 | 1;\n }\n\n /**\n * Adds a duration (e.g., days, months, years) to a given date or timestamp.\n * @param date The base date or timestamp to which the duration will be added.\n * @param duration An object specifying the duration (e.g., `{ days: 1, months: 2 }`).\n * @returns A new Date object with the duration added.\n */\n static addDuration(date: Date, duration: Duration): Date;\n static addDuration(date: number, duration: Duration): Date;\n static addDuration(date: Date | number, duration: Duration): Date {\n const normalizedDate = typeof date === 'number' ? new Date(date) : date;\n return add(normalizedDate, duration);\n }\n\n /**\n * Determines whether a given year is a leap year.\n * @param year The year to check.\n * @returns `true` if the year is a leap year, otherwise `false`.\n */\n static isLeapYear(year: number): boolean {\n return isLeapYear(DateUtil.readDate(year.toString(), 'yyyy', \"UTC\"));\n }\n\n\n /**\n * Converts a timestamp (in milliseconds) to a Date object.\n * @param milliseconds The timestamp in milliseconds since the Unix epoch.\n * @returns A Date object representing the provided timestamp.\n */\n static fromMillis(milliseconds: number): Date {\n return new Date(milliseconds);\n }\n\n /**\n * Converts a Date object to a timestamp (in milliseconds).\n * @param date The Date object to convert.\n * @returns The timestamp in milliseconds since the Unix epoch.\n */\n static toMillis(date: Date): number {\n return date.getTime();\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DateUtil.js","sources":["../../../../src/utils/date/DateUtil.ts"],"sourcesContent":["import { TZDate } from '@date-fns/tz';\nimport { add, compareAsc, differenceInCalendarDays, differenceInCalendarMonths, differenceInCalendarYears, differenceInHours, differenceInSeconds, Duration, endOfDay, format, isLeapYear, isValid, parse, startOfDay } from 'date-fns';\nimport { IllegalArgumentException } from '../../exceptions';\n\n/**\n * Utility class for date and time operations. Provides methods for parsing,\n * formatting, and performing calculations with dates and times.\n */\nexport class DateUtil {\n\n static readonly ISO_8601_FORMAT = \"yyyy-MM-dd'T'HH:mm:ss.SSSxxx\"\n static readonly TIMEZONE = \"UTC\"\n\n /**\n * Gets the current date and time in the specified time zone.\n * @param timeZone The IANA time zone identifier.\n * @returns Current date and time in the specified time zone.\n */\n static now(timeZone: string): Date {\n return new TZDate(new Date(), timeZone);\n }\n\n /**\n * Gets the current time in milliseconds since the Unix epoch.\n * @returns Current time in milliseconds.\n */\n static nowInMillis(): number {\n return Date.now();\n }\n\n /**\n * Parses a date string into a Date object.\n * @param dateString The date string to parse.\n * @param dateFormat The format of the date string (default: ISO_8601_FORMAT).\n * @param timeZone The IANA time zone identifier.\n * @throws {IllegalArgumentException} If the date string is invalid.\n * @returns Parsed Date object.\n */\n static readDate(dateString: string, dateFormat = this.ISO_8601_FORMAT, timeZone: string): Date {\n const date = parse(dateString, dateFormat, TZDate.tz(timeZone));\n if (!isValid(date)) {\n throw new IllegalArgumentException('Invalid date string or date format');\n }\n return date;\n }\n\n /**\n * Formats a Date or timestamp into a string.\n * @param date The date or timestamp to format.\n * @param timeZone The IANA time zone identifier.\n * @param dateFormat The desired output format (default: ISO_8601_FORMAT).\n * @returns Formatted date string.\n */\n static printDate(date: Date, timeZone: string, dateFormat?: string): string;\n static printDate(date: number, timeZone: string, dateFormat?: string): string;\n static printDate(date: Date | number, timeZone: string, dateFormat: string = this.ISO_8601_FORMAT): string {\n const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;\n return format(new TZDate(normalizedDate, timeZone), dateFormat);\n }\n\n /**\n * Gets the start of the day for a given date or timestamp.\n * @param date The date or timestamp to calculate from.\n * @param timeZone The IANA time zone identifier.\n * @returns The start of the day as a Date object.\n */\n static getStartOfDay(date: Date, timeZone: string): Date;\n static getStartOfDay(date: number, timeZone: string): Date;\n static getStartOfDay(date: Date | number, timeZone: string): Date {\n const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;\n return startOfDay(new TZDate(normalizedDate, timeZone));\n }\n\n /**\n * Gets the end of the day for a given date or timestamp.\n * @param date The date or timestamp to calculate from.\n * @param timeZone The IANA time zone identifier.\n * @returns The end of the day as a Date object.\n */\n static getEndOfDay(date: Date, timeZone: string): Date;\n static getEndOfDay(date: number, timeZone: string): Date;\n static getEndOfDay(date: Date | number, timeZone: string): Date {\n const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;\n return endOfDay(new TZDate(normalizedDate, timeZone));\n }\n\n /**\n * Checks if a date string is valid according to the specified format.\n * @param dateString The date string to validate.\n * @param dateFormat Optional date format (default: ISO_8601_FORMAT).\n * @returns True if the date is valid, false otherwise.\n */\n static isValidDate(dateString: string, dateFormat?: string): boolean {\n try {\n DateUtil.readDate(dateString, dateFormat, \"UTC\");\n return true;\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Calculates the absolute number of calendar days between two dates or timestamps.\n * Since day boundaries depend on a calendar, callers can optionally provide a time zone\n * so the same pair of instants is interpreted consistently across machines.\n *\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @param timeZone Optional IANA time zone identifier used for calendar comparisons.\n * @returns Number of days between the two dates.\n */\n static daysInBetween(firstDate: Date, secondDate: Date, timeZone?: string): number;\n static daysInBetween(firstDate: number, secondDate: number, timeZone?: string): number;\n static daysInBetween(firstDate: Date | number, secondDate: Date | number, timeZone?: string): number {\n const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;\n const effectiveTimeZone = timeZone || this.TIMEZONE;\n return Math.abs(\n differenceInCalendarDays(\n new TZDate(first, effectiveTimeZone),\n new TZDate(second, effectiveTimeZone),\n )\n );\n }\n\n /**\n * Calculates the absolute number of calendar months between two dates or timestamps.\n * Since month boundaries depend on a calendar, callers can optionally provide a time zone\n * so the same pair of instants is interpreted consistently across machines.\n *\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @param timeZone Optional IANA time zone identifier used for calendar comparisons.\n * @returns The number of months between the two dates.\n */\n static monthsInBetween(firstDate: Date, secondDate: Date, timeZone?: string): number;\n static monthsInBetween(firstDate: number, secondDate: number, timeZone?: string): number;\n static monthsInBetween(firstDate: Date | number, secondDate: Date | number, timeZone?: string): number {\n const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;\n const effectiveTimeZone = timeZone || this.TIMEZONE;\n return Math.abs(\n differenceInCalendarMonths(\n new TZDate(first, effectiveTimeZone),\n new TZDate(second, effectiveTimeZone),\n )\n );\n }\n\n /**\n * Calculates the absolute number of calendar years between two dates or timestamps.\n * Since year boundaries depend on a calendar, callers can optionally provide a time zone\n * so the same pair of instants is interpreted consistently across machines.\n *\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @param timeZone Optional IANA time zone identifier used for calendar comparisons.\n * @returns The number of years between the two dates.\n */\n static yearsInBetween(firstDate: Date, secondDate: Date, timeZone?: string): number;\n static yearsInBetween(firstDate: number, secondDate: number, timeZone?: string): number;\n static yearsInBetween(firstDate: Date | number, secondDate: Date | number, timeZone?: string): number {\n const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;\n const effectiveTimeZone = timeZone || this.TIMEZONE;\n return Math.abs(\n differenceInCalendarYears(\n new TZDate(first, effectiveTimeZone),\n new TZDate(second, effectiveTimeZone),\n )\n );\n }\n\n /**\n * Calculates the absolute elapsed number of hours between two dates or timestamps.\n * This is duration-based, not calendar-based, so it is independent of time zone.\n *\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns The number of hours between the two dates.\n */\n static hoursInBetween(firstDate: Date, secondDate: Date): number;\n static hoursInBetween(firstDate: number, secondDate: number): number;\n static hoursInBetween(firstDate: Date | number, secondDate: Date | number): number {\n const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;\n return Math.abs(differenceInHours(first, second));\n }\n\n /**\n * Calculates the absolute elapsed number of seconds between two dates or timestamps.\n * This is duration-based, not calendar-based, so it is independent of time zone.\n *\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns The number of seconds between the two dates.\n */\n static secondsInBetween(firstDate: Date, secondDate: Date): number;\n static secondsInBetween(firstDate: number, secondDate: number): number;\n static secondsInBetween(firstDate: Date | number, secondDate: Date | number): number {\n const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;\n return Math.abs(differenceInSeconds(first, second));\n }\n\n /**\n * Compares two dates or timestamps.\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns `-1` if the first date is earlier, `1` if it is later, or `0` if the two dates are equal.\n */\n static compareDates(firstDate: Date, secondDate: Date): -1 | 0 | 1;\n static compareDates(firstDate: number, secondDate: number): -1 | 0 | 1;\n static compareDates(firstDate: Date | number, secondDate: Date | number): -1 | 0 | 1 {\n const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;\n\n return compareAsc(first, second) as -1 | 0 | 1;\n }\n\n /**\n * Adds a duration (e.g., days, months, years) to a given date or timestamp.\n * When a time zone is provided, the duration is applied using calendar arithmetic\n * in that time zone so month-end or day-boundary business rules stay aligned locally.\n *\n * @param date The base date or timestamp to which the duration will be added.\n * @param duration An object specifying the duration (e.g., `{ days: 1, months: 2 }`).\n * @param timeZone Optional IANA time zone identifier used for calendar math.\n * @returns A new Date object with the duration added.\n */\n static addDuration(date: Date, duration: Duration, timeZone?: string): Date;\n static addDuration(date: number, duration: Duration, timeZone?: string): Date;\n static addDuration(date: Date | number, duration: Duration, timeZone?: string): Date {\n const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;\n const effectiveTimeZone = timeZone || this.TIMEZONE;\n return add(new TZDate(normalizedDate, effectiveTimeZone), duration);\n }\n\n /**\n * Determines whether a given year is a leap year.\n * @param year The year to check.\n * @returns `true` if the year is a leap year, otherwise `false`.\n */\n static isLeapYear(year: number): boolean {\n return isLeapYear(DateUtil.readDate(year.toString(), 'yyyy', \"UTC\"));\n }\n\n\n /**\n * Converts a timestamp (in milliseconds) to a Date object.\n * @param milliseconds The timestamp in milliseconds since the Unix epoch.\n * @returns A Date object representing the provided timestamp.\n */\n static fromMillis(milliseconds: number): Date {\n return new Date(milliseconds);\n }\n\n /**\n * Converts a Date object to a timestamp (in milliseconds).\n * @param date The Date object to convert.\n * @returns The timestamp in milliseconds since the Unix epoch.\n */\n static toMillis(date: Date): number {\n return date.getTime();\n }\n}\n"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@ var IllegalArgumentException = require('../../exceptions/IllegalArgumentExceptio
10
10
  */
11
11
  class DateUtil {
12
12
  static { this.ISO_8601_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSxxx"; }
13
+ static { this.TIMEZONE = "UTC"; }
13
14
  /**
14
15
  * Gets the current date and time in the specified time zone.
15
16
  * @param timeZone The IANA time zone identifier.
@@ -41,15 +42,15 @@ class DateUtil {
41
42
  return date;
42
43
  }
43
44
  static printDate(date, timeZone, dateFormat = this.ISO_8601_FORMAT) {
44
- const normalizedDate = typeof date === 'number' ? new Date(date) : date;
45
+ const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;
45
46
  return dateFns.format(new tz.TZDate(normalizedDate, timeZone), dateFormat);
46
47
  }
47
48
  static getStartOfDay(date, timeZone) {
48
- const normalizedDate = typeof date === 'number' ? new Date(date) : date;
49
+ const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;
49
50
  return dateFns.startOfDay(new tz.TZDate(normalizedDate, timeZone));
50
51
  }
51
52
  static getEndOfDay(date, timeZone) {
52
- const normalizedDate = typeof date === 'number' ? new Date(date) : date;
53
+ const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;
53
54
  return dateFns.endOfDay(new tz.TZDate(normalizedDate, timeZone));
54
55
  }
55
56
  /**
@@ -62,35 +63,48 @@ class DateUtil {
62
63
  try {
63
64
  DateUtil.readDate(dateString, dateFormat, "UTC");
64
65
  return true;
65
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
66
66
  }
67
67
  catch (error) {
68
68
  return false;
69
69
  }
70
70
  }
71
- static daysInBetween(firstDate, secondDate) {
72
- const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;
73
- const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;
74
- return Math.abs(dateFns.differenceInCalendarDays(first, second));
71
+ static daysInBetween(firstDate, secondDate, timeZone) {
72
+ const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;
73
+ const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;
74
+ const effectiveTimeZone = timeZone || this.TIMEZONE;
75
+ return Math.abs(dateFns.differenceInCalendarDays(new tz.TZDate(first, effectiveTimeZone), new tz.TZDate(second, effectiveTimeZone)));
75
76
  }
76
- static monthsInBetween(firstDate, secondDate) {
77
- const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;
78
- const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;
79
- return Math.abs(dateFns.differenceInCalendarMonths(first, second));
77
+ static monthsInBetween(firstDate, secondDate, timeZone) {
78
+ const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;
79
+ const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;
80
+ const effectiveTimeZone = timeZone || this.TIMEZONE;
81
+ return Math.abs(dateFns.differenceInCalendarMonths(new tz.TZDate(first, effectiveTimeZone), new tz.TZDate(second, effectiveTimeZone)));
80
82
  }
81
- static yearsInBetween(firstDate, secondDate) {
82
- const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;
83
- const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;
84
- return Math.abs(dateFns.differenceInCalendarYears(first, second));
83
+ static yearsInBetween(firstDate, secondDate, timeZone) {
84
+ const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;
85
+ const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;
86
+ const effectiveTimeZone = timeZone || this.TIMEZONE;
87
+ return Math.abs(dateFns.differenceInCalendarYears(new tz.TZDate(first, effectiveTimeZone), new tz.TZDate(second, effectiveTimeZone)));
88
+ }
89
+ static hoursInBetween(firstDate, secondDate) {
90
+ const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;
91
+ const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;
92
+ return Math.abs(dateFns.differenceInHours(first, second));
93
+ }
94
+ static secondsInBetween(firstDate, secondDate) {
95
+ const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;
96
+ const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;
97
+ return Math.abs(dateFns.differenceInSeconds(first, second));
85
98
  }
86
99
  static compareDates(firstDate, secondDate) {
87
- const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;
88
- const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;
100
+ const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;
101
+ const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;
89
102
  return dateFns.compareAsc(first, second);
90
103
  }
91
- static addDuration(date, duration) {
92
- const normalizedDate = typeof date === 'number' ? new Date(date) : date;
93
- return dateFns.add(normalizedDate, duration);
104
+ static addDuration(date, duration, timeZone) {
105
+ const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;
106
+ const effectiveTimeZone = timeZone || this.TIMEZONE;
107
+ return dateFns.add(new tz.TZDate(normalizedDate, effectiveTimeZone), duration);
94
108
  }
95
109
  /**
96
110
  * Determines whether a given year is a leap year.
@@ -1 +1 @@
1
- {"version":3,"file":"DateUtil.cjs","sources":["../../../../src/utils/date/DateUtil.ts"],"sourcesContent":["import { TZDate } from '@date-fns/tz';\nimport { add, compareAsc, differenceInCalendarDays, differenceInCalendarMonths, differenceInCalendarYears, Duration, endOfDay, format, isLeapYear, isValid, parse, startOfDay } from 'date-fns';\nimport { IllegalArgumentException } from '../../exceptions';\n\n/**\n * Utility class for date and time operations. Provides methods for parsing,\n * formatting, and performing calculations with dates and times.\n */\nexport class DateUtil {\n\n static readonly ISO_8601_FORMAT = \"yyyy-MM-dd'T'HH:mm:ss.SSSxxx\"\n\n /**\n * Gets the current date and time in the specified time zone.\n * @param timeZone The IANA time zone identifier.\n * @returns Current date and time in the specified time zone.\n */\n static now(timeZone: string): Date {\n return new TZDate(new Date(), timeZone);\n }\n\n /**\n * Gets the current time in milliseconds since the Unix epoch.\n * @returns Current time in milliseconds.\n */\n static nowInMillis(): number {\n return Date.now();\n }\n\n /**\n * Parses a date string into a Date object.\n * @param dateString The date string to parse.\n * @param dateFormat The format of the date string (default: ISO_8601_FORMAT).\n * @param timeZone The IANA time zone identifier.\n * @throws {IllegalArgumentException} If the date string is invalid.\n * @returns Parsed Date object.\n */\n static readDate(dateString: string, dateFormat = this.ISO_8601_FORMAT, timeZone: string): Date {\n const date = parse(dateString, dateFormat, TZDate.tz(timeZone));\n if (!isValid(date)) {\n throw new IllegalArgumentException('Invalid date string or date format');\n }\n return date;\n }\n\n /**\n * Formats a Date or timestamp into a string.\n * @param date The date or timestamp to format.\n * @param timeZone The IANA time zone identifier.\n * @param dateFormat The desired output format (default: ISO_8601_FORMAT).\n * @returns Formatted date string.\n */\n static printDate(date: Date, timeZone: string, dateFormat?: string): string;\n static printDate(date: number, timeZone: string, dateFormat?: string): string;\n static printDate(date: Date | number, timeZone: string, dateFormat: string = this.ISO_8601_FORMAT): string {\n const normalizedDate = typeof date === 'number' ? new Date(date) : date;\n return format(new TZDate(normalizedDate, timeZone), dateFormat);\n }\n\n /**\n * Gets the start of the day for a given date or timestamp.\n * @param date The date or timestamp to calculate from.\n * @param timeZone The IANA time zone identifier.\n * @returns The start of the day as a Date object.\n */\n static getStartOfDay(date: Date, timeZone: string): Date;\n static getStartOfDay(date: number, timeZone: string): Date;\n static getStartOfDay(date: Date | number, timeZone: string): Date {\n const normalizedDate = typeof date === 'number' ? new Date(date) : date;\n return startOfDay(new TZDate(normalizedDate, timeZone));\n }\n\n /**\n * Gets the end of the day for a given date or timestamp.\n * @param date The date or timestamp to calculate from.\n * @param timeZone The IANA time zone identifier.\n * @returns The end of the day as a Date object.\n */\n static getEndOfDay(date: Date, timeZone: string): Date;\n static getEndOfDay(date: number, timeZone: string): Date;\n static getEndOfDay(date: Date | number, timeZone: string): Date {\n const normalizedDate = typeof date === 'number' ? new Date(date) : date;\n return endOfDay(new TZDate(normalizedDate, timeZone));\n }\n\n /**\n * Checks if a date string is valid according to the specified format.\n * @param dateString The date string to validate.\n * @param dateFormat Optional date format (default: ISO_8601_FORMAT).\n * @returns True if the date is valid, false otherwise.\n */\n static isValidDate(dateString: string, dateFormat?: string): boolean {\n try {\n DateUtil.readDate(dateString, dateFormat, \"UTC\");\n return true;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Calculates the absolute number of days between two dates or timestamps.\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns Number of days between the two dates.\n */\n static daysInBetween(firstDate: Date, secondDate: Date): number;\n static daysInBetween(firstDate: number, secondDate: number): number;\n static daysInBetween(firstDate: Date | number, secondDate: Date | number): number {\n const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;\n return Math.abs(differenceInCalendarDays(first, second));\n }\n\n /**\n * Calculates the absolute number of months between two dates or timestamps.\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns The number of months between the two dates.\n */\n static monthsInBetween(firstDate: Date, secondDate: Date): number;\n static monthsInBetween(firstDate: number, secondDate: number): number;\n static monthsInBetween(firstDate: Date | number, secondDate: Date | number): number {\n const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;\n return Math.abs(differenceInCalendarMonths(first, second));\n }\n\n /**\n * Calculates the absolute number of years between two dates or timestamps.\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns The number of years between the two dates.\n */\n static yearsInBetween(firstDate: Date, secondDate: Date): number;\n static yearsInBetween(firstDate: number, secondDate: number): number;\n static yearsInBetween(firstDate: Date | number, secondDate: Date | number): number {\n const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;\n return Math.abs(differenceInCalendarYears(first, second));\n }\n\n /**\n * Compares two dates or timestamps.\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns `-1` if the first date is earlier, `1` if it is later, or `0` if the two dates are equal.\n */\n static compareDates(firstDate: Date, secondDate: Date): -1 | 0 | 1;\n static compareDates(firstDate: number, secondDate: number): -1 | 0 | 1;\n static compareDates(firstDate: Date | number, secondDate: Date | number): -1 | 0 | 1 {\n const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;\n\n return compareAsc(first, second) as -1 | 0 | 1;\n }\n\n /**\n * Adds a duration (e.g., days, months, years) to a given date or timestamp.\n * @param date The base date or timestamp to which the duration will be added.\n * @param duration An object specifying the duration (e.g., `{ days: 1, months: 2 }`).\n * @returns A new Date object with the duration added.\n */\n static addDuration(date: Date, duration: Duration): Date;\n static addDuration(date: number, duration: Duration): Date;\n static addDuration(date: Date | number, duration: Duration): Date {\n const normalizedDate = typeof date === 'number' ? new Date(date) : date;\n return add(normalizedDate, duration);\n }\n\n /**\n * Determines whether a given year is a leap year.\n * @param year The year to check.\n * @returns `true` if the year is a leap year, otherwise `false`.\n */\n static isLeapYear(year: number): boolean {\n return isLeapYear(DateUtil.readDate(year.toString(), 'yyyy', \"UTC\"));\n }\n\n\n /**\n * Converts a timestamp (in milliseconds) to a Date object.\n * @param milliseconds The timestamp in milliseconds since the Unix epoch.\n * @returns A Date object representing the provided timestamp.\n */\n static fromMillis(milliseconds: number): Date {\n return new Date(milliseconds);\n }\n\n /**\n * Converts a Date object to a timestamp (in milliseconds).\n * @param date The Date object to convert.\n * @returns The timestamp in milliseconds since the Unix epoch.\n */\n static toMillis(date: Date): number {\n return date.getTime();\n }\n}\n"],"names":["TZDate","parse","isValid","IllegalArgumentException","format","startOfDay","endOfDay","differenceInCalendarDays","differenceInCalendarMonths","differenceInCalendarYears","compareAsc","add","isLeapYear"],"mappings":"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"}
1
+ {"version":3,"file":"DateUtil.cjs","sources":["../../../../src/utils/date/DateUtil.ts"],"sourcesContent":["import { TZDate } from '@date-fns/tz';\nimport { add, compareAsc, differenceInCalendarDays, differenceInCalendarMonths, differenceInCalendarYears, differenceInHours, differenceInSeconds, Duration, endOfDay, format, isLeapYear, isValid, parse, startOfDay } from 'date-fns';\nimport { IllegalArgumentException } from '../../exceptions';\n\n/**\n * Utility class for date and time operations. Provides methods for parsing,\n * formatting, and performing calculations with dates and times.\n */\nexport class DateUtil {\n\n static readonly ISO_8601_FORMAT = \"yyyy-MM-dd'T'HH:mm:ss.SSSxxx\"\n static readonly TIMEZONE = \"UTC\"\n\n /**\n * Gets the current date and time in the specified time zone.\n * @param timeZone The IANA time zone identifier.\n * @returns Current date and time in the specified time zone.\n */\n static now(timeZone: string): Date {\n return new TZDate(new Date(), timeZone);\n }\n\n /**\n * Gets the current time in milliseconds since the Unix epoch.\n * @returns Current time in milliseconds.\n */\n static nowInMillis(): number {\n return Date.now();\n }\n\n /**\n * Parses a date string into a Date object.\n * @param dateString The date string to parse.\n * @param dateFormat The format of the date string (default: ISO_8601_FORMAT).\n * @param timeZone The IANA time zone identifier.\n * @throws {IllegalArgumentException} If the date string is invalid.\n * @returns Parsed Date object.\n */\n static readDate(dateString: string, dateFormat = this.ISO_8601_FORMAT, timeZone: string): Date {\n const date = parse(dateString, dateFormat, TZDate.tz(timeZone));\n if (!isValid(date)) {\n throw new IllegalArgumentException('Invalid date string or date format');\n }\n return date;\n }\n\n /**\n * Formats a Date or timestamp into a string.\n * @param date The date or timestamp to format.\n * @param timeZone The IANA time zone identifier.\n * @param dateFormat The desired output format (default: ISO_8601_FORMAT).\n * @returns Formatted date string.\n */\n static printDate(date: Date, timeZone: string, dateFormat?: string): string;\n static printDate(date: number, timeZone: string, dateFormat?: string): string;\n static printDate(date: Date | number, timeZone: string, dateFormat: string = this.ISO_8601_FORMAT): string {\n const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;\n return format(new TZDate(normalizedDate, timeZone), dateFormat);\n }\n\n /**\n * Gets the start of the day for a given date or timestamp.\n * @param date The date or timestamp to calculate from.\n * @param timeZone The IANA time zone identifier.\n * @returns The start of the day as a Date object.\n */\n static getStartOfDay(date: Date, timeZone: string): Date;\n static getStartOfDay(date: number, timeZone: string): Date;\n static getStartOfDay(date: Date | number, timeZone: string): Date {\n const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;\n return startOfDay(new TZDate(normalizedDate, timeZone));\n }\n\n /**\n * Gets the end of the day for a given date or timestamp.\n * @param date The date or timestamp to calculate from.\n * @param timeZone The IANA time zone identifier.\n * @returns The end of the day as a Date object.\n */\n static getEndOfDay(date: Date, timeZone: string): Date;\n static getEndOfDay(date: number, timeZone: string): Date;\n static getEndOfDay(date: Date | number, timeZone: string): Date {\n const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;\n return endOfDay(new TZDate(normalizedDate, timeZone));\n }\n\n /**\n * Checks if a date string is valid according to the specified format.\n * @param dateString The date string to validate.\n * @param dateFormat Optional date format (default: ISO_8601_FORMAT).\n * @returns True if the date is valid, false otherwise.\n */\n static isValidDate(dateString: string, dateFormat?: string): boolean {\n try {\n DateUtil.readDate(dateString, dateFormat, \"UTC\");\n return true;\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Calculates the absolute number of calendar days between two dates or timestamps.\n * Since day boundaries depend on a calendar, callers can optionally provide a time zone\n * so the same pair of instants is interpreted consistently across machines.\n *\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @param timeZone Optional IANA time zone identifier used for calendar comparisons.\n * @returns Number of days between the two dates.\n */\n static daysInBetween(firstDate: Date, secondDate: Date, timeZone?: string): number;\n static daysInBetween(firstDate: number, secondDate: number, timeZone?: string): number;\n static daysInBetween(firstDate: Date | number, secondDate: Date | number, timeZone?: string): number {\n const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;\n const effectiveTimeZone = timeZone || this.TIMEZONE;\n return Math.abs(\n differenceInCalendarDays(\n new TZDate(first, effectiveTimeZone),\n new TZDate(second, effectiveTimeZone),\n )\n );\n }\n\n /**\n * Calculates the absolute number of calendar months between two dates or timestamps.\n * Since month boundaries depend on a calendar, callers can optionally provide a time zone\n * so the same pair of instants is interpreted consistently across machines.\n *\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @param timeZone Optional IANA time zone identifier used for calendar comparisons.\n * @returns The number of months between the two dates.\n */\n static monthsInBetween(firstDate: Date, secondDate: Date, timeZone?: string): number;\n static monthsInBetween(firstDate: number, secondDate: number, timeZone?: string): number;\n static monthsInBetween(firstDate: Date | number, secondDate: Date | number, timeZone?: string): number {\n const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;\n const effectiveTimeZone = timeZone || this.TIMEZONE;\n return Math.abs(\n differenceInCalendarMonths(\n new TZDate(first, effectiveTimeZone),\n new TZDate(second, effectiveTimeZone),\n )\n );\n }\n\n /**\n * Calculates the absolute number of calendar years between two dates or timestamps.\n * Since year boundaries depend on a calendar, callers can optionally provide a time zone\n * so the same pair of instants is interpreted consistently across machines.\n *\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @param timeZone Optional IANA time zone identifier used for calendar comparisons.\n * @returns The number of years between the two dates.\n */\n static yearsInBetween(firstDate: Date, secondDate: Date, timeZone?: string): number;\n static yearsInBetween(firstDate: number, secondDate: number, timeZone?: string): number;\n static yearsInBetween(firstDate: Date | number, secondDate: Date | number, timeZone?: string): number {\n const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;\n const effectiveTimeZone = timeZone || this.TIMEZONE;\n return Math.abs(\n differenceInCalendarYears(\n new TZDate(first, effectiveTimeZone),\n new TZDate(second, effectiveTimeZone),\n )\n );\n }\n\n /**\n * Calculates the absolute elapsed number of hours between two dates or timestamps.\n * This is duration-based, not calendar-based, so it is independent of time zone.\n *\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns The number of hours between the two dates.\n */\n static hoursInBetween(firstDate: Date, secondDate: Date): number;\n static hoursInBetween(firstDate: number, secondDate: number): number;\n static hoursInBetween(firstDate: Date | number, secondDate: Date | number): number {\n const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;\n return Math.abs(differenceInHours(first, second));\n }\n\n /**\n * Calculates the absolute elapsed number of seconds between two dates or timestamps.\n * This is duration-based, not calendar-based, so it is independent of time zone.\n *\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns The number of seconds between the two dates.\n */\n static secondsInBetween(firstDate: Date, secondDate: Date): number;\n static secondsInBetween(firstDate: number, secondDate: number): number;\n static secondsInBetween(firstDate: Date | number, secondDate: Date | number): number {\n const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;\n return Math.abs(differenceInSeconds(first, second));\n }\n\n /**\n * Compares two dates or timestamps.\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns `-1` if the first date is earlier, `1` if it is later, or `0` if the two dates are equal.\n */\n static compareDates(firstDate: Date, secondDate: Date): -1 | 0 | 1;\n static compareDates(firstDate: number, secondDate: number): -1 | 0 | 1;\n static compareDates(firstDate: Date | number, secondDate: Date | number): -1 | 0 | 1 {\n const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;\n\n return compareAsc(first, second) as -1 | 0 | 1;\n }\n\n /**\n * Adds a duration (e.g., days, months, years) to a given date or timestamp.\n * When a time zone is provided, the duration is applied using calendar arithmetic\n * in that time zone so month-end or day-boundary business rules stay aligned locally.\n *\n * @param date The base date or timestamp to which the duration will be added.\n * @param duration An object specifying the duration (e.g., `{ days: 1, months: 2 }`).\n * @param timeZone Optional IANA time zone identifier used for calendar math.\n * @returns A new Date object with the duration added.\n */\n static addDuration(date: Date, duration: Duration, timeZone?: string): Date;\n static addDuration(date: number, duration: Duration, timeZone?: string): Date;\n static addDuration(date: Date | number, duration: Duration, timeZone?: string): Date {\n const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;\n const effectiveTimeZone = timeZone || this.TIMEZONE;\n return add(new TZDate(normalizedDate, effectiveTimeZone), duration);\n }\n\n /**\n * Determines whether a given year is a leap year.\n * @param year The year to check.\n * @returns `true` if the year is a leap year, otherwise `false`.\n */\n static isLeapYear(year: number): boolean {\n return isLeapYear(DateUtil.readDate(year.toString(), 'yyyy', \"UTC\"));\n }\n\n\n /**\n * Converts a timestamp (in milliseconds) to a Date object.\n * @param milliseconds The timestamp in milliseconds since the Unix epoch.\n * @returns A Date object representing the provided timestamp.\n */\n static fromMillis(milliseconds: number): Date {\n return new Date(milliseconds);\n }\n\n /**\n * Converts a Date object to a timestamp (in milliseconds).\n * @param date The Date object to convert.\n * @returns The timestamp in milliseconds since the Unix epoch.\n */\n static toMillis(date: Date): number {\n return date.getTime();\n }\n}\n"],"names":["TZDate","parse","isValid","IllegalArgumentException","format","startOfDay","endOfDay","differenceInCalendarDays","differenceInCalendarMonths","differenceInCalendarYears","differenceInHours","differenceInSeconds","compareAsc","add","isLeapYear"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { TZDate } from '@date-fns/tz';
2
- import { parse, isValid, format, startOfDay, endOfDay, differenceInCalendarDays, differenceInCalendarMonths, differenceInCalendarYears, compareAsc, add, isLeapYear } from 'date-fns';
2
+ import { parse, isValid, format, startOfDay, endOfDay, differenceInCalendarDays, differenceInCalendarMonths, differenceInCalendarYears, differenceInHours, differenceInSeconds, compareAsc, add, isLeapYear } from 'date-fns';
3
3
  import { IllegalArgumentException } from '../../exceptions/IllegalArgumentException.js';
4
4
 
5
5
  /**
@@ -8,6 +8,7 @@ import { IllegalArgumentException } from '../../exceptions/IllegalArgumentExcept
8
8
  */
9
9
  class DateUtil {
10
10
  static { this.ISO_8601_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSxxx"; }
11
+ static { this.TIMEZONE = "UTC"; }
11
12
  /**
12
13
  * Gets the current date and time in the specified time zone.
13
14
  * @param timeZone The IANA time zone identifier.
@@ -39,15 +40,15 @@ class DateUtil {
39
40
  return date;
40
41
  }
41
42
  static printDate(date, timeZone, dateFormat = this.ISO_8601_FORMAT) {
42
- const normalizedDate = typeof date === 'number' ? new Date(date) : date;
43
+ const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;
43
44
  return format(new TZDate(normalizedDate, timeZone), dateFormat);
44
45
  }
45
46
  static getStartOfDay(date, timeZone) {
46
- const normalizedDate = typeof date === 'number' ? new Date(date) : date;
47
+ const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;
47
48
  return startOfDay(new TZDate(normalizedDate, timeZone));
48
49
  }
49
50
  static getEndOfDay(date, timeZone) {
50
- const normalizedDate = typeof date === 'number' ? new Date(date) : date;
51
+ const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;
51
52
  return endOfDay(new TZDate(normalizedDate, timeZone));
52
53
  }
53
54
  /**
@@ -60,35 +61,48 @@ class DateUtil {
60
61
  try {
61
62
  DateUtil.readDate(dateString, dateFormat, "UTC");
62
63
  return true;
63
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
64
64
  }
65
65
  catch (error) {
66
66
  return false;
67
67
  }
68
68
  }
69
- static daysInBetween(firstDate, secondDate) {
70
- const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;
71
- const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;
72
- return Math.abs(differenceInCalendarDays(first, second));
69
+ static daysInBetween(firstDate, secondDate, timeZone) {
70
+ const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;
71
+ const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;
72
+ const effectiveTimeZone = timeZone || this.TIMEZONE;
73
+ return Math.abs(differenceInCalendarDays(new TZDate(first, effectiveTimeZone), new TZDate(second, effectiveTimeZone)));
73
74
  }
74
- static monthsInBetween(firstDate, secondDate) {
75
- const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;
76
- const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;
77
- return Math.abs(differenceInCalendarMonths(first, second));
75
+ static monthsInBetween(firstDate, secondDate, timeZone) {
76
+ const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;
77
+ const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;
78
+ const effectiveTimeZone = timeZone || this.TIMEZONE;
79
+ return Math.abs(differenceInCalendarMonths(new TZDate(first, effectiveTimeZone), new TZDate(second, effectiveTimeZone)));
78
80
  }
79
- static yearsInBetween(firstDate, secondDate) {
80
- const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;
81
- const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;
82
- return Math.abs(differenceInCalendarYears(first, second));
81
+ static yearsInBetween(firstDate, secondDate, timeZone) {
82
+ const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;
83
+ const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;
84
+ const effectiveTimeZone = timeZone || this.TIMEZONE;
85
+ return Math.abs(differenceInCalendarYears(new TZDate(first, effectiveTimeZone), new TZDate(second, effectiveTimeZone)));
86
+ }
87
+ static hoursInBetween(firstDate, secondDate) {
88
+ const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;
89
+ const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;
90
+ return Math.abs(differenceInHours(first, second));
91
+ }
92
+ static secondsInBetween(firstDate, secondDate) {
93
+ const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;
94
+ const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;
95
+ return Math.abs(differenceInSeconds(first, second));
83
96
  }
84
97
  static compareDates(firstDate, secondDate) {
85
- const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;
86
- const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;
98
+ const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;
99
+ const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;
87
100
  return compareAsc(first, second);
88
101
  }
89
- static addDuration(date, duration) {
90
- const normalizedDate = typeof date === 'number' ? new Date(date) : date;
91
- return add(normalizedDate, duration);
102
+ static addDuration(date, duration, timeZone) {
103
+ const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;
104
+ const effectiveTimeZone = timeZone || this.TIMEZONE;
105
+ return add(new TZDate(normalizedDate, effectiveTimeZone), duration);
92
106
  }
93
107
  /**
94
108
  * Determines whether a given year is a leap year.
@@ -1 +1 @@
1
- {"version":3,"file":"DateUtil.js","sources":["../../../../src/utils/date/DateUtil.ts"],"sourcesContent":["import { TZDate } from '@date-fns/tz';\nimport { add, compareAsc, differenceInCalendarDays, differenceInCalendarMonths, differenceInCalendarYears, Duration, endOfDay, format, isLeapYear, isValid, parse, startOfDay } from 'date-fns';\nimport { IllegalArgumentException } from '../../exceptions';\n\n/**\n * Utility class for date and time operations. Provides methods for parsing,\n * formatting, and performing calculations with dates and times.\n */\nexport class DateUtil {\n\n static readonly ISO_8601_FORMAT = \"yyyy-MM-dd'T'HH:mm:ss.SSSxxx\"\n\n /**\n * Gets the current date and time in the specified time zone.\n * @param timeZone The IANA time zone identifier.\n * @returns Current date and time in the specified time zone.\n */\n static now(timeZone: string): Date {\n return new TZDate(new Date(), timeZone);\n }\n\n /**\n * Gets the current time in milliseconds since the Unix epoch.\n * @returns Current time in milliseconds.\n */\n static nowInMillis(): number {\n return Date.now();\n }\n\n /**\n * Parses a date string into a Date object.\n * @param dateString The date string to parse.\n * @param dateFormat The format of the date string (default: ISO_8601_FORMAT).\n * @param timeZone The IANA time zone identifier.\n * @throws {IllegalArgumentException} If the date string is invalid.\n * @returns Parsed Date object.\n */\n static readDate(dateString: string, dateFormat = this.ISO_8601_FORMAT, timeZone: string): Date {\n const date = parse(dateString, dateFormat, TZDate.tz(timeZone));\n if (!isValid(date)) {\n throw new IllegalArgumentException('Invalid date string or date format');\n }\n return date;\n }\n\n /**\n * Formats a Date or timestamp into a string.\n * @param date The date or timestamp to format.\n * @param timeZone The IANA time zone identifier.\n * @param dateFormat The desired output format (default: ISO_8601_FORMAT).\n * @returns Formatted date string.\n */\n static printDate(date: Date, timeZone: string, dateFormat?: string): string;\n static printDate(date: number, timeZone: string, dateFormat?: string): string;\n static printDate(date: Date | number, timeZone: string, dateFormat: string = this.ISO_8601_FORMAT): string {\n const normalizedDate = typeof date === 'number' ? new Date(date) : date;\n return format(new TZDate(normalizedDate, timeZone), dateFormat);\n }\n\n /**\n * Gets the start of the day for a given date or timestamp.\n * @param date The date or timestamp to calculate from.\n * @param timeZone The IANA time zone identifier.\n * @returns The start of the day as a Date object.\n */\n static getStartOfDay(date: Date, timeZone: string): Date;\n static getStartOfDay(date: number, timeZone: string): Date;\n static getStartOfDay(date: Date | number, timeZone: string): Date {\n const normalizedDate = typeof date === 'number' ? new Date(date) : date;\n return startOfDay(new TZDate(normalizedDate, timeZone));\n }\n\n /**\n * Gets the end of the day for a given date or timestamp.\n * @param date The date or timestamp to calculate from.\n * @param timeZone The IANA time zone identifier.\n * @returns The end of the day as a Date object.\n */\n static getEndOfDay(date: Date, timeZone: string): Date;\n static getEndOfDay(date: number, timeZone: string): Date;\n static getEndOfDay(date: Date | number, timeZone: string): Date {\n const normalizedDate = typeof date === 'number' ? new Date(date) : date;\n return endOfDay(new TZDate(normalizedDate, timeZone));\n }\n\n /**\n * Checks if a date string is valid according to the specified format.\n * @param dateString The date string to validate.\n * @param dateFormat Optional date format (default: ISO_8601_FORMAT).\n * @returns True if the date is valid, false otherwise.\n */\n static isValidDate(dateString: string, dateFormat?: string): boolean {\n try {\n DateUtil.readDate(dateString, dateFormat, \"UTC\");\n return true;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Calculates the absolute number of days between two dates or timestamps.\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns Number of days between the two dates.\n */\n static daysInBetween(firstDate: Date, secondDate: Date): number;\n static daysInBetween(firstDate: number, secondDate: number): number;\n static daysInBetween(firstDate: Date | number, secondDate: Date | number): number {\n const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;\n return Math.abs(differenceInCalendarDays(first, second));\n }\n\n /**\n * Calculates the absolute number of months between two dates or timestamps.\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns The number of months between the two dates.\n */\n static monthsInBetween(firstDate: Date, secondDate: Date): number;\n static monthsInBetween(firstDate: number, secondDate: number): number;\n static monthsInBetween(firstDate: Date | number, secondDate: Date | number): number {\n const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;\n return Math.abs(differenceInCalendarMonths(first, second));\n }\n\n /**\n * Calculates the absolute number of years between two dates or timestamps.\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns The number of years between the two dates.\n */\n static yearsInBetween(firstDate: Date, secondDate: Date): number;\n static yearsInBetween(firstDate: number, secondDate: number): number;\n static yearsInBetween(firstDate: Date | number, secondDate: Date | number): number {\n const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;\n return Math.abs(differenceInCalendarYears(first, second));\n }\n\n /**\n * Compares two dates or timestamps.\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns `-1` if the first date is earlier, `1` if it is later, or `0` if the two dates are equal.\n */\n static compareDates(firstDate: Date, secondDate: Date): -1 | 0 | 1;\n static compareDates(firstDate: number, secondDate: number): -1 | 0 | 1;\n static compareDates(firstDate: Date | number, secondDate: Date | number): -1 | 0 | 1 {\n const first = typeof firstDate === 'number' ? new Date(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? new Date(secondDate) : secondDate;\n\n return compareAsc(first, second) as -1 | 0 | 1;\n }\n\n /**\n * Adds a duration (e.g., days, months, years) to a given date or timestamp.\n * @param date The base date or timestamp to which the duration will be added.\n * @param duration An object specifying the duration (e.g., `{ days: 1, months: 2 }`).\n * @returns A new Date object with the duration added.\n */\n static addDuration(date: Date, duration: Duration): Date;\n static addDuration(date: number, duration: Duration): Date;\n static addDuration(date: Date | number, duration: Duration): Date {\n const normalizedDate = typeof date === 'number' ? new Date(date) : date;\n return add(normalizedDate, duration);\n }\n\n /**\n * Determines whether a given year is a leap year.\n * @param year The year to check.\n * @returns `true` if the year is a leap year, otherwise `false`.\n */\n static isLeapYear(year: number): boolean {\n return isLeapYear(DateUtil.readDate(year.toString(), 'yyyy', \"UTC\"));\n }\n\n\n /**\n * Converts a timestamp (in milliseconds) to a Date object.\n * @param milliseconds The timestamp in milliseconds since the Unix epoch.\n * @returns A Date object representing the provided timestamp.\n */\n static fromMillis(milliseconds: number): Date {\n return new Date(milliseconds);\n }\n\n /**\n * Converts a Date object to a timestamp (in milliseconds).\n * @param date The Date object to convert.\n * @returns The timestamp in milliseconds since the Unix epoch.\n */\n static toMillis(date: Date): number {\n return date.getTime();\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DateUtil.js","sources":["../../../../src/utils/date/DateUtil.ts"],"sourcesContent":["import { TZDate } from '@date-fns/tz';\nimport { add, compareAsc, differenceInCalendarDays, differenceInCalendarMonths, differenceInCalendarYears, differenceInHours, differenceInSeconds, Duration, endOfDay, format, isLeapYear, isValid, parse, startOfDay } from 'date-fns';\nimport { IllegalArgumentException } from '../../exceptions';\n\n/**\n * Utility class for date and time operations. Provides methods for parsing,\n * formatting, and performing calculations with dates and times.\n */\nexport class DateUtil {\n\n static readonly ISO_8601_FORMAT = \"yyyy-MM-dd'T'HH:mm:ss.SSSxxx\"\n static readonly TIMEZONE = \"UTC\"\n\n /**\n * Gets the current date and time in the specified time zone.\n * @param timeZone The IANA time zone identifier.\n * @returns Current date and time in the specified time zone.\n */\n static now(timeZone: string): Date {\n return new TZDate(new Date(), timeZone);\n }\n\n /**\n * Gets the current time in milliseconds since the Unix epoch.\n * @returns Current time in milliseconds.\n */\n static nowInMillis(): number {\n return Date.now();\n }\n\n /**\n * Parses a date string into a Date object.\n * @param dateString The date string to parse.\n * @param dateFormat The format of the date string (default: ISO_8601_FORMAT).\n * @param timeZone The IANA time zone identifier.\n * @throws {IllegalArgumentException} If the date string is invalid.\n * @returns Parsed Date object.\n */\n static readDate(dateString: string, dateFormat = this.ISO_8601_FORMAT, timeZone: string): Date {\n const date = parse(dateString, dateFormat, TZDate.tz(timeZone));\n if (!isValid(date)) {\n throw new IllegalArgumentException('Invalid date string or date format');\n }\n return date;\n }\n\n /**\n * Formats a Date or timestamp into a string.\n * @param date The date or timestamp to format.\n * @param timeZone The IANA time zone identifier.\n * @param dateFormat The desired output format (default: ISO_8601_FORMAT).\n * @returns Formatted date string.\n */\n static printDate(date: Date, timeZone: string, dateFormat?: string): string;\n static printDate(date: number, timeZone: string, dateFormat?: string): string;\n static printDate(date: Date | number, timeZone: string, dateFormat: string = this.ISO_8601_FORMAT): string {\n const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;\n return format(new TZDate(normalizedDate, timeZone), dateFormat);\n }\n\n /**\n * Gets the start of the day for a given date or timestamp.\n * @param date The date or timestamp to calculate from.\n * @param timeZone The IANA time zone identifier.\n * @returns The start of the day as a Date object.\n */\n static getStartOfDay(date: Date, timeZone: string): Date;\n static getStartOfDay(date: number, timeZone: string): Date;\n static getStartOfDay(date: Date | number, timeZone: string): Date {\n const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;\n return startOfDay(new TZDate(normalizedDate, timeZone));\n }\n\n /**\n * Gets the end of the day for a given date or timestamp.\n * @param date The date or timestamp to calculate from.\n * @param timeZone The IANA time zone identifier.\n * @returns The end of the day as a Date object.\n */\n static getEndOfDay(date: Date, timeZone: string): Date;\n static getEndOfDay(date: number, timeZone: string): Date;\n static getEndOfDay(date: Date | number, timeZone: string): Date {\n const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;\n return endOfDay(new TZDate(normalizedDate, timeZone));\n }\n\n /**\n * Checks if a date string is valid according to the specified format.\n * @param dateString The date string to validate.\n * @param dateFormat Optional date format (default: ISO_8601_FORMAT).\n * @returns True if the date is valid, false otherwise.\n */\n static isValidDate(dateString: string, dateFormat?: string): boolean {\n try {\n DateUtil.readDate(dateString, dateFormat, \"UTC\");\n return true;\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Calculates the absolute number of calendar days between two dates or timestamps.\n * Since day boundaries depend on a calendar, callers can optionally provide a time zone\n * so the same pair of instants is interpreted consistently across machines.\n *\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @param timeZone Optional IANA time zone identifier used for calendar comparisons.\n * @returns Number of days between the two dates.\n */\n static daysInBetween(firstDate: Date, secondDate: Date, timeZone?: string): number;\n static daysInBetween(firstDate: number, secondDate: number, timeZone?: string): number;\n static daysInBetween(firstDate: Date | number, secondDate: Date | number, timeZone?: string): number {\n const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;\n const effectiveTimeZone = timeZone || this.TIMEZONE;\n return Math.abs(\n differenceInCalendarDays(\n new TZDate(first, effectiveTimeZone),\n new TZDate(second, effectiveTimeZone),\n )\n );\n }\n\n /**\n * Calculates the absolute number of calendar months between two dates or timestamps.\n * Since month boundaries depend on a calendar, callers can optionally provide a time zone\n * so the same pair of instants is interpreted consistently across machines.\n *\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @param timeZone Optional IANA time zone identifier used for calendar comparisons.\n * @returns The number of months between the two dates.\n */\n static monthsInBetween(firstDate: Date, secondDate: Date, timeZone?: string): number;\n static monthsInBetween(firstDate: number, secondDate: number, timeZone?: string): number;\n static monthsInBetween(firstDate: Date | number, secondDate: Date | number, timeZone?: string): number {\n const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;\n const effectiveTimeZone = timeZone || this.TIMEZONE;\n return Math.abs(\n differenceInCalendarMonths(\n new TZDate(first, effectiveTimeZone),\n new TZDate(second, effectiveTimeZone),\n )\n );\n }\n\n /**\n * Calculates the absolute number of calendar years between two dates or timestamps.\n * Since year boundaries depend on a calendar, callers can optionally provide a time zone\n * so the same pair of instants is interpreted consistently across machines.\n *\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @param timeZone Optional IANA time zone identifier used for calendar comparisons.\n * @returns The number of years between the two dates.\n */\n static yearsInBetween(firstDate: Date, secondDate: Date, timeZone?: string): number;\n static yearsInBetween(firstDate: number, secondDate: number, timeZone?: string): number;\n static yearsInBetween(firstDate: Date | number, secondDate: Date | number, timeZone?: string): number {\n const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;\n const effectiveTimeZone = timeZone || this.TIMEZONE;\n return Math.abs(\n differenceInCalendarYears(\n new TZDate(first, effectiveTimeZone),\n new TZDate(second, effectiveTimeZone),\n )\n );\n }\n\n /**\n * Calculates the absolute elapsed number of hours between two dates or timestamps.\n * This is duration-based, not calendar-based, so it is independent of time zone.\n *\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns The number of hours between the two dates.\n */\n static hoursInBetween(firstDate: Date, secondDate: Date): number;\n static hoursInBetween(firstDate: number, secondDate: number): number;\n static hoursInBetween(firstDate: Date | number, secondDate: Date | number): number {\n const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;\n return Math.abs(differenceInHours(first, second));\n }\n\n /**\n * Calculates the absolute elapsed number of seconds between two dates or timestamps.\n * This is duration-based, not calendar-based, so it is independent of time zone.\n *\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns The number of seconds between the two dates.\n */\n static secondsInBetween(firstDate: Date, secondDate: Date): number;\n static secondsInBetween(firstDate: number, secondDate: number): number;\n static secondsInBetween(firstDate: Date | number, secondDate: Date | number): number {\n const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;\n return Math.abs(differenceInSeconds(first, second));\n }\n\n /**\n * Compares two dates or timestamps.\n * @param firstDate The first date or timestamp.\n * @param secondDate The second date or timestamp.\n * @returns `-1` if the first date is earlier, `1` if it is later, or `0` if the two dates are equal.\n */\n static compareDates(firstDate: Date, secondDate: Date): -1 | 0 | 1;\n static compareDates(firstDate: number, secondDate: number): -1 | 0 | 1;\n static compareDates(firstDate: Date | number, secondDate: Date | number): -1 | 0 | 1 {\n const first = typeof firstDate === 'number' ? DateUtil.fromMillis(firstDate) : firstDate;\n const second = typeof secondDate === 'number' ? DateUtil.fromMillis(secondDate) : secondDate;\n\n return compareAsc(first, second) as -1 | 0 | 1;\n }\n\n /**\n * Adds a duration (e.g., days, months, years) to a given date or timestamp.\n * When a time zone is provided, the duration is applied using calendar arithmetic\n * in that time zone so month-end or day-boundary business rules stay aligned locally.\n *\n * @param date The base date or timestamp to which the duration will be added.\n * @param duration An object specifying the duration (e.g., `{ days: 1, months: 2 }`).\n * @param timeZone Optional IANA time zone identifier used for calendar math.\n * @returns A new Date object with the duration added.\n */\n static addDuration(date: Date, duration: Duration, timeZone?: string): Date;\n static addDuration(date: number, duration: Duration, timeZone?: string): Date;\n static addDuration(date: Date | number, duration: Duration, timeZone?: string): Date {\n const normalizedDate = typeof date === 'number' ? DateUtil.fromMillis(date) : date;\n const effectiveTimeZone = timeZone || this.TIMEZONE;\n return add(new TZDate(normalizedDate, effectiveTimeZone), duration);\n }\n\n /**\n * Determines whether a given year is a leap year.\n * @param year The year to check.\n * @returns `true` if the year is a leap year, otherwise `false`.\n */\n static isLeapYear(year: number): boolean {\n return isLeapYear(DateUtil.readDate(year.toString(), 'yyyy', \"UTC\"));\n }\n\n\n /**\n * Converts a timestamp (in milliseconds) to a Date object.\n * @param milliseconds The timestamp in milliseconds since the Unix epoch.\n * @returns A Date object representing the provided timestamp.\n */\n static fromMillis(milliseconds: number): Date {\n return new Date(milliseconds);\n }\n\n /**\n * Converts a Date object to a timestamp (in milliseconds).\n * @param date The Date object to convert.\n * @returns The timestamp in milliseconds since the Unix epoch.\n */\n static toMillis(date: Date): number {\n return date.getTime();\n }\n}\n"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@ import { Duration } from 'date-fns';
6
6
  */
7
7
  declare class DateUtil {
8
8
  static readonly ISO_8601_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSxxx";
9
+ static readonly TIMEZONE = "UTC";
9
10
  /**
10
11
  * Gets the current date and time in the specified time zone.
11
12
  * @param timeZone The IANA time zone identifier.
@@ -59,29 +60,61 @@ declare class DateUtil {
59
60
  */
60
61
  static isValidDate(dateString: string, dateFormat?: string): boolean;
61
62
  /**
62
- * Calculates the absolute number of days between two dates or timestamps.
63
+ * Calculates the absolute number of calendar days between two dates or timestamps.
64
+ * Since day boundaries depend on a calendar, callers can optionally provide a time zone
65
+ * so the same pair of instants is interpreted consistently across machines.
66
+ *
63
67
  * @param firstDate The first date or timestamp.
64
68
  * @param secondDate The second date or timestamp.
69
+ * @param timeZone Optional IANA time zone identifier used for calendar comparisons.
65
70
  * @returns Number of days between the two dates.
66
71
  */
67
- static daysInBetween(firstDate: Date, secondDate: Date): number;
68
- static daysInBetween(firstDate: number, secondDate: number): number;
72
+ static daysInBetween(firstDate: Date, secondDate: Date, timeZone?: string): number;
73
+ static daysInBetween(firstDate: number, secondDate: number, timeZone?: string): number;
69
74
  /**
70
- * Calculates the absolute number of months between two dates or timestamps.
71
- * @param firstDate The first date or timestamp.
72
- * @param secondDate The second date or timestamp.
73
- * @returns The number of months between the two dates.
74
- */
75
- static monthsInBetween(firstDate: Date, secondDate: Date): number;
76
- static monthsInBetween(firstDate: number, secondDate: number): number;
75
+ * Calculates the absolute number of calendar months between two dates or timestamps.
76
+ * Since month boundaries depend on a calendar, callers can optionally provide a time zone
77
+ * so the same pair of instants is interpreted consistently across machines.
78
+ *
79
+ * @param firstDate The first date or timestamp.
80
+ * @param secondDate The second date or timestamp.
81
+ * @param timeZone Optional IANA time zone identifier used for calendar comparisons.
82
+ * @returns The number of months between the two dates.
83
+ */
84
+ static monthsInBetween(firstDate: Date, secondDate: Date, timeZone?: string): number;
85
+ static monthsInBetween(firstDate: number, secondDate: number, timeZone?: string): number;
77
86
  /**
78
- * Calculates the absolute number of years between two dates or timestamps.
87
+ * Calculates the absolute number of calendar years between two dates or timestamps.
88
+ * Since year boundaries depend on a calendar, callers can optionally provide a time zone
89
+ * so the same pair of instants is interpreted consistently across machines.
90
+ *
79
91
  * @param firstDate The first date or timestamp.
80
92
  * @param secondDate The second date or timestamp.
93
+ * @param timeZone Optional IANA time zone identifier used for calendar comparisons.
81
94
  * @returns The number of years between the two dates.
82
95
  */
83
- static yearsInBetween(firstDate: Date, secondDate: Date): number;
84
- static yearsInBetween(firstDate: number, secondDate: number): number;
96
+ static yearsInBetween(firstDate: Date, secondDate: Date, timeZone?: string): number;
97
+ static yearsInBetween(firstDate: number, secondDate: number, timeZone?: string): number;
98
+ /**
99
+ * Calculates the absolute elapsed number of hours between two dates or timestamps.
100
+ * This is duration-based, not calendar-based, so it is independent of time zone.
101
+ *
102
+ * @param firstDate The first date or timestamp.
103
+ * @param secondDate The second date or timestamp.
104
+ * @returns The number of hours between the two dates.
105
+ */
106
+ static hoursInBetween(firstDate: Date, secondDate: Date): number;
107
+ static hoursInBetween(firstDate: number, secondDate: number): number;
108
+ /**
109
+ * Calculates the absolute elapsed number of seconds between two dates or timestamps.
110
+ * This is duration-based, not calendar-based, so it is independent of time zone.
111
+ *
112
+ * @param firstDate The first date or timestamp.
113
+ * @param secondDate The second date or timestamp.
114
+ * @returns The number of seconds between the two dates.
115
+ */
116
+ static secondsInBetween(firstDate: Date, secondDate: Date): number;
117
+ static secondsInBetween(firstDate: number, secondDate: number): number;
85
118
  /**
86
119
  * Compares two dates or timestamps.
87
120
  * @param firstDate The first date or timestamp.
@@ -92,12 +125,16 @@ declare class DateUtil {
92
125
  static compareDates(firstDate: number, secondDate: number): -1 | 0 | 1;
93
126
  /**
94
127
  * Adds a duration (e.g., days, months, years) to a given date or timestamp.
128
+ * When a time zone is provided, the duration is applied using calendar arithmetic
129
+ * in that time zone so month-end or day-boundary business rules stay aligned locally.
130
+ *
95
131
  * @param date The base date or timestamp to which the duration will be added.
96
132
  * @param duration An object specifying the duration (e.g., `{ days: 1, months: 2 }`).
133
+ * @param timeZone Optional IANA time zone identifier used for calendar math.
97
134
  * @returns A new Date object with the duration added.
98
135
  */
99
- static addDuration(date: Date, duration: Duration): Date;
100
- static addDuration(date: number, duration: Duration): Date;
136
+ static addDuration(date: Date, duration: Duration, timeZone?: string): Date;
137
+ static addDuration(date: number, duration: Duration, timeZone?: string): Date;
101
138
  /**
102
139
  * Determines whether a given year is a leap year.
103
140
  * @param year The year to check.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@org-quicko/core",
3
- "version": "2.0.3",
3
+ "version": "2.0.5",
4
4
  "description": "A library in typescript for common entities and utilities across Quicko",
5
5
  "author": "Quicko",
6
6
  "main": "dist/cjs/build/node/index.cjs",
@@ -9,11 +9,13 @@
9
9
  "types": "dist/types/index.d.ts",
10
10
  "type": "module",
11
11
  "scripts": {
12
- "clean": "rm -rf dist && npm cache clean --force",
12
+ "clean": "rm -rf ./dist",
13
+ "clean:all": "rm -rf ./node_modules ./package-lock.json ./dist && npm cache clean --force",
13
14
  "lint": "eslint .",
14
15
  "lint:fix": "eslint . --fix",
15
16
  "prebuild": "npm run clean && npm run lint",
16
17
  "build": "rollup -c",
18
+ "test": "set NODE_ENV=local && node --experimental-vm-modules node_modules/jest/bin/jest.js",
17
19
  "test:date:util": "set NODE_ENV=local && node --experimental-vm-modules node_modules/jest/bin/jest.js run ./tests/DateUtil.test.ts"
18
20
  },
19
21
  "license": "ISC",
@@ -78,37 +80,9 @@
78
80
  },
79
81
  "./package.json": "./package.json"
80
82
  },
81
- "typesVersions": {
82
- "*": {
83
- "*": [
84
- "dist/types/*"
85
- ],
86
- "beans": [
87
- "dist/types/src/beans/index.d.ts"
88
- ],
89
- "types": [
90
- "dist/types/src/types/index.d.ts"
91
- ],
92
- "utils": [
93
- "dist/types/src/utils/index.d.ts"
94
- ],
95
- "utils/date": [
96
- "dist/types/src/utils/date/index.d.ts"
97
- ],
98
- "exceptions": [
99
- "dist/types/src/exceptions/index.d.ts"
100
- ],
101
- "logger": [
102
- "dist/types/src/logger/index.d.ts"
103
- ]
104
- }
105
- },
106
83
  "directories": {
107
84
  "lib": "./dist"
108
85
  },
109
- "engines": {
110
- "node": ">=14"
111
- },
112
86
  "dependencies": {
113
87
  "@date-fns/tz": "^1.1.2",
114
88
  "class-transformer": "^0.5.1",
@@ -121,6 +95,7 @@
121
95
  "@rollup/plugin-commonjs": "^28.0.3",
122
96
  "@rollup/plugin-node-resolve": "^16.0.1",
123
97
  "@rollup/plugin-typescript": "^12.1.2",
98
+ "@types/jest": "^29.5.12",
124
99
  "@types/node": "^22.7.0",
125
100
  "@typescript-eslint/eslint-plugin": "^8.33.1",
126
101
  "@typescript-eslint/parser": "^8.33.1",
@@ -129,12 +104,12 @@
129
104
  "eslint-config-prettier": "^10.1.5",
130
105
  "eslint-import-resolver-typescript": "^3.7.0",
131
106
  "glob": "^11.0.2",
107
+ "jest": "^29.7.0",
132
108
  "rollup": "^4.40.2",
133
109
  "rollup-plugin-dts": "^6.2.1",
110
+ "rollup-plugin-node-externals": "^8.1.2",
111
+ "ts-jest": "^29.2.5",
134
112
  "ts-node": "^10.9.2",
135
- "typescript": "^5.6.2",
136
- "@types/jest": "^29.5.12",
137
- "jest": "^29.7.0",
138
- "ts-jest": "^29.2.5"
113
+ "typescript": "^5.6.2"
139
114
  }
140
- }
115
+ }