@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,2 @@
1
+ import type { CalendarAdapter } from "../types.js";
2
+ export declare const buddhistAdapter: CalendarAdapter;
@@ -0,0 +1,33 @@
1
+ import { absoluteDayFromGregorian, gregorianFromAbsoluteDay, } from "../gregory/absolute-day.js";
2
+ import { BUDDHIST_ERA_YEAR_OFFSET, BUDDHIST_IDENTITY } from "./constants.js";
3
+ import { assertBuddhistDate, buddhistValidator } from "./validator.js";
4
+ export const buddhistAdapter = {
5
+ identity: BUDDHIST_IDENTITY,
6
+ converter: {
7
+ identity: BUDDHIST_IDENTITY,
8
+ toAbsoluteDay(date) {
9
+ assertBuddhistDate(date);
10
+ return absoluteDayFromGregorian({
11
+ year: date.year - BUDDHIST_ERA_YEAR_OFFSET,
12
+ monthCode: date.monthCode,
13
+ day: date.day,
14
+ });
15
+ },
16
+ fromAbsoluteDay(day) {
17
+ const gregorian = gregorianFromAbsoluteDay(day);
18
+ const year = gregorian.year + BUDDHIST_ERA_YEAR_OFFSET;
19
+ return {
20
+ kind: "calendar-date",
21
+ calendar: "buddhist",
22
+ era: "BE",
23
+ eraYear: year,
24
+ year,
25
+ monthCode: gregorian.monthCode,
26
+ month: gregorian.month,
27
+ day: gregorian.day,
28
+ };
29
+ },
30
+ },
31
+ validator: buddhistValidator,
32
+ };
33
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/calendar/buddhist/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAKvE,MAAM,CAAC,MAAM,eAAe,GAAoB;IAC9C,QAAQ,EAAE,iBAAiB;IAE3B,SAAS,EAAE;QACT,QAAQ,EAAE,iBAAiB;QAC3B,aAAa,CAAC,IAAkB;YAC9B,kBAAkB,CAAC,IAAI,CAAC,CAAC;YAEzB,OAAO,wBAAwB,CAAC;gBAC9B,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,wBAAwB;gBAC1C,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,GAAG,EAAE,IAAI,CAAC,GAAG;aACd,CAAC,CAAC;QACL,CAAC;QAED,eAAe,CAAC,GAAW;YACzB,MAAM,SAAS,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAC;YAChD,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,GAAG,wBAAwB,CAAC;YAEvD,OAAO;gBACL,IAAI,EAAE,eAAe;gBACrB,QAAQ,EAAE,UAAU;gBACpB,GAAG,EAAE,IAAI;gBACT,OAAO,EAAE,IAAI;gBACb,IAAI;gBACJ,SAAS,EAAE,SAAS,CAAC,SAAS;gBAC9B,KAAK,EAAE,SAAS,CAAC,KAAK;gBACtB,GAAG,EAAE,SAAS,CAAC,GAAG;aACnB,CAAC;QACJ,CAAC;KACF;IAED,SAAS,EAAE,iBAAiB;CAC7B,CAAC","sourcesContent":["import {\n absoluteDayFromGregorian,\n gregorianFromAbsoluteDay,\n} from \"../gregory/absolute-day.js\";\nimport { BUDDHIST_ERA_YEAR_OFFSET, BUDDHIST_IDENTITY } from \"./constants.js\";\nimport { assertBuddhistDate, buddhistValidator } from \"./validator.js\";\n\nimport type { CalendarDate } from \"../../public-types.js\";\nimport type { CalendarAdapter } from \"../types.js\";\n\nexport const buddhistAdapter: CalendarAdapter = {\n identity: BUDDHIST_IDENTITY,\n\n converter: {\n identity: BUDDHIST_IDENTITY,\n toAbsoluteDay(date: CalendarDate): number {\n assertBuddhistDate(date);\n\n return absoluteDayFromGregorian({\n year: date.year - BUDDHIST_ERA_YEAR_OFFSET,\n monthCode: date.monthCode,\n day: date.day,\n });\n },\n\n fromAbsoluteDay(day: number): CalendarDate {\n const gregorian = gregorianFromAbsoluteDay(day);\n const year = gregorian.year + BUDDHIST_ERA_YEAR_OFFSET;\n\n return {\n kind: \"calendar-date\",\n calendar: \"buddhist\",\n era: \"BE\",\n eraYear: year,\n year,\n monthCode: gregorian.monthCode,\n month: gregorian.month,\n day: gregorian.day,\n };\n },\n },\n\n validator: buddhistValidator,\n};\n"]}
@@ -0,0 +1,3 @@
1
+ import type { CalendarIdentity } from "../types.js";
2
+ export declare const BUDDHIST_ERA_YEAR_OFFSET = 543;
3
+ export declare const BUDDHIST_IDENTITY: CalendarIdentity;
@@ -0,0 +1,14 @@
1
+ import { MAX_ABSOLUTE_DAY, MIN_ABSOLUTE_DAY } from "../../core/absolute-day.js";
2
+ export const BUDDHIST_ERA_YEAR_OFFSET = 543;
3
+ export const BUDDHIST_IDENTITY = {
4
+ id: "buddhist",
5
+ algorithm: "chronera-buddhist-v1",
6
+ deterministic: true,
7
+ validRange: {
8
+ first: MIN_ABSOLUTE_DAY,
9
+ last: MAX_ABSOLUTE_DAY,
10
+ },
11
+ validFrom: { kind: "local-date", year: 1, month: 1, day: 1 },
12
+ validTo: { kind: "local-date", year: 9999, month: 12, day: 31 },
13
+ };
14
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/calendar/buddhist/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAIhF,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAE5C,MAAM,CAAC,MAAM,iBAAiB,GAAqB;IACjD,EAAE,EAAE,UAAU;IACd,SAAS,EAAE,sBAAsB;IACjC,aAAa,EAAE,IAAI;IACnB,UAAU,EAAE;QACV,KAAK,EAAE,gBAAgB;QACvB,IAAI,EAAE,gBAAgB;KACvB;IACD,SAAS,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;IAC5D,OAAO,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;CAChE,CAAC","sourcesContent":["import { MAX_ABSOLUTE_DAY, MIN_ABSOLUTE_DAY } from \"../../core/absolute-day.js\";\n\nimport type { CalendarIdentity } from \"../types.js\";\n\nexport const BUDDHIST_ERA_YEAR_OFFSET = 543;\n\nexport const BUDDHIST_IDENTITY: CalendarIdentity = {\n id: \"buddhist\",\n algorithm: \"chronera-buddhist-v1\",\n deterministic: true,\n validRange: {\n first: MIN_ABSOLUTE_DAY,\n last: MAX_ABSOLUTE_DAY,\n },\n validFrom: { kind: \"local-date\", year: 1, month: 1, day: 1 },\n validTo: { kind: \"local-date\", year: 9999, month: 12, day: 31 },\n};\n"]}
@@ -0,0 +1,3 @@
1
+ export { buddhistAdapter } from "./adapter.js";
2
+ export { BUDDHIST_ERA_YEAR_OFFSET, BUDDHIST_IDENTITY } from "./constants.js";
3
+ export { buddhistValidator } from "./validator.js";
@@ -0,0 +1,4 @@
1
+ export { buddhistAdapter } from "./adapter.js";
2
+ export { BUDDHIST_ERA_YEAR_OFFSET, BUDDHIST_IDENTITY } from "./constants.js";
3
+ export { buddhistValidator } from "./validator.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/calendar/buddhist/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC","sourcesContent":["export { buddhistAdapter } from \"./adapter.js\";\nexport { BUDDHIST_ERA_YEAR_OFFSET, BUDDHIST_IDENTITY } from \"./constants.js\";\nexport { buddhistValidator } from \"./validator.js\";\n"]}
@@ -0,0 +1,4 @@
1
+ import type { CalendarDate } from "../../public-types.js";
2
+ import type { CalendarValidator } from "../types.js";
3
+ export declare function assertBuddhistDate(date: CalendarDate): void;
4
+ export declare const buddhistValidator: CalendarValidator;
@@ -0,0 +1,60 @@
1
+ import { daysInGregorianMonth, isGregorianLeapYear, parseGregorianMonthCode, } from "../../core/gregorian-math.js";
2
+ import { ChroneraError } from "../../errors/errors.js";
3
+ import { BUDDHIST_ERA_YEAR_OFFSET, BUDDHIST_IDENTITY } from "./constants.js";
4
+ export function assertBuddhistDate(date) {
5
+ if (date.calendar !== "buddhist") {
6
+ throw new ChroneraError("CHRONERA_INVALID_CALENDAR", `Expected calendar "buddhist"; received "${date.calendar}".`);
7
+ }
8
+ }
9
+ export const buddhistValidator = {
10
+ identity: BUDDHIST_IDENTITY,
11
+ validate(date) {
12
+ assertBuddhistDate(date);
13
+ const issues = [];
14
+ const minYear = 1 + BUDDHIST_ERA_YEAR_OFFSET;
15
+ const maxYear = 9999 + BUDDHIST_ERA_YEAR_OFFSET;
16
+ if (date.year < minYear || date.year > maxYear) {
17
+ issues.push({
18
+ code: "CHRONERA_OUT_OF_RANGE",
19
+ message: `Buddhist year must be between ${minYear} and ${maxYear}; received ${date.year}.`,
20
+ path: ["year"],
21
+ });
22
+ }
23
+ let month = 0;
24
+ try {
25
+ month = parseGregorianMonthCode(date.monthCode);
26
+ }
27
+ catch {
28
+ issues.push({
29
+ code: "CHRONERA_INVALID_DATE",
30
+ message: `Invalid Buddhist monthCode: "${date.monthCode}". Expected M01-M12.`,
31
+ path: ["monthCode"],
32
+ });
33
+ }
34
+ if (month >= 1 &&
35
+ month <= 12 &&
36
+ date.year >= minYear &&
37
+ date.year <= maxYear) {
38
+ const gregYear = date.year - BUDDHIST_ERA_YEAR_OFFSET;
39
+ const maxDays = daysInGregorianMonth(gregYear, month);
40
+ if (date.day < 1 || date.day > maxDays) {
41
+ issues.push({
42
+ code: "CHRONERA_INVALID_DATE",
43
+ message: `Invalid day ${date.day} for month ${date.monthCode} in Buddhist year ${date.year}.`,
44
+ path: ["day"],
45
+ });
46
+ }
47
+ }
48
+ return issues;
49
+ },
50
+ daysInMonth(year, monthCode) {
51
+ const gregYear = year - BUDDHIST_ERA_YEAR_OFFSET;
52
+ const month = parseGregorianMonthCode(monthCode);
53
+ return daysInGregorianMonth(gregYear, month);
54
+ },
55
+ isLeapYear(year) {
56
+ const gregYear = year - BUDDHIST_ERA_YEAR_OFFSET;
57
+ return isGregorianLeapYear(gregYear);
58
+ },
59
+ };
60
+ //# sourceMappingURL=validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../../src/calendar/buddhist/validator.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAS7E,MAAM,UAAU,kBAAkB,CAAC,IAAkB;IACnD,IAAI,IAAI,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;QACjC,MAAM,IAAI,aAAa,CACrB,2BAA2B,EAC3B,2CAA2C,IAAI,CAAC,QAAQ,IAAI,CAC7D,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAsB;IAClD,QAAQ,EAAE,iBAAiB;IAE3B,QAAQ,CAAC,IAAkB;QACzB,kBAAkB,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,MAAM,GAAoB,EAAE,CAAC;QAEnC,MAAM,OAAO,GAAG,CAAC,GAAG,wBAAwB,CAAC;QAC7C,MAAM,OAAO,GAAG,IAAI,GAAG,wBAAwB,CAAC;QAEhD,IAAI,IAAI,CAAC,IAAI,GAAG,OAAO,IAAI,IAAI,CAAC,IAAI,GAAG,OAAO,EAAE,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,uBAAuB;gBAC7B,OAAO,EAAE,iCAAiC,OAAO,QAAQ,OAAO,cAAc,IAAI,CAAC,IAAI,GAAG;gBAC1F,IAAI,EAAE,CAAC,MAAM,CAAC;aACf,CAAC,CAAC;QACL,CAAC;QAED,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAI,CAAC;YACH,KAAK,GAAG,uBAAuB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,uBAAuB;gBAC7B,OAAO,EAAE,gCAAgC,IAAI,CAAC,SAAS,sBAAsB;gBAC7E,IAAI,EAAE,CAAC,WAAW,CAAC;aACpB,CAAC,CAAC;QACL,CAAC;QAED,IACE,KAAK,IAAI,CAAC;YACV,KAAK,IAAI,EAAE;YACX,IAAI,CAAC,IAAI,IAAI,OAAO;YACpB,IAAI,CAAC,IAAI,IAAI,OAAO,EACpB,CAAC;YACD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;YACtD,MAAM,OAAO,GAAG,oBAAoB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACtD,IAAI,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,GAAG,OAAO,EAAE,CAAC;gBACvC,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,uBAAuB;oBAC7B,OAAO,EAAE,eAAe,IAAI,CAAC,GAAG,cAAc,IAAI,CAAC,SAAS,qBAAqB,IAAI,CAAC,IAAI,GAAG;oBAC7F,IAAI,EAAE,CAAC,KAAK,CAAC;iBACd,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,WAAW,CAAC,IAAY,EAAE,SAAoB;QAC5C,MAAM,QAAQ,GAAG,IAAI,GAAG,wBAAwB,CAAC;QACjD,MAAM,KAAK,GAAG,uBAAuB,CAAC,SAAS,CAAC,CAAC;QACjD,OAAO,oBAAoB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;IAED,UAAU,CAAC,IAAY;QACrB,MAAM,QAAQ,GAAG,IAAI,GAAG,wBAAwB,CAAC;QACjD,OAAO,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;CACF,CAAC","sourcesContent":["import {\n daysInGregorianMonth,\n isGregorianLeapYear,\n parseGregorianMonthCode,\n} from \"../../core/gregorian-math.js\";\nimport { ChroneraError } from \"../../errors/errors.js\";\nimport { BUDDHIST_ERA_YEAR_OFFSET, BUDDHIST_IDENTITY } from \"./constants.js\";\n\nimport type {\n CalendarDate,\n ChroneraIssue,\n MonthCode,\n} from \"../../public-types.js\";\nimport type { CalendarValidator } from \"../types.js\";\n\nexport function assertBuddhistDate(date: CalendarDate): void {\n if (date.calendar !== \"buddhist\") {\n throw new ChroneraError(\n \"CHRONERA_INVALID_CALENDAR\",\n `Expected calendar \"buddhist\"; received \"${date.calendar}\".`,\n );\n }\n}\n\nexport const buddhistValidator: CalendarValidator = {\n identity: BUDDHIST_IDENTITY,\n\n validate(date: CalendarDate): readonly ChroneraIssue[] {\n assertBuddhistDate(date);\n const issues: ChroneraIssue[] = [];\n\n const minYear = 1 + BUDDHIST_ERA_YEAR_OFFSET;\n const maxYear = 9999 + BUDDHIST_ERA_YEAR_OFFSET;\n\n if (date.year < minYear || date.year > maxYear) {\n issues.push({\n code: \"CHRONERA_OUT_OF_RANGE\",\n message: `Buddhist year must be between ${minYear} and ${maxYear}; received ${date.year}.`,\n path: [\"year\"],\n });\n }\n\n let month = 0;\n try {\n month = parseGregorianMonthCode(date.monthCode);\n } catch {\n issues.push({\n code: \"CHRONERA_INVALID_DATE\",\n message: `Invalid Buddhist monthCode: \"${date.monthCode}\". Expected M01-M12.`,\n path: [\"monthCode\"],\n });\n }\n\n if (\n month >= 1 &&\n month <= 12 &&\n date.year >= minYear &&\n date.year <= maxYear\n ) {\n const gregYear = date.year - BUDDHIST_ERA_YEAR_OFFSET;\n const maxDays = daysInGregorianMonth(gregYear, month);\n if (date.day < 1 || date.day > maxDays) {\n issues.push({\n code: \"CHRONERA_INVALID_DATE\",\n message: `Invalid day ${date.day} for month ${date.monthCode} in Buddhist year ${date.year}.`,\n path: [\"day\"],\n });\n }\n }\n\n return issues;\n },\n\n daysInMonth(year: number, monthCode: MonthCode): number {\n const gregYear = year - BUDDHIST_ERA_YEAR_OFFSET;\n const month = parseGregorianMonthCode(monthCode);\n return daysInGregorianMonth(gregYear, month);\n },\n\n isLeapYear(year: number): boolean {\n const gregYear = year - BUDDHIST_ERA_YEAR_OFFSET;\n return isGregorianLeapYear(gregYear);\n },\n};\n"]}
@@ -0,0 +1,12 @@
1
+ import type { MonthCode } from "../../public-types.js";
2
+ export declare function absoluteDayFromGregorian(date: {
3
+ year: number;
4
+ monthCode: MonthCode;
5
+ day: number;
6
+ }): number;
7
+ export declare function gregorianFromAbsoluteDay(day: number): {
8
+ year: number;
9
+ month: number;
10
+ monthCode: MonthCode;
11
+ day: number;
12
+ };
@@ -0,0 +1,14 @@
1
+ import { absoluteDayFromGregorianFields, gregorianFieldsFromAbsoluteDay, } from "../../core/absolute-day.js";
2
+ import { formatGregorianMonthCode, parseGregorianMonthCode, } from "../../core/gregorian-math.js";
3
+ export function absoluteDayFromGregorian(date) {
4
+ const month = parseGregorianMonthCode(date.monthCode);
5
+ return absoluteDayFromGregorianFields(date.year, month, date.day);
6
+ }
7
+ export function gregorianFromAbsoluteDay(day) {
8
+ const fields = gregorianFieldsFromAbsoluteDay(day);
9
+ return {
10
+ ...fields,
11
+ monthCode: formatGregorianMonthCode(fields.month),
12
+ };
13
+ }
14
+ //# sourceMappingURL=absolute-day.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"absolute-day.js","sourceRoot":"","sources":["../../../src/calendar/gregory/absolute-day.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,8BAA8B,GAC/B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,8BAA8B,CAAC;AAItC,MAAM,UAAU,wBAAwB,CAAC,IAIxC;IACC,MAAM,KAAK,GAAG,uBAAuB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACtD,OAAO,8BAA8B,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,GAAW;IAMlD,MAAM,MAAM,GAAG,8BAA8B,CAAC,GAAG,CAAC,CAAC;IACnD,OAAO;QACL,GAAG,MAAM;QACT,SAAS,EAAE,wBAAwB,CAAC,MAAM,CAAC,KAAK,CAAC;KAClD,CAAC;AACJ,CAAC","sourcesContent":["import {\n absoluteDayFromGregorianFields,\n gregorianFieldsFromAbsoluteDay,\n} from \"../../core/absolute-day.js\";\nimport {\n formatGregorianMonthCode,\n parseGregorianMonthCode,\n} from \"../../core/gregorian-math.js\";\n\nimport type { MonthCode } from \"../../public-types.js\";\n\nexport function absoluteDayFromGregorian(date: {\n year: number;\n monthCode: MonthCode;\n day: number;\n}): number {\n const month = parseGregorianMonthCode(date.monthCode);\n return absoluteDayFromGregorianFields(date.year, month, date.day);\n}\n\nexport function gregorianFromAbsoluteDay(day: number): {\n year: number;\n month: number;\n monthCode: MonthCode;\n day: number;\n} {\n const fields = gregorianFieldsFromAbsoluteDay(day);\n return {\n ...fields,\n monthCode: formatGregorianMonthCode(fields.month),\n };\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { CalendarAdapter } from "../types.js";
2
+ export declare const gregorianAdapter: CalendarAdapter;
3
+ export declare const iso8601Adapter: CalendarAdapter;
@@ -0,0 +1,93 @@
1
+ import { absoluteDayFromGregorian, gregorianFromAbsoluteDay, } from "./absolute-day.js";
2
+ import { GREGORIAN_IDENTITY, ISO8601_IDENTITY } from "./constants.js";
3
+ import { gregorianValidator } from "./validator.js";
4
+ import { ChroneraError } from "../../errors/errors.js";
5
+ import { daysInGregorianMonth } from "../../core/gregorian-math.js";
6
+ function addGregorianDuration(date, dur, overflow) {
7
+ let year = date.year + (dur.years ?? 0);
8
+ let month = date.month ?? Number.parseInt(date.monthCode.slice(1), 10);
9
+ month += dur.months ?? 0;
10
+ // Normalize year and month
11
+ while (month > 12) {
12
+ year += 1;
13
+ month -= 12;
14
+ }
15
+ while (month < 1) {
16
+ year -= 1;
17
+ month += 12;
18
+ }
19
+ let day = date.day;
20
+ const maxDay = daysInGregorianMonth(year, month);
21
+ if (day > maxDay) {
22
+ if (overflow === "reject") {
23
+ throw new ChroneraError("CHRONERA_OUT_OF_RANGE", `Day ${day} exceeds maximum days ${maxDay} for month ${month} in year ${year}.`);
24
+ }
25
+ day = maxDay;
26
+ }
27
+ // Days and weeks addition via absolute day
28
+ let absDay = absoluteDayFromGregorian({
29
+ year,
30
+ monthCode: `M${String(month).padStart(2, "0")}`,
31
+ day,
32
+ });
33
+ const extraDays = (dur.days ?? 0) + (dur.weeks ?? 0) * 7;
34
+ absDay += extraDays;
35
+ const resultFields = gregorianFromAbsoluteDay(absDay);
36
+ return {
37
+ kind: "calendar-date",
38
+ calendar: date.calendar,
39
+ year: resultFields.year,
40
+ monthCode: resultFields.monthCode,
41
+ month: resultFields.month,
42
+ day: resultFields.day,
43
+ era: date.era ?? "CE",
44
+ eraYear: resultFields.year,
45
+ };
46
+ }
47
+ export const gregorianAdapter = {
48
+ identity: GREGORIAN_IDENTITY,
49
+ converter: {
50
+ identity: GREGORIAN_IDENTITY,
51
+ toAbsoluteDay(date) {
52
+ return absoluteDayFromGregorian({
53
+ year: date.year,
54
+ monthCode: date.monthCode,
55
+ day: date.day,
56
+ });
57
+ },
58
+ fromAbsoluteDay(day) {
59
+ const g = gregorianFromAbsoluteDay(day);
60
+ return {
61
+ kind: "calendar-date",
62
+ calendar: "gregory",
63
+ era: "CE",
64
+ eraYear: g.year,
65
+ year: g.year,
66
+ monthCode: g.monthCode,
67
+ month: g.month,
68
+ day: g.day,
69
+ };
70
+ },
71
+ },
72
+ validator: gregorianValidator,
73
+ arithmetic: {
74
+ identity: GREGORIAN_IDENTITY,
75
+ add: addGregorianDuration,
76
+ },
77
+ };
78
+ export const iso8601Adapter = {
79
+ ...gregorianAdapter,
80
+ identity: ISO8601_IDENTITY,
81
+ converter: {
82
+ identity: ISO8601_IDENTITY,
83
+ toAbsoluteDay: gregorianAdapter.converter.toAbsoluteDay,
84
+ fromAbsoluteDay(day) {
85
+ const base = gregorianAdapter.converter.fromAbsoluteDay(day);
86
+ return {
87
+ ...base,
88
+ calendar: "iso8601",
89
+ };
90
+ },
91
+ },
92
+ };
93
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/calendar/gregory/adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n absoluteDayFromGregorian,\n gregorianFromAbsoluteDay,\n} from \"./absolute-day.js\";\nimport { GREGORIAN_IDENTITY, ISO8601_IDENTITY } from \"./constants.js\";\nimport { gregorianValidator } from \"./validator.js\";\nimport { ChroneraError } from \"../../errors/errors.js\";\nimport { daysInGregorianMonth } from \"../../core/gregorian-math.js\";\n\nimport type { CalendarAdapter } from \"../types.js\";\nimport type { CalendarDate, Duration, MonthCode } from \"../../public-types.js\";\n\nfunction addGregorianDuration(\n date: CalendarDate,\n dur: Duration,\n overflow: \"constrain\" | \"reject\",\n): CalendarDate {\n let year = date.year + (dur.years ?? 0);\n let month = date.month ?? Number.parseInt(date.monthCode.slice(1), 10);\n month += dur.months ?? 0;\n\n // Normalize year and month\n while (month > 12) {\n year += 1;\n month -= 12;\n }\n while (month < 1) {\n year -= 1;\n month += 12;\n }\n\n let day = date.day;\n const maxDay = daysInGregorianMonth(year, month);\n if (day > maxDay) {\n if (overflow === \"reject\") {\n throw new ChroneraError(\n \"CHRONERA_OUT_OF_RANGE\",\n `Day ${day} exceeds maximum days ${maxDay} for month ${month} in year ${year}.`,\n );\n }\n day = maxDay;\n }\n\n // Days and weeks addition via absolute day\n let absDay = absoluteDayFromGregorian({\n year,\n monthCode: `M${String(month).padStart(2, \"0\")}` as MonthCode,\n day,\n });\n\n const extraDays = (dur.days ?? 0) + (dur.weeks ?? 0) * 7;\n absDay += extraDays;\n\n const resultFields = gregorianFromAbsoluteDay(absDay);\n return {\n kind: \"calendar-date\",\n calendar: date.calendar,\n year: resultFields.year,\n monthCode: resultFields.monthCode,\n month: resultFields.month,\n day: resultFields.day,\n era: date.era ?? \"CE\",\n eraYear: resultFields.year,\n };\n}\n\nexport const gregorianAdapter: CalendarAdapter = {\n identity: GREGORIAN_IDENTITY,\n\n converter: {\n identity: GREGORIAN_IDENTITY,\n toAbsoluteDay(date: CalendarDate): number {\n return absoluteDayFromGregorian({\n year: date.year,\n monthCode: date.monthCode,\n day: date.day,\n });\n },\n fromAbsoluteDay(day: number): CalendarDate {\n const g = gregorianFromAbsoluteDay(day);\n return {\n kind: \"calendar-date\",\n calendar: \"gregory\",\n era: \"CE\",\n eraYear: g.year,\n year: g.year,\n monthCode: g.monthCode,\n month: g.month,\n day: g.day,\n };\n },\n },\n\n validator: gregorianValidator,\n\n arithmetic: {\n identity: GREGORIAN_IDENTITY,\n add: addGregorianDuration,\n },\n};\n\nexport const iso8601Adapter: CalendarAdapter = {\n ...gregorianAdapter,\n identity: ISO8601_IDENTITY,\n converter: {\n identity: ISO8601_IDENTITY,\n toAbsoluteDay: gregorianAdapter.converter!.toAbsoluteDay,\n fromAbsoluteDay(day: number): CalendarDate {\n const base = gregorianAdapter.converter!.fromAbsoluteDay(day);\n return {\n ...base,\n calendar: \"iso8601\",\n };\n },\n },\n};\n"]}
@@ -0,0 +1,3 @@
1
+ import type { CalendarIdentity } from "../types.js";
2
+ export declare const GREGORIAN_IDENTITY: CalendarIdentity;
3
+ export declare const ISO8601_IDENTITY: CalendarIdentity;
@@ -0,0 +1,18 @@
1
+ import { MAX_ABSOLUTE_DAY, MIN_ABSOLUTE_DAY } from "../../core/absolute-day.js";
2
+ export const GREGORIAN_IDENTITY = {
3
+ id: "gregory",
4
+ algorithm: "chronera-proleptic-gregorian-v1",
5
+ deterministic: true,
6
+ validRange: {
7
+ first: MIN_ABSOLUTE_DAY,
8
+ last: MAX_ABSOLUTE_DAY,
9
+ },
10
+ validFrom: { kind: "local-date", year: 1, month: 1, day: 1 },
11
+ validTo: { kind: "local-date", year: 9999, month: 12, day: 31 },
12
+ };
13
+ export const ISO8601_IDENTITY = {
14
+ ...GREGORIAN_IDENTITY,
15
+ id: "iso8601",
16
+ algorithm: "chronera-iso8601-civil-v1",
17
+ };
18
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/calendar/gregory/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAIhF,MAAM,CAAC,MAAM,kBAAkB,GAAqB;IAClD,EAAE,EAAE,SAAS;IACb,SAAS,EAAE,iCAAiC;IAC5C,aAAa,EAAE,IAAI;IACnB,UAAU,EAAE;QACV,KAAK,EAAE,gBAAgB;QACvB,IAAI,EAAE,gBAAgB;KACvB;IACD,SAAS,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;IAC5D,OAAO,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;CAChE,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAqB;IAChD,GAAG,kBAAkB;IACrB,EAAE,EAAE,SAAS;IACb,SAAS,EAAE,2BAA2B;CACvC,CAAC","sourcesContent":["import { MAX_ABSOLUTE_DAY, MIN_ABSOLUTE_DAY } from \"../../core/absolute-day.js\";\n\nimport type { CalendarIdentity } from \"../types.js\";\n\nexport const GREGORIAN_IDENTITY: CalendarIdentity = {\n id: \"gregory\",\n algorithm: \"chronera-proleptic-gregorian-v1\",\n deterministic: true,\n validRange: {\n first: MIN_ABSOLUTE_DAY,\n last: MAX_ABSOLUTE_DAY,\n },\n validFrom: { kind: \"local-date\", year: 1, month: 1, day: 1 },\n validTo: { kind: \"local-date\", year: 9999, month: 12, day: 31 },\n};\n\nexport const ISO8601_IDENTITY: CalendarIdentity = {\n ...GREGORIAN_IDENTITY,\n id: \"iso8601\",\n algorithm: \"chronera-iso8601-civil-v1\",\n};\n"]}
@@ -0,0 +1,4 @@
1
+ export { gregorianAdapter, iso8601Adapter } from "./adapter.js";
2
+ export { GREGORIAN_IDENTITY, ISO8601_IDENTITY } from "./constants.js";
3
+ export { gregorianValidator } from "./validator.js";
4
+ export { absoluteDayFromGregorian, gregorianFromAbsoluteDay, } from "./absolute-day.js";
@@ -0,0 +1,5 @@
1
+ export { gregorianAdapter, iso8601Adapter } from "./adapter.js";
2
+ export { GREGORIAN_IDENTITY, ISO8601_IDENTITY } from "./constants.js";
3
+ export { gregorianValidator } from "./validator.js";
4
+ export { absoluteDayFromGregorian, gregorianFromAbsoluteDay, } from "./absolute-day.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/calendar/gregory/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EACL,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,mBAAmB,CAAC","sourcesContent":["export { gregorianAdapter, iso8601Adapter } from \"./adapter.js\";\nexport { GREGORIAN_IDENTITY, ISO8601_IDENTITY } from \"./constants.js\";\nexport { gregorianValidator } from \"./validator.js\";\nexport {\n absoluteDayFromGregorian,\n gregorianFromAbsoluteDay,\n} from \"./absolute-day.js\";\n"]}
@@ -0,0 +1 @@
1
+ export { isGregorianLeapYear } from "../../core/gregorian-math.js";
@@ -0,0 +1,2 @@
1
+ export { isGregorianLeapYear } from "../../core/gregorian-math.js";
2
+ //# sourceMappingURL=leap-year.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"leap-year.js","sourceRoot":"","sources":["../../../src/calendar/gregory/leap-year.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC","sourcesContent":["export { isGregorianLeapYear } from \"../../core/gregorian-math.js\";\n"]}
@@ -0,0 +1,2 @@
1
+ import type { CalendarValidator } from "../types.js";
2
+ export declare const gregorianValidator: CalendarValidator;
@@ -0,0 +1,45 @@
1
+ import { daysInGregorianMonth, isGregorianLeapYear, parseGregorianMonthCode, } from "../../core/gregorian-math.js";
2
+ import { GREGORIAN_IDENTITY } from "./constants.js";
3
+ export const gregorianValidator = {
4
+ identity: GREGORIAN_IDENTITY,
5
+ validate(date) {
6
+ const issues = [];
7
+ if (date.year < 1 || date.year > 9999) {
8
+ issues.push({
9
+ code: "CHRONERA_OUT_OF_RANGE",
10
+ message: `Gregorian year must be between 1 and 9999; received ${date.year}.`,
11
+ path: ["year"],
12
+ });
13
+ }
14
+ let month = 0;
15
+ try {
16
+ month = parseGregorianMonthCode(date.monthCode);
17
+ }
18
+ catch {
19
+ issues.push({
20
+ code: "CHRONERA_INVALID_DATE",
21
+ message: `Invalid Gregorian monthCode: "${date.monthCode}". Expected M01-M12.`,
22
+ path: ["monthCode"],
23
+ });
24
+ }
25
+ if (month >= 1 && month <= 12 && date.year >= 1 && date.year <= 9999) {
26
+ const maxDays = daysInGregorianMonth(date.year, month);
27
+ if (date.day < 1 || date.day > maxDays) {
28
+ issues.push({
29
+ code: "CHRONERA_INVALID_DATE",
30
+ message: `Invalid day ${date.day} for month ${date.monthCode} in Gregorian year ${date.year}.`,
31
+ path: ["day"],
32
+ });
33
+ }
34
+ }
35
+ return issues;
36
+ },
37
+ daysInMonth(year, monthCode) {
38
+ const month = parseGregorianMonthCode(monthCode);
39
+ return daysInGregorianMonth(year, month);
40
+ },
41
+ isLeapYear(year) {
42
+ return isGregorianLeapYear(year);
43
+ },
44
+ };
45
+ //# sourceMappingURL=validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../../src/calendar/gregory/validator.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AASpD,MAAM,CAAC,MAAM,kBAAkB,GAAsB;IACnD,QAAQ,EAAE,kBAAkB;IAE5B,QAAQ,CAAC,IAAkB;QACzB,MAAM,MAAM,GAAoB,EAAE,CAAC;QAEnC,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,GAAG,IAAI,EAAE,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,uBAAuB;gBAC7B,OAAO,EAAE,uDAAuD,IAAI,CAAC,IAAI,GAAG;gBAC5E,IAAI,EAAE,CAAC,MAAM,CAAC;aACf,CAAC,CAAC;QACL,CAAC;QAED,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAI,CAAC;YACH,KAAK,GAAG,uBAAuB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,uBAAuB;gBAC7B,OAAO,EAAE,iCAAiC,IAAI,CAAC,SAAS,sBAAsB;gBAC9E,IAAI,EAAE,CAAC,WAAW,CAAC;aACpB,CAAC,CAAC;QACL,CAAC;QAED,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;YACrE,MAAM,OAAO,GAAG,oBAAoB,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACvD,IAAI,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,GAAG,OAAO,EAAE,CAAC;gBACvC,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,uBAAuB;oBAC7B,OAAO,EAAE,eAAe,IAAI,CAAC,GAAG,cAAc,IAAI,CAAC,SAAS,sBAAsB,IAAI,CAAC,IAAI,GAAG;oBAC9F,IAAI,EAAE,CAAC,KAAK,CAAC;iBACd,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,WAAW,CAAC,IAAY,EAAE,SAAoB;QAC5C,MAAM,KAAK,GAAG,uBAAuB,CAAC,SAAS,CAAC,CAAC;QACjD,OAAO,oBAAoB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,UAAU,CAAC,IAAY;QACrB,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;CACF,CAAC","sourcesContent":["import {\n daysInGregorianMonth,\n isGregorianLeapYear,\n parseGregorianMonthCode,\n} from \"../../core/gregorian-math.js\";\nimport { GREGORIAN_IDENTITY } from \"./constants.js\";\n\nimport type {\n CalendarDate,\n ChroneraIssue,\n MonthCode,\n} from \"../../public-types.js\";\nimport type { CalendarValidator } from \"../types.js\";\n\nexport const gregorianValidator: CalendarValidator = {\n identity: GREGORIAN_IDENTITY,\n\n validate(date: CalendarDate): readonly ChroneraIssue[] {\n const issues: ChroneraIssue[] = [];\n\n if (date.year < 1 || date.year > 9999) {\n issues.push({\n code: \"CHRONERA_OUT_OF_RANGE\",\n message: `Gregorian year must be between 1 and 9999; received ${date.year}.`,\n path: [\"year\"],\n });\n }\n\n let month = 0;\n try {\n month = parseGregorianMonthCode(date.monthCode);\n } catch {\n issues.push({\n code: \"CHRONERA_INVALID_DATE\",\n message: `Invalid Gregorian monthCode: \"${date.monthCode}\". Expected M01-M12.`,\n path: [\"monthCode\"],\n });\n }\n\n if (month >= 1 && month <= 12 && date.year >= 1 && date.year <= 9999) {\n const maxDays = daysInGregorianMonth(date.year, month);\n if (date.day < 1 || date.day > maxDays) {\n issues.push({\n code: \"CHRONERA_INVALID_DATE\",\n message: `Invalid day ${date.day} for month ${date.monthCode} in Gregorian year ${date.year}.`,\n path: [\"day\"],\n });\n }\n }\n\n return issues;\n },\n\n daysInMonth(year: number, monthCode: MonthCode): number {\n const month = parseGregorianMonthCode(monthCode);\n return daysInGregorianMonth(year, month);\n },\n\n isLeapYear(year: number): boolean {\n return isGregorianLeapYear(year);\n },\n};\n"]}
@@ -0,0 +1,12 @@
1
+ import type { CalendarAdapter, CalendarIdentity, CalendarValidator } from "../types.js";
2
+ export declare function isIslamicCivilLeapYear(year: number): boolean;
3
+ export declare function daysInIslamicCivilMonth(year: number, month: number): number;
4
+ export declare function islamicCivilToAbsoluteDay(year: number, month: number, day: number): number;
5
+ export declare function islamicCivilFromAbsoluteDay(absDay: number): {
6
+ year: number;
7
+ month: number;
8
+ day: number;
9
+ };
10
+ export declare const ISLAMIC_CIVIL_IDENTITY: CalendarIdentity;
11
+ export declare const islamicCivilValidator: CalendarValidator;
12
+ export declare const islamicCivilAdapter: CalendarAdapter;
@@ -0,0 +1,132 @@
1
+ import { ChroneraError } from "../../errors/errors.js";
2
+ // Islamic Civil: Friday 16 July 622 CE (Julian) -> absolute day -492997
3
+ const ISLAMIC_CIVIL_EPOCH = -492997;
4
+ const LEAP_YEARS_IN_30 = new Set([2, 5, 7, 10, 13, 16, 18, 21, 24, 26, 29]);
5
+ export function isIslamicCivilLeapYear(year) {
6
+ const cycleYear = ((year % 30) + 30) % 30;
7
+ return LEAP_YEARS_IN_30.has(cycleYear);
8
+ }
9
+ export function daysInIslamicCivilMonth(year, month) {
10
+ if (month < 1 || month > 12) {
11
+ throw new ChroneraError("CHRONERA_INVALID_DATE", `Islamic civil month must be between 1 and 12; received ${month}.`);
12
+ }
13
+ if (month === 12) {
14
+ return isIslamicCivilLeapYear(year) ? 30 : 29;
15
+ }
16
+ return month % 2 === 1 ? 30 : 29;
17
+ }
18
+ export function islamicCivilToAbsoluteDay(year, month, day) {
19
+ const yMinus1 = year - 1;
20
+ const cycles = Math.floor(yMinus1 / 30);
21
+ const remainingYears = yMinus1 - cycles * 30;
22
+ let days = cycles * 10631;
23
+ for (let y = 1; y <= remainingYears; y++) {
24
+ days += isIslamicCivilLeapYear(y) ? 355 : 354;
25
+ }
26
+ for (let m = 1; m < month; m++) {
27
+ days += daysInIslamicCivilMonth(year, m);
28
+ }
29
+ days += day - 1;
30
+ return ISLAMIC_CIVIL_EPOCH + days;
31
+ }
32
+ export function islamicCivilFromAbsoluteDay(absDay) {
33
+ let days = absDay - ISLAMIC_CIVIL_EPOCH;
34
+ if (days < 0) {
35
+ throw new ChroneraError("CHRONERA_OUT_OF_RANGE", `Absolute day ${absDay} is prior to the Islamic civil epoch.`);
36
+ }
37
+ const cycles = Math.floor(days / 10631);
38
+ let year = cycles * 30 + 1;
39
+ days -= cycles * 10631;
40
+ while (true) {
41
+ const daysInYear = isIslamicCivilLeapYear(year) ? 355 : 354;
42
+ if (days < daysInYear) {
43
+ break;
44
+ }
45
+ days -= daysInYear;
46
+ year++;
47
+ }
48
+ let month = 1;
49
+ while (month <= 12) {
50
+ const mDays = daysInIslamicCivilMonth(year, month);
51
+ if (days < mDays) {
52
+ break;
53
+ }
54
+ days -= mDays;
55
+ month++;
56
+ }
57
+ const day = days + 1;
58
+ return { year, month, day };
59
+ }
60
+ export const ISLAMIC_CIVIL_IDENTITY = {
61
+ id: "islamic-civil",
62
+ algorithm: "chronera-islamic-civil-tabular-v1",
63
+ deterministic: true,
64
+ validRange: {
65
+ first: ISLAMIC_CIVIL_EPOCH,
66
+ last: 2932896,
67
+ },
68
+ };
69
+ export const islamicCivilValidator = {
70
+ identity: ISLAMIC_CIVIL_IDENTITY,
71
+ validate(date) {
72
+ const issues = [];
73
+ if (date.year < 1) {
74
+ issues.push({
75
+ code: "CHRONERA_OUT_OF_RANGE",
76
+ message: `Islamic civil year must be >= 1; received ${date.year}.`,
77
+ path: ["year"],
78
+ });
79
+ }
80
+ const month = date.month ?? Number.parseInt(date.monthCode.slice(1), 10);
81
+ if (month < 1 || month > 12) {
82
+ issues.push({
83
+ code: "CHRONERA_INVALID_DATE",
84
+ message: `Invalid month ${month}. Expected 1-12.`,
85
+ path: ["monthCode"],
86
+ });
87
+ }
88
+ else if (date.year >= 1) {
89
+ const maxDay = daysInIslamicCivilMonth(date.year, month);
90
+ if (date.day < 1 || date.day > maxDay) {
91
+ issues.push({
92
+ code: "CHRONERA_INVALID_DATE",
93
+ message: `Invalid day ${date.day} for month ${date.monthCode} in Islamic civil year ${date.year}.`,
94
+ path: ["day"],
95
+ });
96
+ }
97
+ }
98
+ return issues;
99
+ },
100
+ daysInMonth(year, monthCode) {
101
+ const month = Number.parseInt(monthCode.slice(1), 10);
102
+ return daysInIslamicCivilMonth(year, month);
103
+ },
104
+ isLeapYear(year) {
105
+ return isIslamicCivilLeapYear(year);
106
+ },
107
+ };
108
+ export const islamicCivilAdapter = {
109
+ identity: ISLAMIC_CIVIL_IDENTITY,
110
+ converter: {
111
+ identity: ISLAMIC_CIVIL_IDENTITY,
112
+ toAbsoluteDay(date) {
113
+ const month = date.month ?? Number.parseInt(date.monthCode.slice(1), 10);
114
+ return islamicCivilToAbsoluteDay(date.year, month, date.day);
115
+ },
116
+ fromAbsoluteDay(day) {
117
+ const res = islamicCivilFromAbsoluteDay(day);
118
+ return {
119
+ kind: "calendar-date",
120
+ calendar: "islamic-civil",
121
+ era: "AH",
122
+ eraYear: res.year,
123
+ year: res.year,
124
+ monthCode: `M${String(res.month).padStart(2, "0")}`,
125
+ month: res.month,
126
+ day: res.day,
127
+ };
128
+ },
129
+ },
130
+ validator: islamicCivilValidator,
131
+ };
132
+ //# sourceMappingURL=civil-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"civil-adapter.js","sourceRoot":"","sources":["../../../src/calendar/hijri/civil-adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChroneraError } from \"../../errors/errors.js\";\n\nimport type {\n CalendarAdapter,\n CalendarIdentity,\n CalendarValidator,\n} from \"../types.js\";\nimport type {\n CalendarDate,\n ChroneraIssue,\n MonthCode,\n} from \"../../public-types.js\";\n\n// Islamic Civil: Friday 16 July 622 CE (Julian) -> absolute day -492997\nconst ISLAMIC_CIVIL_EPOCH = -492997;\n\nconst LEAP_YEARS_IN_30 = new Set([2, 5, 7, 10, 13, 16, 18, 21, 24, 26, 29]);\n\nexport function isIslamicCivilLeapYear(year: number): boolean {\n const cycleYear = ((year % 30) + 30) % 30;\n return LEAP_YEARS_IN_30.has(cycleYear);\n}\n\nexport function daysInIslamicCivilMonth(year: number, month: number): number {\n if (month < 1 || month > 12) {\n throw new ChroneraError(\n \"CHRONERA_INVALID_DATE\",\n `Islamic civil month must be between 1 and 12; received ${month}.`,\n );\n }\n if (month === 12) {\n return isIslamicCivilLeapYear(year) ? 30 : 29;\n }\n return month % 2 === 1 ? 30 : 29;\n}\n\nexport function islamicCivilToAbsoluteDay(\n year: number,\n month: number,\n day: number,\n): number {\n const yMinus1 = year - 1;\n const cycles = Math.floor(yMinus1 / 30);\n const remainingYears = yMinus1 - cycles * 30;\n\n let days = cycles * 10631;\n for (let y = 1; y <= remainingYears; y++) {\n days += isIslamicCivilLeapYear(y) ? 355 : 354;\n }\n\n for (let m = 1; m < month; m++) {\n days += daysInIslamicCivilMonth(year, m);\n }\n\n days += day - 1;\n return ISLAMIC_CIVIL_EPOCH + days;\n}\n\nexport function islamicCivilFromAbsoluteDay(absDay: number): {\n year: number;\n month: number;\n day: number;\n} {\n let days = absDay - ISLAMIC_CIVIL_EPOCH;\n if (days < 0) {\n throw new ChroneraError(\n \"CHRONERA_OUT_OF_RANGE\",\n `Absolute day ${absDay} is prior to the Islamic civil epoch.`,\n );\n }\n\n const cycles = Math.floor(days / 10631);\n let year = cycles * 30 + 1;\n days -= cycles * 10631;\n\n while (true) {\n const daysInYear = isIslamicCivilLeapYear(year) ? 355 : 354;\n if (days < daysInYear) {\n break;\n }\n days -= daysInYear;\n year++;\n }\n\n let month = 1;\n while (month <= 12) {\n const mDays = daysInIslamicCivilMonth(year, month);\n if (days < mDays) {\n break;\n }\n days -= mDays;\n month++;\n }\n\n const day = days + 1;\n return { year, month, day };\n}\n\nexport const ISLAMIC_CIVIL_IDENTITY: CalendarIdentity = {\n id: \"islamic-civil\",\n algorithm: \"chronera-islamic-civil-tabular-v1\",\n deterministic: true,\n validRange: {\n first: ISLAMIC_CIVIL_EPOCH,\n last: 2932896,\n },\n};\n\nexport const islamicCivilValidator: CalendarValidator = {\n identity: ISLAMIC_CIVIL_IDENTITY,\n validate(date: CalendarDate): readonly ChroneraIssue[] {\n const issues: ChroneraIssue[] = [];\n if (date.year < 1) {\n issues.push({\n code: \"CHRONERA_OUT_OF_RANGE\",\n message: `Islamic civil year must be >= 1; received ${date.year}.`,\n path: [\"year\"],\n });\n }\n const month = date.month ?? Number.parseInt(date.monthCode.slice(1), 10);\n if (month < 1 || month > 12) {\n issues.push({\n code: \"CHRONERA_INVALID_DATE\",\n message: `Invalid month ${month}. Expected 1-12.`,\n path: [\"monthCode\"],\n });\n } else if (date.year >= 1) {\n const maxDay = daysInIslamicCivilMonth(date.year, month);\n if (date.day < 1 || date.day > maxDay) {\n issues.push({\n code: \"CHRONERA_INVALID_DATE\",\n message: `Invalid day ${date.day} for month ${date.monthCode} in Islamic civil year ${date.year}.`,\n path: [\"day\"],\n });\n }\n }\n return issues;\n },\n daysInMonth(year: number, monthCode: MonthCode): number {\n const month = Number.parseInt(monthCode.slice(1), 10);\n return daysInIslamicCivilMonth(year, month);\n },\n isLeapYear(year: number): boolean {\n return isIslamicCivilLeapYear(year);\n },\n};\n\nexport const islamicCivilAdapter: CalendarAdapter = {\n identity: ISLAMIC_CIVIL_IDENTITY,\n converter: {\n identity: ISLAMIC_CIVIL_IDENTITY,\n toAbsoluteDay(date: CalendarDate): number {\n const month = date.month ?? Number.parseInt(date.monthCode.slice(1), 10);\n return islamicCivilToAbsoluteDay(date.year, month, date.day);\n },\n fromAbsoluteDay(day: number): CalendarDate {\n const res = islamicCivilFromAbsoluteDay(day);\n return {\n kind: \"calendar-date\",\n calendar: \"islamic-civil\",\n era: \"AH\",\n eraYear: res.year,\n year: res.year,\n monthCode: `M${String(res.month).padStart(2, \"0\")}`,\n month: res.month,\n day: res.day,\n };\n },\n },\n validator: islamicCivilValidator,\n};\n"]}
@@ -0,0 +1,3 @@
1
+ export { islamicCivilAdapter, ISLAMIC_CIVIL_IDENTITY, islamicCivilValidator, isIslamicCivilLeapYear, daysInIslamicCivilMonth, } from "./civil-adapter.js";
2
+ export { islamicTblaAdapter, ISLAMIC_TBLA_IDENTITY, islamicTblaValidator, } from "./tabular-adapter.js";
3
+ export { islamicUmalquraAdapter, ISLAMIC_UMALQURA_IDENTITY, } from "./umm-al-qura-adapter.js";
@@ -0,0 +1,4 @@
1
+ export { islamicCivilAdapter, ISLAMIC_CIVIL_IDENTITY, islamicCivilValidator, isIslamicCivilLeapYear, daysInIslamicCivilMonth, } from "./civil-adapter.js";
2
+ export { islamicTblaAdapter, ISLAMIC_TBLA_IDENTITY, islamicTblaValidator, } from "./tabular-adapter.js";
3
+ export { islamicUmalquraAdapter, ISLAMIC_UMALQURA_IDENTITY, } from "./umm-al-qura-adapter.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/calendar/hijri/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,0BAA0B,CAAC","sourcesContent":["export {\n islamicCivilAdapter,\n ISLAMIC_CIVIL_IDENTITY,\n islamicCivilValidator,\n isIslamicCivilLeapYear,\n daysInIslamicCivilMonth,\n} from \"./civil-adapter.js\";\n\nexport {\n islamicTblaAdapter,\n ISLAMIC_TBLA_IDENTITY,\n islamicTblaValidator,\n} from \"./tabular-adapter.js\";\n\nexport {\n islamicUmalquraAdapter,\n ISLAMIC_UMALQURA_IDENTITY,\n} from \"./umm-al-qura-adapter.js\";\n"]}
@@ -0,0 +1,4 @@
1
+ import type { CalendarAdapter, CalendarIdentity, CalendarValidator } from "../types.js";
2
+ export declare const ISLAMIC_TBLA_IDENTITY: CalendarIdentity;
3
+ export declare const islamicTblaValidator: CalendarValidator;
4
+ export declare const islamicTblaAdapter: CalendarAdapter;