@northguild/gmt 1.14.2 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/README.md +43 -13
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.js +1 -0
  4. package/dist/plain/calculate/diffDateAsDuration.js +1 -1
  5. package/dist/plain/calculate/index.d.ts +2 -1
  6. package/dist/plain/calculate/index.js +2 -1
  7. package/dist/plain/calculate/{weekOfYear.d.ts → weekOfYearForDate.d.ts} +0 -14
  8. package/dist/plain/calculate/weekOfYearForDate.js +28 -0
  9. package/dist/plain/calculate/weekOfYearForDateTime.d.ts +14 -0
  10. package/dist/plain/calculate/{weekOfYear.js → weekOfYearForDateTime.js} +1 -27
  11. package/dist/plain/format/formatCalendar.d.ts +2 -2
  12. package/dist/plain/format/formatDate.d.ts +3 -2
  13. package/dist/plain/format/formatDate.js +1 -1
  14. package/dist/plain/format/formatDateRange.d.ts +3 -2
  15. package/dist/plain/format/formatDateRange.js +1 -1
  16. package/dist/plain/format/formatDateTime.d.ts +3 -2
  17. package/dist/plain/format/formatDateTime.js +1 -1
  18. package/dist/plain/format/formatDateTimeRange.d.ts +3 -2
  19. package/dist/plain/format/formatDateTimeRange.js +1 -1
  20. package/dist/plain/format/formatDateTimeToParts.d.ts +3 -2
  21. package/dist/plain/format/formatDateTimeToParts.js +1 -1
  22. package/dist/plain/format/formatDateToParts.d.ts +3 -2
  23. package/dist/plain/format/formatDateToParts.js +1 -1
  24. package/dist/plain/format/formatRelativeDate.d.ts +3 -14
  25. package/dist/plain/format/formatRelativeDateTime.d.ts +3 -14
  26. package/dist/plain/format/formatRelativeTime.d.ts +3 -14
  27. package/dist/plain/format/formatTime.d.ts +2 -1
  28. package/dist/plain/get/getNowUnit.d.ts +2 -3
  29. package/dist/plain/interval/splitIntervalByUnitDate.js +1 -1
  30. package/dist/regex/calendar-date.d.ts +19 -0
  31. package/dist/regex/calendar-date.js +19 -10
  32. package/dist/regex/calendar-zoned-date-time.d.ts +45 -0
  33. package/dist/regex/calendar-zoned-date-time.js +45 -40
  34. package/dist/regex/date-time.d.ts +18 -0
  35. package/dist/regex/date-time.js +18 -1
  36. package/dist/regex/date.d.ts +16 -0
  37. package/dist/regex/date.js +16 -1
  38. package/dist/regex/http-date.d.ts +15 -0
  39. package/dist/regex/http-date.js +15 -6
  40. package/dist/regex/leap-second.d.ts +12 -0
  41. package/dist/regex/leap-second.js +12 -1
  42. package/dist/regex/rfc-2822.d.ts +18 -0
  43. package/dist/regex/rfc-2822.js +18 -8
  44. package/dist/regex/rfc-3339.d.ts +19 -0
  45. package/dist/regex/rfc-3339.js +19 -6
  46. package/dist/regex/sql-date-time.d.ts +14 -0
  47. package/dist/regex/sql-date-time.js +14 -6
  48. package/dist/regex/time-zone-like.d.ts +21 -0
  49. package/dist/regex/time-zone-like.js +21 -0
  50. package/dist/regex/time.d.ts +59 -0
  51. package/dist/regex/time.js +59 -3
  52. package/dist/regex/unix.d.ts +21 -0
  53. package/dist/regex/unix.js +21 -0
  54. package/dist/regex/utc-date-time.d.ts +20 -0
  55. package/dist/regex/utc-date-time.js +20 -1
  56. package/dist/types/calendar-options.d.ts +11 -0
  57. package/dist/types/calendar-options.js +0 -0
  58. package/dist/types/datetime-format-options.d.ts +6 -0
  59. package/dist/types/datetime-format-options.js +0 -0
  60. package/dist/types/duration-unit.d.ts +5 -0
  61. package/dist/types/duration-unit.js +0 -0
  62. package/dist/types/index.d.ts +11 -0
  63. package/dist/types/index.js +11 -0
  64. package/dist/types/now-unit.d.ts +5 -0
  65. package/dist/types/now-unit.js +0 -0
  66. package/dist/types/relative-date-time-unit.d.ts +6 -0
  67. package/dist/types/relative-date-time-unit.js +0 -0
  68. package/dist/types/relative-date-unit.d.ts +5 -0
  69. package/dist/types/relative-date-unit.js +0 -0
  70. package/dist/types/relative-time-options.d.ts +18 -0
  71. package/dist/types/relative-time-options.js +0 -0
  72. package/dist/types/relative-time-unit.d.ts +5 -0
  73. package/dist/types/relative-time-unit.js +0 -0
  74. package/dist/types/relative-unit.d.ts +6 -0
  75. package/dist/types/relative-unit.js +0 -0
  76. package/dist/types/unix-now-unit.d.ts +5 -0
  77. package/dist/types/unix-now-unit.js +0 -0
  78. package/dist/types/utc-now-unit.d.ts +5 -0
  79. package/dist/types/utc-now-unit.js +0 -0
  80. package/dist/unix/calculate/startOrEndOfUnix.d.ts +18 -0
  81. package/dist/unix/calculate/startOrEndOfUnix.js +18 -0
  82. package/dist/unix/format/formatCalendarUnix.d.ts +27 -1
  83. package/dist/unix/format/formatRelativeUnix.d.ts +1 -8
  84. package/dist/unix/format/formatUnix.d.ts +19 -0
  85. package/dist/unix/format/formatUnix.js +19 -0
  86. package/dist/unix/get/getUnixNowUnit.d.ts +2 -3
  87. package/dist/unix/parse/parseUnitFromUnix.d.ts +24 -0
  88. package/dist/unix/validate/isValidUnixUnit.d.ts +15 -0
  89. package/dist/utc/calculate/startOrEndOfUtc.d.ts +17 -0
  90. package/dist/utc/calculate/startOrEndOfUtc.js +17 -0
  91. package/dist/utc/format/formatCalendarUtc.d.ts +2 -2
  92. package/dist/utc/format/formatRelativeUtc.d.ts +2 -12
  93. package/dist/utc/format/formatUtc.d.ts +33 -0
  94. package/dist/utc/format/formatUtc.js +17 -0
  95. package/dist/utc/get/getUtcNowUnit.d.ts +2 -3
  96. package/dist/utc/parse/parseUnitFromUtc.d.ts +23 -0
  97. package/dist/zoned/format/formatRelativeZoned.d.ts +1 -8
  98. package/dist/zoned/format/formatTimeZoneName.d.ts +15 -0
  99. package/dist/zoned/format/formatZonedDateTime.d.ts +2 -1
  100. package/dist/zoned/format/formatZonedRange.d.ts +2 -1
  101. package/dist/zoned/format/formatZonedToParts.d.ts +2 -1
  102. package/dist/zoned/get/getDstTransitions.d.ts +18 -2
  103. package/dist/zoned/get/getZonedNowUnit.d.ts +24 -0
  104. package/dist/zoned/interval/intervalDifferenceZoned.d.ts +3 -3
  105. package/dist/zoned/interval/intervalDifferenceZoned.js +3 -3
  106. package/dist/zoned/interval/intervalXorZoned.d.ts +6 -4
  107. package/dist/zoned/interval/intervalXorZoned.js +6 -4
  108. package/dist/zoned/parse/getZonedOffsetAs.d.ts +11 -0
  109. package/dist/zoned/parse/parseUnitFromZoned.d.ts +24 -0
  110. package/package.json +25 -7
  111. package/skills/gmt-arithmetic/SKILL.md +83 -0
  112. package/skills/gmt-basics/SKILL.md +80 -0
  113. package/skills/gmt-integration/SKILL.md +73 -0
  114. package/skills/gmt-timezone/SKILL.md +80 -0
  115. package/skills/_artifacts/domain_map.yaml +0 -547
  116. package/skills/_artifacts/skill_spec.md +0 -67
  117. package/skills/_artifacts/skill_tree.yaml +0 -278
  118. package/skills/api-expansion-workflow/SKILL.md +0 -52
  119. package/skills/app-integration/SKILL.md +0 -38
  120. package/skills/calculate-dates/SKILL.md +0 -432
  121. package/skills/compare-dates/SKILL.md +0 -412
  122. package/skills/convert-types/SKILL.md +0 -305
  123. package/skills/durations/SKILL.md +0 -418
  124. package/skills/format-date-time/SKILL.md +0 -486
  125. package/skills/format-date-time/references/format-api.md +0 -34
  126. package/skills/format-relative-time/SKILL.md +0 -223
  127. package/skills/get-current/SKILL.md +0 -229
  128. package/skills/interval-ops/SKILL.md +0 -432
  129. package/skills/issue-creation/SKILL.md +0 -118
  130. package/skills/lint-package-suggestion/SKILL.md +0 -37
  131. package/skills/new-method-implementation/SKILL.md +0 -71
  132. package/skills/parse-date-time/SKILL.md +0 -349
  133. package/skills/pr-contribution/SKILL.md +0 -180
  134. package/skills/unit-test-generation/SKILL.md +0 -56
  135. package/skills/validate-dates/SKILL.md +0 -438
  136. package/skills/zoned-date-ops/SKILL.md +0 -422
  137. package/skills/zoned-date-ops/references/timezones.md +0 -13
@@ -1,15 +1,6 @@
1
- import type { RelativeRoundingMethod } from "../../types/index.js";
2
- type RelativeUnit = "year" | "month" | "week" | "day" | "hour" | "minute" | "second";
3
- export interface FormatRelativeUtcOptions {
4
- style?: "long" | "short" | "narrow";
5
- numeric?: "always" | "auto";
1
+ import type { RelativeTimeFormatOptions, RelativeUnit } from "../../types/index.js";
2
+ export interface FormatRelativeUtcOptions extends RelativeTimeFormatOptions {
6
3
  largestUnit?: RelativeUnit;
7
- /**
8
- * How the computed distance rounds to the display unit: "floor" rounds toward the
9
- * earlier boundary, "ceil" toward the later boundary, "round" (default) to the nearest —
10
- * matches current behavior when omitted.
11
- */
12
- roundingMethod?: RelativeRoundingMethod;
13
4
  reference?: string;
14
5
  timeZone?: string;
15
6
  }
@@ -30,4 +21,3 @@ export interface FormatRelativeUtcOptions {
30
21
  * @example formatRelativeUtc("not-a-date") // ""
31
22
  */
32
23
  export declare function formatRelativeUtc(value: string, locale?: string, options?: FormatRelativeUtcOptions): string;
33
- export {};
@@ -1,5 +1,38 @@
1
+ /**
2
+ * Options for `formatUtc`. Extends `Intl.DateTimeFormatOptions`; only the
3
+ * added/overridden members are listed below. All `Intl.DateTimeFormatOptions`
4
+ * (`dateStyle`, `timeStyle`, etc.) apply to the time-of-day portion.
5
+ *
6
+ * @remarks Members:
7
+ *
8
+ * | Member | Type | Default | Description |
9
+ * | --- | --- | --- | --- |
10
+ * | `timeZone` | `string` | `"UTC"` | IANA zone for rendering; invalid/omitted falls back to UTC via `normalizeTimeZone`. |
11
+ * | `includeTimeZoneName` | `boolean` | `false` | Appends the localized zone name (style via `Intl`) when true. |
12
+ *
13
+ * @example
14
+ * import { FormatUtcOptions } from "@northguild/gmt/utc";
15
+ * const opts: FormatUtcOptions = { includeTimeZoneName: true };
16
+ */
1
17
  export interface FormatUtcOptions extends Intl.DateTimeFormatOptions {
2
18
  timeZone?: string;
3
19
  includeTimeZoneName?: boolean;
4
20
  }
21
+ /**
22
+ * Format a UTC ISO string as a localized date/time string.
23
+ *
24
+ * - Returns `""` if the input is not a valid UTC string.
25
+ * - `timeZone` controls the IANA zone used for rendering; defaults to `"UTC"`.
26
+ * - `includeTimeZoneName` appends the localized timezone name when true.
27
+ *
28
+ * @param value UTC ISO string to format
29
+ * @param locale optional: BCP 47 locale tag
30
+ * @param options optional: { timeZone, includeTimeZoneName }
31
+ * @returns the formatted date/time string, or "" on invalid input
32
+ *
33
+ * @example formatUtc("2026-03-16T18:30:00Z") // "3/16/2026, 6:30:00 PM"
34
+ * @example formatUtc("2026-03-16T18:30:00Z", "en-US", { timeZone: "America/New_York" }) // "3/16/2026, 2:30:00 PM"
35
+ * @example formatUtc("2026-03-16T18:30:00Z", "en-US", { timeZone: "America/New_York", includeTimeZoneName: true }) // "3/16/2026, 2:30:00 PM EDT"
36
+ * @example formatUtc("not-a-date") // ""
37
+ */
5
38
  export declare function formatUtc(value: string, locale?: string, options?: FormatUtcOptions): string;
@@ -2,6 +2,23 @@ import { normalizeDateTime } from "../../internal/normalizeDateTime.js";
2
2
  import { normalizeTimeZone } from "../../internal/normalizeTimeZone.js";
3
3
  import { toInstantFromUtc } from "../../internal/toInstantFromUtc.js";
4
4
  import { isValidUtc } from "../validate/index.js";
5
+ /**
6
+ * Format a UTC ISO string as a localized date/time string.
7
+ *
8
+ * - Returns `""` if the input is not a valid UTC string.
9
+ * - `timeZone` controls the IANA zone used for rendering; defaults to `"UTC"`.
10
+ * - `includeTimeZoneName` appends the localized timezone name when true.
11
+ *
12
+ * @param value UTC ISO string to format
13
+ * @param locale optional: BCP 47 locale tag
14
+ * @param options optional: { timeZone, includeTimeZoneName }
15
+ * @returns the formatted date/time string, or "" on invalid input
16
+ *
17
+ * @example formatUtc("2026-03-16T18:30:00Z") // "3/16/2026, 6:30:00 PM"
18
+ * @example formatUtc("2026-03-16T18:30:00Z", "en-US", { timeZone: "America/New_York" }) // "3/16/2026, 2:30:00 PM"
19
+ * @example formatUtc("2026-03-16T18:30:00Z", "en-US", { timeZone: "America/New_York", includeTimeZoneName: true }) // "3/16/2026, 2:30:00 PM EDT"
20
+ * @example formatUtc("not-a-date") // ""
21
+ */
5
22
  export function formatUtc(value, locale, options) {
6
23
  if (!isValidUtc(value))
7
24
  return "";
@@ -1,5 +1,5 @@
1
- import type { DateTimeUnit } from "../../types/index.js";
2
- type UtcNowUnit = DateTimeUnit | "dayOfWeek";
1
+ import type { UtcNowUnit } from "../../types/index.js";
2
+ export type { UtcNowUnit };
3
3
  /**
4
4
  * Return the requested unit value from the current UTC instant.
5
5
  *
@@ -15,4 +15,3 @@ type UtcNowUnit = DateTimeUnit | "dayOfWeek";
15
15
  * @example getUtcNowUnit("invalid") // ""
16
16
  */
17
17
  export declare function getUtcNowUnit(unit: UtcNowUnit): string;
18
- export {};
@@ -1,3 +1,26 @@
1
+ /**
2
+ * Units supported by `parseUnitFromUtc` when extracting a value from a UTC ISO
3
+ * string. Excludes `microsecond` and `nanosecond`, which `parseUnitFromUtc`
4
+ * does not expose.
5
+ *
6
+ * @remarks Members:
7
+ *
8
+ * | Member | Description |
9
+ * | --- | --- |
10
+ * | `year` | Full year, no padding (e.g. `2024`). |
11
+ * | `month` | Zero-padded 2 (e.g. `03`). |
12
+ * | `week` | Week-of-year, 1–53 (`weekStartsOn`-controlled). |
13
+ * | `day` | Zero-padded 2. |
14
+ * | `dayOfWeek` | 1 (Mon)–7 (Sun). |
15
+ * | `hour` | Zero-padded 2. |
16
+ * | `minute` | Zero-padded 2. |
17
+ * | `second` | Zero-padded 2. |
18
+ * | `millisecond` | Zero-padded 3. |
19
+ *
20
+ * @example
21
+ * import { UtcUnit } from "@northguild/gmt/utc";
22
+ * const u: UtcUnit = "month";
23
+ */
1
24
  export type UtcUnit = "year" | "month" | "week" | "day" | "dayOfWeek" | "hour" | "minute" | "second" | "millisecond";
2
25
  /**
3
26
  * Extract a unit from a UTC datetime string.
@@ -1,14 +1,8 @@
1
- import type { RelativeRoundingMethod } from "../../types/index.js";
2
- type RelativeUnit = "year" | "month" | "week" | "day" | "hour" | "minute" | "second";
1
+ import type { RelativeRoundingMethod, RelativeUnit } from "../../types/index.js";
3
2
  export interface FormatRelativeZonedOptions {
4
3
  style?: "long" | "short" | "narrow";
5
4
  numeric?: "always" | "auto";
6
5
  largestUnit?: RelativeUnit;
7
- /**
8
- * How the computed distance rounds to the display unit: "floor" rounds toward the
9
- * earlier boundary, "ceil" toward the later boundary, "round" (default) to the nearest —
10
- * matches current behavior when omitted.
11
- */
12
6
  roundingMethod?: RelativeRoundingMethod;
13
7
  /**
14
8
  * Anchor point for the relative diff.
@@ -41,4 +35,3 @@ export interface FormatRelativeZonedOptions {
41
35
  * @example formatRelativeZoned("not-a-date") // ""
42
36
  */
43
37
  export declare function formatRelativeZoned(value: string, locale?: string, options?: FormatRelativeZonedOptions): string;
44
- export {};
@@ -1,6 +1,21 @@
1
1
  /**
2
2
  * Name style for `formatTimeZoneName`, mirroring
3
3
  * `Intl.DateTimeFormatOptions`'s `timeZoneName` values.
4
+ *
5
+ * @remarks Members:
6
+ *
7
+ * | Member | Example (America/New_York) | Description |
8
+ * | --- | --- | --- |
9
+ * | `short` | `EST`/`EDT` | Abbreviated zone name; seasonal for DST zones. |
10
+ * | `long` | `Eastern Standard Time` | Full zone name; seasonal for DST zones. |
11
+ * | `shortOffset` | `GMT-5` | Short UTC offset; seasonal. |
12
+ * | `longOffset` | `GMT-05:00` | Zero-padded UTC offset; seasonal. |
13
+ * | `shortGeneric` | `ET` | Season-independent generic abbreviation. |
14
+ * | `longGeneric` | `Eastern Time` | Season-independent generic full name. |
15
+ *
16
+ * @example
17
+ * import { TimeZoneNameStyle } from "@northguild/gmt/zoned";
18
+ * const s: TimeZoneNameStyle = "shortGeneric";
4
19
  */
5
20
  export type TimeZoneNameStyle = "short" | "long" | "shortOffset" | "longOffset" | "shortGeneric" | "longGeneric";
6
21
  export interface FormatTimeZoneNameOptions {
@@ -1,3 +1,4 @@
1
+ import type { DateTimeFormatOptions } from "../../types/index.js";
1
2
  /**
2
3
  * Format a zoned ISO 8601 datetime string using the Intl.DateTimeFormat implementation.
3
4
  *
@@ -14,4 +15,4 @@
14
15
  * @example formatZonedDateTime("2024-02-29T12:34:56.789+00:00[UTC]", "en-GB", { dateStyle: "short", timeStyle: "short" }) // "29/02/2024, 12:34"
15
16
  * @example formatZonedDateTime("invalid", "en-US") // "" (invalid input)
16
17
  */
17
- export declare function formatZonedDateTime(value: string, locale?: string, options?: Intl.DateTimeFormatOptions): string;
18
+ export declare function formatZonedDateTime(value: string, locale?: string, options?: DateTimeFormatOptions): string;
@@ -1,3 +1,4 @@
1
+ import type { DateTimeFormatOptions } from "../../types/index.js";
1
2
  /**
2
3
  * Format a zoned datetime range using the Temporal Intl.DateTimeFormat formatRange API.
3
4
  *
@@ -15,4 +16,4 @@
15
16
  * @example formatZonedRange("2024-02-29T12:00:00.000+00:00[UTC]", "2024-02-29T14:00:00.000+00:00[UTC]", "en-GB", { dateStyle: "short", timeStyle: "short" }) // "29/02/2024, 12:00 – 14:00"
16
17
  * @example formatZonedRange("invalid", "2024-02-29T14:00:00.000+00:00[UTC]", "en-US") // "" (invalid input)
17
18
  */
18
- export declare function formatZonedRange(from: string, to: string, locale?: string, options?: Intl.DateTimeFormatOptions): string;
19
+ export declare function formatZonedRange(from: string, to: string, locale?: string, options?: DateTimeFormatOptions): string;
@@ -1,3 +1,4 @@
1
+ import type { DateTimeFormatOptions } from "../../types/index.js";
1
2
  /**
2
3
  * Return the locale-formatted parts of a ZonedDateTime.
3
4
  *
@@ -23,7 +24,7 @@
23
24
  * @example formatZonedToParts("2024-03-15T14:30:00.000-04:00[America/New_York]", "en-US", { timeZoneName: "longOffset" }) // includes { type: "timeZoneName", value: "GMT-4" }
24
25
  * @example formatZonedToParts("invalid", "en-US") // []
25
26
  */
26
- export declare function formatZonedToParts(value: string, locale?: string, options?: Intl.DateTimeFormatOptions): Array<{
27
+ export declare function formatZonedToParts(value: string, locale?: string, options?: DateTimeFormatOptions): Array<{
27
28
  type: string;
28
29
  value: string;
29
30
  }>;
@@ -1,6 +1,22 @@
1
1
  /**
2
- * A single DST transition instant, with the UTC offset in effect immediately
3
- * before and after the change.
2
+ * A single DST transition instant: the UTC instant of an offset change plus the
3
+ * offset in effect immediately before and after it.
4
+ *
5
+ * @remarks Members:
6
+ *
7
+ * | Member | Type | Description |
8
+ * | --- | --- | --- |
9
+ * | `instant` | `string` | UTC instant of the offset change, ISO 8601 ending in `Z` (e.g. `2024-03-10T07:00:00Z`). |
10
+ * | `offsetBefore` | `string` | UTC offset in effect immediately before the transition (e.g. `-05:00`). |
11
+ * | `offsetAfter` | `string` | UTC offset in effect immediately after the transition (e.g. `-04:00`). |
12
+ *
13
+ * @example
14
+ * import { DstTransition } from "@northguild/gmt/zoned";
15
+ * const t: DstTransition = {
16
+ * instant: "2024-03-10T07:00:00Z",
17
+ * offsetBefore: "-05:00",
18
+ * offsetAfter: "-04:00",
19
+ * };
4
20
  */
5
21
  export interface DstTransition {
6
22
  instant: string;
@@ -1,3 +1,27 @@
1
+ /**
2
+ * Units extractable from the current time in a specific IANA timeZone, as
3
+ * consumed by `getZonedNowUnit`.
4
+ *
5
+ * @remarks Members:
6
+ *
7
+ * | Member | Description |
8
+ * | --- | --- |
9
+ * | `year` | Full calendar year (e.g. `2024`), no padding. |
10
+ * | `month` | 1–12, zero-padded to 2 digits (e.g. `02`). |
11
+ * | `week` | Week-of-year from `parseWeekFromDate`, 1–53. |
12
+ * | `day` | Day of month 1–31, zero-padded (e.g. `15`). |
13
+ * | `dayOfWeek` | 1 (Mon)–7 (Sun). |
14
+ * | `hour` | 0–23, zero-padded. |
15
+ * | `minute` | 0–59, zero-padded. |
16
+ * | `second` | 0–59, zero-padded. |
17
+ * | `millisecond` | 0–999, zero-padded to 3. |
18
+ * | `microsecond` | Sub-millisecond microseconds (0–999999). |
19
+ * | `nanosecond` | Sub-millisecond nanoseconds (0–999999999). |
20
+ *
21
+ * @example
22
+ * import { ZonedNowUnit } from "@northguild/gmt/zoned";
23
+ * const u: ZonedNowUnit = "hour";
24
+ */
1
25
  export type ZonedNowUnit = "year" | "month" | "week" | "day" | "dayOfWeek" | "hour" | "minute" | "second" | "millisecond" | "microsecond" | "nanosecond";
2
26
  /**
3
27
  * Return the requested current unit value for the specified IANA timeZone.
@@ -2,8 +2,8 @@
2
2
  * Return the portion(s) of interval A not covered by interval B.
3
3
  *
4
4
  * - Uses `Temporal.Instant.compare` for comparison (via `.toInstant()`).
5
- * - Returns `[]` when B fully covers A.
6
- * - Returns `[{ start, end }]` when B overlaps one edge of A (or equals A).
5
+ * - Returns `[]` when B fully covers A (this includes B being identical to A).
6
+ * - Returns `[{ start, end }]` when B overlaps exactly one edge of A.
7
7
  * - Returns `[{ start, end }, { start, end }]` when B is fully inside A with gaps on both sides.
8
8
  * - Returns `[]` if either interval is invalid (`start > end`).
9
9
  * - Returns `[]` on invalid input (wrong type, malformed strings, leap seconds).
@@ -28,7 +28,7 @@
28
28
  * @param bEnd ISO 8601 zoned datetime string for the second interval end
29
29
  * @returns array of `{ start, end }` records representing A minus B, or `[]` on invalid input
30
30
  *
31
- * @example intervalDifferenceZoned("2024-01-01T09:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]", "2024-06-01T12:00:00+00:00[UTC]", "2024-07-01T13:00:00+00:00[UTC]") // [{ start: "2024-01-01T09:00:00+00:00[UTC]", end: "2024-05-31T17:00:00+00:00[UTC]" }, { start: "2024-07-01T13:00:01+00:00[UTC]", end: "2024-12-31T17:00:00+00:00[UTC]" }]
31
+ * @example intervalDifferenceZoned("2024-01-01T09:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]", "2024-06-01T12:00:00+00:00[UTC]", "2024-07-01T13:00:00+00:00[UTC]") // [{ start: "2024-01-01T09:00:00+00:00[UTC]", end: "2024-06-01T11:59:59.999999999+00:00[UTC]" }, { start: "2024-07-01T13:00:00.000000001+00:00[UTC]", end: "2024-12-31T17:00:00+00:00[UTC]" }]
32
32
  * @example intervalDifferenceZoned("2024-01-01T09:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]", "2024-01-01T09:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]") // []
33
33
  * @example intervalDifferenceZoned("invalid", "2024-12-31T17:00:00+00:00[UTC]", "2024-06-01T12:00:00+00:00[UTC]", "2024-07-01T13:00:00+00:00[UTC]") // []
34
34
  */
@@ -5,8 +5,8 @@ import { isValidCalendarZonedDateTime } from "../validate/index.js";
5
5
  * Return the portion(s) of interval A not covered by interval B.
6
6
  *
7
7
  * - Uses `Temporal.Instant.compare` for comparison (via `.toInstant()`).
8
- * - Returns `[]` when B fully covers A.
9
- * - Returns `[{ start, end }]` when B overlaps one edge of A (or equals A).
8
+ * - Returns `[]` when B fully covers A (this includes B being identical to A).
9
+ * - Returns `[{ start, end }]` when B overlaps exactly one edge of A.
10
10
  * - Returns `[{ start, end }, { start, end }]` when B is fully inside A with gaps on both sides.
11
11
  * - Returns `[]` if either interval is invalid (`start > end`).
12
12
  * - Returns `[]` on invalid input (wrong type, malformed strings, leap seconds).
@@ -31,7 +31,7 @@ import { isValidCalendarZonedDateTime } from "../validate/index.js";
31
31
  * @param bEnd ISO 8601 zoned datetime string for the second interval end
32
32
  * @returns array of `{ start, end }` records representing A minus B, or `[]` on invalid input
33
33
  *
34
- * @example intervalDifferenceZoned("2024-01-01T09:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]", "2024-06-01T12:00:00+00:00[UTC]", "2024-07-01T13:00:00+00:00[UTC]") // [{ start: "2024-01-01T09:00:00+00:00[UTC]", end: "2024-05-31T17:00:00+00:00[UTC]" }, { start: "2024-07-01T13:00:01+00:00[UTC]", end: "2024-12-31T17:00:00+00:00[UTC]" }]
34
+ * @example intervalDifferenceZoned("2024-01-01T09:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]", "2024-06-01T12:00:00+00:00[UTC]", "2024-07-01T13:00:00+00:00[UTC]") // [{ start: "2024-01-01T09:00:00+00:00[UTC]", end: "2024-06-01T11:59:59.999999999+00:00[UTC]" }, { start: "2024-07-01T13:00:00.000000001+00:00[UTC]", end: "2024-12-31T17:00:00+00:00[UTC]" }]
35
35
  * @example intervalDifferenceZoned("2024-01-01T09:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]", "2024-01-01T09:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]") // []
36
36
  * @example intervalDifferenceZoned("invalid", "2024-12-31T17:00:00+00:00[UTC]", "2024-06-01T12:00:00+00:00[UTC]", "2024-07-01T13:00:00+00:00[UTC]") // []
37
37
  */
@@ -3,8 +3,10 @@
3
3
  *
4
4
  * - Uses `Temporal.Instant.compare` for comparison (via `.toInstant()`).
5
5
  * - Returns `[]` when intervals are identical or both invalid.
6
- * - Returns `[{ start, end }]` when one interval fully contains the other.
7
- * - Returns `[{ start, end }, { start, end }]` when intervals partially overlap.
6
+ * - Returns `[{ start, end }]` when the intervals share exactly one boundary — one starts (or
7
+ * ends) precisely where the other ends (or starts), so only one remainder piece exists.
8
+ * - Returns `[{ start, end }, { start, end }]` when intervals partially overlap, and also when
9
+ * one interval strictly contains the other (the piece before B and the piece after B).
8
10
  * - Returns `[]` if either interval is invalid (`start > end`).
9
11
  * - Returns `[]` on invalid input (wrong type, malformed strings, leap seconds).
10
12
  * - Accepts GMT calendar-annotated zoned strings (as produced by `convertZonedToCalendar`) as
@@ -28,8 +30,8 @@
28
30
  * @param bEnd ISO 8601 zoned datetime string for the second interval end
29
31
  * @returns array of `{ start, end }` records representing the symmetric difference, or `[]` on invalid input
30
32
  *
31
- * @example intervalXorZoned("2024-01-01T09:00:00+00:00[UTC]", "2024-06-30T12:00:00+00:00[UTC]", "2024-04-01T11:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]") // [{ start: "2024-01-01T09:00:00+00:00[UTC]", end: "2024-03-31T17:00:00+00:00[UTC]" }, { start: "2024-06-30T12:00:01+00:00[UTC]", end: "2024-12-31T17:00:00+00:00[UTC]" }]
32
- * @example intervalXorZoned("2024-01-01T09:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]", "2024-04-01T11:00:00+00:00[UTC]", "2024-06-30T12:00:00+00:00[UTC]") // [{ start: "2024-01-01T09:00:00+00:00[UTC]", end: "2024-03-31T17:00:00+00:00[UTC]" }, { start: "2024-06-30T12:00:01+00:00[UTC]", end: "2024-12-31T17:00:00+00:00[UTC]" }]
33
+ * @example intervalXorZoned("2024-01-01T09:00:00+00:00[UTC]", "2024-06-30T12:00:00+00:00[UTC]", "2024-04-01T11:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]") // partial overlap — [{ start: "2024-01-01T09:00:00+00:00[UTC]", end: "2024-04-01T10:59:59.999999999+00:00[UTC]" }, { start: "2024-06-30T12:00:00.000000001+00:00[UTC]", end: "2024-12-31T17:00:00+00:00[UTC]" }]
34
+ * @example intervalXorZoned("2024-01-01T09:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]", "2024-02-01T08:00:00+00:00[UTC]", "2024-03-01T10:00:00+00:00[UTC]") // B strictly inside A — two remainder pieces — [{ start: "2024-01-01T09:00:00+00:00[UTC]", end: "2024-02-01T07:59:59.999999999+00:00[UTC]" }, { start: "2024-03-01T10:00:00.000000001+00:00[UTC]", end: "2024-12-31T17:00:00+00:00[UTC]" }]
33
35
  * @example intervalXorZoned("2024-01-01T09:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]", "2024-01-01T09:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]") // []
34
36
  * @example intervalXorZoned("invalid", "2024-06-30T12:00:00+00:00[UTC]", "2024-07-01T13:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]") // []
35
37
  */
@@ -6,8 +6,10 @@ import { isValidCalendarZonedDateTime } from "../validate/index.js";
6
6
  *
7
7
  * - Uses `Temporal.Instant.compare` for comparison (via `.toInstant()`).
8
8
  * - Returns `[]` when intervals are identical or both invalid.
9
- * - Returns `[{ start, end }]` when one interval fully contains the other.
10
- * - Returns `[{ start, end }, { start, end }]` when intervals partially overlap.
9
+ * - Returns `[{ start, end }]` when the intervals share exactly one boundary — one starts (or
10
+ * ends) precisely where the other ends (or starts), so only one remainder piece exists.
11
+ * - Returns `[{ start, end }, { start, end }]` when intervals partially overlap, and also when
12
+ * one interval strictly contains the other (the piece before B and the piece after B).
11
13
  * - Returns `[]` if either interval is invalid (`start > end`).
12
14
  * - Returns `[]` on invalid input (wrong type, malformed strings, leap seconds).
13
15
  * - Accepts GMT calendar-annotated zoned strings (as produced by `convertZonedToCalendar`) as
@@ -31,8 +33,8 @@ import { isValidCalendarZonedDateTime } from "../validate/index.js";
31
33
  * @param bEnd ISO 8601 zoned datetime string for the second interval end
32
34
  * @returns array of `{ start, end }` records representing the symmetric difference, or `[]` on invalid input
33
35
  *
34
- * @example intervalXorZoned("2024-01-01T09:00:00+00:00[UTC]", "2024-06-30T12:00:00+00:00[UTC]", "2024-04-01T11:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]") // [{ start: "2024-01-01T09:00:00+00:00[UTC]", end: "2024-03-31T17:00:00+00:00[UTC]" }, { start: "2024-06-30T12:00:01+00:00[UTC]", end: "2024-12-31T17:00:00+00:00[UTC]" }]
35
- * @example intervalXorZoned("2024-01-01T09:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]", "2024-04-01T11:00:00+00:00[UTC]", "2024-06-30T12:00:00+00:00[UTC]") // [{ start: "2024-01-01T09:00:00+00:00[UTC]", end: "2024-03-31T17:00:00+00:00[UTC]" }, { start: "2024-06-30T12:00:01+00:00[UTC]", end: "2024-12-31T17:00:00+00:00[UTC]" }]
36
+ * @example intervalXorZoned("2024-01-01T09:00:00+00:00[UTC]", "2024-06-30T12:00:00+00:00[UTC]", "2024-04-01T11:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]") // partial overlap — [{ start: "2024-01-01T09:00:00+00:00[UTC]", end: "2024-04-01T10:59:59.999999999+00:00[UTC]" }, { start: "2024-06-30T12:00:00.000000001+00:00[UTC]", end: "2024-12-31T17:00:00+00:00[UTC]" }]
37
+ * @example intervalXorZoned("2024-01-01T09:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]", "2024-02-01T08:00:00+00:00[UTC]", "2024-03-01T10:00:00+00:00[UTC]") // B strictly inside A — two remainder pieces — [{ start: "2024-01-01T09:00:00+00:00[UTC]", end: "2024-02-01T07:59:59.999999999+00:00[UTC]" }, { start: "2024-03-01T10:00:00.000000001+00:00[UTC]", end: "2024-12-31T17:00:00+00:00[UTC]" }]
36
38
  * @example intervalXorZoned("2024-01-01T09:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]", "2024-01-01T09:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]") // []
37
39
  * @example intervalXorZoned("invalid", "2024-06-30T12:00:00+00:00[UTC]", "2024-07-01T13:00:00+00:00[UTC]", "2024-12-31T17:00:00+00:00[UTC]") // []
38
40
  */
@@ -1,5 +1,16 @@
1
1
  /**
2
2
  * Unit a zoned value's UTC offset can be read as via `getZonedOffsetAs`.
3
+ *
4
+ * @remarks Members:
5
+ *
6
+ * | Member | Description |
7
+ * | --- | --- |
8
+ * | `minutes` | Whole-minute offset (e.g. `-240` for `-04:00`). |
9
+ * | `nanoseconds` | Raw `offsetNanoseconds` from Temporal (e.g. `-14400000000000`). |
10
+ *
11
+ * @example
12
+ * import { getZonedOffsetAs } from "@northguild/gmt/zoned";
13
+ * getZonedOffsetAs("2024-07-15T12:00:00-04:00[America/New_York]", "minutes");
3
14
  */
4
15
  export type ZonedOffsetUnit = "minutes" | "nanoseconds";
5
16
  /**
@@ -1,3 +1,27 @@
1
+ /**
2
+ * Units supported by `parseUnitFromZoned` when extracting a value from a zoned
3
+ * ISO string. Includes `timeZone` for reading the zone identifier.
4
+ *
5
+ * @remarks Members:
6
+ *
7
+ * | Member | Description |
8
+ * | --- | --- |
9
+ * | `year` | Full year, no padding (e.g. `2024`). |
10
+ * | `month` | Zero-padded 2 (e.g. `03`). |
11
+ * | `week` | Week-of-year, 1–53 (`weekStartsOn`-controlled). |
12
+ * | `day` | Zero-padded 2. |
13
+ * | `dayOfWeek` | 1 (Mon)–7 (Sun). |
14
+ * | `hour` | Zero-padded 2. |
15
+ * | `minute` | Zero-padded 2. |
16
+ * | `second` | Zero-padded 2. |
17
+ * | `millisecond` | Zero-padded 3. |
18
+ * | `nanosecond` | Zero-padded 3. |
19
+ * | `timeZone` | IANA timeZone identifier string. |
20
+ *
21
+ * @example
22
+ * import { ZonedParseUnit } from "@northguild/gmt/zoned";
23
+ * const u: ZonedParseUnit = "month";
24
+ */
1
25
  export type ZonedParseUnit = "year" | "month" | "week" | "day" | "dayOfWeek" | "hour" | "minute" | "second" | "millisecond" | "nanosecond" | "timeZone";
2
26
  /**
3
27
  * Return the requested unit value from an ISO 8601 zoned datetime string.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@northguild/gmt",
3
- "version": "1.14.2",
3
+ "version": "1.15.0",
4
4
  "description": "Temporal-based date and time utilities with timezone support and polyfill integration",
5
5
  "keywords": [
6
6
  "date",
@@ -11,7 +11,7 @@
11
11
  "time",
12
12
  "timezone"
13
13
  ],
14
- "homepage": "https://github.com/northguild/gmt#readme",
14
+ "homepage": "https://gmt-dox.northguild.workers.dev",
15
15
  "bugs": {
16
16
  "url": "https://github.com/northguild/gmt/issues"
17
17
  },
@@ -34,7 +34,11 @@
34
34
  "files": [
35
35
  "dist",
36
36
  "LICENSE",
37
- "skills"
37
+ "README.md",
38
+ "skills/gmt-basics",
39
+ "skills/gmt-arithmetic",
40
+ "skills/gmt-timezone",
41
+ "skills/gmt-integration"
38
42
  ],
39
43
  "type": "module",
40
44
  "main": "./dist/index.js",
@@ -67,8 +71,13 @@
67
71
  "default": "./dist/regex/index.js"
68
72
  },
69
73
  "./regex/*": {
70
- "types": "./dist/regex/*.d.ts",
71
- "default": "./dist/regex/*.js"
74
+ "types": "./dist/regex/*/index.d.ts",
75
+ "default": "./dist/regex/*/index.js"
76
+ },
77
+ "./regex/*/*": null,
78
+ "./types": {
79
+ "types": "./dist/types/index.d.ts",
80
+ "default": "./dist/types/index.js"
72
81
  },
73
82
  "./unix": {
74
83
  "types": "./dist/unix/index.d.ts",
@@ -87,7 +96,16 @@
87
96
  "types": "./dist/utc/*/index.d.ts",
88
97
  "default": "./dist/utc/*/index.js"
89
98
  },
90
- "./utc/*/*": null
99
+ "./utc/*/*": null,
100
+ "./duration": {
101
+ "types": "./dist/duration/index.d.ts",
102
+ "default": "./dist/duration/index.js"
103
+ },
104
+ "./duration/*": {
105
+ "types": "./dist/duration/*/index.d.ts",
106
+ "default": "./dist/duration/*/index.js"
107
+ },
108
+ "./duration/*/*": null
91
109
  },
92
110
  "publishConfig": {
93
111
  "access": "public",
@@ -97,7 +115,7 @@
97
115
  "@js-temporal/polyfill": "^0.5.1"
98
116
  },
99
117
  "devDependencies": {
100
- "@tanstack/intent": "^0.3.6",
118
+ "@tanstack/intent": "^0.3.8",
101
119
  "oxfmt": "^0.62.0",
102
120
  "oxlint": "^1.0.0",
103
121
  "@northguild/gmt-oxlint": "1.1.5"
@@ -0,0 +1,83 @@
1
+ ---
2
+ name: gmt-arithmetic
3
+ description: >
4
+ Date arithmetic — add/subtract duration objects, diff values, clamp/closest,
5
+ ISO 8601 duration strings, and interval range math (contain, overlap, union,
6
+ split, count boundaries). Reads the installed package README.md and source
7
+ JSDoc for API details; this skill is a routing pointer, not an API dump.
8
+ sources:
9
+ - 'northguild/gmt:README.md'
10
+ - 'northguild/gmt:packages/gmt/src/plain/calculate/index.ts'
11
+ - 'northguild/gmt:packages/gmt/src/duration/index.ts'
12
+ - 'northguild/gmt:packages/gmt/src/plain/interval/index.ts'
13
+ - 'northguild/gmt:packages/gmt/src/zoned/interval/index.ts'
14
+ - 'northguild/gmt:packages/gmt/src/unix/interval/index.ts'
15
+ - 'northguild/gmt:packages/gmt/src/utc/interval/index.ts'
16
+ metadata:
17
+ type: core
18
+ library: '@northguild/gmt'
19
+ library_version: '1.15.0'
20
+ ---
21
+
22
+ # GMT Arithmetic
23
+
24
+ Use this skill when the task involves adding, subtracting, diffing, clamping,
25
+ or doing range math over date/time values — including ISO 8601 duration strings
26
+ and full interval set operations.
27
+
28
+ ## When to load
29
+
30
+ - The user wants to move a date forward/backward by a quantity.
31
+ - The user needs the difference between two dates as a number or a duration
32
+ string.
33
+ - The user wants to restrict a value to a min/max range, or find the nearest
34
+ candidate.
35
+ - The user needs range math: "do these overlap?", "merge these", "split this
36
+ into n parts".
37
+
38
+ ## Core rules
39
+
40
+ 1. **`add*` takes a `{ unit: number }` object, not an ISO duration string.**
41
+ `addDate("2024-03-15", { days: 5 })` works; `addDate("2024-03-15", "P5D")`
42
+ returns `""`. Use `diffDateAsDuration` / `addDuration` for duration strings.
43
+ 2. **`overflow`** defaults to `"constrain"` (clamps to a valid date). Pass
44
+ `{ overflow: "reject" }` to get the `""` sentinel instead of a clamp.
45
+ 3. **Calendar units need `relativeTo`.** `durationAs`, `normalizeDuration`, and
46
+ `compareDurations` return `null`/`""` for year/month/week arithmetic without
47
+ a `relativeTo` anchor — a month is not a fixed length.
48
+ 4. **Read the README.** This skill is a routing pointer. For full option shapes,
49
+ locale matrices, and code examples, read the installed package's `README.md`
50
+ and the source JSDoc of the function you intend to call.
51
+
52
+ ## Key functions
53
+
54
+ - **Point arithmetic**: `addDate`, `addDateTime`, `addTime`, `subtractTime`,
55
+ `addBusinessDays`, `subtractBusinessDays`, `cycleDate`, `setDate`
56
+ - **Diffs**: `diffDate`, `diffDateTime`, `diffTime` (+ `diffZoned`,
57
+ `diffUnix`, `diffUtc` in their namespaces)
58
+ - **Bounds**: `clampDate`, `closestDateTo`, `startOfDate`, `endOfDate`,
59
+ `startOfQuarterForDate`, `getLocaleStartOfWeek`
60
+ - **Durations (ISO 8601)**: `isValidDuration`, `parseDuration`, `addDuration`,
61
+ `subtractDuration`, `normalizeDuration`, `durationAs`, `formatDuration`,
62
+ `negateDuration`, `absDuration`, `compareDurations`, `getDurationUnit`,
63
+ `getDurationSign`
64
+ - **Diff-to-duration bridge**: `diffDateAsDuration`,
65
+ `diffZonedAsDuration`, `diffUnixAsDuration`, `diffUtcAsDuration`
66
+ - **Intervals (range math)**: `isValidDateInterval`, `intervalContainsDate`,
67
+ `intervalsOverlapDate`, `intervalIntersectionDate`, `intervalUnionDate`,
68
+ `intervalDifferenceDate`, `intervalXorDate`, `intervalFromDurationDate`,
69
+ `splitIntervalByUnitDate`, `intervalCountDate`, `intervalLengthDate`,
70
+ `intervalDivideEquallyDate`, `mergeIntervalsDate`
71
+
72
+ ## Namespace selection
73
+
74
+ - `plain/*` — timezone-free dates, times, datetimes
75
+ - `zoned/*` — IANA-timezone-aware (see `gmt-timezone` skill for disambiguation)
76
+ - `unix/*` — epoch seconds/milliseconds
77
+ - `utc/*` — UTC instants (`"2024-03-15T14:30:45Z"`)
78
+ - `duration/*` — ISO 8601 duration strings
79
+
80
+ ## References
81
+
82
+ - [README — Quick Start](README.md)
83
+ - [Interval function reference](/reference/plain)