@gobrand/tiempo 2.5.4 → 2.6.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 (43) hide show
  1. package/dist/chunk-HFQUXON5.js +41 -0
  2. package/dist/chunk-HFQUXON5.js.map +1 -0
  3. package/dist/chunk-JHRXY36W.js +25 -0
  4. package/dist/chunk-JHRXY36W.js.map +1 -0
  5. package/dist/chunk-MMI2HHT7.js +25 -0
  6. package/dist/chunk-MMI2HHT7.js.map +1 -0
  7. package/dist/chunk-UJW2FPI4.js +25 -0
  8. package/dist/chunk-UJW2FPI4.js.map +1 -0
  9. package/dist/chunk-UJWM2BV2.js +41 -0
  10. package/dist/chunk-UJWM2BV2.js.map +1 -0
  11. package/dist/index.d.ts +3 -0
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +36 -24
  14. package/dist/roundToNearestHour.d.ts +77 -0
  15. package/dist/roundToNearestHour.d.ts.map +1 -0
  16. package/dist/roundToNearestHour.js +8 -0
  17. package/dist/roundToNearestHour.js.map +1 -0
  18. package/dist/roundToNearestHour.test.d.ts +2 -0
  19. package/dist/roundToNearestHour.test.d.ts.map +1 -0
  20. package/dist/roundToNearestMinute.d.ts +76 -0
  21. package/dist/roundToNearestMinute.d.ts.map +1 -0
  22. package/dist/roundToNearestMinute.js +8 -0
  23. package/dist/roundToNearestMinute.js.map +1 -0
  24. package/dist/roundToNearestMinute.test.d.ts +2 -0
  25. package/dist/roundToNearestMinute.test.d.ts.map +1 -0
  26. package/dist/roundToNearestSecond.d.ts +75 -0
  27. package/dist/roundToNearestSecond.d.ts.map +1 -0
  28. package/dist/roundToNearestSecond.js +8 -0
  29. package/dist/roundToNearestSecond.js.map +1 -0
  30. package/dist/roundToNearestSecond.test.d.ts +2 -0
  31. package/dist/roundToNearestSecond.test.d.ts.map +1 -0
  32. package/dist/toPlainDate.d.ts +14 -7
  33. package/dist/toPlainDate.d.ts.map +1 -1
  34. package/dist/toPlainDate.js +1 -1
  35. package/dist/toPlainTime.d.ts +15 -7
  36. package/dist/toPlainTime.d.ts.map +1 -1
  37. package/dist/toPlainTime.js +1 -1
  38. package/dist/types.d.ts.map +1 -1
  39. package/package.json +1 -1
  40. package/dist/chunk-G45S5B4O.js +0 -25
  41. package/dist/chunk-G45S5B4O.js.map +0 -1
  42. package/dist/chunk-UCCWUJ2K.js +0 -25
  43. package/dist/chunk-UCCWUJ2K.js.map +0 -1
@@ -0,0 +1,41 @@
1
+ // src/toPlainDate.ts
2
+ import { Temporal } from "@js-temporal/polyfill";
3
+ var PLAIN_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
4
+ function toPlainDate(input, timezone) {
5
+ if (input instanceof Temporal.ZonedDateTime && timezone === void 0) {
6
+ return input.toPlainDate();
7
+ }
8
+ if (input instanceof Date) {
9
+ if (timezone === void 0) {
10
+ throw new Error("Timezone is required unless input is a ZonedDateTime, PlainDateLike, or plain date string");
11
+ }
12
+ return Temporal.Instant.from(input.toISOString()).toZonedDateTimeISO(timezone).toPlainDate();
13
+ }
14
+ if (input instanceof Temporal.Instant) {
15
+ if (timezone === void 0) {
16
+ throw new Error("Timezone is required unless input is a ZonedDateTime, PlainDateLike, or plain date string");
17
+ }
18
+ return input.toZonedDateTimeISO(timezone).toPlainDate();
19
+ }
20
+ if (input instanceof Temporal.ZonedDateTime) {
21
+ if (timezone === void 0) {
22
+ throw new Error("Timezone is required unless input is a ZonedDateTime, PlainDateLike, or plain date string");
23
+ }
24
+ return input.toInstant().toZonedDateTimeISO(timezone).toPlainDate();
25
+ }
26
+ if (typeof input === "string") {
27
+ if (timezone !== void 0) {
28
+ return Temporal.Instant.from(input).toZonedDateTimeISO(timezone).toPlainDate();
29
+ }
30
+ if (PLAIN_DATE_PATTERN.test(input)) {
31
+ return Temporal.PlainDate.from(input);
32
+ }
33
+ throw new Error("Timezone is required unless input is a ZonedDateTime, PlainDateLike, or plain date string");
34
+ }
35
+ return Temporal.PlainDate.from(input);
36
+ }
37
+
38
+ export {
39
+ toPlainDate
40
+ };
41
+ //# sourceMappingURL=chunk-HFQUXON5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/toPlainDate.ts"],"sourcesContent":["import { Temporal } from '@js-temporal/polyfill';\nimport type { Timezone } from './types';\n\n// Pattern to detect plain date strings: YYYY-MM-DD\nconst PLAIN_DATE_PATTERN = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/**\n * Parse a plain date or extract the calendar date from a datetime.\n *\n * @param input - A PlainDateLike object, plain date string (YYYY-MM-DD), ZonedDateTime, or datetime input requiring timezone\n * @param timezone - IANA timezone identifier. Required for ISO strings, Date, and Instant inputs.\n * @returns A Temporal.PlainDate representing the calendar date\n *\n * @example\n * ```typescript\n * import { toPlainDate, toZonedTime } from '@gobrand/tiempo';\n *\n * // From PlainDateLike object (no timezone needed)\n * const date = toPlainDate({ year: 2025, month: 1, day: 20 }); // 2025-01-20\n *\n * // From plain date string (no timezone needed)\n * const date2 = toPlainDate(\"2025-01-20\"); // 2025-01-20\n *\n * // From ZonedDateTime (no timezone needed)\n * const zdt = toZonedTime(\"2025-01-20T15:30:00Z\", \"America/New_York\");\n * const date3 = toPlainDate(zdt); // 2025-01-20\n *\n * // From UTC string with timezone\n * const date4 = toPlainDate(\"2025-01-20T15:30:00Z\", \"America/New_York\"); // 2025-01-20\n *\n * // From Date with timezone\n * const jsDate = new Date(\"2025-01-20T15:30:00.000Z\");\n * const date5 = toPlainDate(jsDate, \"Europe/London\"); // 2025-01-20\n *\n * // Date boundary crossing: 23:00 UTC on Jan 20 → Jan 21 in Tokyo\n * const date6 = toPlainDate(\"2025-01-20T23:00:00Z\", \"Asia/Tokyo\"); // 2025-01-21\n * ```\n */\nexport function toPlainDate(input: Temporal.ZonedDateTime): Temporal.PlainDate;\nexport function toPlainDate(\n input: string | Date | Temporal.Instant | Temporal.ZonedDateTime,\n timezone: Timezone\n): Temporal.PlainDate;\nexport function toPlainDate(input: Temporal.PlainDateLike | string): Temporal.PlainDate;\nexport function toPlainDate(\n input: string | Date | Temporal.Instant | Temporal.ZonedDateTime | Temporal.PlainDateLike,\n timezone?: Timezone\n): Temporal.PlainDate {\n // ZonedDateTime without timezone override\n if (input instanceof Temporal.ZonedDateTime && timezone === undefined) {\n return input.toPlainDate();\n }\n\n // Date requires timezone\n if (input instanceof Date) {\n if (timezone === undefined) {\n throw new Error('Timezone is required unless input is a ZonedDateTime, PlainDateLike, or plain date string');\n }\n return Temporal.Instant.from(input.toISOString()).toZonedDateTimeISO(timezone).toPlainDate();\n }\n\n // Instant requires timezone\n if (input instanceof Temporal.Instant) {\n if (timezone === undefined) {\n throw new Error('Timezone is required unless input is a ZonedDateTime, PlainDateLike, or plain date string');\n }\n return input.toZonedDateTimeISO(timezone).toPlainDate();\n }\n\n // ZonedDateTime with timezone override\n if (input instanceof Temporal.ZonedDateTime) {\n if (timezone === undefined) {\n throw new Error('Timezone is required unless input is a ZonedDateTime, PlainDateLike, or plain date string');\n }\n return input.toInstant().toZonedDateTimeISO(timezone).toPlainDate();\n }\n\n // String: ISO datetime (requires timezone) or plain date (no timezone)\n if (typeof input === 'string') {\n if (timezone !== undefined) {\n return Temporal.Instant.from(input).toZonedDateTimeISO(timezone).toPlainDate();\n }\n if (PLAIN_DATE_PATTERN.test(input)) {\n return Temporal.PlainDate.from(input);\n }\n throw new Error('Timezone is required unless input is a ZonedDateTime, PlainDateLike, or plain date string');\n }\n\n // PlainDateLike object - pass directly to Temporal.PlainDate.from()\n return Temporal.PlainDate.from(input);\n}\n"],"mappings":";AAAA,SAAS,gBAAgB;AAIzB,IAAM,qBAAqB;AAwCpB,SAAS,YACd,OACA,UACoB;AAEpB,MAAI,iBAAiB,SAAS,iBAAiB,aAAa,QAAW;AACrE,WAAO,MAAM,YAAY;AAAA,EAC3B;AAGA,MAAI,iBAAiB,MAAM;AACzB,QAAI,aAAa,QAAW;AAC1B,YAAM,IAAI,MAAM,2FAA2F;AAAA,IAC7G;AACA,WAAO,SAAS,QAAQ,KAAK,MAAM,YAAY,CAAC,EAAE,mBAAmB,QAAQ,EAAE,YAAY;AAAA,EAC7F;AAGA,MAAI,iBAAiB,SAAS,SAAS;AACrC,QAAI,aAAa,QAAW;AAC1B,YAAM,IAAI,MAAM,2FAA2F;AAAA,IAC7G;AACA,WAAO,MAAM,mBAAmB,QAAQ,EAAE,YAAY;AAAA,EACxD;AAGA,MAAI,iBAAiB,SAAS,eAAe;AAC3C,QAAI,aAAa,QAAW;AAC1B,YAAM,IAAI,MAAM,2FAA2F;AAAA,IAC7G;AACA,WAAO,MAAM,UAAU,EAAE,mBAAmB,QAAQ,EAAE,YAAY;AAAA,EACpE;AAGA,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,aAAa,QAAW;AAC1B,aAAO,SAAS,QAAQ,KAAK,KAAK,EAAE,mBAAmB,QAAQ,EAAE,YAAY;AAAA,IAC/E;AACA,QAAI,mBAAmB,KAAK,KAAK,GAAG;AAClC,aAAO,SAAS,UAAU,KAAK,KAAK;AAAA,IACtC;AACA,UAAM,IAAI,MAAM,2FAA2F;AAAA,EAC7G;AAGA,SAAO,SAAS,UAAU,KAAK,KAAK;AACtC;","names":[]}
@@ -0,0 +1,25 @@
1
+ import {
2
+ normalizeTemporalInput
3
+ } from "./chunk-MJSZNWCV.js";
4
+
5
+ // src/roundToNearestSecond.ts
6
+ var MODE_TO_ROUNDING_MODE = {
7
+ round: "halfExpand",
8
+ ceil: "ceil",
9
+ floor: "floor"
10
+ };
11
+ function roundToNearestSecond(input, options) {
12
+ const zonedDateTime = normalizeTemporalInput(input);
13
+ const mode = options?.mode ?? "round";
14
+ const nearestTo = options?.nearestTo ?? 1;
15
+ return zonedDateTime.round({
16
+ smallestUnit: "second",
17
+ roundingMode: MODE_TO_ROUNDING_MODE[mode],
18
+ roundingIncrement: nearestTo
19
+ });
20
+ }
21
+
22
+ export {
23
+ roundToNearestSecond
24
+ };
25
+ //# sourceMappingURL=chunk-JHRXY36W.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/roundToNearestSecond.ts"],"sourcesContent":["import type { Temporal } from '@js-temporal/polyfill';\nimport { normalizeTemporalInput } from './shared/normalizeTemporalInput';\n\n/**\n * Options for rounding to nearest second.\n */\nexport interface RoundToNearestSecondOptions {\n /**\n * The rounding mode to use.\n *\n * Given time 14:37:42.300:\n * - `'round'` → 14:37:42 (300ms < 500, rounds DOWN to nearest)\n * - `'ceil'` → 14:37:43 (always rounds UP to next second)\n * - `'floor'` → 14:37:42 (always rounds DOWN to current second)\n *\n * Given time 14:37:42 with nearestTo: 10:\n * - `'round'` → 14:37:40 (42 is closer to 40 than 50)\n * - `'ceil'` → 14:37:50 (always rounds UP to next 10-sec mark)\n * - `'floor'` → 14:37:40 (always rounds DOWN to current 10-sec mark)\n *\n * @default 'round'\n */\n mode?: 'round' | 'ceil' | 'floor';\n /**\n * Round to the nearest N seconds. Must divide evenly into 60.\n * Valid values: 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30\n * @example nearestTo: 10 rounds to 10-second marks (00, 10, 20, 30, 40, 50)\n */\n nearestTo?: 1 | 2 | 3 | 4 | 5 | 6 | 10 | 12 | 15 | 20 | 30;\n}\n\nconst MODE_TO_ROUNDING_MODE = {\n round: 'halfExpand',\n ceil: 'ceil',\n floor: 'floor',\n} as const;\n\n/**\n * Rounds a datetime to the nearest second boundary.\n *\n * ## Mode comparison (given 14:37:42.567)\n *\n * ```\n * :42 ─────────────────●─────────────── :43\n * .567\n *\n * 'round' → :43 (nearest second - 567ms >= 500)\n * 'ceil' → :43 (next second - always up)\n * 'floor' → :42 (current second - always down)\n * ```\n *\n * @param input - A Temporal.Instant (UTC) or Temporal.ZonedDateTime\n * @param options - Rounding options\n * @returns ZonedDateTime rounded to the second boundary\n *\n * @example\n * ```ts\n * const time = Temporal.ZonedDateTime.from('2025-01-20T14:37:42.567[America/New_York]');\n *\n * roundToNearestSecond(time); // → 14:37:43 (567ms >= 500)\n * roundToNearestSecond(time, { mode: 'ceil' }); // → 14:37:43 (always up)\n * roundToNearestSecond(time, { mode: 'floor' }); // → 14:37:42 (always down)\n * ```\n *\n * @example\n * ```ts\n * // 10-second intervals\n * const time = Temporal.ZonedDateTime.from('2025-01-20T14:37:42[America/New_York]');\n *\n * roundToNearestSecond(time, { nearestTo: 10 }); // → 14:37:40 (nearest)\n * roundToNearestSecond(time, { mode: 'ceil', nearestTo: 10 }); // → 14:37:50 (next 10s)\n * roundToNearestSecond(time, { mode: 'floor', nearestTo: 10 }); // → 14:37:40 (current 10s)\n * ```\n *\n * @example\n * ```ts\n * // Remove sub-second precision for logging\n * const logTime = Temporal.ZonedDateTime.from('2025-01-20T14:37:42.123456789[UTC]');\n * roundToNearestSecond(logTime, { mode: 'floor' });\n * // → 14:37:42.000000000 (clean timestamp)\n * ```\n */\nexport function roundToNearestSecond(\n input: Temporal.Instant | Temporal.ZonedDateTime,\n options?: RoundToNearestSecondOptions\n): Temporal.ZonedDateTime {\n const zonedDateTime = normalizeTemporalInput(input);\n const mode = options?.mode ?? 'round';\n const nearestTo = options?.nearestTo ?? 1;\n\n return zonedDateTime.round({\n smallestUnit: 'second',\n roundingMode: MODE_TO_ROUNDING_MODE[mode],\n roundingIncrement: nearestTo,\n });\n}\n"],"mappings":";;;;;AA+BA,IAAM,wBAAwB;AAAA,EAC5B,OAAO;AAAA,EACP,MAAM;AAAA,EACN,OAAO;AACT;AA+CO,SAAS,qBACd,OACA,SACwB;AACxB,QAAM,gBAAgB,uBAAuB,KAAK;AAClD,QAAM,OAAO,SAAS,QAAQ;AAC9B,QAAM,YAAY,SAAS,aAAa;AAExC,SAAO,cAAc,MAAM;AAAA,IACzB,cAAc;AAAA,IACd,cAAc,sBAAsB,IAAI;AAAA,IACxC,mBAAmB;AAAA,EACrB,CAAC;AACH;","names":[]}
@@ -0,0 +1,25 @@
1
+ import {
2
+ normalizeTemporalInput
3
+ } from "./chunk-MJSZNWCV.js";
4
+
5
+ // src/roundToNearestHour.ts
6
+ var MODE_TO_ROUNDING_MODE = {
7
+ round: "halfExpand",
8
+ ceil: "ceil",
9
+ floor: "floor"
10
+ };
11
+ function roundToNearestHour(input, options) {
12
+ const zonedDateTime = normalizeTemporalInput(input);
13
+ const mode = options?.mode ?? "round";
14
+ const nearestTo = options?.nearestTo ?? 1;
15
+ return zonedDateTime.round({
16
+ smallestUnit: "hour",
17
+ roundingMode: MODE_TO_ROUNDING_MODE[mode],
18
+ roundingIncrement: nearestTo
19
+ });
20
+ }
21
+
22
+ export {
23
+ roundToNearestHour
24
+ };
25
+ //# sourceMappingURL=chunk-MMI2HHT7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/roundToNearestHour.ts"],"sourcesContent":["import type { Temporal } from '@js-temporal/polyfill';\nimport { normalizeTemporalInput } from './shared/normalizeTemporalInput';\n\n/**\n * Options for rounding to nearest hour.\n */\nexport interface RoundToNearestHourOptions {\n /**\n * The rounding mode to use.\n *\n * Given time 14:20:\n * - `'round'` → 14:00 (20 min < 30, rounds DOWN to nearest)\n * - `'ceil'` → 15:00 (always rounds UP to next hour)\n * - `'floor'` → 14:00 (always rounds DOWN to current hour)\n *\n * Given time 14:40:\n * - `'round'` → 15:00 (40 min >= 30, rounds UP to nearest)\n * - `'ceil'` → 15:00 (always rounds UP to next hour)\n * - `'floor'` → 14:00 (always rounds DOWN to current hour)\n *\n * @default 'round'\n */\n mode?: 'round' | 'ceil' | 'floor';\n /**\n * Round to the nearest N hours. Must divide evenly into 24.\n * Valid values: 1, 2, 3, 4, 6, 8, 12\n * @example nearestTo: 6 rounds to 00:00, 06:00, 12:00, or 18:00\n */\n nearestTo?: 1 | 2 | 3 | 4 | 6 | 8 | 12;\n}\n\nconst MODE_TO_ROUNDING_MODE = {\n round: 'halfExpand',\n ceil: 'ceil',\n floor: 'floor',\n} as const;\n\n/**\n * Rounds a datetime to the nearest hour boundary.\n *\n * ## Mode comparison (given 14:20)\n *\n * ```\n * 14:00 ─────────────●───────────────── 15:00\n * 14:20\n *\n * 'round' → 14:00 (nearest hour - 20 min < 30)\n * 'ceil' → 15:00 (next hour - always up)\n * 'floor' → 14:00 (current hour - always down)\n * ```\n *\n * @param input - A Temporal.Instant (UTC) or Temporal.ZonedDateTime\n * @param options - Rounding options\n * @returns ZonedDateTime rounded to the hour boundary\n *\n * @example\n * ```ts\n * const time = Temporal.ZonedDateTime.from('2025-01-20T14:20:00[America/New_York]');\n *\n * roundToNearestHour(time); // → 14:00 (nearest)\n * roundToNearestHour(time, { mode: 'ceil' }); // → 15:00 (always up)\n * roundToNearestHour(time, { mode: 'floor' }); // → 14:00 (always down)\n * ```\n *\n * @example\n * ```ts\n * // With 37 minutes (past the halfway point)\n * const time = Temporal.ZonedDateTime.from('2025-01-20T14:37:00[America/New_York]');\n *\n * roundToNearestHour(time); // → 15:00 (nearest - 37 >= 30)\n * roundToNearestHour(time, { mode: 'ceil' }); // → 15:00 (always up)\n * roundToNearestHour(time, { mode: 'floor' }); // → 14:00 (always down)\n * ```\n *\n * @example\n * ```ts\n * // Round to 6-hour blocks (shift scheduling)\n * const time = Temporal.ZonedDateTime.from('2025-01-20T14:00:00[America/New_York]');\n *\n * roundToNearestHour(time, { nearestTo: 6 }); // → 12:00\n * roundToNearestHour(time, { mode: 'ceil', nearestTo: 6 }); // → 18:00\n * roundToNearestHour(time, { mode: 'floor', nearestTo: 6 }); // → 12:00\n * ```\n */\nexport function roundToNearestHour(\n input: Temporal.Instant | Temporal.ZonedDateTime,\n options?: RoundToNearestHourOptions\n): Temporal.ZonedDateTime {\n const zonedDateTime = normalizeTemporalInput(input);\n const mode = options?.mode ?? 'round';\n const nearestTo = options?.nearestTo ?? 1;\n\n return zonedDateTime.round({\n smallestUnit: 'hour',\n roundingMode: MODE_TO_ROUNDING_MODE[mode],\n roundingIncrement: nearestTo,\n });\n}\n"],"mappings":";;;;;AA+BA,IAAM,wBAAwB;AAAA,EAC5B,OAAO;AAAA,EACP,MAAM;AAAA,EACN,OAAO;AACT;AAiDO,SAAS,mBACd,OACA,SACwB;AACxB,QAAM,gBAAgB,uBAAuB,KAAK;AAClD,QAAM,OAAO,SAAS,QAAQ;AAC9B,QAAM,YAAY,SAAS,aAAa;AAExC,SAAO,cAAc,MAAM;AAAA,IACzB,cAAc;AAAA,IACd,cAAc,sBAAsB,IAAI;AAAA,IACxC,mBAAmB;AAAA,EACrB,CAAC;AACH;","names":[]}
@@ -0,0 +1,25 @@
1
+ import {
2
+ normalizeTemporalInput
3
+ } from "./chunk-MJSZNWCV.js";
4
+
5
+ // src/roundToNearestMinute.ts
6
+ var MODE_TO_ROUNDING_MODE = {
7
+ round: "halfExpand",
8
+ ceil: "ceil",
9
+ floor: "floor"
10
+ };
11
+ function roundToNearestMinute(input, options) {
12
+ const zonedDateTime = normalizeTemporalInput(input);
13
+ const mode = options?.mode ?? "round";
14
+ const nearestTo = options?.nearestTo ?? 1;
15
+ return zonedDateTime.round({
16
+ smallestUnit: "minute",
17
+ roundingMode: MODE_TO_ROUNDING_MODE[mode],
18
+ roundingIncrement: nearestTo
19
+ });
20
+ }
21
+
22
+ export {
23
+ roundToNearestMinute
24
+ };
25
+ //# sourceMappingURL=chunk-UJW2FPI4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/roundToNearestMinute.ts"],"sourcesContent":["import type { Temporal } from '@js-temporal/polyfill';\nimport { normalizeTemporalInput } from './shared/normalizeTemporalInput';\n\n/**\n * Options for rounding to nearest minute.\n */\nexport interface RoundToNearestMinuteOptions {\n /**\n * The rounding mode to use.\n *\n * Given time 14:37:20:\n * - `'round'` → 14:37 (20 sec < 30, rounds DOWN to nearest)\n * - `'ceil'` → 14:38 (always rounds UP to next minute)\n * - `'floor'` → 14:37 (always rounds DOWN to current minute)\n *\n * Given time 14:37:00 with nearestTo: 15:\n * - `'round'` → 14:30 (37 is closer to 30 than 45)\n * - `'ceil'` → 14:45 (always rounds UP to next 15-min slot)\n * - `'floor'` → 14:30 (always rounds DOWN to current 15-min slot)\n *\n * @default 'round'\n */\n mode?: 'round' | 'ceil' | 'floor';\n /**\n * Round to the nearest N minutes. Must divide evenly into 60.\n * Valid values: 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30\n * @example nearestTo: 15 rounds to quarter-hour marks (00, 15, 30, 45)\n */\n nearestTo?: 1 | 2 | 3 | 4 | 5 | 6 | 10 | 12 | 15 | 20 | 30;\n}\n\nconst MODE_TO_ROUNDING_MODE = {\n round: 'halfExpand',\n ceil: 'ceil',\n floor: 'floor',\n} as const;\n\n/**\n * Rounds a datetime to the nearest minute boundary.\n *\n * ## Mode comparison (given 14:37 with 15-min slots)\n *\n * ```\n * 14:30 ─────────●───────────────────── 14:45\n * 14:37\n *\n * 'round' → 14:30 (nearest slot - 37 is closer to 30 than 45)\n * 'ceil' → 14:45 (next slot - always up)\n * 'floor' → 14:30 (current slot - always down)\n * ```\n *\n * @param input - A Temporal.Instant (UTC) or Temporal.ZonedDateTime\n * @param options - Rounding options\n * @returns ZonedDateTime rounded to the minute boundary\n *\n * @example\n * ```ts\n * // 15-minute booking slots at 14:37\n * const time = Temporal.ZonedDateTime.from('2025-01-20T14:37:00[America/New_York]');\n *\n * roundToNearestMinute(time, { nearestTo: 15 }); // → 14:30 (nearest)\n * roundToNearestMinute(time, { mode: 'ceil', nearestTo: 15 }); // → 14:45 (next slot)\n * roundToNearestMinute(time, { mode: 'floor', nearestTo: 15 }); // → 14:30 (current slot)\n * ```\n *\n * @example\n * ```ts\n * // Basic minute rounding (no slots)\n * const time = Temporal.ZonedDateTime.from('2025-01-20T14:37:42[America/New_York]');\n *\n * roundToNearestMinute(time); // → 14:38 (42 sec >= 30)\n * roundToNearestMinute(time, { mode: 'ceil' }); // → 14:38 (always up)\n * roundToNearestMinute(time, { mode: 'floor' }); // → 14:37 (always down)\n * ```\n *\n * @example\n * ```ts\n * // Billing: round up to 30-minute increments\n * const sessionEnd = Temporal.ZonedDateTime.from('2025-01-20T11:07:00[America/New_York]');\n * roundToNearestMinute(sessionEnd, { mode: 'ceil', nearestTo: 30 });\n * // → 11:30 (bill for 30 mins even though session was 7 mins)\n * ```\n */\nexport function roundToNearestMinute(\n input: Temporal.Instant | Temporal.ZonedDateTime,\n options?: RoundToNearestMinuteOptions\n): Temporal.ZonedDateTime {\n const zonedDateTime = normalizeTemporalInput(input);\n const mode = options?.mode ?? 'round';\n const nearestTo = options?.nearestTo ?? 1;\n\n return zonedDateTime.round({\n smallestUnit: 'minute',\n roundingMode: MODE_TO_ROUNDING_MODE[mode],\n roundingIncrement: nearestTo,\n });\n}\n"],"mappings":";;;;;AA+BA,IAAM,wBAAwB;AAAA,EAC5B,OAAO;AAAA,EACP,MAAM;AAAA,EACN,OAAO;AACT;AAgDO,SAAS,qBACd,OACA,SACwB;AACxB,QAAM,gBAAgB,uBAAuB,KAAK;AAClD,QAAM,OAAO,SAAS,QAAQ;AAC9B,QAAM,YAAY,SAAS,aAAa;AAExC,SAAO,cAAc,MAAM;AAAA,IACzB,cAAc;AAAA,IACd,cAAc,sBAAsB,IAAI;AAAA,IACxC,mBAAmB;AAAA,EACrB,CAAC;AACH;","names":[]}
@@ -0,0 +1,41 @@
1
+ // src/toPlainTime.ts
2
+ import { Temporal } from "@js-temporal/polyfill";
3
+ var PLAIN_TIME_PATTERN = /^\d{2}:\d{2}(:\d{2}(\.\d+)?)?$/;
4
+ function toPlainTime(input, timezone) {
5
+ if (input instanceof Temporal.ZonedDateTime && timezone === void 0) {
6
+ return input.toPlainTime();
7
+ }
8
+ if (input instanceof Date) {
9
+ if (timezone === void 0) {
10
+ throw new Error("Timezone is required unless input is a ZonedDateTime, PlainTimeLike, or plain time string");
11
+ }
12
+ return Temporal.Instant.from(input.toISOString()).toZonedDateTimeISO(timezone).toPlainTime();
13
+ }
14
+ if (input instanceof Temporal.Instant) {
15
+ if (timezone === void 0) {
16
+ throw new Error("Timezone is required unless input is a ZonedDateTime, PlainTimeLike, or plain time string");
17
+ }
18
+ return input.toZonedDateTimeISO(timezone).toPlainTime();
19
+ }
20
+ if (input instanceof Temporal.ZonedDateTime) {
21
+ if (timezone === void 0) {
22
+ throw new Error("Timezone is required unless input is a ZonedDateTime, PlainTimeLike, or plain time string");
23
+ }
24
+ return input.toInstant().toZonedDateTimeISO(timezone).toPlainTime();
25
+ }
26
+ if (typeof input === "string") {
27
+ if (timezone !== void 0) {
28
+ return Temporal.Instant.from(input).toZonedDateTimeISO(timezone).toPlainTime();
29
+ }
30
+ if (PLAIN_TIME_PATTERN.test(input)) {
31
+ return Temporal.PlainTime.from(input);
32
+ }
33
+ throw new Error("Timezone is required unless input is a ZonedDateTime, PlainTimeLike, or plain time string");
34
+ }
35
+ return Temporal.PlainTime.from(input);
36
+ }
37
+
38
+ export {
39
+ toPlainTime
40
+ };
41
+ //# sourceMappingURL=chunk-UJWM2BV2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/toPlainTime.ts"],"sourcesContent":["import { Temporal } from '@js-temporal/polyfill';\nimport type { Timezone } from './types';\n\n// Pattern to detect plain time strings: HH:MM, HH:MM:SS, or HH:MM:SS.fractional\nconst PLAIN_TIME_PATTERN = /^\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?$/;\n\n/**\n * Parse a plain time or extract the wall-clock time from a datetime.\n *\n * @param input - A PlainTimeLike object, plain time string (HH:MM or HH:MM:SS), ZonedDateTime, or datetime input requiring timezone\n * @param timezone - IANA timezone identifier. Required for ISO strings, Date, and Instant inputs.\n * @returns A Temporal.PlainTime representing the wall-clock time\n *\n * @example\n * ```typescript\n * import { toPlainTime, toZonedTime } from '@gobrand/tiempo';\n *\n * // From PlainTimeLike object (no timezone needed)\n * const time = toPlainTime({ hour: 14, minute: 30 }); // 14:30\n *\n * // From plain time string (no timezone needed)\n * const time2 = toPlainTime(\"14:30\"); // 14:30\n * const timeWithSeconds = toPlainTime(\"14:30:45\"); // 14:30:45\n *\n * // From ZonedDateTime (no timezone needed)\n * const zdt = toZonedTime(\"2025-01-20T15:30:00Z\", \"America/New_York\");\n * const time3 = toPlainTime(zdt); // 10:30\n *\n * // From UTC string with timezone\n * const time4 = toPlainTime(\"2025-01-20T15:30:00Z\", \"America/New_York\"); // 10:30\n *\n * // From Date with timezone\n * const date = new Date(\"2025-01-20T15:30:00.000Z\");\n * const time5 = toPlainTime(date, \"Europe/London\"); // 15:30\n *\n * // From Instant with timezone\n * const instant = Temporal.Instant.from(\"2025-01-20T15:30:00Z\");\n * const time6 = toPlainTime(instant, \"Asia/Tokyo\"); // 00:30\n * ```\n */\nexport function toPlainTime(input: Temporal.ZonedDateTime): Temporal.PlainTime;\nexport function toPlainTime(\n input: string | Date | Temporal.Instant | Temporal.ZonedDateTime,\n timezone: Timezone\n): Temporal.PlainTime;\nexport function toPlainTime(input: Temporal.PlainTimeLike | string): Temporal.PlainTime;\nexport function toPlainTime(\n input: string | Date | Temporal.Instant | Temporal.ZonedDateTime | Temporal.PlainTimeLike,\n timezone?: Timezone\n): Temporal.PlainTime {\n // ZonedDateTime without timezone override\n if (input instanceof Temporal.ZonedDateTime && timezone === undefined) {\n return input.toPlainTime();\n }\n\n // Date requires timezone\n if (input instanceof Date) {\n if (timezone === undefined) {\n throw new Error('Timezone is required unless input is a ZonedDateTime, PlainTimeLike, or plain time string');\n }\n return Temporal.Instant.from(input.toISOString()).toZonedDateTimeISO(timezone).toPlainTime();\n }\n\n // Instant requires timezone\n if (input instanceof Temporal.Instant) {\n if (timezone === undefined) {\n throw new Error('Timezone is required unless input is a ZonedDateTime, PlainTimeLike, or plain time string');\n }\n return input.toZonedDateTimeISO(timezone).toPlainTime();\n }\n\n // ZonedDateTime with timezone override\n if (input instanceof Temporal.ZonedDateTime) {\n if (timezone === undefined) {\n throw new Error('Timezone is required unless input is a ZonedDateTime, PlainTimeLike, or plain time string');\n }\n return input.toInstant().toZonedDateTimeISO(timezone).toPlainTime();\n }\n\n // String: ISO datetime (requires timezone) or plain time (no timezone)\n if (typeof input === 'string') {\n if (timezone !== undefined) {\n return Temporal.Instant.from(input).toZonedDateTimeISO(timezone).toPlainTime();\n }\n if (PLAIN_TIME_PATTERN.test(input)) {\n return Temporal.PlainTime.from(input);\n }\n throw new Error('Timezone is required unless input is a ZonedDateTime, PlainTimeLike, or plain time string');\n }\n\n // PlainTimeLike object - pass directly to Temporal.PlainTime.from()\n return Temporal.PlainTime.from(input);\n}\n"],"mappings":";AAAA,SAAS,gBAAgB;AAIzB,IAAM,qBAAqB;AA0CpB,SAAS,YACd,OACA,UACoB;AAEpB,MAAI,iBAAiB,SAAS,iBAAiB,aAAa,QAAW;AACrE,WAAO,MAAM,YAAY;AAAA,EAC3B;AAGA,MAAI,iBAAiB,MAAM;AACzB,QAAI,aAAa,QAAW;AAC1B,YAAM,IAAI,MAAM,2FAA2F;AAAA,IAC7G;AACA,WAAO,SAAS,QAAQ,KAAK,MAAM,YAAY,CAAC,EAAE,mBAAmB,QAAQ,EAAE,YAAY;AAAA,EAC7F;AAGA,MAAI,iBAAiB,SAAS,SAAS;AACrC,QAAI,aAAa,QAAW;AAC1B,YAAM,IAAI,MAAM,2FAA2F;AAAA,IAC7G;AACA,WAAO,MAAM,mBAAmB,QAAQ,EAAE,YAAY;AAAA,EACxD;AAGA,MAAI,iBAAiB,SAAS,eAAe;AAC3C,QAAI,aAAa,QAAW;AAC1B,YAAM,IAAI,MAAM,2FAA2F;AAAA,IAC7G;AACA,WAAO,MAAM,UAAU,EAAE,mBAAmB,QAAQ,EAAE,YAAY;AAAA,EACpE;AAGA,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,aAAa,QAAW;AAC1B,aAAO,SAAS,QAAQ,KAAK,KAAK,EAAE,mBAAmB,QAAQ,EAAE,YAAY;AAAA,IAC/E;AACA,QAAI,mBAAmB,KAAK,KAAK,GAAG;AAClC,aAAO,SAAS,UAAU,KAAK,KAAK;AAAA,IACtC;AACA,UAAM,IAAI,MAAM,2FAA2F;AAAA,EAC7G;AAGA,SAAO,SAAS,UAAU,KAAK,KAAK;AACtC;","names":[]}
package/dist/index.d.ts CHANGED
@@ -64,6 +64,9 @@ export { differenceInDays } from './differenceInDays';
64
64
  export { differenceInWeeks } from './differenceInWeeks';
65
65
  export { differenceInMonths } from './differenceInMonths';
66
66
  export { differenceInYears } from './differenceInYears';
67
+ export { roundToNearestHour, type RoundToNearestHourOptions, } from './roundToNearestHour';
68
+ export { roundToNearestMinute, type RoundToNearestMinuteOptions, } from './roundToNearestMinute';
69
+ export { roundToNearestSecond, type RoundToNearestSecondOptions, } from './roundToNearestSecond';
67
70
  export { intlFormatDistance, type IntlFormatDistanceOptions, } from './intlFormatDistance';
68
71
  export { isPlainDateBefore } from './isPlainDateBefore';
69
72
  export { isPlainDateAfter } from './isPlainDateAfter';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,KAAK,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EACL,SAAS,EACT,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,WAAW,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EACL,kBAAkB,EAClB,KAAK,yBAAyB,GAC/B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,9 +1,27 @@
1
+ import {
2
+ toPlainDate
3
+ } from "./chunk-HFQUXON5.js";
4
+ import {
5
+ toPlainTime
6
+ } from "./chunk-UJWM2BV2.js";
7
+ import {
8
+ toUtc
9
+ } from "./chunk-BW5SFCKS.js";
1
10
  import {
2
11
  toZonedTime
3
12
  } from "./chunk-MXQFENCR.js";
4
13
  import {
5
14
  today
6
15
  } from "./chunk-KZB6NERH.js";
16
+ import {
17
+ subNanoseconds
18
+ } from "./chunk-WVHAYLBW.js";
19
+ import {
20
+ subSeconds
21
+ } from "./chunk-BH2YB4MV.js";
22
+ import {
23
+ subWeeks
24
+ } from "./chunk-U4RNUZXO.js";
7
25
  import {
8
26
  subYears
9
27
  } from "./chunk-AHMKY474.js";
@@ -17,14 +35,14 @@ import {
17
35
  toIso9075
18
36
  } from "./chunk-DFLGGK4F.js";
19
37
  import {
20
- toPlainDate
21
- } from "./chunk-UCCWUJ2K.js";
38
+ startOfWeek
39
+ } from "./chunk-EZ7NVTZI.js";
22
40
  import {
23
- toPlainTime
24
- } from "./chunk-G45S5B4O.js";
41
+ startOfYear
42
+ } from "./chunk-ID52RFFD.js";
25
43
  import {
26
- toUtc
27
- } from "./chunk-BW5SFCKS.js";
44
+ subDays
45
+ } from "./chunk-YKBP3G7L.js";
28
46
  import {
29
47
  subHours
30
48
  } from "./chunk-XW5MLXX5.js";
@@ -40,21 +58,21 @@ import {
40
58
  import {
41
59
  subMonths
42
60
  } from "./chunk-52NEOY34.js";
43
- import {
44
- subNanoseconds
45
- } from "./chunk-WVHAYLBW.js";
46
- import {
47
- subSeconds
48
- } from "./chunk-BH2YB4MV.js";
49
- import {
50
- subWeeks
51
- } from "./chunk-U4RNUZXO.js";
52
61
  import {
53
62
  isSameYear
54
63
  } from "./chunk-VLZ3HQQA.js";
55
64
  import {
56
65
  now
57
66
  } from "./chunk-FSD3DDFC.js";
67
+ import {
68
+ roundToNearestHour
69
+ } from "./chunk-MMI2HHT7.js";
70
+ import {
71
+ roundToNearestMinute
72
+ } from "./chunk-UJW2FPI4.js";
73
+ import {
74
+ roundToNearestSecond
75
+ } from "./chunk-JHRXY36W.js";
58
76
  import {
59
77
  simpleFormat
60
78
  } from "./chunk-TFSZ55L7.js";
@@ -64,15 +82,6 @@ import {
64
82
  import {
65
83
  startOfMonth
66
84
  } from "./chunk-7GEIOKVQ.js";
67
- import {
68
- startOfWeek
69
- } from "./chunk-EZ7NVTZI.js";
70
- import {
71
- startOfYear
72
- } from "./chunk-ID52RFFD.js";
73
- import {
74
- subDays
75
- } from "./chunk-YKBP3G7L.js";
76
85
  import {
77
86
  isSameHour
78
87
  } from "./chunk-EEQ3REET.js";
@@ -267,6 +276,9 @@ export {
267
276
  isSameWeek,
268
277
  isSameYear,
269
278
  now,
279
+ roundToNearestHour,
280
+ roundToNearestMinute,
281
+ roundToNearestSecond,
270
282
  simpleFormat,
271
283
  startOfDay,
272
284
  startOfMonth,
@@ -0,0 +1,77 @@
1
+ import type { Temporal } from '@js-temporal/polyfill';
2
+ /**
3
+ * Options for rounding to nearest hour.
4
+ */
5
+ export interface RoundToNearestHourOptions {
6
+ /**
7
+ * The rounding mode to use.
8
+ *
9
+ * Given time 14:20:
10
+ * - `'round'` → 14:00 (20 min < 30, rounds DOWN to nearest)
11
+ * - `'ceil'` → 15:00 (always rounds UP to next hour)
12
+ * - `'floor'` → 14:00 (always rounds DOWN to current hour)
13
+ *
14
+ * Given time 14:40:
15
+ * - `'round'` → 15:00 (40 min >= 30, rounds UP to nearest)
16
+ * - `'ceil'` → 15:00 (always rounds UP to next hour)
17
+ * - `'floor'` → 14:00 (always rounds DOWN to current hour)
18
+ *
19
+ * @default 'round'
20
+ */
21
+ mode?: 'round' | 'ceil' | 'floor';
22
+ /**
23
+ * Round to the nearest N hours. Must divide evenly into 24.
24
+ * Valid values: 1, 2, 3, 4, 6, 8, 12
25
+ * @example nearestTo: 6 rounds to 00:00, 06:00, 12:00, or 18:00
26
+ */
27
+ nearestTo?: 1 | 2 | 3 | 4 | 6 | 8 | 12;
28
+ }
29
+ /**
30
+ * Rounds a datetime to the nearest hour boundary.
31
+ *
32
+ * ## Mode comparison (given 14:20)
33
+ *
34
+ * ```
35
+ * 14:00 ─────────────●───────────────── 15:00
36
+ * 14:20
37
+ *
38
+ * 'round' → 14:00 (nearest hour - 20 min < 30)
39
+ * 'ceil' → 15:00 (next hour - always up)
40
+ * 'floor' → 14:00 (current hour - always down)
41
+ * ```
42
+ *
43
+ * @param input - A Temporal.Instant (UTC) or Temporal.ZonedDateTime
44
+ * @param options - Rounding options
45
+ * @returns ZonedDateTime rounded to the hour boundary
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * const time = Temporal.ZonedDateTime.from('2025-01-20T14:20:00[America/New_York]');
50
+ *
51
+ * roundToNearestHour(time); // → 14:00 (nearest)
52
+ * roundToNearestHour(time, { mode: 'ceil' }); // → 15:00 (always up)
53
+ * roundToNearestHour(time, { mode: 'floor' }); // → 14:00 (always down)
54
+ * ```
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * // With 37 minutes (past the halfway point)
59
+ * const time = Temporal.ZonedDateTime.from('2025-01-20T14:37:00[America/New_York]');
60
+ *
61
+ * roundToNearestHour(time); // → 15:00 (nearest - 37 >= 30)
62
+ * roundToNearestHour(time, { mode: 'ceil' }); // → 15:00 (always up)
63
+ * roundToNearestHour(time, { mode: 'floor' }); // → 14:00 (always down)
64
+ * ```
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * // Round to 6-hour blocks (shift scheduling)
69
+ * const time = Temporal.ZonedDateTime.from('2025-01-20T14:00:00[America/New_York]');
70
+ *
71
+ * roundToNearestHour(time, { nearestTo: 6 }); // → 12:00
72
+ * roundToNearestHour(time, { mode: 'ceil', nearestTo: 6 }); // → 18:00
73
+ * roundToNearestHour(time, { mode: 'floor', nearestTo: 6 }); // → 12:00
74
+ * ```
75
+ */
76
+ export declare function roundToNearestHour(input: Temporal.Instant | Temporal.ZonedDateTime, options?: RoundToNearestHourOptions): Temporal.ZonedDateTime;
77
+ //# sourceMappingURL=roundToNearestHour.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roundToNearestHour.d.ts","sourceRoot":"","sources":["../src/roundToNearestHour.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGtD;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;;;;;;;;;;;;OAcG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;IAClC;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;CACxC;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,aAAa,EAChD,OAAO,CAAC,EAAE,yBAAyB,GAClC,QAAQ,CAAC,aAAa,CAUxB"}
@@ -0,0 +1,8 @@
1
+ import {
2
+ roundToNearestHour
3
+ } from "./chunk-MMI2HHT7.js";
4
+ import "./chunk-MJSZNWCV.js";
5
+ export {
6
+ roundToNearestHour
7
+ };
8
+ //# sourceMappingURL=roundToNearestHour.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=roundToNearestHour.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roundToNearestHour.test.d.ts","sourceRoot":"","sources":["../src/roundToNearestHour.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,76 @@
1
+ import type { Temporal } from '@js-temporal/polyfill';
2
+ /**
3
+ * Options for rounding to nearest minute.
4
+ */
5
+ export interface RoundToNearestMinuteOptions {
6
+ /**
7
+ * The rounding mode to use.
8
+ *
9
+ * Given time 14:37:20:
10
+ * - `'round'` → 14:37 (20 sec < 30, rounds DOWN to nearest)
11
+ * - `'ceil'` → 14:38 (always rounds UP to next minute)
12
+ * - `'floor'` → 14:37 (always rounds DOWN to current minute)
13
+ *
14
+ * Given time 14:37:00 with nearestTo: 15:
15
+ * - `'round'` → 14:30 (37 is closer to 30 than 45)
16
+ * - `'ceil'` → 14:45 (always rounds UP to next 15-min slot)
17
+ * - `'floor'` → 14:30 (always rounds DOWN to current 15-min slot)
18
+ *
19
+ * @default 'round'
20
+ */
21
+ mode?: 'round' | 'ceil' | 'floor';
22
+ /**
23
+ * Round to the nearest N minutes. Must divide evenly into 60.
24
+ * Valid values: 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30
25
+ * @example nearestTo: 15 rounds to quarter-hour marks (00, 15, 30, 45)
26
+ */
27
+ nearestTo?: 1 | 2 | 3 | 4 | 5 | 6 | 10 | 12 | 15 | 20 | 30;
28
+ }
29
+ /**
30
+ * Rounds a datetime to the nearest minute boundary.
31
+ *
32
+ * ## Mode comparison (given 14:37 with 15-min slots)
33
+ *
34
+ * ```
35
+ * 14:30 ─────────●───────────────────── 14:45
36
+ * 14:37
37
+ *
38
+ * 'round' → 14:30 (nearest slot - 37 is closer to 30 than 45)
39
+ * 'ceil' → 14:45 (next slot - always up)
40
+ * 'floor' → 14:30 (current slot - always down)
41
+ * ```
42
+ *
43
+ * @param input - A Temporal.Instant (UTC) or Temporal.ZonedDateTime
44
+ * @param options - Rounding options
45
+ * @returns ZonedDateTime rounded to the minute boundary
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * // 15-minute booking slots at 14:37
50
+ * const time = Temporal.ZonedDateTime.from('2025-01-20T14:37:00[America/New_York]');
51
+ *
52
+ * roundToNearestMinute(time, { nearestTo: 15 }); // → 14:30 (nearest)
53
+ * roundToNearestMinute(time, { mode: 'ceil', nearestTo: 15 }); // → 14:45 (next slot)
54
+ * roundToNearestMinute(time, { mode: 'floor', nearestTo: 15 }); // → 14:30 (current slot)
55
+ * ```
56
+ *
57
+ * @example
58
+ * ```ts
59
+ * // Basic minute rounding (no slots)
60
+ * const time = Temporal.ZonedDateTime.from('2025-01-20T14:37:42[America/New_York]');
61
+ *
62
+ * roundToNearestMinute(time); // → 14:38 (42 sec >= 30)
63
+ * roundToNearestMinute(time, { mode: 'ceil' }); // → 14:38 (always up)
64
+ * roundToNearestMinute(time, { mode: 'floor' }); // → 14:37 (always down)
65
+ * ```
66
+ *
67
+ * @example
68
+ * ```ts
69
+ * // Billing: round up to 30-minute increments
70
+ * const sessionEnd = Temporal.ZonedDateTime.from('2025-01-20T11:07:00[America/New_York]');
71
+ * roundToNearestMinute(sessionEnd, { mode: 'ceil', nearestTo: 30 });
72
+ * // → 11:30 (bill for 30 mins even though session was 7 mins)
73
+ * ```
74
+ */
75
+ export declare function roundToNearestMinute(input: Temporal.Instant | Temporal.ZonedDateTime, options?: RoundToNearestMinuteOptions): Temporal.ZonedDateTime;
76
+ //# sourceMappingURL=roundToNearestMinute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roundToNearestMinute.d.ts","sourceRoot":"","sources":["../src/roundToNearestMinute.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGtD;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;;;;;;;;;;;;OAcG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;IAClC;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;CAC5D;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,aAAa,EAChD,OAAO,CAAC,EAAE,2BAA2B,GACpC,QAAQ,CAAC,aAAa,CAUxB"}
@@ -0,0 +1,8 @@
1
+ import {
2
+ roundToNearestMinute
3
+ } from "./chunk-UJW2FPI4.js";
4
+ import "./chunk-MJSZNWCV.js";
5
+ export {
6
+ roundToNearestMinute
7
+ };
8
+ //# sourceMappingURL=roundToNearestMinute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=roundToNearestMinute.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roundToNearestMinute.test.d.ts","sourceRoot":"","sources":["../src/roundToNearestMinute.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,75 @@
1
+ import type { Temporal } from '@js-temporal/polyfill';
2
+ /**
3
+ * Options for rounding to nearest second.
4
+ */
5
+ export interface RoundToNearestSecondOptions {
6
+ /**
7
+ * The rounding mode to use.
8
+ *
9
+ * Given time 14:37:42.300:
10
+ * - `'round'` → 14:37:42 (300ms < 500, rounds DOWN to nearest)
11
+ * - `'ceil'` → 14:37:43 (always rounds UP to next second)
12
+ * - `'floor'` → 14:37:42 (always rounds DOWN to current second)
13
+ *
14
+ * Given time 14:37:42 with nearestTo: 10:
15
+ * - `'round'` → 14:37:40 (42 is closer to 40 than 50)
16
+ * - `'ceil'` → 14:37:50 (always rounds UP to next 10-sec mark)
17
+ * - `'floor'` → 14:37:40 (always rounds DOWN to current 10-sec mark)
18
+ *
19
+ * @default 'round'
20
+ */
21
+ mode?: 'round' | 'ceil' | 'floor';
22
+ /**
23
+ * Round to the nearest N seconds. Must divide evenly into 60.
24
+ * Valid values: 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30
25
+ * @example nearestTo: 10 rounds to 10-second marks (00, 10, 20, 30, 40, 50)
26
+ */
27
+ nearestTo?: 1 | 2 | 3 | 4 | 5 | 6 | 10 | 12 | 15 | 20 | 30;
28
+ }
29
+ /**
30
+ * Rounds a datetime to the nearest second boundary.
31
+ *
32
+ * ## Mode comparison (given 14:37:42.567)
33
+ *
34
+ * ```
35
+ * :42 ─────────────────●─────────────── :43
36
+ * .567
37
+ *
38
+ * 'round' → :43 (nearest second - 567ms >= 500)
39
+ * 'ceil' → :43 (next second - always up)
40
+ * 'floor' → :42 (current second - always down)
41
+ * ```
42
+ *
43
+ * @param input - A Temporal.Instant (UTC) or Temporal.ZonedDateTime
44
+ * @param options - Rounding options
45
+ * @returns ZonedDateTime rounded to the second boundary
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * const time = Temporal.ZonedDateTime.from('2025-01-20T14:37:42.567[America/New_York]');
50
+ *
51
+ * roundToNearestSecond(time); // → 14:37:43 (567ms >= 500)
52
+ * roundToNearestSecond(time, { mode: 'ceil' }); // → 14:37:43 (always up)
53
+ * roundToNearestSecond(time, { mode: 'floor' }); // → 14:37:42 (always down)
54
+ * ```
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * // 10-second intervals
59
+ * const time = Temporal.ZonedDateTime.from('2025-01-20T14:37:42[America/New_York]');
60
+ *
61
+ * roundToNearestSecond(time, { nearestTo: 10 }); // → 14:37:40 (nearest)
62
+ * roundToNearestSecond(time, { mode: 'ceil', nearestTo: 10 }); // → 14:37:50 (next 10s)
63
+ * roundToNearestSecond(time, { mode: 'floor', nearestTo: 10 }); // → 14:37:40 (current 10s)
64
+ * ```
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * // Remove sub-second precision for logging
69
+ * const logTime = Temporal.ZonedDateTime.from('2025-01-20T14:37:42.123456789[UTC]');
70
+ * roundToNearestSecond(logTime, { mode: 'floor' });
71
+ * // → 14:37:42.000000000 (clean timestamp)
72
+ * ```
73
+ */
74
+ export declare function roundToNearestSecond(input: Temporal.Instant | Temporal.ZonedDateTime, options?: RoundToNearestSecondOptions): Temporal.ZonedDateTime;
75
+ //# sourceMappingURL=roundToNearestSecond.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roundToNearestSecond.d.ts","sourceRoot":"","sources":["../src/roundToNearestSecond.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGtD;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;;;;;;;;;;;;OAcG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;IAClC;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;CAC5D;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,aAAa,EAChD,OAAO,CAAC,EAAE,2BAA2B,GACpC,QAAQ,CAAC,aAAa,CAUxB"}
@@ -0,0 +1,8 @@
1
+ import {
2
+ roundToNearestSecond
3
+ } from "./chunk-JHRXY36W.js";
4
+ import "./chunk-MJSZNWCV.js";
5
+ export {
6
+ roundToNearestSecond
7
+ };
8
+ //# sourceMappingURL=roundToNearestSecond.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=roundToNearestSecond.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roundToNearestSecond.test.d.ts","sourceRoot":"","sources":["../src/roundToNearestSecond.test.ts"],"names":[],"mappings":""}
@@ -1,31 +1,38 @@
1
1
  import { Temporal } from '@js-temporal/polyfill';
2
2
  import type { Timezone } from './types';
3
3
  /**
4
- * Extract the calendar date from a ZonedDateTime or convert an input to a timezone and extract the date.
4
+ * Parse a plain date or extract the calendar date from a datetime.
5
5
  *
6
- * @param input - A Temporal.ZonedDateTime (timezone optional) or a UTC ISO string, Date, Instant, or ZonedDateTime (timezone required)
7
- * @param timezone - IANA timezone identifier. Required unless input is a ZonedDateTime.
6
+ * @param input - A PlainDateLike object, plain date string (YYYY-MM-DD), ZonedDateTime, or datetime input requiring timezone
7
+ * @param timezone - IANA timezone identifier. Required for ISO strings, Date, and Instant inputs.
8
8
  * @returns A Temporal.PlainDate representing the calendar date
9
9
  *
10
10
  * @example
11
11
  * ```typescript
12
12
  * import { toPlainDate, toZonedTime } from '@gobrand/tiempo';
13
13
  *
14
+ * // From PlainDateLike object (no timezone needed)
15
+ * const date = toPlainDate({ year: 2025, month: 1, day: 20 }); // 2025-01-20
16
+ *
17
+ * // From plain date string (no timezone needed)
18
+ * const date2 = toPlainDate("2025-01-20"); // 2025-01-20
19
+ *
14
20
  * // From ZonedDateTime (no timezone needed)
15
21
  * const zdt = toZonedTime("2025-01-20T15:30:00Z", "America/New_York");
16
- * const date = toPlainDate(zdt); // 2025-01-20
22
+ * const date3 = toPlainDate(zdt); // 2025-01-20
17
23
  *
18
24
  * // From UTC string with timezone
19
- * const date2 = toPlainDate("2025-01-20T15:30:00Z", "America/New_York"); // 2025-01-20
25
+ * const date4 = toPlainDate("2025-01-20T15:30:00Z", "America/New_York"); // 2025-01-20
20
26
  *
21
27
  * // From Date with timezone
22
28
  * const jsDate = new Date("2025-01-20T15:30:00.000Z");
23
- * const date3 = toPlainDate(jsDate, "Europe/London"); // 2025-01-20
29
+ * const date5 = toPlainDate(jsDate, "Europe/London"); // 2025-01-20
24
30
  *
25
31
  * // Date boundary crossing: 23:00 UTC on Jan 20 → Jan 21 in Tokyo
26
- * const date4 = toPlainDate("2025-01-20T23:00:00Z", "Asia/Tokyo"); // 2025-01-21
32
+ * const date6 = toPlainDate("2025-01-20T23:00:00Z", "Asia/Tokyo"); // 2025-01-21
27
33
  * ```
28
34
  */
29
35
  export declare function toPlainDate(input: Temporal.ZonedDateTime): Temporal.PlainDate;
30
36
  export declare function toPlainDate(input: string | Date | Temporal.Instant | Temporal.ZonedDateTime, timezone: Timezone): Temporal.PlainDate;
37
+ export declare function toPlainDate(input: Temporal.PlainDateLike | string): Temporal.PlainDate;
31
38
  //# sourceMappingURL=toPlainDate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"toPlainDate.d.ts","sourceRoot":"","sources":["../src/toPlainDate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,aAAa,GAAG,QAAQ,CAAC,SAAS,CAAC;AAC/E,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,aAAa,EAChE,QAAQ,EAAE,QAAQ,GACjB,QAAQ,CAAC,SAAS,CAAC"}
1
+ {"version":3,"file":"toPlainDate.d.ts","sourceRoot":"","sources":["../src/toPlainDate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAKxC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,aAAa,GAAG,QAAQ,CAAC,SAAS,CAAC;AAC/E,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,aAAa,EAChE,QAAQ,EAAE,QAAQ,GACjB,QAAQ,CAAC,SAAS,CAAC;AACtB,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,aAAa,GAAG,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  toPlainDate
3
- } from "./chunk-UCCWUJ2K.js";
3
+ } from "./chunk-HFQUXON5.js";
4
4
  export {
5
5
  toPlainDate
6
6
  };
@@ -1,32 +1,40 @@
1
1
  import { Temporal } from '@js-temporal/polyfill';
2
2
  import type { Timezone } from './types';
3
3
  /**
4
- * Extract the wall-clock time from a ZonedDateTime or convert an input to a timezone and extract the time.
4
+ * Parse a plain time or extract the wall-clock time from a datetime.
5
5
  *
6
- * @param input - A Temporal.ZonedDateTime (timezone optional) or a UTC ISO string, Date, Instant, or ZonedDateTime (timezone required)
7
- * @param timezone - IANA timezone identifier. Required unless input is a ZonedDateTime.
6
+ * @param input - A PlainTimeLike object, plain time string (HH:MM or HH:MM:SS), ZonedDateTime, or datetime input requiring timezone
7
+ * @param timezone - IANA timezone identifier. Required for ISO strings, Date, and Instant inputs.
8
8
  * @returns A Temporal.PlainTime representing the wall-clock time
9
9
  *
10
10
  * @example
11
11
  * ```typescript
12
12
  * import { toPlainTime, toZonedTime } from '@gobrand/tiempo';
13
13
  *
14
+ * // From PlainTimeLike object (no timezone needed)
15
+ * const time = toPlainTime({ hour: 14, minute: 30 }); // 14:30
16
+ *
17
+ * // From plain time string (no timezone needed)
18
+ * const time2 = toPlainTime("14:30"); // 14:30
19
+ * const timeWithSeconds = toPlainTime("14:30:45"); // 14:30:45
20
+ *
14
21
  * // From ZonedDateTime (no timezone needed)
15
22
  * const zdt = toZonedTime("2025-01-20T15:30:00Z", "America/New_York");
16
- * const time = toPlainTime(zdt); // 10:30
23
+ * const time3 = toPlainTime(zdt); // 10:30
17
24
  *
18
25
  * // From UTC string with timezone
19
- * const time2 = toPlainTime("2025-01-20T15:30:00Z", "America/New_York"); // 10:30
26
+ * const time4 = toPlainTime("2025-01-20T15:30:00Z", "America/New_York"); // 10:30
20
27
  *
21
28
  * // From Date with timezone
22
29
  * const date = new Date("2025-01-20T15:30:00.000Z");
23
- * const time3 = toPlainTime(date, "Europe/London"); // 15:30
30
+ * const time5 = toPlainTime(date, "Europe/London"); // 15:30
24
31
  *
25
32
  * // From Instant with timezone
26
33
  * const instant = Temporal.Instant.from("2025-01-20T15:30:00Z");
27
- * const time4 = toPlainTime(instant, "Asia/Tokyo"); // 00:30
34
+ * const time6 = toPlainTime(instant, "Asia/Tokyo"); // 00:30
28
35
  * ```
29
36
  */
30
37
  export declare function toPlainTime(input: Temporal.ZonedDateTime): Temporal.PlainTime;
31
38
  export declare function toPlainTime(input: string | Date | Temporal.Instant | Temporal.ZonedDateTime, timezone: Timezone): Temporal.PlainTime;
39
+ export declare function toPlainTime(input: Temporal.PlainTimeLike | string): Temporal.PlainTime;
32
40
  //# sourceMappingURL=toPlainTime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"toPlainTime.d.ts","sourceRoot":"","sources":["../src/toPlainTime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,aAAa,GAAG,QAAQ,CAAC,SAAS,CAAC;AAC/E,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,aAAa,EAChE,QAAQ,EAAE,QAAQ,GACjB,QAAQ,CAAC,SAAS,CAAC"}
1
+ {"version":3,"file":"toPlainTime.d.ts","sourceRoot":"","sources":["../src/toPlainTime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAKxC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,aAAa,GAAG,QAAQ,CAAC,SAAS,CAAC;AAC/E,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,aAAa,EAChE,QAAQ,EAAE,QAAQ,GACjB,QAAQ,CAAC,SAAS,CAAC;AACtB,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,aAAa,GAAG,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  toPlainTime
3
- } from "./chunk-G45S5B4O.js";
3
+ } from "./chunk-UJWM2BV2.js";
4
4
  export {
5
5
  toPlainTime
6
6
  };
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,YAAY,CAAC;AAE5C,YAAY,EAAE,YAAY,EAAE,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,YAAY,CAAC;AAE5C,YAAY,EAAE,YAAY,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobrand/tiempo",
3
- "version": "2.5.4",
3
+ "version": "2.6.0",
4
4
  "description": "Lightweight utility functions for converting between UTC and timezone-aware datetimes using the Temporal API",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -1,25 +0,0 @@
1
- // src/toPlainTime.ts
2
- import { Temporal } from "@js-temporal/polyfill";
3
- function toPlainTime(input, timezone) {
4
- if (input instanceof Temporal.ZonedDateTime && timezone === void 0) {
5
- return input.toPlainTime();
6
- }
7
- if (timezone === void 0) {
8
- throw new Error("Timezone is required unless input is a ZonedDateTime");
9
- }
10
- if (typeof input === "string") {
11
- return Temporal.Instant.from(input).toZonedDateTimeISO(timezone).toPlainTime();
12
- }
13
- if (input instanceof Date) {
14
- return Temporal.Instant.from(input.toISOString()).toZonedDateTimeISO(timezone).toPlainTime();
15
- }
16
- if (input instanceof Temporal.Instant) {
17
- return input.toZonedDateTimeISO(timezone).toPlainTime();
18
- }
19
- return input.toInstant().toZonedDateTimeISO(timezone).toPlainTime();
20
- }
21
-
22
- export {
23
- toPlainTime
24
- };
25
- //# sourceMappingURL=chunk-G45S5B4O.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/toPlainTime.ts"],"sourcesContent":["import { Temporal } from '@js-temporal/polyfill';\nimport type { Timezone } from './types';\n\n/**\n * Extract the wall-clock time from a ZonedDateTime or convert an input to a timezone and extract the time.\n *\n * @param input - A Temporal.ZonedDateTime (timezone optional) or a UTC ISO string, Date, Instant, or ZonedDateTime (timezone required)\n * @param timezone - IANA timezone identifier. Required unless input is a ZonedDateTime.\n * @returns A Temporal.PlainTime representing the wall-clock time\n *\n * @example\n * ```typescript\n * import { toPlainTime, toZonedTime } from '@gobrand/tiempo';\n *\n * // From ZonedDateTime (no timezone needed)\n * const zdt = toZonedTime(\"2025-01-20T15:30:00Z\", \"America/New_York\");\n * const time = toPlainTime(zdt); // 10:30\n *\n * // From UTC string with timezone\n * const time2 = toPlainTime(\"2025-01-20T15:30:00Z\", \"America/New_York\"); // 10:30\n *\n * // From Date with timezone\n * const date = new Date(\"2025-01-20T15:30:00.000Z\");\n * const time3 = toPlainTime(date, \"Europe/London\"); // 15:30\n *\n * // From Instant with timezone\n * const instant = Temporal.Instant.from(\"2025-01-20T15:30:00Z\");\n * const time4 = toPlainTime(instant, \"Asia/Tokyo\"); // 00:30\n * ```\n */\nexport function toPlainTime(input: Temporal.ZonedDateTime): Temporal.PlainTime;\nexport function toPlainTime(\n input: string | Date | Temporal.Instant | Temporal.ZonedDateTime,\n timezone: Timezone\n): Temporal.PlainTime;\nexport function toPlainTime(\n input: string | Date | Temporal.Instant | Temporal.ZonedDateTime,\n timezone?: Timezone\n): Temporal.PlainTime {\n if (input instanceof Temporal.ZonedDateTime && timezone === undefined) {\n return input.toPlainTime();\n }\n\n if (timezone === undefined) {\n throw new Error('Timezone is required unless input is a ZonedDateTime');\n }\n\n if (typeof input === 'string') {\n return Temporal.Instant.from(input).toZonedDateTimeISO(timezone).toPlainTime();\n }\n\n if (input instanceof Date) {\n return Temporal.Instant.from(input.toISOString()).toZonedDateTimeISO(timezone).toPlainTime();\n }\n\n if (input instanceof Temporal.Instant) {\n return input.toZonedDateTimeISO(timezone).toPlainTime();\n }\n\n return input.toInstant().toZonedDateTimeISO(timezone).toPlainTime();\n}\n"],"mappings":";AAAA,SAAS,gBAAgB;AAmClB,SAAS,YACd,OACA,UACoB;AACpB,MAAI,iBAAiB,SAAS,iBAAiB,aAAa,QAAW;AACrE,WAAO,MAAM,YAAY;AAAA,EAC3B;AAEA,MAAI,aAAa,QAAW;AAC1B,UAAM,IAAI,MAAM,sDAAsD;AAAA,EACxE;AAEA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,SAAS,QAAQ,KAAK,KAAK,EAAE,mBAAmB,QAAQ,EAAE,YAAY;AAAA,EAC/E;AAEA,MAAI,iBAAiB,MAAM;AACzB,WAAO,SAAS,QAAQ,KAAK,MAAM,YAAY,CAAC,EAAE,mBAAmB,QAAQ,EAAE,YAAY;AAAA,EAC7F;AAEA,MAAI,iBAAiB,SAAS,SAAS;AACrC,WAAO,MAAM,mBAAmB,QAAQ,EAAE,YAAY;AAAA,EACxD;AAEA,SAAO,MAAM,UAAU,EAAE,mBAAmB,QAAQ,EAAE,YAAY;AACpE;","names":[]}
@@ -1,25 +0,0 @@
1
- // src/toPlainDate.ts
2
- import { Temporal } from "@js-temporal/polyfill";
3
- function toPlainDate(input, timezone) {
4
- if (input instanceof Temporal.ZonedDateTime && timezone === void 0) {
5
- return input.toPlainDate();
6
- }
7
- if (timezone === void 0) {
8
- throw new Error("Timezone is required unless input is a ZonedDateTime");
9
- }
10
- if (typeof input === "string") {
11
- return Temporal.Instant.from(input).toZonedDateTimeISO(timezone).toPlainDate();
12
- }
13
- if (input instanceof Date) {
14
- return Temporal.Instant.from(input.toISOString()).toZonedDateTimeISO(timezone).toPlainDate();
15
- }
16
- if (input instanceof Temporal.Instant) {
17
- return input.toZonedDateTimeISO(timezone).toPlainDate();
18
- }
19
- return input.toInstant().toZonedDateTimeISO(timezone).toPlainDate();
20
- }
21
-
22
- export {
23
- toPlainDate
24
- };
25
- //# sourceMappingURL=chunk-UCCWUJ2K.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/toPlainDate.ts"],"sourcesContent":["import { Temporal } from '@js-temporal/polyfill';\nimport type { Timezone } from './types';\n\n/**\n * Extract the calendar date from a ZonedDateTime or convert an input to a timezone and extract the date.\n *\n * @param input - A Temporal.ZonedDateTime (timezone optional) or a UTC ISO string, Date, Instant, or ZonedDateTime (timezone required)\n * @param timezone - IANA timezone identifier. Required unless input is a ZonedDateTime.\n * @returns A Temporal.PlainDate representing the calendar date\n *\n * @example\n * ```typescript\n * import { toPlainDate, toZonedTime } from '@gobrand/tiempo';\n *\n * // From ZonedDateTime (no timezone needed)\n * const zdt = toZonedTime(\"2025-01-20T15:30:00Z\", \"America/New_York\");\n * const date = toPlainDate(zdt); // 2025-01-20\n *\n * // From UTC string with timezone\n * const date2 = toPlainDate(\"2025-01-20T15:30:00Z\", \"America/New_York\"); // 2025-01-20\n *\n * // From Date with timezone\n * const jsDate = new Date(\"2025-01-20T15:30:00.000Z\");\n * const date3 = toPlainDate(jsDate, \"Europe/London\"); // 2025-01-20\n *\n * // Date boundary crossing: 23:00 UTC on Jan 20 → Jan 21 in Tokyo\n * const date4 = toPlainDate(\"2025-01-20T23:00:00Z\", \"Asia/Tokyo\"); // 2025-01-21\n * ```\n */\nexport function toPlainDate(input: Temporal.ZonedDateTime): Temporal.PlainDate;\nexport function toPlainDate(\n input: string | Date | Temporal.Instant | Temporal.ZonedDateTime,\n timezone: Timezone\n): Temporal.PlainDate;\nexport function toPlainDate(\n input: string | Date | Temporal.Instant | Temporal.ZonedDateTime,\n timezone?: Timezone\n): Temporal.PlainDate {\n if (input instanceof Temporal.ZonedDateTime && timezone === undefined) {\n return input.toPlainDate();\n }\n\n if (timezone === undefined) {\n throw new Error('Timezone is required unless input is a ZonedDateTime');\n }\n\n if (typeof input === 'string') {\n return Temporal.Instant.from(input).toZonedDateTimeISO(timezone).toPlainDate();\n }\n\n if (input instanceof Date) {\n return Temporal.Instant.from(input.toISOString()).toZonedDateTimeISO(timezone).toPlainDate();\n }\n\n if (input instanceof Temporal.Instant) {\n return input.toZonedDateTimeISO(timezone).toPlainDate();\n }\n\n return input.toInstant().toZonedDateTimeISO(timezone).toPlainDate();\n}\n"],"mappings":";AAAA,SAAS,gBAAgB;AAkClB,SAAS,YACd,OACA,UACoB;AACpB,MAAI,iBAAiB,SAAS,iBAAiB,aAAa,QAAW;AACrE,WAAO,MAAM,YAAY;AAAA,EAC3B;AAEA,MAAI,aAAa,QAAW;AAC1B,UAAM,IAAI,MAAM,sDAAsD;AAAA,EACxE;AAEA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,SAAS,QAAQ,KAAK,KAAK,EAAE,mBAAmB,QAAQ,EAAE,YAAY;AAAA,EAC/E;AAEA,MAAI,iBAAiB,MAAM;AACzB,WAAO,SAAS,QAAQ,KAAK,MAAM,YAAY,CAAC,EAAE,mBAAmB,QAAQ,EAAE,YAAY;AAAA,EAC7F;AAEA,MAAI,iBAAiB,SAAS,SAAS;AACrC,WAAO,MAAM,mBAAmB,QAAQ,EAAE,YAAY;AAAA,EACxD;AAEA,SAAO,MAAM,UAAU,EAAE,mBAAmB,QAAQ,EAAE,YAAY;AACpE;","names":[]}