@intech-software/chronera 0.1.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 (282) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +6644 -0
  3. package/dist/calendar/buddhist/adapter.d.ts +2 -0
  4. package/dist/calendar/buddhist/adapter.js +33 -0
  5. package/dist/calendar/buddhist/adapter.js.map +1 -0
  6. package/dist/calendar/buddhist/constants.d.ts +3 -0
  7. package/dist/calendar/buddhist/constants.js +14 -0
  8. package/dist/calendar/buddhist/constants.js.map +1 -0
  9. package/dist/calendar/buddhist/index.d.ts +3 -0
  10. package/dist/calendar/buddhist/index.js +4 -0
  11. package/dist/calendar/buddhist/index.js.map +1 -0
  12. package/dist/calendar/buddhist/validator.d.ts +4 -0
  13. package/dist/calendar/buddhist/validator.js +60 -0
  14. package/dist/calendar/buddhist/validator.js.map +1 -0
  15. package/dist/calendar/gregory/absolute-day.d.ts +12 -0
  16. package/dist/calendar/gregory/absolute-day.js +14 -0
  17. package/dist/calendar/gregory/absolute-day.js.map +1 -0
  18. package/dist/calendar/gregory/adapter.d.ts +3 -0
  19. package/dist/calendar/gregory/adapter.js +93 -0
  20. package/dist/calendar/gregory/adapter.js.map +1 -0
  21. package/dist/calendar/gregory/constants.d.ts +3 -0
  22. package/dist/calendar/gregory/constants.js +18 -0
  23. package/dist/calendar/gregory/constants.js.map +1 -0
  24. package/dist/calendar/gregory/index.d.ts +4 -0
  25. package/dist/calendar/gregory/index.js +5 -0
  26. package/dist/calendar/gregory/index.js.map +1 -0
  27. package/dist/calendar/gregory/leap-year.d.ts +1 -0
  28. package/dist/calendar/gregory/leap-year.js +2 -0
  29. package/dist/calendar/gregory/leap-year.js.map +1 -0
  30. package/dist/calendar/gregory/validator.d.ts +2 -0
  31. package/dist/calendar/gregory/validator.js +45 -0
  32. package/dist/calendar/gregory/validator.js.map +1 -0
  33. package/dist/calendar/hijri/civil-adapter.d.ts +12 -0
  34. package/dist/calendar/hijri/civil-adapter.js +132 -0
  35. package/dist/calendar/hijri/civil-adapter.js.map +1 -0
  36. package/dist/calendar/hijri/index.d.ts +3 -0
  37. package/dist/calendar/hijri/index.js +4 -0
  38. package/dist/calendar/hijri/index.js.map +1 -0
  39. package/dist/calendar/hijri/tabular-adapter.d.ts +4 -0
  40. package/dist/calendar/hijri/tabular-adapter.js +79 -0
  41. package/dist/calendar/hijri/tabular-adapter.js.map +1 -0
  42. package/dist/calendar/hijri/umm-al-qura-adapter.d.ts +4 -0
  43. package/dist/calendar/hijri/umm-al-qura-adapter.js +27 -0
  44. package/dist/calendar/hijri/umm-al-qura-adapter.js.map +1 -0
  45. package/dist/calendar/index.d.ts +13 -0
  46. package/dist/calendar/index.js +12 -0
  47. package/dist/calendar/index.js.map +1 -0
  48. package/dist/calendar/indian/adapter.d.ts +2 -0
  49. package/dist/calendar/indian/adapter.js +66 -0
  50. package/dist/calendar/indian/adapter.js.map +1 -0
  51. package/dist/calendar/indian/constants.d.ts +5 -0
  52. package/dist/calendar/indian/constants.js +43 -0
  53. package/dist/calendar/indian/constants.js.map +1 -0
  54. package/dist/calendar/indian/index.d.ts +3 -0
  55. package/dist/calendar/indian/index.js +4 -0
  56. package/dist/calendar/indian/index.js.map +1 -0
  57. package/dist/calendar/indian/validator.d.ts +6 -0
  58. package/dist/calendar/indian/validator.js +65 -0
  59. package/dist/calendar/indian/validator.js.map +1 -0
  60. package/dist/calendar/japanese/adapter.d.ts +3 -0
  61. package/dist/calendar/japanese/adapter.js +63 -0
  62. package/dist/calendar/japanese/adapter.js.map +1 -0
  63. package/dist/calendar/japanese/constants.d.ts +17 -0
  64. package/dist/calendar/japanese/constants.js +85 -0
  65. package/dist/calendar/japanese/constants.js.map +1 -0
  66. package/dist/calendar/japanese/index.d.ts +3 -0
  67. package/dist/calendar/japanese/index.js +4 -0
  68. package/dist/calendar/japanese/index.js.map +1 -0
  69. package/dist/calendar/japanese/validator.d.ts +5 -0
  70. package/dist/calendar/japanese/validator.js +76 -0
  71. package/dist/calendar/japanese/validator.js.map +1 -0
  72. package/dist/calendar/persian/adapter.d.ts +2 -0
  73. package/dist/calendar/persian/adapter.js +42 -0
  74. package/dist/calendar/persian/adapter.js.map +1 -0
  75. package/dist/calendar/persian/constants.d.ts +5 -0
  76. package/dist/calendar/persian/constants.js +43 -0
  77. package/dist/calendar/persian/constants.js.map +1 -0
  78. package/dist/calendar/persian/index.d.ts +4 -0
  79. package/dist/calendar/persian/index.js +5 -0
  80. package/dist/calendar/persian/index.js.map +1 -0
  81. package/dist/calendar/persian/math.d.ts +24 -0
  82. package/dist/calendar/persian/math.js +109 -0
  83. package/dist/calendar/persian/math.js.map +1 -0
  84. package/dist/calendar/persian/validator.d.ts +4 -0
  85. package/dist/calendar/persian/validator.js +52 -0
  86. package/dist/calendar/persian/validator.js.map +1 -0
  87. package/dist/calendar/registry.d.ts +9 -0
  88. package/dist/calendar/registry.js +119 -0
  89. package/dist/calendar/registry.js.map +1 -0
  90. package/dist/calendar/roc/adapter.d.ts +2 -0
  91. package/dist/calendar/roc/adapter.js +47 -0
  92. package/dist/calendar/roc/adapter.js.map +1 -0
  93. package/dist/calendar/roc/constants.d.ts +6 -0
  94. package/dist/calendar/roc/constants.js +34 -0
  95. package/dist/calendar/roc/constants.js.map +1 -0
  96. package/dist/calendar/roc/index.d.ts +3 -0
  97. package/dist/calendar/roc/index.js +4 -0
  98. package/dist/calendar/roc/index.js.map +1 -0
  99. package/dist/calendar/roc/validator.d.ts +4 -0
  100. package/dist/calendar/roc/validator.js +52 -0
  101. package/dist/calendar/roc/validator.js.map +1 -0
  102. package/dist/calendar/types.d.ts +34 -0
  103. package/dist/calendar/types.js +2 -0
  104. package/dist/calendar/types.js.map +1 -0
  105. package/dist/core/absolute-day.d.ts +8 -0
  106. package/dist/core/absolute-day.js +39 -0
  107. package/dist/core/absolute-day.js.map +1 -0
  108. package/dist/core/calendar-date.d.ts +11 -0
  109. package/dist/core/calendar-date.js +37 -0
  110. package/dist/core/calendar-date.js.map +1 -0
  111. package/dist/core/day-of-year.d.ts +16 -0
  112. package/dist/core/day-of-year.js +30 -0
  113. package/dist/core/day-of-year.js.map +1 -0
  114. package/dist/core/duration.d.ts +2 -0
  115. package/dist/core/duration.js +31 -0
  116. package/dist/core/duration.js.map +1 -0
  117. package/dist/core/fiscal.d.ts +31 -0
  118. package/dist/core/fiscal.js +45 -0
  119. package/dist/core/fiscal.js.map +1 -0
  120. package/dist/core/gregorian-math.d.ts +4 -0
  121. package/dist/core/gregorian-math.js +30 -0
  122. package/dist/core/gregorian-math.js.map +1 -0
  123. package/dist/core/instant.d.ts +6 -0
  124. package/dist/core/instant.js +26 -0
  125. package/dist/core/instant.js.map +1 -0
  126. package/dist/core/integer.d.ts +1 -0
  127. package/dist/core/integer.js +7 -0
  128. package/dist/core/integer.js.map +1 -0
  129. package/dist/core/iso-week.d.ts +19 -0
  130. package/dist/core/iso-week.js +41 -0
  131. package/dist/core/iso-week.js.map +1 -0
  132. package/dist/core/julian-day.d.ts +26 -0
  133. package/dist/core/julian-day.js +35 -0
  134. package/dist/core/julian-day.js.map +1 -0
  135. package/dist/core/local-date-time.d.ts +2 -0
  136. package/dist/core/local-date-time.js +15 -0
  137. package/dist/core/local-date-time.js.map +1 -0
  138. package/dist/core/local-date.d.ts +2 -0
  139. package/dist/core/local-date.js +22 -0
  140. package/dist/core/local-date.js.map +1 -0
  141. package/dist/core/local-time.d.ts +2 -0
  142. package/dist/core/local-time.js +28 -0
  143. package/dist/core/local-time.js.map +1 -0
  144. package/dist/core/range.d.ts +2 -0
  145. package/dist/core/range.js +9 -0
  146. package/dist/core/range.js.map +1 -0
  147. package/dist/create-chronera.d.ts +2 -0
  148. package/dist/create-chronera.js +59 -0
  149. package/dist/create-chronera.js.map +1 -0
  150. package/dist/errors/error-codes.d.ts +1 -0
  151. package/dist/errors/error-codes.js +2 -0
  152. package/dist/errors/error-codes.js.map +1 -0
  153. package/dist/errors/errors.d.ts +16 -0
  154. package/dist/errors/errors.js +22 -0
  155. package/dist/errors/errors.js.map +1 -0
  156. package/dist/errors/index.d.ts +2 -0
  157. package/dist/errors/index.js +2 -0
  158. package/dist/errors/index.js.map +1 -0
  159. package/dist/format/format-date-range.d.ts +2 -0
  160. package/dist/format/format-date-range.js +89 -0
  161. package/dist/format/format-date-range.js.map +1 -0
  162. package/dist/format/format-date-time.d.ts +2 -0
  163. package/dist/format/format-date-time.js +51 -0
  164. package/dist/format/format-date-time.js.map +1 -0
  165. package/dist/format/format-date.d.ts +4 -0
  166. package/dist/format/format-date.js +103 -0
  167. package/dist/format/format-date.js.map +1 -0
  168. package/dist/format/format-pattern.d.ts +4 -0
  169. package/dist/format/format-pattern.js +266 -0
  170. package/dist/format/format-pattern.js.map +1 -0
  171. package/dist/format/format-relative.d.ts +2 -0
  172. package/dist/format/format-relative.js +93 -0
  173. package/dist/format/format-relative.js.map +1 -0
  174. package/dist/format/format-time.d.ts +2 -0
  175. package/dist/format/format-time.js +48 -0
  176. package/dist/format/format-time.js.map +1 -0
  177. package/dist/format/index.d.ts +13 -0
  178. package/dist/format/index.js +12 -0
  179. package/dist/format/index.js.map +1 -0
  180. package/dist/format/pattern-scanner.d.ts +8 -0
  181. package/dist/format/pattern-scanner.js +102 -0
  182. package/dist/format/pattern-scanner.js.map +1 -0
  183. package/dist/format/presets/japanese-official.d.ts +8 -0
  184. package/dist/format/presets/japanese-official.js +39 -0
  185. package/dist/format/presets/japanese-official.js.map +1 -0
  186. package/dist/format/presets/taiwan-official.d.ts +6 -0
  187. package/dist/format/presets/taiwan-official.js +23 -0
  188. package/dist/format/presets/taiwan-official.js.map +1 -0
  189. package/dist/format/presets/thai-official.d.ts +2 -0
  190. package/dist/format/presets/thai-official.js +45 -0
  191. package/dist/format/presets/thai-official.js.map +1 -0
  192. package/dist/format/presets/types.d.ts +2 -0
  193. package/dist/format/presets/types.js +2 -0
  194. package/dist/format/presets/types.js.map +1 -0
  195. package/dist/format/presets/world-locales.d.ts +29 -0
  196. package/dist/format/presets/world-locales.js +330 -0
  197. package/dist/format/presets/world-locales.js.map +1 -0
  198. package/dist/format/resolve-date-input.d.ts +9 -0
  199. package/dist/format/resolve-date-input.js +93 -0
  200. package/dist/format/resolve-date-input.js.map +1 -0
  201. package/dist/format/rfc2822.d.ts +17 -0
  202. package/dist/format/rfc2822.js +59 -0
  203. package/dist/format/rfc2822.js.map +1 -0
  204. package/dist/index.d.ts +19 -0
  205. package/dist/index.js +19 -0
  206. package/dist/index.js.map +1 -0
  207. package/dist/internal/engine.d.ts +8 -0
  208. package/dist/internal/engine.js +11 -0
  209. package/dist/internal/engine.js.map +1 -0
  210. package/dist/locale/numbering-system.d.ts +4 -0
  211. package/dist/locale/numbering-system.js +133 -0
  212. package/dist/locale/numbering-system.js.map +1 -0
  213. package/dist/locale/resolve-locale.d.ts +7 -0
  214. package/dist/locale/resolve-locale.js +51 -0
  215. package/dist/locale/resolve-locale.js.map +1 -0
  216. package/dist/locale/types.d.ts +1 -0
  217. package/dist/locale/types.js +2 -0
  218. package/dist/locale/types.js.map +1 -0
  219. package/dist/operations/arithmetic.d.ts +4 -0
  220. package/dist/operations/arithmetic.js +13 -0
  221. package/dist/operations/arithmetic.js.map +1 -0
  222. package/dist/operations/compare.d.ts +5 -0
  223. package/dist/operations/compare.js +50 -0
  224. package/dist/operations/compare.js.map +1 -0
  225. package/dist/operations/convert-calendar-date.d.ts +4 -0
  226. package/dist/operations/convert-calendar-date.js +54 -0
  227. package/dist/operations/convert-calendar-date.js.map +1 -0
  228. package/dist/operations/day-of-year.d.ts +7 -0
  229. package/dist/operations/day-of-year.js +29 -0
  230. package/dist/operations/day-of-year.js.map +1 -0
  231. package/dist/operations/fiscal.d.ts +5 -0
  232. package/dist/operations/fiscal.js +25 -0
  233. package/dist/operations/fiscal.js.map +1 -0
  234. package/dist/operations/iso-week.d.ts +9 -0
  235. package/dist/operations/iso-week.js +29 -0
  236. package/dist/operations/iso-week.js.map +1 -0
  237. package/dist/operations/julian-day.d.ts +6 -0
  238. package/dist/operations/julian-day.js +37 -0
  239. package/dist/operations/julian-day.js.map +1 -0
  240. package/dist/operations/validate.d.ts +10 -0
  241. package/dist/operations/validate.js +55 -0
  242. package/dist/operations/validate.js.map +1 -0
  243. package/dist/parse/field-normalizer.d.ts +1 -0
  244. package/dist/parse/field-normalizer.js +5 -0
  245. package/dist/parse/field-normalizer.js.map +1 -0
  246. package/dist/parse/index.d.ts +4 -0
  247. package/dist/parse/index.js +4 -0
  248. package/dist/parse/index.js.map +1 -0
  249. package/dist/parse/parse-instant.d.ts +2 -0
  250. package/dist/parse/parse-instant.js +97 -0
  251. package/dist/parse/parse-instant.js.map +1 -0
  252. package/dist/parse/parse-local-date.d.ts +2 -0
  253. package/dist/parse/parse-local-date.js +31 -0
  254. package/dist/parse/parse-local-date.js.map +1 -0
  255. package/dist/parse/pattern-parser.d.ts +2 -0
  256. package/dist/parse/pattern-parser.js +150 -0
  257. package/dist/parse/pattern-parser.js.map +1 -0
  258. package/dist/parse/safe-parse.d.ts +3 -0
  259. package/dist/parse/safe-parse.js +46 -0
  260. package/dist/parse/safe-parse.js.map +1 -0
  261. package/dist/public-types.d.ts +209 -0
  262. package/dist/public-types.js +2 -0
  263. package/dist/public-types.js.map +1 -0
  264. package/dist/runtime/bounded-lru.d.ts +11 -0
  265. package/dist/runtime/bounded-lru.js +42 -0
  266. package/dist/runtime/bounded-lru.js.map +1 -0
  267. package/dist/runtime/capabilities.d.ts +5 -0
  268. package/dist/runtime/capabilities.js +61 -0
  269. package/dist/runtime/capabilities.js.map +1 -0
  270. package/dist/runtime/intl-date-time.d.ts +11 -0
  271. package/dist/runtime/intl-date-time.js +38 -0
  272. package/dist/runtime/intl-date-time.js.map +1 -0
  273. package/dist/runtime/intl-number.d.ts +7 -0
  274. package/dist/runtime/intl-number.js +35 -0
  275. package/dist/runtime/intl-number.js.map +1 -0
  276. package/dist/runtime/intl-relative-time.d.ts +7 -0
  277. package/dist/runtime/intl-relative-time.js +35 -0
  278. package/dist/runtime/intl-relative-time.js.map +1 -0
  279. package/dist/runtime/timezone.d.ts +14 -0
  280. package/dist/runtime/timezone.js +95 -0
  281. package/dist/runtime/timezone.js.map +1 -0
  282. package/package.json +155 -0
@@ -0,0 +1,37 @@
1
+ import { defaultCalendarRegistry } from "../calendar/registry.js";
2
+ import { absoluteDayFromGregorianFields, gregorianFieldsFromAbsoluteDay, } from "../core/absolute-day.js";
3
+ import { fromJulianDayNumber as coreFromJdn, fromModifiedJulianDay as coreFromMjd, toJulianDayNumber as coreToJdn, toModifiedJulianDay as coreToMjd, } from "../core/julian-day.js";
4
+ import { localDate } from "../core/local-date.js";
5
+ import { ChroneraError } from "../errors/errors.js";
6
+ function getAbsoluteDay(input, registry) {
7
+ if (input.kind === "local-date") {
8
+ return absoluteDayFromGregorianFields(input.year, input.month, input.day);
9
+ }
10
+ if (input.kind === "calendar-date") {
11
+ const adapter = registry.getAdapter(input.calendar);
12
+ if (!adapter.converter) {
13
+ throw new ChroneraError("CHRONERA_UNSUPPORTED_OPERATION", `Calendar "${input.calendar}" does not support conversion to absolute day.`);
14
+ }
15
+ return adapter.converter.toAbsoluteDay(input);
16
+ }
17
+ throw new ChroneraError("CHRONERA_INVALID_DATE", "Invalid input for Julian Day calculation; expected LocalDate or CalendarDate.");
18
+ }
19
+ export function toJulianDayNumber(input, registry = defaultCalendarRegistry) {
20
+ const absDay = getAbsoluteDay(input, registry);
21
+ return coreToJdn(absDay);
22
+ }
23
+ export function toModifiedJulianDay(input, registry = defaultCalendarRegistry) {
24
+ const absDay = getAbsoluteDay(input, registry);
25
+ return coreToMjd(absDay);
26
+ }
27
+ export function localDateFromJulianDayNumber(jdn) {
28
+ const absDay = coreFromJdn(jdn);
29
+ const { year, month, day } = gregorianFieldsFromAbsoluteDay(absDay);
30
+ return localDate(year, month, day);
31
+ }
32
+ export function localDateFromModifiedJulianDay(mjd) {
33
+ const absDay = coreFromMjd(mjd);
34
+ const { year, month, day } = gregorianFieldsFromAbsoluteDay(absDay);
35
+ return localDate(year, month, day);
36
+ }
37
+ //# sourceMappingURL=julian-day.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"julian-day.js","sourceRoot":"","sources":["../../src/operations/julian-day.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EACL,8BAA8B,EAC9B,8BAA8B,GAC/B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,mBAAmB,IAAI,WAAW,EAClC,qBAAqB,IAAI,WAAW,EACpC,iBAAiB,IAAI,SAAS,EAC9B,mBAAmB,IAAI,SAAS,GACjC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKpD,SAAS,cAAc,CACrB,KAA+B,EAC/B,QAA0B;IAE1B,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QAChC,OAAO,8BAA8B,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAC5E,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACpD,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;YACvB,MAAM,IAAI,aAAa,CACrB,gCAAgC,EAChC,aAAa,KAAK,CAAC,QAAQ,gDAAgD,CAC5E,CAAC;QACJ,CAAC;QACD,OAAO,OAAO,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC;IACD,MAAM,IAAI,aAAa,CACrB,uBAAuB,EACvB,+EAA+E,CAChF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,KAA+B,EAC/B,WAA6B,uBAAuB;IAEpD,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC/C,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,KAA+B,EAC/B,WAA6B,uBAAuB;IAEpD,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC/C,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,GAAW;IACtD,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,8BAA8B,CAAC,MAAM,CAAC,CAAC;IACpE,OAAO,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,8BAA8B,CAAC,GAAW;IACxD,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,8BAA8B,CAAC,MAAM,CAAC,CAAC;IACpE,OAAO,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AACrC,CAAC","sourcesContent":["import { defaultCalendarRegistry } from \"../calendar/registry.js\";\nimport {\n absoluteDayFromGregorianFields,\n gregorianFieldsFromAbsoluteDay,\n} from \"../core/absolute-day.js\";\nimport {\n fromJulianDayNumber as coreFromJdn,\n fromModifiedJulianDay as coreFromMjd,\n toJulianDayNumber as coreToJdn,\n toModifiedJulianDay as coreToMjd,\n} from \"../core/julian-day.js\";\nimport { localDate } from \"../core/local-date.js\";\nimport { ChroneraError } from \"../errors/errors.js\";\n\nimport type { CalendarRegistry } from \"../calendar/registry.js\";\nimport type { CalendarDate, LocalDate } from \"../public-types.js\";\n\nfunction getAbsoluteDay(\n input: LocalDate | CalendarDate,\n registry: CalendarRegistry,\n): number {\n if (input.kind === \"local-date\") {\n return absoluteDayFromGregorianFields(input.year, input.month, input.day);\n }\n if (input.kind === \"calendar-date\") {\n const adapter = registry.getAdapter(input.calendar);\n if (!adapter.converter) {\n throw new ChroneraError(\n \"CHRONERA_UNSUPPORTED_OPERATION\",\n `Calendar \"${input.calendar}\" does not support conversion to absolute day.`,\n );\n }\n return adapter.converter.toAbsoluteDay(input);\n }\n throw new ChroneraError(\n \"CHRONERA_INVALID_DATE\",\n \"Invalid input for Julian Day calculation; expected LocalDate or CalendarDate.\",\n );\n}\n\nexport function toJulianDayNumber(\n input: LocalDate | CalendarDate,\n registry: CalendarRegistry = defaultCalendarRegistry,\n): number {\n const absDay = getAbsoluteDay(input, registry);\n return coreToJdn(absDay);\n}\n\nexport function toModifiedJulianDay(\n input: LocalDate | CalendarDate,\n registry: CalendarRegistry = defaultCalendarRegistry,\n): number {\n const absDay = getAbsoluteDay(input, registry);\n return coreToMjd(absDay);\n}\n\nexport function localDateFromJulianDayNumber(jdn: number): LocalDate {\n const absDay = coreFromJdn(jdn);\n const { year, month, day } = gregorianFieldsFromAbsoluteDay(absDay);\n return localDate(year, month, day);\n}\n\nexport function localDateFromModifiedJulianDay(mjd: number): LocalDate {\n const absDay = coreFromMjd(mjd);\n const { year, month, day } = gregorianFieldsFromAbsoluteDay(absDay);\n return localDate(year, month, day);\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import type { CalendarCapabilities, CalendarDate, CalendarId, MonthCode } from "../public-types.js";
2
+ import type { CalendarRegistry } from "../calendar/registry.js";
3
+ export declare function isValidCalendarDateWithRegistry(registry: CalendarRegistry, value: CalendarDate): boolean;
4
+ export declare function isValidCalendarDate(value: CalendarDate): boolean;
5
+ export declare function daysInMonthWithRegistry(registry: CalendarRegistry, year: number, monthCode: MonthCode, calendar: CalendarId): number;
6
+ export declare function daysInMonth(year: number, monthCode: MonthCode, calendar: CalendarId): number;
7
+ export declare function isLeapYearWithRegistry(registry: CalendarRegistry, year: number, calendar: CalendarId): boolean;
8
+ export declare function isLeapYear(year: number, calendar: CalendarId): boolean;
9
+ export declare function getCalendarCapabilitiesWithRegistry(registry: CalendarRegistry, calendar: CalendarId): CalendarCapabilities;
10
+ export declare function getCalendarCapabilities(calendar: CalendarId): CalendarCapabilities;
@@ -0,0 +1,55 @@
1
+ import { defaultCalendarRegistry } from "../calendar/registry.js";
2
+ import { ChroneraError } from "../errors/errors.js";
3
+ export function isValidCalendarDateWithRegistry(registry, value) {
4
+ const adapter = registry.getAdapter(value.calendar);
5
+ const issues = adapter.validator.validate(value);
6
+ return issues.length === 0;
7
+ }
8
+ export function isValidCalendarDate(value) {
9
+ return isValidCalendarDateWithRegistry(defaultCalendarRegistry, value);
10
+ }
11
+ export function daysInMonthWithRegistry(registry, year, monthCode, calendar) {
12
+ const adapter = registry.getAdapter(calendar);
13
+ return adapter.validator.daysInMonth(year, monthCode);
14
+ }
15
+ export function daysInMonth(year, monthCode, calendar) {
16
+ return daysInMonthWithRegistry(defaultCalendarRegistry, year, monthCode, calendar);
17
+ }
18
+ export function isLeapYearWithRegistry(registry, year, calendar) {
19
+ const adapter = registry.getAdapter(calendar);
20
+ return adapter.validator.isLeapYear(year);
21
+ }
22
+ export function isLeapYear(year, calendar) {
23
+ return isLeapYearWithRegistry(defaultCalendarRegistry, year, calendar);
24
+ }
25
+ export function getCalendarCapabilitiesWithRegistry(registry, calendar) {
26
+ if (!registry.hasAdapter(calendar)) {
27
+ throw new ChroneraError("CHRONERA_UNSUPPORTED_CALENDAR", `Calendar "${calendar}" is not configured.`);
28
+ }
29
+ const adapter = registry.getAdapter(calendar);
30
+ const identity = adapter.identity;
31
+ return {
32
+ calendar,
33
+ maturity: identity.deterministic ? "stable" : "runtime-dependent",
34
+ canFormat: true,
35
+ canParse: true,
36
+ canConvertFromAbsoluteDate: adapter.converter !== undefined,
37
+ canConvertToAbsoluteDate: adapter.converter !== undefined,
38
+ canValidate: true,
39
+ canAddYears: adapter.arithmetic !== undefined,
40
+ canAddMonths: adapter.arithmetic !== undefined,
41
+ deterministic: identity.deterministic,
42
+ algorithm: identity.algorithm,
43
+ ...(identity.dataVersion !== undefined
44
+ ? { dataVersion: identity.dataVersion }
45
+ : {}),
46
+ ...(identity.validFrom !== undefined
47
+ ? { validFrom: identity.validFrom }
48
+ : {}),
49
+ ...(identity.validTo !== undefined ? { validTo: identity.validTo } : {}),
50
+ };
51
+ }
52
+ export function getCalendarCapabilities(calendar) {
53
+ return getCalendarCapabilitiesWithRegistry(defaultCalendarRegistry, calendar);
54
+ }
55
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/operations/validate.ts"],"names":[],"mappings":"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","sourcesContent":["import { defaultCalendarRegistry } from \"../calendar/registry.js\";\nimport { ChroneraError } from \"../errors/errors.js\";\n\nimport type {\n CalendarCapabilities,\n CalendarDate,\n CalendarId,\n MonthCode,\n} from \"../public-types.js\";\nimport type { CalendarRegistry } from \"../calendar/registry.js\";\n\nexport function isValidCalendarDateWithRegistry(\n registry: CalendarRegistry,\n value: CalendarDate,\n): boolean {\n const adapter = registry.getAdapter(value.calendar);\n const issues = adapter.validator.validate(value);\n return issues.length === 0;\n}\n\nexport function isValidCalendarDate(value: CalendarDate): boolean {\n return isValidCalendarDateWithRegistry(defaultCalendarRegistry, value);\n}\n\nexport function daysInMonthWithRegistry(\n registry: CalendarRegistry,\n year: number,\n monthCode: MonthCode,\n calendar: CalendarId,\n): number {\n const adapter = registry.getAdapter(calendar);\n return adapter.validator.daysInMonth(year, monthCode);\n}\n\nexport function daysInMonth(\n year: number,\n monthCode: MonthCode,\n calendar: CalendarId,\n): number {\n return daysInMonthWithRegistry(\n defaultCalendarRegistry,\n year,\n monthCode,\n calendar,\n );\n}\n\nexport function isLeapYearWithRegistry(\n registry: CalendarRegistry,\n year: number,\n calendar: CalendarId,\n): boolean {\n const adapter = registry.getAdapter(calendar);\n return adapter.validator.isLeapYear(year);\n}\n\nexport function isLeapYear(year: number, calendar: CalendarId): boolean {\n return isLeapYearWithRegistry(defaultCalendarRegistry, year, calendar);\n}\n\nexport function getCalendarCapabilitiesWithRegistry(\n registry: CalendarRegistry,\n calendar: CalendarId,\n): CalendarCapabilities {\n if (!registry.hasAdapter(calendar)) {\n throw new ChroneraError(\n \"CHRONERA_UNSUPPORTED_CALENDAR\",\n `Calendar \"${calendar}\" is not configured.`,\n );\n }\n\n const adapter = registry.getAdapter(calendar);\n const identity = adapter.identity;\n\n return {\n calendar,\n maturity: identity.deterministic ? \"stable\" : \"runtime-dependent\",\n canFormat: true,\n canParse: true,\n canConvertFromAbsoluteDate: adapter.converter !== undefined,\n canConvertToAbsoluteDate: adapter.converter !== undefined,\n canValidate: true,\n canAddYears: adapter.arithmetic !== undefined,\n canAddMonths: adapter.arithmetic !== undefined,\n deterministic: identity.deterministic,\n algorithm: identity.algorithm,\n ...(identity.dataVersion !== undefined\n ? { dataVersion: identity.dataVersion }\n : {}),\n ...(identity.validFrom !== undefined\n ? { validFrom: identity.validFrom }\n : {}),\n ...(identity.validTo !== undefined ? { validTo: identity.validTo } : {}),\n };\n}\n\nexport function getCalendarCapabilities(\n calendar: CalendarId,\n): CalendarCapabilities {\n return getCalendarCapabilitiesWithRegistry(defaultCalendarRegistry, calendar);\n}\n"]}
@@ -0,0 +1 @@
1
+ export declare function normalizeInputDigits(input: string): string;
@@ -0,0 +1,5 @@
1
+ import { parseDigitsToLatin } from "../locale/numbering-system.js";
2
+ export function normalizeInputDigits(input) {
3
+ return parseDigitsToLatin(input);
4
+ }
5
+ //# sourceMappingURL=field-normalizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-normalizer.js","sourceRoot":"","sources":["../../src/parse/field-normalizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC","sourcesContent":["import { parseDigitsToLatin } from \"../locale/numbering-system.js\";\n\nexport function normalizeInputDigits(input: string): string {\n return parseDigitsToLatin(input);\n}\n"]}
@@ -0,0 +1,4 @@
1
+ export { parseLocalDate } from "./parse-local-date.js";
2
+ export { safeParseLocalDate, safeParseInstant } from "./safe-parse.js";
3
+ export { parseInstant } from "./parse-instant.js";
4
+ export type { ParseInstantOptions, ParseLocalDateOptions, SafeParseResult, } from "../public-types.js";
@@ -0,0 +1,4 @@
1
+ export { parseLocalDate } from "./parse-local-date.js";
2
+ export { safeParseLocalDate, safeParseInstant } from "./safe-parse.js";
3
+ export { parseInstant } from "./parse-instant.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parse/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC","sourcesContent":["export { parseLocalDate } from \"./parse-local-date.js\";\nexport { safeParseLocalDate, safeParseInstant } from \"./safe-parse.js\";\nexport { parseInstant } from \"./parse-instant.js\";\n\nexport type {\n ParseInstantOptions,\n ParseLocalDateOptions,\n SafeParseResult,\n} from \"../public-types.js\";\n"]}
@@ -0,0 +1,2 @@
1
+ import type { Instant, ParseInstantOptions } from "../public-types.js";
2
+ export declare function parseInstant(input: string, options?: Readonly<ParseInstantOptions>): Instant;
@@ -0,0 +1,97 @@
1
+ import { ChroneraError, ChroneraParseError } from "../errors/errors.js";
2
+ import { daysInGregorianMonth } from "../core/gregorian-math.js";
3
+ import { instantFromEpochMilliseconds, MAX_EPOCH_MILLISECONDS, MIN_EPOCH_MILLISECONDS, } from "../core/instant.js";
4
+ const RFC3339_REGEX = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(\.\d+)?(Z|([+-])(\d{2}):(\d{2}))$/;
5
+ export function parseInstant(input, options) {
6
+ if (typeof input !== "string") {
7
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Expected string input; received ${typeof input}.`);
8
+ }
9
+ if (input.length > 4096) {
10
+ throw new ChroneraError("CHRONERA_INPUT_TOO_LONG", `Input length ${input.length} exceeds maximum allowed limit of 4096 characters.`);
11
+ }
12
+ // Reject -00:00 specifically
13
+ if (input.endsWith("-00:00")) {
14
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", "Offset '-00:00' is not accepted in this RFC 3339 profile.");
15
+ }
16
+ const match = RFC3339_REGEX.exec(input);
17
+ if (!match) {
18
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Invalid RFC 3339 timestamp format: "${input}". An explicit offset (Z or ±HH:mm) is required.`);
19
+ }
20
+ const year = Number.parseInt(match[1], 10);
21
+ const month = Number.parseInt(match[2], 10);
22
+ const day = Number.parseInt(match[3], 10);
23
+ const hour = Number.parseInt(match[4], 10);
24
+ const minute = Number.parseInt(match[5], 10);
25
+ const second = Number.parseInt(match[6], 10);
26
+ const fractionStr = match[7]; // e.g. ".1234"
27
+ const tzOffset = match[8]; // "Z" or "+HH:mm"
28
+ if (year < 1 || year > 9999) {
29
+ throw new ChroneraParseError("CHRONERA_OUT_OF_RANGE", `Year ${year} is outside supported range [0001, 9999].`);
30
+ }
31
+ if (month < 1 || month > 12) {
32
+ throw new ChroneraParseError("CHRONERA_INVALID_DATE", `Month must be between 1 and 12; received ${month}.`);
33
+ }
34
+ const maxDay = daysInGregorianMonth(year, month);
35
+ if (day < 1 || day > maxDay) {
36
+ throw new ChroneraParseError("CHRONERA_INVALID_DATE", `Day ${day} is invalid for month ${month} in year ${year}.`);
37
+ }
38
+ if (hour < 0 || hour > 23) {
39
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Hour must be between 0 and 23; received ${hour}. Hour 24 is rejected.`);
40
+ }
41
+ if (minute < 0 || minute > 59) {
42
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Minute must be between 0 and 59; received ${minute}.`);
43
+ }
44
+ if (second < 0 || second > 59) {
45
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Second must be between 0 and 59; received ${second}. Leap seconds are not supported.`);
46
+ }
47
+ // Parse fraction of second
48
+ let millisecond = 0;
49
+ let carrySeconds = 0;
50
+ if (fractionStr) {
51
+ const rawDigits = fractionStr.slice(1); // strip leading dot
52
+ const mode = options?.excessFractionalSeconds ?? "reject";
53
+ if (rawDigits.length <= 3) {
54
+ millisecond = Number.parseInt(rawDigits.padEnd(3, "0"), 10);
55
+ }
56
+ else {
57
+ const excess = rawDigits.slice(3);
58
+ const hasExcessPrecision = /[1-9]/.test(excess);
59
+ if (mode === "reject" && hasExcessPrecision) {
60
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Excess fractional second precision beyond milliseconds encountered in "${input}".`);
61
+ }
62
+ if (mode === "truncate" || !hasExcessPrecision) {
63
+ millisecond = Number.parseInt(rawDigits.slice(0, 3), 10);
64
+ }
65
+ else if (mode === "round") {
66
+ const floatVal = Number.parseFloat(`0.${rawDigits}`) * 1000;
67
+ const rounded = Math.round(floatVal);
68
+ if (rounded >= 1000) {
69
+ carrySeconds = Math.floor(rounded / 1000);
70
+ millisecond = rounded % 1000;
71
+ }
72
+ else {
73
+ millisecond = rounded;
74
+ }
75
+ }
76
+ }
77
+ }
78
+ // Parse offset
79
+ let offsetMs = 0;
80
+ if (tzOffset !== "Z") {
81
+ const sign = match[9] === "-" ? -1 : 1;
82
+ const offHour = Number.parseInt(match[10], 10);
83
+ const offMin = Number.parseInt(match[11], 10);
84
+ if (offHour > 23 || offMin > 59) {
85
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Invalid offset in timestamp: "${tzOffset}".`);
86
+ }
87
+ offsetMs = sign * (offHour * 60 + offMin) * 60000;
88
+ }
89
+ // Calculate UTC epoch ms
90
+ const baseUtcMs = Date.UTC(year, month - 1, day, hour, minute, second);
91
+ const totalMs = baseUtcMs + carrySeconds * 1000 + millisecond - offsetMs;
92
+ if (totalMs < MIN_EPOCH_MILLISECONDS || totalMs > MAX_EPOCH_MILLISECONDS) {
93
+ throw new ChroneraError("CHRONERA_OUT_OF_RANGE", `Timestamp "${input}" resolves to epoch milliseconds ${totalMs}, outside supported range.`);
94
+ }
95
+ return instantFromEpochMilliseconds(totalMs);
96
+ }
97
+ //# sourceMappingURL=parse-instant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-instant.js","sourceRoot":"","sources":["../../src/parse/parse-instant.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChroneraError, ChroneraParseError } from \"../errors/errors.js\";\nimport { daysInGregorianMonth } from \"../core/gregorian-math.js\";\nimport {\n instantFromEpochMilliseconds,\n MAX_EPOCH_MILLISECONDS,\n MIN_EPOCH_MILLISECONDS,\n} from \"../core/instant.js\";\n\nimport type { Instant, ParseInstantOptions } from \"../public-types.js\";\n\nconst RFC3339_REGEX =\n /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(\\.\\d+)?(Z|([+-])(\\d{2}):(\\d{2}))$/;\n\nexport function parseInstant(\n input: string,\n options?: Readonly<ParseInstantOptions>,\n): Instant {\n if (typeof input !== \"string\") {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Expected string input; received ${typeof input}.`,\n );\n }\n\n if (input.length > 4096) {\n throw new ChroneraError(\n \"CHRONERA_INPUT_TOO_LONG\",\n `Input length ${input.length} exceeds maximum allowed limit of 4096 characters.`,\n );\n }\n\n // Reject -00:00 specifically\n if (input.endsWith(\"-00:00\")) {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n \"Offset '-00:00' is not accepted in this RFC 3339 profile.\",\n );\n }\n\n const match = RFC3339_REGEX.exec(input);\n if (!match) {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Invalid RFC 3339 timestamp format: \"${input}\". An explicit offset (Z or ±HH:mm) is required.`,\n );\n }\n\n const year = Number.parseInt(match[1]!, 10);\n const month = Number.parseInt(match[2]!, 10);\n const day = Number.parseInt(match[3]!, 10);\n const hour = Number.parseInt(match[4]!, 10);\n const minute = Number.parseInt(match[5]!, 10);\n const second = Number.parseInt(match[6]!, 10);\n const fractionStr = match[7]; // e.g. \".1234\"\n const tzOffset = match[8]!; // \"Z\" or \"+HH:mm\"\n\n if (year < 1 || year > 9999) {\n throw new ChroneraParseError(\n \"CHRONERA_OUT_OF_RANGE\",\n `Year ${year} is outside supported range [0001, 9999].`,\n );\n }\n\n if (month < 1 || month > 12) {\n throw new ChroneraParseError(\n \"CHRONERA_INVALID_DATE\",\n `Month must be between 1 and 12; received ${month}.`,\n );\n }\n\n const maxDay = daysInGregorianMonth(year, month);\n if (day < 1 || day > maxDay) {\n throw new ChroneraParseError(\n \"CHRONERA_INVALID_DATE\",\n `Day ${day} is invalid for month ${month} in year ${year}.`,\n );\n }\n\n if (hour < 0 || hour > 23) {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Hour must be between 0 and 23; received ${hour}. Hour 24 is rejected.`,\n );\n }\n\n if (minute < 0 || minute > 59) {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Minute must be between 0 and 59; received ${minute}.`,\n );\n }\n\n if (second < 0 || second > 59) {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Second must be between 0 and 59; received ${second}. Leap seconds are not supported.`,\n );\n }\n\n // Parse fraction of second\n let millisecond = 0;\n let carrySeconds = 0;\n if (fractionStr) {\n const rawDigits = fractionStr.slice(1); // strip leading dot\n const mode = options?.excessFractionalSeconds ?? \"reject\";\n\n if (rawDigits.length <= 3) {\n millisecond = Number.parseInt(rawDigits.padEnd(3, \"0\"), 10);\n } else {\n const excess = rawDigits.slice(3);\n const hasExcessPrecision = /[1-9]/.test(excess);\n\n if (mode === \"reject\" && hasExcessPrecision) {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Excess fractional second precision beyond milliseconds encountered in \"${input}\".`,\n );\n }\n\n if (mode === \"truncate\" || !hasExcessPrecision) {\n millisecond = Number.parseInt(rawDigits.slice(0, 3), 10);\n } else if (mode === \"round\") {\n const floatVal = Number.parseFloat(`0.${rawDigits}`) * 1000;\n const rounded = Math.round(floatVal);\n if (rounded >= 1000) {\n carrySeconds = Math.floor(rounded / 1000);\n millisecond = rounded % 1000;\n } else {\n millisecond = rounded;\n }\n }\n }\n }\n\n // Parse offset\n let offsetMs = 0;\n if (tzOffset !== \"Z\") {\n const sign = match[9] === \"-\" ? -1 : 1;\n const offHour = Number.parseInt(match[10]!, 10);\n const offMin = Number.parseInt(match[11]!, 10);\n\n if (offHour > 23 || offMin > 59) {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Invalid offset in timestamp: \"${tzOffset}\".`,\n );\n }\n offsetMs = sign * (offHour * 60 + offMin) * 60000;\n }\n\n // Calculate UTC epoch ms\n const baseUtcMs = Date.UTC(year, month - 1, day, hour, minute, second);\n const totalMs = baseUtcMs + carrySeconds * 1000 + millisecond - offsetMs;\n\n if (totalMs < MIN_EPOCH_MILLISECONDS || totalMs > MAX_EPOCH_MILLISECONDS) {\n throw new ChroneraError(\n \"CHRONERA_OUT_OF_RANGE\",\n `Timestamp \"${input}\" resolves to epoch milliseconds ${totalMs}, outside supported range.`,\n );\n }\n\n return instantFromEpochMilliseconds(totalMs);\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import type { LocalDate, ParseLocalDateOptions } from "../public-types.js";
2
+ export declare function parseLocalDate(input: string, options?: Readonly<ParseLocalDateOptions>): LocalDate;
@@ -0,0 +1,31 @@
1
+ import { ChroneraError, ChroneraParseError } from "../errors/errors.js";
2
+ import { localDate } from "../core/local-date.js";
3
+ import { parseDateWithPattern } from "./pattern-parser.js";
4
+ import { validateAndResolveLocale } from "../locale/resolve-locale.js";
5
+ const ISO_DATE_REGEX = /^(\d{4})-(\d{2})-(\d{2})$/;
6
+ export function parseLocalDate(input, options) {
7
+ if (typeof input !== "string") {
8
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Expected string input; received ${typeof input}.`);
9
+ }
10
+ if (input.length > 4096) {
11
+ throw new ChroneraError("CHRONERA_INPUT_TOO_LONG", `Input length ${input.length} exceeds maximum allowed limit of 4096 characters.`);
12
+ }
13
+ if (options?.pattern) {
14
+ const localeInfo = validateAndResolveLocale(options.locale);
15
+ return parseDateWithPattern(input, options.pattern, localeInfo.baseLocale);
16
+ }
17
+ // Strict ISO YYYY-MM-DD parser
18
+ const match = ISO_DATE_REGEX.exec(input);
19
+ if (!match) {
20
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Invalid ISO date format: "${input}". Expected format YYYY-MM-DD.`);
21
+ }
22
+ const year = Number.parseInt(match[1], 10);
23
+ const month = Number.parseInt(match[2], 10);
24
+ const day = Number.parseInt(match[3], 10);
25
+ if (year === 0) {
26
+ throw new ChroneraParseError("CHRONERA_INVALID_DATE", "Year zero is not accepted in this civil-date API.");
27
+ }
28
+ // localDate validates month and day bounds according to Gregorian calendar
29
+ return localDate(year, month, day);
30
+ }
31
+ //# sourceMappingURL=parse-local-date.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-local-date.js","sourceRoot":"","sources":["../../src/parse/parse-local-date.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAIvE,MAAM,cAAc,GAAG,2BAA2B,CAAC;AAEnD,MAAM,UAAU,cAAc,CAC5B,KAAa,EACb,OAAyC;IAEzC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,kBAAkB,CAC1B,uBAAuB,EACvB,mCAAmC,OAAO,KAAK,GAAG,CACnD,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;QACxB,MAAM,IAAI,aAAa,CACrB,yBAAyB,EACzB,gBAAgB,KAAK,CAAC,MAAM,oDAAoD,CACjF,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,EAAE,OAAO,EAAE,CAAC;QACrB,MAAM,UAAU,GAAG,wBAAwB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5D,OAAO,oBAAoB,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;IAC7E,CAAC;IAED,+BAA+B;IAC/B,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,kBAAkB,CAC1B,uBAAuB,EACvB,6BAA6B,KAAK,gCAAgC,CACnE,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;IAE3C,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;QACf,MAAM,IAAI,kBAAkB,CAC1B,uBAAuB,EACvB,mDAAmD,CACpD,CAAC;IACJ,CAAC;IAED,2EAA2E;IAC3E,OAAO,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AACrC,CAAC","sourcesContent":["import { ChroneraError, ChroneraParseError } from \"../errors/errors.js\";\nimport { localDate } from \"../core/local-date.js\";\nimport { parseDateWithPattern } from \"./pattern-parser.js\";\nimport { validateAndResolveLocale } from \"../locale/resolve-locale.js\";\n\nimport type { LocalDate, ParseLocalDateOptions } from \"../public-types.js\";\n\nconst ISO_DATE_REGEX = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\nexport function parseLocalDate(\n input: string,\n options?: Readonly<ParseLocalDateOptions>,\n): LocalDate {\n if (typeof input !== \"string\") {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Expected string input; received ${typeof input}.`,\n );\n }\n\n if (input.length > 4096) {\n throw new ChroneraError(\n \"CHRONERA_INPUT_TOO_LONG\",\n `Input length ${input.length} exceeds maximum allowed limit of 4096 characters.`,\n );\n }\n\n if (options?.pattern) {\n const localeInfo = validateAndResolveLocale(options.locale);\n return parseDateWithPattern(input, options.pattern, localeInfo.baseLocale);\n }\n\n // Strict ISO YYYY-MM-DD parser\n const match = ISO_DATE_REGEX.exec(input);\n if (!match) {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Invalid ISO date format: \"${input}\". Expected format YYYY-MM-DD.`,\n );\n }\n\n const year = Number.parseInt(match[1]!, 10);\n const month = Number.parseInt(match[2]!, 10);\n const day = Number.parseInt(match[3]!, 10);\n\n if (year === 0) {\n throw new ChroneraParseError(\n \"CHRONERA_INVALID_DATE\",\n \"Year zero is not accepted in this civil-date API.\",\n );\n }\n\n // localDate validates month and day bounds according to Gregorian calendar\n return localDate(year, month, day);\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import type { LocalDate } from "../public-types.js";
2
+ export declare function parseDateWithPattern(input: string, pattern: string, locale?: string): LocalDate;
@@ -0,0 +1,150 @@
1
+ import { scanPattern } from "../format/pattern-scanner.js";
2
+ import { ChroneraParseError } from "../errors/errors.js";
3
+ import { localDate } from "../core/local-date.js";
4
+ import { parseDigitsToLatin } from "../locale/numbering-system.js";
5
+ export function parseDateWithPattern(input, pattern, locale = "en-US") {
6
+ const tokens = scanPattern(pattern);
7
+ const normalizedInput = parseDigitsToLatin(input);
8
+ let pos = 0;
9
+ let year;
10
+ let month;
11
+ let day;
12
+ // Build month name tables for locale
13
+ const shortMonths = [];
14
+ const longMonths = [];
15
+ for (let m = 1; m <= 12; m++) {
16
+ const d = new Date(Date.UTC(2026, m - 1, 1));
17
+ shortMonths[m] = new Intl.DateTimeFormat(locale, {
18
+ month: "short",
19
+ timeZone: "UTC",
20
+ })
21
+ .format(d)
22
+ .toLowerCase();
23
+ longMonths[m] = new Intl.DateTimeFormat(locale, {
24
+ month: "long",
25
+ timeZone: "UTC",
26
+ })
27
+ .format(d)
28
+ .toLowerCase();
29
+ }
30
+ for (const token of tokens) {
31
+ if (token.type === "literal") {
32
+ const lit = token.value;
33
+ if (normalizedInput.slice(pos, pos + lit.length) !== lit) {
34
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Expected literal "${lit}" at position ${pos} in input "${input}".`);
35
+ }
36
+ pos += lit.length;
37
+ continue;
38
+ }
39
+ const sym = token.symbol;
40
+ if (sym === "yyyy") {
41
+ const chunk = normalizedInput.slice(pos, pos + 4);
42
+ if (!/^\d{4}$/.test(chunk)) {
43
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Expected 4-digit year at position ${pos}.`);
44
+ }
45
+ year = Number.parseInt(chunk, 10);
46
+ pos += 4;
47
+ }
48
+ else if (sym === "y") {
49
+ let run = "";
50
+ while (pos < normalizedInput.length && /\d/.test(normalizedInput[pos])) {
51
+ run += normalizedInput[pos];
52
+ pos++;
53
+ }
54
+ if (run.length === 0 || run.length > 6) {
55
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Expected 1 to 6 digit year at position ${pos}.`);
56
+ }
57
+ year = Number.parseInt(run, 10);
58
+ }
59
+ else if (sym === "MM") {
60
+ const chunk = normalizedInput.slice(pos, pos + 2);
61
+ if (!/^\d{2}$/.test(chunk)) {
62
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Expected 2-digit month at position ${pos}.`);
63
+ }
64
+ month = Number.parseInt(chunk, 10);
65
+ pos += 2;
66
+ }
67
+ else if (sym === "M") {
68
+ let run = "";
69
+ while (pos < normalizedInput.length &&
70
+ /\d/.test(normalizedInput[pos]) &&
71
+ run.length < 2) {
72
+ run += normalizedInput[pos];
73
+ pos++;
74
+ }
75
+ if (run.length === 0) {
76
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Expected numeric month at position ${pos}.`);
77
+ }
78
+ month = Number.parseInt(run, 10);
79
+ }
80
+ else if (sym === "MMM") {
81
+ let matched = false;
82
+ for (let m = 1; m <= 12; m++) {
83
+ const name = shortMonths[m];
84
+ if (normalizedInput.slice(pos, pos + name.length).toLowerCase() === name) {
85
+ month = m;
86
+ pos += name.length;
87
+ matched = true;
88
+ break;
89
+ }
90
+ }
91
+ if (!matched) {
92
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Expected abbreviated month name at position ${pos}.`);
93
+ }
94
+ }
95
+ else if (sym === "MMMM") {
96
+ let matched = false;
97
+ for (let m = 1; m <= 12; m++) {
98
+ const name = longMonths[m];
99
+ if (normalizedInput.slice(pos, pos + name.length).toLowerCase() === name) {
100
+ month = m;
101
+ pos += name.length;
102
+ matched = true;
103
+ break;
104
+ }
105
+ }
106
+ if (!matched) {
107
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Expected full month name at position ${pos}.`);
108
+ }
109
+ }
110
+ else if (sym === "dd") {
111
+ const chunk = normalizedInput.slice(pos, pos + 2);
112
+ if (!/^\d{2}$/.test(chunk)) {
113
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Expected 2-digit day at position ${pos}.`);
114
+ }
115
+ day = Number.parseInt(chunk, 10);
116
+ pos += 2;
117
+ }
118
+ else if (sym === "d") {
119
+ let run = "";
120
+ while (pos < normalizedInput.length &&
121
+ /\d/.test(normalizedInput[pos]) &&
122
+ run.length < 2) {
123
+ run += normalizedInput[pos];
124
+ pos++;
125
+ }
126
+ if (run.length === 0) {
127
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Expected numeric day at position ${pos}.`);
128
+ }
129
+ day = Number.parseInt(run, 10);
130
+ }
131
+ else if (sym === "G") {
132
+ // Consume era letters
133
+ while (pos < normalizedInput.length &&
134
+ /[A-Za-z]/.test(normalizedInput[pos])) {
135
+ pos++;
136
+ }
137
+ }
138
+ else {
139
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Unsupported parse pattern token: "${sym}".`);
140
+ }
141
+ }
142
+ if (pos !== normalizedInput.length) {
143
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", `Unexpected trailing data at position ${pos} in "${input}".`);
144
+ }
145
+ if (year === undefined || month === undefined || day === undefined) {
146
+ throw new ChroneraParseError("CHRONERA_PARSE_FAILED", "Pattern parsing did not extract all required fields (year, month, day).");
147
+ }
148
+ return localDate(year, month, day);
149
+ }
150
+ //# sourceMappingURL=pattern-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pattern-parser.js","sourceRoot":"","sources":["../../src/parse/pattern-parser.ts"],"names":[],"mappings":"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","sourcesContent":["import { scanPattern } from \"../format/pattern-scanner.js\";\nimport { ChroneraParseError } from \"../errors/errors.js\";\nimport { localDate } from \"../core/local-date.js\";\nimport { parseDigitsToLatin } from \"../locale/numbering-system.js\";\n\nimport type { LocalDate } from \"../public-types.js\";\n\nexport function parseDateWithPattern(\n input: string,\n pattern: string,\n locale: string = \"en-US\",\n): LocalDate {\n const tokens = scanPattern(pattern);\n const normalizedInput = parseDigitsToLatin(input);\n\n let pos = 0;\n let year: number | undefined;\n let month: number | undefined;\n let day: number | undefined;\n\n // Build month name tables for locale\n const shortMonths: string[] = [];\n const longMonths: string[] = [];\n for (let m = 1; m <= 12; m++) {\n const d = new Date(Date.UTC(2026, m - 1, 1));\n shortMonths[m] = new Intl.DateTimeFormat(locale, {\n month: \"short\",\n timeZone: \"UTC\",\n })\n .format(d)\n .toLowerCase();\n longMonths[m] = new Intl.DateTimeFormat(locale, {\n month: \"long\",\n timeZone: \"UTC\",\n })\n .format(d)\n .toLowerCase();\n }\n\n for (const token of tokens) {\n if (token.type === \"literal\") {\n const lit = token.value;\n if (normalizedInput.slice(pos, pos + lit.length) !== lit) {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Expected literal \"${lit}\" at position ${pos} in input \"${input}\".`,\n );\n }\n pos += lit.length;\n continue;\n }\n\n const sym = token.symbol;\n if (sym === \"yyyy\") {\n const chunk = normalizedInput.slice(pos, pos + 4);\n if (!/^\\d{4}$/.test(chunk)) {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Expected 4-digit year at position ${pos}.`,\n );\n }\n year = Number.parseInt(chunk, 10);\n pos += 4;\n } else if (sym === \"y\") {\n let run = \"\";\n while (pos < normalizedInput.length && /\\d/.test(normalizedInput[pos]!)) {\n run += normalizedInput[pos];\n pos++;\n }\n if (run.length === 0 || run.length > 6) {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Expected 1 to 6 digit year at position ${pos}.`,\n );\n }\n year = Number.parseInt(run, 10);\n } else if (sym === \"MM\") {\n const chunk = normalizedInput.slice(pos, pos + 2);\n if (!/^\\d{2}$/.test(chunk)) {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Expected 2-digit month at position ${pos}.`,\n );\n }\n month = Number.parseInt(chunk, 10);\n pos += 2;\n } else if (sym === \"M\") {\n let run = \"\";\n while (\n pos < normalizedInput.length &&\n /\\d/.test(normalizedInput[pos]!) &&\n run.length < 2\n ) {\n run += normalizedInput[pos];\n pos++;\n }\n if (run.length === 0) {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Expected numeric month at position ${pos}.`,\n );\n }\n month = Number.parseInt(run, 10);\n } else if (sym === \"MMM\") {\n let matched = false;\n for (let m = 1; m <= 12; m++) {\n const name = shortMonths[m]!;\n if (\n normalizedInput.slice(pos, pos + name.length).toLowerCase() === name\n ) {\n month = m;\n pos += name.length;\n matched = true;\n break;\n }\n }\n if (!matched) {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Expected abbreviated month name at position ${pos}.`,\n );\n }\n } else if (sym === \"MMMM\") {\n let matched = false;\n for (let m = 1; m <= 12; m++) {\n const name = longMonths[m]!;\n if (\n normalizedInput.slice(pos, pos + name.length).toLowerCase() === name\n ) {\n month = m;\n pos += name.length;\n matched = true;\n break;\n }\n }\n if (!matched) {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Expected full month name at position ${pos}.`,\n );\n }\n } else if (sym === \"dd\") {\n const chunk = normalizedInput.slice(pos, pos + 2);\n if (!/^\\d{2}$/.test(chunk)) {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Expected 2-digit day at position ${pos}.`,\n );\n }\n day = Number.parseInt(chunk, 10);\n pos += 2;\n } else if (sym === \"d\") {\n let run = \"\";\n while (\n pos < normalizedInput.length &&\n /\\d/.test(normalizedInput[pos]!) &&\n run.length < 2\n ) {\n run += normalizedInput[pos];\n pos++;\n }\n if (run.length === 0) {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Expected numeric day at position ${pos}.`,\n );\n }\n day = Number.parseInt(run, 10);\n } else if (sym === \"G\") {\n // Consume era letters\n while (\n pos < normalizedInput.length &&\n /[A-Za-z]/.test(normalizedInput[pos]!)\n ) {\n pos++;\n }\n } else {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Unsupported parse pattern token: \"${sym}\".`,\n );\n }\n }\n\n if (pos !== normalizedInput.length) {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n `Unexpected trailing data at position ${pos} in \"${input}\".`,\n );\n }\n\n if (year === undefined || month === undefined || day === undefined) {\n throw new ChroneraParseError(\n \"CHRONERA_PARSE_FAILED\",\n \"Pattern parsing did not extract all required fields (year, month, day).\",\n );\n }\n\n return localDate(year, month, day);\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { Instant, LocalDate, ParseInstantOptions, ParseLocalDateOptions, SafeParseResult } from "../public-types.js";
2
+ export declare function safeParseLocalDate(input: string, options?: Readonly<ParseLocalDateOptions>): SafeParseResult<LocalDate>;
3
+ export declare function safeParseInstant(input: string, options?: Readonly<ParseInstantOptions>): SafeParseResult<Instant>;
@@ -0,0 +1,46 @@
1
+ import { ChroneraError } from "../errors/errors.js";
2
+ import { parseLocalDate } from "./parse-local-date.js";
3
+ import { parseInstant } from "./parse-instant.js";
4
+ export function safeParseLocalDate(input, options) {
5
+ try {
6
+ const value = parseLocalDate(input, options);
7
+ return {
8
+ success: true,
9
+ value,
10
+ };
11
+ }
12
+ catch (err) {
13
+ if (err instanceof ChroneraError) {
14
+ return {
15
+ success: false,
16
+ error: {
17
+ code: err.code,
18
+ message: err.message,
19
+ },
20
+ };
21
+ }
22
+ throw err;
23
+ }
24
+ }
25
+ export function safeParseInstant(input, options) {
26
+ try {
27
+ const value = parseInstant(input, options);
28
+ return {
29
+ success: true,
30
+ value,
31
+ };
32
+ }
33
+ catch (err) {
34
+ if (err instanceof ChroneraError) {
35
+ return {
36
+ success: false,
37
+ error: {
38
+ code: err.code,
39
+ message: err.message,
40
+ },
41
+ };
42
+ }
43
+ throw err;
44
+ }
45
+ }
46
+ //# sourceMappingURL=safe-parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-parse.js","sourceRoot":"","sources":["../../src/parse/safe-parse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAUlD,MAAM,UAAU,kBAAkB,CAChC,KAAa,EACb,OAAyC;IAEzC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC7C,OAAO;YACL,OAAO,EAAE,IAAI;YACb,KAAK;SACN,CAAC;IACJ,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,IAAI,GAAG,YAAY,aAAa,EAAE,CAAC;YACjC,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE;oBACL,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,OAAO,EAAE,GAAG,CAAC,OAAO;iBACrB;aACF,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,KAAa,EACb,OAAuC;IAEvC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC3C,OAAO;YACL,OAAO,EAAE,IAAI;YACb,KAAK;SACN,CAAC;IACJ,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,IAAI,GAAG,YAAY,aAAa,EAAE,CAAC;YACjC,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE;oBACL,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,OAAO,EAAE,GAAG,CAAC,OAAO;iBACrB;aACF,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC","sourcesContent":["import { ChroneraError } from \"../errors/errors.js\";\nimport { parseLocalDate } from \"./parse-local-date.js\";\nimport { parseInstant } from \"./parse-instant.js\";\n\nimport type {\n Instant,\n LocalDate,\n ParseInstantOptions,\n ParseLocalDateOptions,\n SafeParseResult,\n} from \"../public-types.js\";\n\nexport function safeParseLocalDate(\n input: string,\n options?: Readonly<ParseLocalDateOptions>,\n): SafeParseResult<LocalDate> {\n try {\n const value = parseLocalDate(input, options);\n return {\n success: true,\n value,\n };\n } catch (err: unknown) {\n if (err instanceof ChroneraError) {\n return {\n success: false,\n error: {\n code: err.code,\n message: err.message,\n },\n };\n }\n throw err;\n }\n}\n\nexport function safeParseInstant(\n input: string,\n options?: Readonly<ParseInstantOptions>,\n): SafeParseResult<Instant> {\n try {\n const value = parseInstant(input, options);\n return {\n success: true,\n value,\n };\n } catch (err: unknown) {\n if (err instanceof ChroneraError) {\n return {\n success: false,\n error: {\n code: err.code,\n message: err.message,\n },\n };\n }\n throw err;\n }\n}\n"]}