siderust-js 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 (272) hide show
  1. package/.github/workflows/ci.yml +166 -0
  2. package/.gitmodules +9 -0
  3. package/CHANGELOG.md +26 -0
  4. package/LICENSE +661 -0
  5. package/README.md +138 -0
  6. package/package.json +12 -0
  7. package/qtty-js/.github/workflows/ci.yml +151 -0
  8. package/qtty-js/.gitmodules +3 -0
  9. package/qtty-js/CHANGELOG.md +31 -0
  10. package/qtty-js/LICENSE +661 -0
  11. package/qtty-js/README.md +132 -0
  12. package/qtty-js/package.json +20 -0
  13. package/qtty-js/qtty/.github/workflows/ci.yml +155 -0
  14. package/qtty-js/qtty/CHANGELOG.md +120 -0
  15. package/qtty-js/qtty/Cargo.lock +1462 -0
  16. package/qtty-js/qtty/Cargo.toml +12 -0
  17. package/qtty-js/qtty/LICENSE +661 -0
  18. package/qtty-js/qtty/README.md +9 -0
  19. package/qtty-js/qtty/qtty/Cargo.toml +41 -0
  20. package/qtty-js/qtty/qtty/README.md +8 -0
  21. package/qtty-js/qtty/qtty/examples/angles.rs +14 -0
  22. package/qtty-js/qtty/qtty/examples/astronomy.rs +17 -0
  23. package/qtty-js/qtty/qtty/examples/dimensional_arithmetic.rs +83 -0
  24. package/qtty-js/qtty/qtty/examples/python_integration.rs +61 -0
  25. package/qtty-js/qtty/qtty/examples/quickstart.rs +15 -0
  26. package/qtty-js/qtty/qtty/examples/ratios.rs +12 -0
  27. package/qtty-js/qtty/qtty/examples/serde_with_unit.rs +234 -0
  28. package/qtty-js/qtty/qtty/examples/serialization.rs +141 -0
  29. package/qtty-js/qtty/qtty/examples/serialization_advanced.rs +155 -0
  30. package/qtty-js/qtty/qtty/src/f32.rs +108 -0
  31. package/qtty-js/qtty/qtty/src/f64.rs +30 -0
  32. package/qtty-js/qtty/qtty/src/i128.rs +111 -0
  33. package/qtty-js/qtty/qtty/src/i16.rs +111 -0
  34. package/qtty-js/qtty/qtty/src/i32.rs +111 -0
  35. package/qtty-js/qtty/qtty/src/i64.rs +111 -0
  36. package/qtty-js/qtty/qtty/src/i8.rs +111 -0
  37. package/qtty-js/qtty/qtty/src/lib.rs +238 -0
  38. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-no-std/Cargo.lock +83 -0
  39. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-no-std/Cargo.toml +10 -0
  40. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-no-std/src/lib.rs +7 -0
  41. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-no-std-alloc/Cargo.lock +83 -0
  42. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-no-std-alloc/Cargo.toml +10 -0
  43. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-no-std-alloc/src/lib.rs +7 -0
  44. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-std/Cargo.lock +83 -0
  45. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-std/Cargo.toml +10 -0
  46. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-std/src/lib.rs +5 -0
  47. package/qtty-js/qtty/qtty/tests/integration_tests.rs +529 -0
  48. package/qtty-js/qtty/qtty/tests/qtty_vec_feature_matrix.rs +58 -0
  49. package/qtty-js/qtty/qtty-core/Cargo.toml +41 -0
  50. package/qtty-js/qtty/qtty-core/README.md +8 -0
  51. package/qtty-js/qtty/qtty-core/examples/diesel_integration.rs +145 -0
  52. package/qtty-js/qtty/qtty-core/examples/quantity_db_serde.rs +215 -0
  53. package/qtty-js/qtty/qtty-core/src/dimension.rs +249 -0
  54. package/qtty-js/qtty/qtty-core/src/feature_diesel.rs +318 -0
  55. package/qtty-js/qtty/qtty-core/src/feature_pyo3.rs +27 -0
  56. package/qtty-js/qtty/qtty-core/src/feature_serde.rs +203 -0
  57. package/qtty-js/qtty/qtty-core/src/feature_tiberius.rs +28 -0
  58. package/qtty-js/qtty/qtty-core/src/lib.rs +744 -0
  59. package/qtty-js/qtty/qtty-core/src/macros.rs +93 -0
  60. package/qtty-js/qtty/qtty-core/src/quantity.rs +810 -0
  61. package/qtty-js/qtty/qtty-core/src/scalar.rs +1742 -0
  62. package/qtty-js/qtty/qtty-core/src/unit.rs +332 -0
  63. package/qtty-js/qtty/qtty-core/src/units/angular.rs +1228 -0
  64. package/qtty-js/qtty/qtty-core/src/units/area.rs +243 -0
  65. package/qtty-js/qtty/qtty-core/src/units/frequency.rs +179 -0
  66. package/qtty-js/qtty/qtty-core/src/units/length.rs +1270 -0
  67. package/qtty-js/qtty/qtty-core/src/units/mass.rs +488 -0
  68. package/qtty-js/qtty/qtty-core/src/units/mod.rs +26 -0
  69. package/qtty-js/qtty/qtty-core/src/units/power.rs +324 -0
  70. package/qtty-js/qtty/qtty-core/src/units/time.rs +667 -0
  71. package/qtty-js/qtty/qtty-core/src/units/unitless.rs +212 -0
  72. package/qtty-js/qtty/qtty-core/src/units/velocity.rs +210 -0
  73. package/qtty-js/qtty/qtty-core/src/units/volume.rs +269 -0
  74. package/qtty-js/qtty/qtty-core/tests/core.rs +628 -0
  75. package/qtty-js/qtty/qtty-core/tests/diesel.rs +461 -0
  76. package/qtty-js/qtty/qtty-core/tests/integers.rs +632 -0
  77. package/qtty-js/qtty/qtty-core/tests/no_cross_unit_ops.rs +35 -0
  78. package/qtty-js/qtty/qtty-core/tests/pyo3.rs +334 -0
  79. package/qtty-js/qtty/qtty-core/tests/quantity_f32.rs +276 -0
  80. package/qtty-js/qtty/qtty-core/tests/scalar_decimal.rs +258 -0
  81. package/qtty-js/qtty/qtty-core/tests/scalar_f32.rs +286 -0
  82. package/qtty-js/qtty/qtty-core/tests/scalar_f64_real.rs +287 -0
  83. package/qtty-js/qtty/qtty-core/tests/scalar_rational.rs +260 -0
  84. package/qtty-js/qtty/qtty-core/tests/serde.rs +256 -0
  85. package/qtty-js/qtty/qtty-core/tests/tiberius.rs +208 -0
  86. package/qtty-js/qtty/qtty-derive/Cargo.toml +23 -0
  87. package/qtty-js/qtty/qtty-derive/README.md +8 -0
  88. package/qtty-js/qtty/qtty-derive/src/lib.rs +340 -0
  89. package/qtty-js/qtty/qtty-ffi/ARCHITECTURE.md +3 -0
  90. package/qtty-js/qtty/qtty-ffi/Cargo.toml +31 -0
  91. package/qtty-js/qtty/qtty-ffi/README.md +9 -0
  92. package/qtty-js/qtty/qtty-ffi/build.rs +326 -0
  93. package/qtty-js/qtty/qtty-ffi/cbindgen.toml +105 -0
  94. package/qtty-js/qtty/qtty-ffi/include/qtty_ffi.h +1126 -0
  95. package/qtty-js/qtty/qtty-ffi/src/ffi.rs +1251 -0
  96. package/qtty-js/qtty/qtty-ffi/src/ffi_serde.rs +294 -0
  97. package/qtty-js/qtty/qtty-ffi/src/helpers.rs +310 -0
  98. package/qtty-js/qtty/qtty-ffi/src/lib.rs +229 -0
  99. package/qtty-js/qtty/qtty-ffi/src/macros.rs +121 -0
  100. package/qtty-js/qtty/qtty-ffi/src/registry.rs +274 -0
  101. package/qtty-js/qtty/qtty-ffi/src/types.rs +620 -0
  102. package/qtty-js/qtty/qtty-ffi/tests/integration_tests.rs +842 -0
  103. package/qtty-js/qtty/qtty-ffi/units.csv +156 -0
  104. package/qtty-js/qtty/qtty-ffi/units.csv.md +3 -0
  105. package/qtty-js/qtty-node/.prettierignore +6 -0
  106. package/qtty-js/qtty-node/.prettierrc.json +6 -0
  107. package/qtty-js/qtty-node/README.md +250 -0
  108. package/qtty-js/qtty-node/c8.config.json +11 -0
  109. package/qtty-js/qtty-node/eslint.config.js +31 -0
  110. package/qtty-js/qtty-node/examples/arithmetic.mjs +64 -0
  111. package/qtty-js/qtty-node/examples/astronomy.mjs +90 -0
  112. package/qtty-js/qtty-node/examples/quickstart.mjs +36 -0
  113. package/qtty-js/qtty-node/examples/serialization.mjs +125 -0
  114. package/qtty-js/qtty-node/examples/unit_factories.mjs +74 -0
  115. package/qtty-js/qtty-node/index.d.ts +219 -0
  116. package/qtty-js/qtty-node/index.js +323 -0
  117. package/qtty-js/qtty-node/lib/DerivedQuantity.js +122 -0
  118. package/qtty-js/qtty-node/lib/Quantity.js +151 -0
  119. package/qtty-js/qtty-node/lib/backend.js +25 -0
  120. package/qtty-js/qtty-node/native.cjs +306 -0
  121. package/qtty-js/qtty-node/package-lock.json +3223 -0
  122. package/qtty-js/qtty-node/package.json +70 -0
  123. package/qtty-js/qtty-node/units.d.ts +299 -0
  124. package/qtty-js/qtty-node/units.js +210 -0
  125. package/qtty-js/qtty-web/Cargo.lock +767 -0
  126. package/qtty-js/qtty-web/Cargo.toml +21 -0
  127. package/qtty-js/qtty-web/index.d.ts +140 -0
  128. package/qtty-js/qtty-web/index.js +20 -0
  129. package/qtty-js/qtty-web/lib/DerivedQuantity.js +58 -0
  130. package/qtty-js/qtty-web/lib/Quantity.js +75 -0
  131. package/qtty-js/qtty-web/lib/backend.js +80 -0
  132. package/qtty-js/qtty-web/package.json +45 -0
  133. package/qtty-js/qtty-web/src/lib.rs +111 -0
  134. package/qtty-js/scripts/ci.sh +73 -0
  135. package/scripts/ci.sh +123 -0
  136. package/siderust-core/Cargo.lock +787 -0
  137. package/siderust-core/Cargo.toml +18 -0
  138. package/siderust-core/DEDUPLICATION.md +124 -0
  139. package/siderust-core/src/body.rs +120 -0
  140. package/siderust-core/src/events.rs +184 -0
  141. package/siderust-core/src/lib.rs +20 -0
  142. package/siderust-core/src/observer.rs +55 -0
  143. package/siderust-core/src/position.rs +213 -0
  144. package/siderust-node/.prettierignore +7 -0
  145. package/siderust-node/.prettierrc.json +6 -0
  146. package/siderust-node/Cargo.lock +906 -0
  147. package/siderust-node/Cargo.toml +29 -0
  148. package/siderust-node/README.md +109 -0
  149. package/siderust-node/__test__/index.test.mjs +248 -0
  150. package/siderust-node/build.rs +5 -0
  151. package/siderust-node/c8.config.json +3 -0
  152. package/siderust-node/eslint.config.js +31 -0
  153. package/siderust-node/examples/01_basic_coordinates.mjs +24 -0
  154. package/siderust-node/examples/02_coordinate_transformations.mjs +25 -0
  155. package/siderust-node/examples/03_all_frames_conversions.mjs +26 -0
  156. package/siderust-node/examples/04_all_center_conversions.mjs +24 -0
  157. package/siderust-node/examples/05_target_tracking.mjs +22 -0
  158. package/siderust-node/examples/06_night_events.mjs +18 -0
  159. package/siderust-node/examples/07_moon_properties.mjs +21 -0
  160. package/siderust-node/examples/08_solar_system.mjs +19 -0
  161. package/siderust-node/examples/09_star_observability.mjs +22 -0
  162. package/siderust-node/examples/10_time_periods.mjs +9 -0
  163. package/siderust-node/examples/11_serialization.mjs +31 -0
  164. package/siderust-node/examples/12_runtime_ephemeris.mjs +27 -0
  165. package/siderust-node/examples/13_coordinate_operations.mjs +20 -0
  166. package/siderust-node/index.d.ts +623 -0
  167. package/siderust-node/index.js +79 -0
  168. package/siderust-node/lib/Observer.js +112 -0
  169. package/siderust-node/lib/Star.js +118 -0
  170. package/siderust-node/lib/backend.js +63 -0
  171. package/siderust-node/lib/wrappers.js +566 -0
  172. package/siderust-node/main.js +20 -0
  173. package/siderust-node/native.cjs +360 -0
  174. package/siderust-node/package-lock.json +3261 -0
  175. package/siderust-node/package.json +71 -0
  176. package/siderust-node/src/body.rs +74 -0
  177. package/siderust-node/src/coordinates.rs +372 -0
  178. package/siderust-node/src/ephemeris.rs +462 -0
  179. package/siderust-node/src/events.rs +577 -0
  180. package/siderust-node/src/lib.rs +43 -0
  181. package/siderust-node/src/observer.rs +132 -0
  182. package/siderust-node/src/phase.rs +218 -0
  183. package/siderust-node/src/position.rs +292 -0
  184. package/siderust-node/src/star.rs +200 -0
  185. package/siderust-web/Cargo.lock +855 -0
  186. package/siderust-web/Cargo.toml +34 -0
  187. package/siderust-web/README.md +100 -0
  188. package/siderust-web/__test__/index.test.mjs +118 -0
  189. package/siderust-web/examples/github-pages/README.md +31 -0
  190. package/siderust-web/examples/github-pages/index.html +135 -0
  191. package/siderust-web/index.d.ts +311 -0
  192. package/siderust-web/index.js +66 -0
  193. package/siderust-web/lib/Observer.js +103 -0
  194. package/siderust-web/lib/Star.js +116 -0
  195. package/siderust-web/lib/backend.js +400 -0
  196. package/siderust-web/lib/wrappers.js +512 -0
  197. package/siderust-web/package.json +55 -0
  198. package/siderust-web/src/body.rs +69 -0
  199. package/siderust-web/src/coordinates.rs +302 -0
  200. package/siderust-web/src/ephemeris.rs +456 -0
  201. package/siderust-web/src/events.rs +520 -0
  202. package/siderust-web/src/lib.rs +51 -0
  203. package/siderust-web/src/observer.rs +117 -0
  204. package/siderust-web/src/phase.rs +190 -0
  205. package/siderust-web/src/position.rs +291 -0
  206. package/siderust-web/src/star.rs +178 -0
  207. package/tempoch-js/.github/workflows/ci.yml +142 -0
  208. package/tempoch-js/.gitmodules +3 -0
  209. package/tempoch-js/CHANGELOG.md +25 -0
  210. package/tempoch-js/LICENSE +661 -0
  211. package/tempoch-js/README.md +126 -0
  212. package/tempoch-js/package.json +20 -0
  213. package/tempoch-js/scripts/ci.sh +73 -0
  214. package/tempoch-js/tempoch/.github/workflows/ci.yml +113 -0
  215. package/tempoch-js/tempoch/CHANGELOG.md +82 -0
  216. package/tempoch-js/tempoch/Cargo.lock +947 -0
  217. package/tempoch-js/tempoch/Cargo.toml +3 -0
  218. package/tempoch-js/tempoch/LICENSE +661 -0
  219. package/tempoch-js/tempoch/README.md +76 -0
  220. package/tempoch-js/tempoch/tempoch/Cargo.toml +27 -0
  221. package/tempoch-js/tempoch/tempoch/examples/periods.rs +45 -0
  222. package/tempoch-js/tempoch/tempoch/examples/quickstart.rs +13 -0
  223. package/tempoch-js/tempoch/tempoch/src/lib.rs +49 -0
  224. package/tempoch-js/tempoch/tempoch/tests/integration.rs +57 -0
  225. package/tempoch-js/tempoch/tempoch-core/Cargo.toml +24 -0
  226. package/tempoch-js/tempoch/tempoch-core/src/delta_t.rs +345 -0
  227. package/tempoch-js/tempoch/tempoch-core/src/instant.rs +811 -0
  228. package/tempoch-js/tempoch/tempoch-core/src/julian_date_ext.rs +142 -0
  229. package/tempoch-js/tempoch/tempoch-core/src/lib.rs +81 -0
  230. package/tempoch-js/tempoch/tempoch-core/src/period.rs +1168 -0
  231. package/tempoch-js/tempoch/tempoch-core/src/scales.rs +779 -0
  232. package/tempoch-js/tempoch/tempoch-ffi/Cargo.lock +889 -0
  233. package/tempoch-js/tempoch/tempoch-ffi/Cargo.toml +26 -0
  234. package/tempoch-js/tempoch/tempoch-ffi/build.rs +24 -0
  235. package/tempoch-js/tempoch/tempoch-ffi/cbindgen.toml +30 -0
  236. package/tempoch-js/tempoch/tempoch-ffi/src/error.rs +19 -0
  237. package/tempoch-js/tempoch/tempoch-ffi/src/lib.rs +82 -0
  238. package/tempoch-js/tempoch/tempoch-ffi/src/period.rs +101 -0
  239. package/tempoch-js/tempoch/tempoch-ffi/src/time.rs +711 -0
  240. package/tempoch-js/tempoch/tempoch-ffi/tests/ffi.rs +265 -0
  241. package/tempoch-js/tempoch-node/.prettierignore +6 -0
  242. package/tempoch-js/tempoch-node/.prettierrc.json +6 -0
  243. package/tempoch-js/tempoch-node/Cargo.lock +496 -0
  244. package/tempoch-js/tempoch-node/Cargo.toml +29 -0
  245. package/tempoch-js/tempoch-node/README.md +265 -0
  246. package/tempoch-js/tempoch-node/__test__/index.test.mjs +598 -0
  247. package/tempoch-js/tempoch-node/build.rs +5 -0
  248. package/tempoch-js/tempoch-node/c8.config.json +3 -0
  249. package/tempoch-js/tempoch-node/eslint.config.js +31 -0
  250. package/tempoch-js/tempoch-node/examples/periods.mjs +79 -0
  251. package/tempoch-js/tempoch-node/examples/quickstart.mjs +71 -0
  252. package/tempoch-js/tempoch-node/examples/timescales.mjs +92 -0
  253. package/tempoch-js/tempoch-node/index.d.ts +280 -0
  254. package/tempoch-js/tempoch-node/index.js +32 -0
  255. package/tempoch-js/tempoch-node/lib/JulianDate.js +176 -0
  256. package/tempoch-js/tempoch-node/lib/ModifiedJulianDate.js +156 -0
  257. package/tempoch-js/tempoch-node/lib/Period.js +133 -0
  258. package/tempoch-js/tempoch-node/lib/backend.js +38 -0
  259. package/tempoch-js/tempoch-node/lib/qttyCompat.js +92 -0
  260. package/tempoch-js/tempoch-node/native.cjs +317 -0
  261. package/tempoch-js/tempoch-node/package-lock.json +3223 -0
  262. package/tempoch-js/tempoch-node/package.json +56 -0
  263. package/tempoch-js/tempoch-node/src/lib.rs +573 -0
  264. package/tempoch-js/tempoch-web/Cargo.toml +23 -0
  265. package/tempoch-js/tempoch-web/index.d.ts +95 -0
  266. package/tempoch-js/tempoch-web/index.js +27 -0
  267. package/tempoch-js/tempoch-web/lib/JulianDate.js +170 -0
  268. package/tempoch-js/tempoch-web/lib/ModifiedJulianDate.js +145 -0
  269. package/tempoch-js/tempoch-web/lib/Period.js +121 -0
  270. package/tempoch-js/tempoch-web/lib/backend.js +118 -0
  271. package/tempoch-js/tempoch-web/package.json +46 -0
  272. package/tempoch-js/tempoch-web/src/lib.rs +184 -0
@@ -0,0 +1,176 @@
1
+ /**
2
+ * @siderust/tempoch — JulianDate façade class.
3
+ *
4
+ * A Julian Date — continuous count of days from the Julian Period origin.
5
+ * This is a plain JS class that delegates computation to the native backend.
6
+ *
7
+ * @module @siderust/tempoch/lib/JulianDate
8
+ */
9
+
10
+ 'use strict';
11
+
12
+ const { Quantity, convert, quantityDimension } = require('./qttyCompat.js');
13
+ const backend = require('./backend.js');
14
+
15
+ class JulianDate {
16
+ /**
17
+ * Create a Julian Date from a raw scalar (days since the Julian Period).
18
+ * @param {number} value
19
+ */
20
+ constructor(value) {
21
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
22
+ throw new Error('Julian date value must be finite (not NaN or ±infinity)');
23
+ }
24
+ this._value = value;
25
+ }
26
+
27
+ /**
28
+ * Create a Julian Date from a JavaScript `Date` object.
29
+ * @param {Date} date
30
+ * @returns {JulianDate}
31
+ */
32
+ static fromDate(date) {
33
+ const raw = backend.jdFromDate(date);
34
+ return new JulianDate(raw);
35
+ }
36
+
37
+ /**
38
+ * Create a Julian Date from explicit UTC components.
39
+ * @param {number} year
40
+ * @param {number} month
41
+ * @param {number} day
42
+ * @param {number} hour
43
+ * @param {number} minute
44
+ * @param {number} second
45
+ * @returns {JulianDate}
46
+ */
47
+ static fromUtc(year, month, day, hour, minute, second) {
48
+ // Delegate to the native class for ΔT correction
49
+ const nativeJd = backend.NativeJulianDate.fromUtc(year, month, day, hour, minute, second);
50
+ return new JulianDate(nativeJd.value);
51
+ }
52
+
53
+ /**
54
+ * The J2000.0 epoch — JD 2 451 545.0.
55
+ * @returns {JulianDate}
56
+ */
57
+ static j2000() {
58
+ return new JulianDate(2_451_545.0);
59
+ }
60
+
61
+ /** Raw Julian Date value. */
62
+ get value() {
63
+ return this._value;
64
+ }
65
+
66
+ /** The JD value as a `Quantity` in Days. */
67
+ get days() {
68
+ return new Quantity(this._value, 'Day');
69
+ }
70
+
71
+ /**
72
+ * Convert to a `ModifiedJulianDate`.
73
+ * @returns {import('./ModifiedJulianDate.js').ModifiedJulianDate}
74
+ */
75
+ toMjd() {
76
+ // Lazy require to break circular dependency
77
+ const { ModifiedJulianDate } = require('./ModifiedJulianDate.js');
78
+ return new ModifiedJulianDate(backend.jdToMjd(this._value));
79
+ }
80
+
81
+ /**
82
+ * Convert to a JavaScript `Date` (UTC).
83
+ * @returns {Date}
84
+ */
85
+ toDate() {
86
+ return backend.jdToDate(this._value);
87
+ }
88
+
89
+ /**
90
+ * Julian centuries since J2000.0 (T).
91
+ * @returns {Quantity} Quantity in JulianCentury
92
+ */
93
+ julianCenturies() {
94
+ return new Quantity(backend.julianCenturies(this._value), 'JulianCentury');
95
+ }
96
+
97
+ /**
98
+ * Julian years since J2000.0.
99
+ * @returns {Quantity} Quantity in JulianYear
100
+ */
101
+ julianYears() {
102
+ return new Quantity(backend.julianYears(this._value), 'JulianYear');
103
+ }
104
+
105
+ /**
106
+ * Add a time duration (Quantity or number of days).
107
+ * @param {Quantity | number} duration A time `Quantity` or raw days
108
+ * @returns {JulianDate}
109
+ */
110
+ add(duration) {
111
+ const days = _toDays(duration);
112
+ return new JulianDate(this._value + days);
113
+ }
114
+
115
+ /**
116
+ * Subtract a time duration.
117
+ * @param {Quantity | number} duration A time `Quantity` or raw days
118
+ * @returns {JulianDate}
119
+ */
120
+ sub(duration) {
121
+ const days = _toDays(duration);
122
+ return new JulianDate(this._value - days);
123
+ }
124
+
125
+ /**
126
+ * Add a duration in days, returning a new `JulianDate`.
127
+ * @param {number} days
128
+ * @returns {JulianDate}
129
+ * @deprecated Use `add(Days(n))` instead.
130
+ */
131
+ addDays(days) {
132
+ if (!Number.isFinite(days)) {
133
+ throw new Error('days must be finite');
134
+ }
135
+ return new JulianDate(this._value + days);
136
+ }
137
+
138
+ /**
139
+ * Signed difference `self − other` in days as a `Quantity`.
140
+ * @param {JulianDate} other
141
+ * @returns {Quantity} Quantity in Day
142
+ */
143
+ difference(other) {
144
+ return new Quantity(this._value - other._value, 'Day');
145
+ }
146
+
147
+ /**
148
+ * Human-readable representation.
149
+ * @returns {string}
150
+ */
151
+ format() {
152
+ return `Julian Day: ${this._value} d`;
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Convert a duration argument to days (number).
158
+ * @param {Quantity | number} d
159
+ * @returns {number}
160
+ */
161
+ function _toDays(d) {
162
+ if (typeof d === 'number') {
163
+ if (!Number.isFinite(d)) throw new Error('Duration must be finite');
164
+ return d;
165
+ }
166
+ if (d && typeof d.value === 'number' && typeof d.unit === 'string') {
167
+ const dimension = quantityDimension(d);
168
+ if (dimension !== 'Time') {
169
+ throw new Error(`Expected a time Quantity, got ${dimension}`);
170
+ }
171
+ return convert(d.value, d.unit, 'Day');
172
+ }
173
+ throw new Error('Expected a Quantity or number');
174
+ }
175
+
176
+ module.exports = { JulianDate };
@@ -0,0 +1,156 @@
1
+ /**
2
+ * @siderust/tempoch — ModifiedJulianDate façade class.
3
+ *
4
+ * A Modified Julian Date — `JD − 2 400 000.5`.
5
+ *
6
+ * @module @siderust/tempoch/lib/ModifiedJulianDate
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const { Quantity, convert, quantityDimension } = require('./qttyCompat.js');
12
+ const backend = require('./backend.js');
13
+
14
+ class ModifiedJulianDate {
15
+ /**
16
+ * Create a Modified Julian Date from a raw scalar.
17
+ * @param {number} value
18
+ */
19
+ constructor(value) {
20
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
21
+ throw new Error('MJD value must be finite (not NaN or ±infinity)');
22
+ }
23
+ this._value = value;
24
+ }
25
+
26
+ /**
27
+ * Create a Modified Julian Date from a JavaScript `Date` object.
28
+ * @param {Date} date
29
+ * @returns {ModifiedJulianDate}
30
+ */
31
+ static fromDate(date) {
32
+ const raw = backend.mjdFromDate(date);
33
+ return new ModifiedJulianDate(raw);
34
+ }
35
+
36
+ /**
37
+ * Create a Modified Julian Date from explicit UTC components.
38
+ * @param {number} year
39
+ * @param {number} month
40
+ * @param {number} day
41
+ * @param {number} hour
42
+ * @param {number} minute
43
+ * @param {number} second
44
+ * @returns {ModifiedJulianDate}
45
+ */
46
+ static fromUtc(year, month, day, hour, minute, second) {
47
+ const nativeMjd = backend.NativeModifiedJulianDate.fromUtc(
48
+ year,
49
+ month,
50
+ day,
51
+ hour,
52
+ minute,
53
+ second,
54
+ );
55
+ return new ModifiedJulianDate(nativeMjd.value);
56
+ }
57
+
58
+ /** Raw MJD value. */
59
+ get value() {
60
+ return this._value;
61
+ }
62
+
63
+ /** The MJD value as a `Quantity` in Days. */
64
+ get days() {
65
+ return new Quantity(this._value, 'Day');
66
+ }
67
+
68
+ /**
69
+ * Convert to a `JulianDate`.
70
+ * @returns {import('./JulianDate.js').JulianDate}
71
+ */
72
+ toJd() {
73
+ const { JulianDate } = require('./JulianDate.js');
74
+ return new JulianDate(backend.mjdToJd(this._value));
75
+ }
76
+
77
+ /**
78
+ * Convert to a JavaScript `Date` (UTC).
79
+ * @returns {Date}
80
+ */
81
+ toDate() {
82
+ return backend.mjdToDate(this._value);
83
+ }
84
+
85
+ /**
86
+ * Add a time duration (Quantity or number of days).
87
+ * @param {Quantity | number} duration
88
+ * @returns {ModifiedJulianDate}
89
+ */
90
+ add(duration) {
91
+ const days = _toDays(duration);
92
+ return new ModifiedJulianDate(this._value + days);
93
+ }
94
+
95
+ /**
96
+ * Subtract a time duration.
97
+ * @param {Quantity | number} duration
98
+ * @returns {ModifiedJulianDate}
99
+ */
100
+ sub(duration) {
101
+ const days = _toDays(duration);
102
+ return new ModifiedJulianDate(this._value - days);
103
+ }
104
+
105
+ /**
106
+ * Add a duration in days, returning a new `ModifiedJulianDate`.
107
+ * @param {number} days
108
+ * @returns {ModifiedJulianDate}
109
+ * @deprecated Use `add(Days(n))` instead.
110
+ */
111
+ addDays(days) {
112
+ if (!Number.isFinite(days)) {
113
+ throw new Error('days must be finite');
114
+ }
115
+ return new ModifiedJulianDate(this._value + days);
116
+ }
117
+
118
+ /**
119
+ * Signed difference `self − other` in days as a `Quantity`.
120
+ * @param {ModifiedJulianDate} other
121
+ * @returns {Quantity} Quantity in Day
122
+ */
123
+ difference(other) {
124
+ return new Quantity(this._value - other._value, 'Day');
125
+ }
126
+
127
+ /**
128
+ * Human-readable representation.
129
+ * @returns {string}
130
+ */
131
+ format() {
132
+ return `MJD ${this._value} d`;
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Convert a duration argument to days (number).
138
+ * @param {Quantity | number} d
139
+ * @returns {number}
140
+ */
141
+ function _toDays(d) {
142
+ if (typeof d === 'number') {
143
+ if (!Number.isFinite(d)) throw new Error('Duration must be finite');
144
+ return d;
145
+ }
146
+ if (d && typeof d.value === 'number' && typeof d.unit === 'string') {
147
+ const dimension = quantityDimension(d);
148
+ if (dimension !== 'Time') {
149
+ throw new Error(`Expected a time Quantity, got ${dimension}`);
150
+ }
151
+ return convert(d.value, d.unit, 'Day');
152
+ }
153
+ throw new Error('Expected a Quantity or number');
154
+ }
155
+
156
+ module.exports = { ModifiedJulianDate };
@@ -0,0 +1,133 @@
1
+ /**
2
+ * @siderust/tempoch — Period façade class.
3
+ *
4
+ * A time period (interval) defined by two `ModifiedJulianDate` endpoints.
5
+ * Intervals are half-open `[start, end)`.
6
+ *
7
+ * @module @siderust/tempoch/lib/Period
8
+ */
9
+
10
+ 'use strict';
11
+
12
+ const { Quantity } = require('./qttyCompat.js');
13
+ const { ModifiedJulianDate } = require('./ModifiedJulianDate.js');
14
+ const backend = require('./backend.js');
15
+
16
+ class Period {
17
+ /**
18
+ * Create a period from two `ModifiedJulianDate` objects.
19
+ *
20
+ * @param {ModifiedJulianDate} start
21
+ * @param {ModifiedJulianDate} end
22
+ */
23
+ constructor(start, end) {
24
+ // Accept either ModifiedJulianDate objects or raw numbers (backward compat).
25
+ const startVal = typeof start === 'number' ? start : start._value;
26
+ const endVal = typeof end === 'number' ? end : end._value;
27
+
28
+ if (!Number.isFinite(startVal) || !Number.isFinite(endVal)) {
29
+ throw new Error('Period endpoints must be finite');
30
+ }
31
+ if (startVal > endVal) {
32
+ throw new Error('Period start must not be after end');
33
+ }
34
+ this._startMjd = startVal;
35
+ this._endMjd = endVal;
36
+ }
37
+
38
+ /**
39
+ * Create a period from two JavaScript `Date` objects.
40
+ * @param {Date} start
41
+ * @param {Date} end
42
+ * @returns {Period}
43
+ */
44
+ static fromDates(start, end) {
45
+ const startMjd = backend.mjdFromDate(start);
46
+ const endMjd = backend.mjdFromDate(end);
47
+ if (startMjd > endMjd) {
48
+ throw new Error('Period start must not be after end');
49
+ }
50
+ return new Period(startMjd, endMjd);
51
+ }
52
+
53
+ /** Start of the period as a raw MJD value. */
54
+ get startMjd() {
55
+ return this._startMjd;
56
+ }
57
+
58
+ /** End of the period as a raw MJD value. */
59
+ get endMjd() {
60
+ return this._endMjd;
61
+ }
62
+
63
+ /** Start as a `ModifiedJulianDate` object. */
64
+ get start() {
65
+ return new ModifiedJulianDate(this._startMjd);
66
+ }
67
+
68
+ /** End as a `ModifiedJulianDate` object. */
69
+ get end() {
70
+ return new ModifiedJulianDate(this._endMjd);
71
+ }
72
+
73
+ /**
74
+ * Duration of the period as a `Quantity` in Days.
75
+ * @returns {Quantity}
76
+ */
77
+ duration() {
78
+ return new Quantity(this._endMjd - this._startMjd, 'Day');
79
+ }
80
+
81
+ /**
82
+ * Duration of the period in days (raw number).
83
+ * @returns {number}
84
+ */
85
+ durationDays() {
86
+ return this._endMjd - this._startMjd;
87
+ }
88
+
89
+ /**
90
+ * Return the overlapping sub-period, or `null` if they do not overlap.
91
+ * @param {Period} other
92
+ * @returns {Period | null}
93
+ */
94
+ intersection(other) {
95
+ const s = Math.max(this._startMjd, other._startMjd);
96
+ const e = Math.min(this._endMjd, other._endMjd);
97
+ if (s >= e) return null;
98
+ return new Period(s, e);
99
+ }
100
+
101
+ /**
102
+ * Return `true` if the MJD value falls inside `[start, end)`.
103
+ * @param {number | ModifiedJulianDate} mjd
104
+ * @returns {boolean}
105
+ */
106
+ contains(mjd) {
107
+ const val = typeof mjd === 'number' ? mjd : mjd._value;
108
+ return val >= this._startMjd && val < this._endMjd;
109
+ }
110
+
111
+ /**
112
+ * Return start and end as millisecond timestamps.
113
+ * @returns {{ startMs: number, endMs: number }}
114
+ */
115
+ toUtc() {
116
+ const startDate = backend.mjdToDate(this._startMjd);
117
+ const endDate = backend.mjdToDate(this._endMjd);
118
+ return {
119
+ startMs: startDate.getTime(),
120
+ endMs: endDate.getTime(),
121
+ };
122
+ }
123
+
124
+ /**
125
+ * Human-readable representation.
126
+ * @returns {string}
127
+ */
128
+ format() {
129
+ return `Period(MJD ${this._startMjd.toFixed(6)} to MJD ${this._endMjd.toFixed(6)})`;
130
+ }
131
+ }
132
+
133
+ module.exports = { Period };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @siderust/tempoch — Internal native backend abstraction.
3
+ *
4
+ * Loads the NAPI-RS addon and re-exports only the primitive-level helpers
5
+ * that the JS façade classes need. Consumer code should never import this
6
+ * module directly.
7
+ *
8
+ * @module @siderust/tempoch/lib/backend
9
+ * @private
10
+ */
11
+
12
+ 'use strict';
13
+
14
+ const native = require('../native.cjs');
15
+
16
+ // The native classes are used internally for operations that are cheaper
17
+ // to do in Rust (e.g. fromUtc with ΔT correction, Date↔JD/MJD conversion).
18
+ // The JS façade wraps the results.
19
+
20
+ module.exports = {
21
+ // Native classes — used internally, never exposed directly
22
+ NativeJulianDate: native.JulianDate,
23
+ NativeModifiedJulianDate: native.ModifiedJulianDate,
24
+ NativePeriod: native.Period,
25
+
26
+ // Free functions
27
+ jdToMjd: native.jdToMjd,
28
+ mjdToJd: native.mjdToJd,
29
+ julianCenturies: native.julianCenturies,
30
+ julianYears: native.julianYears,
31
+ jdFromDate: native.jdFromDate,
32
+ mjdFromDate: native.mjdFromDate,
33
+ jdToDate: native.jdToDate,
34
+ mjdToDate: native.mjdToDate,
35
+ jdDifference: native.jdDifference,
36
+ mjdDifference: native.mjdDifference,
37
+ version: native.version,
38
+ };
@@ -0,0 +1,92 @@
1
+ 'use strict';
2
+
3
+ function loadExternalQtty() {
4
+ try {
5
+ return require('@siderust/qtty');
6
+ } catch {
7
+ try {
8
+ return require('qtty-js/qtty-node');
9
+ } catch {
10
+ return null;
11
+ }
12
+ }
13
+ }
14
+
15
+ const externalQtty = loadExternalQtty();
16
+
17
+ const TIME_UNITS_IN_DAYS = {
18
+ Millisecond: 1 / 86_400_000,
19
+ Second: 1 / 86_400,
20
+ Minute: 1 / 1_440,
21
+ Hour: 1 / 24,
22
+ Day: 1,
23
+ Week: 7,
24
+ JulianYear: 365.25,
25
+ JulianCentury: 36_525,
26
+ };
27
+
28
+ class Quantity {
29
+ constructor(value, unit) {
30
+ if (!Number.isFinite(value)) {
31
+ throw new Error('Quantity value must be finite');
32
+ }
33
+ if (!(unit in TIME_UNITS_IN_DAYS)) {
34
+ throw new Error(`Unsupported time unit: ${unit}`);
35
+ }
36
+ this._value = value;
37
+ this._unit = unit;
38
+ }
39
+
40
+ get value() {
41
+ return this._value;
42
+ }
43
+
44
+ get unit() {
45
+ return this._unit;
46
+ }
47
+
48
+ get dimension() {
49
+ return 'Time';
50
+ }
51
+
52
+ to(unit) {
53
+ return new Quantity(convert(this._value, this._unit, unit), unit);
54
+ }
55
+
56
+ toString() {
57
+ return `${this._value} ${this._unit}`;
58
+ }
59
+ }
60
+
61
+ function convert(value, fromUnit, toUnit) {
62
+ if (!Number.isFinite(value)) {
63
+ throw new Error('Quantity value must be finite');
64
+ }
65
+ if (!(fromUnit in TIME_UNITS_IN_DAYS)) {
66
+ throw new Error(`Unsupported time unit: ${fromUnit}`);
67
+ }
68
+ if (!(toUnit in TIME_UNITS_IN_DAYS)) {
69
+ throw new Error(`Unsupported time unit: ${toUnit}`);
70
+ }
71
+
72
+ const days = value * TIME_UNITS_IN_DAYS[fromUnit];
73
+ return days / TIME_UNITS_IN_DAYS[toUnit];
74
+ }
75
+
76
+ function quantityDimension(quantity) {
77
+ if (typeof quantity?.dimension === 'string') {
78
+ return quantity.dimension;
79
+ }
80
+
81
+ if (typeof quantity?.unit === 'string' && quantity.unit in TIME_UNITS_IN_DAYS) {
82
+ return 'Time';
83
+ }
84
+
85
+ return undefined;
86
+ }
87
+
88
+ module.exports = {
89
+ Quantity: externalQtty?.Quantity ?? Quantity,
90
+ convert: externalQtty?.convert ?? convert,
91
+ quantityDimension,
92
+ };