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,79 @@
1
+ // examples/periods.mjs
2
+ // Run: node examples/periods.mjs
3
+ import { createRequire } from 'node:module';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { dirname, join } from 'node:path';
6
+
7
+ const require = createRequire(import.meta.url);
8
+ const { Period } = require(join(dirname(fileURLToPath(import.meta.url)), '..', 'index.js'));
9
+
10
+ const line = (label = '') =>
11
+ console.log(
12
+ label ? `─── ${label} ${'─'.repeat(Math.max(0, 52 - label.length))}` : '─'.repeat(56),
13
+ );
14
+
15
+ // ─── Construction ─────────────────────────────────────────────────────────
16
+ line('Period construction');
17
+
18
+ // From raw MJD values
19
+ const J2000_MJD = 51_544.5;
20
+ const p1 = new Period(J2000_MJD, J2000_MJD + 30);
21
+ console.log(`p1 : ${p1.format()}`);
22
+ console.log(` duration : ${p1.durationDays()} d`);
23
+
24
+ // From JavaScript Date objects
25
+ const start2024 = new Date('2024-01-01T00:00:00Z');
26
+ const end2024 = new Date('2025-01-01T00:00:00Z');
27
+ const year2024 = Period.fromDates(start2024, end2024);
28
+ console.log(`2024 calendar year:`);
29
+ console.log(` startMjd : ${year2024.startMjd.toFixed(2)}`);
30
+ console.log(` endMjd : ${year2024.endMjd.toFixed(2)}`);
31
+ console.log(` duration : ${year2024.durationDays().toFixed(2)} d (2024 is a leap year)`);
32
+
33
+ // ─── Accessors ────────────────────────────────────────────────────────────
34
+ line('Accessors');
35
+ const p = new Period(J2000_MJD, J2000_MJD + 10);
36
+ const startObj = p.start; // ModifiedJulianDate
37
+ const endObj = p.end; // ModifiedJulianDate
38
+ console.log(`start : MJD ${startObj.value} → ${startObj.toDate().toISOString()}`);
39
+ console.log(`end : MJD ${endObj.value} → ${endObj.toDate().toISOString()}`);
40
+
41
+ // ─── Containment ──────────────────────────────────────────────────────────
42
+ line('Containment [start, end)');
43
+ const week = new Period(J2000_MJD, J2000_MJD + 7);
44
+ const points = [
45
+ [J2000_MJD, 'start (included)'],
46
+ [J2000_MJD + 3.5, 'midpoint (included)'],
47
+ [J2000_MJD + 7, 'end (excluded — half-open)'],
48
+ [J2000_MJD - 1, 'before start (excluded)'],
49
+ ];
50
+ for (const [mjd, label] of points) {
51
+ console.log(` contains(${mjd.toFixed(1)}): ${week.contains(mjd)} ← ${label}`);
52
+ }
53
+
54
+ // ─── Intersection ─────────────────────────────────────────────────────────
55
+ line('Intersection');
56
+ const a = new Period(J2000_MJD, J2000_MJD + 10);
57
+ const b = new Period(J2000_MJD + 5, J2000_MJD + 15);
58
+ const c = new Period(J2000_MJD + 20, J2000_MJD + 30);
59
+
60
+ console.log(`a = [${a.startMjd}, ${a.endMjd})`);
61
+ console.log(`b = [${b.startMjd}, ${b.endMjd})`);
62
+ console.log(`c = [${c.startMjd}, ${c.endMjd})`);
63
+
64
+ const ab = a.intersection(b);
65
+ console.log(`a ∩ b = ${ab ? `[${ab.startMjd}, ${ab.endMjd}) → ${ab.durationDays()} d` : 'null'}`);
66
+
67
+ const ac = a.intersection(c);
68
+ console.log(`a ∩ c = ${ac ? `[${ac.startMjd}, ${ac.endMjd})` : 'null (no overlap)'}`);
69
+
70
+ // ─── UTC round-trip ───────────────────────────────────────────────────────
71
+ line('UTC bounds');
72
+ const obs = Period.fromDates(new Date('2025-04-01T20:00:00Z'), new Date('2025-04-02T06:00:00Z'));
73
+ const { startMs, endMs } = obs.toUtc();
74
+ const startDate = new Date(startMs);
75
+ const endDate = new Date(endMs);
76
+ console.log(`Observation window:`);
77
+ console.log(` start : ${startDate.toISOString()}`);
78
+ console.log(` end : ${endDate.toISOString()}`);
79
+ console.log(` duration : ${(obs.durationDays() * 24).toFixed(1)} h`);
@@ -0,0 +1,71 @@
1
+ // examples/quickstart.mjs
2
+ // Run: node examples/quickstart.mjs
3
+ import { createRequire } from 'node:module';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { dirname, join } from 'node:path';
6
+
7
+ const require = createRequire(import.meta.url);
8
+ const {
9
+ JulianDate,
10
+ ModifiedJulianDate,
11
+ jdToMjd,
12
+ mjdToJd,
13
+ jdFromDate,
14
+ mjdFromDate,
15
+ jdToDate,
16
+ } = require(join(dirname(fileURLToPath(import.meta.url)), '..', 'index.js'));
17
+
18
+ const line = (label = '') =>
19
+ console.log(
20
+ label ? `─── ${label} ${'─'.repeat(Math.max(0, 52 - label.length))}` : '─'.repeat(56),
21
+ );
22
+
23
+ // ─── Construction ─────────────────────────────────────────────────────────
24
+ line('Construction');
25
+ const J2000 = JulianDate.j2000();
26
+ console.log(`J2000.0 JD : ${J2000.value}`);
27
+ console.log(`J2000.0 MJD : ${J2000.toMjd().value}`);
28
+
29
+ const now = new Date();
30
+ const jdNow = JulianDate.fromDate(now);
31
+ console.log(`Now (JD) : ${jdNow.value.toFixed(5)}`);
32
+ console.log(`Now (MJD) : ${jdNow.toMjd().value.toFixed(5)}`);
33
+
34
+ // ─── UTC ↔ JD conversion ──────────────────────────────────────────────────
35
+ line('UTC ↔ JD');
36
+ const vernal2025 = JulianDate.fromUtc(2025, 3, 20, 9, 1, 0);
37
+ console.log(`2025 Vernal Equinox JD : ${vernal2025.value.toFixed(4)}`);
38
+ const utcBack = vernal2025.toDate();
39
+ console.log(`Back to UTC : ${utcBack.toISOString()}`);
40
+
41
+ // ─── Free conversion functions ────────────────────────────────────────────
42
+ line('Free functions');
43
+ const d = new Date('2025-01-01T00:00:00Z');
44
+ console.log(`2025-01-01 JD : ${jdFromDate(d).toFixed(4)}`);
45
+ console.log(`2025-01-01 MJD : ${mjdFromDate(d).toFixed(4)}`);
46
+ console.log(`jdToMjd(J2000) : ${jdToMjd(2_451_545.0)}`);
47
+ console.log(`mjdToJd(51544.5): ${mjdToJd(51_544.5)}`);
48
+
49
+ // ─── Epoch-based quantities ───────────────────────────────────────────────
50
+ line('Epoch quantities');
51
+ const obsDate = JulianDate.fromUtc(2025, 6, 15, 0, 0, 0);
52
+ console.log(`JD : ${obsDate.value.toFixed(4)}`);
53
+ console.log(`Julian centuries (T): ${obsDate.julianCenturies().toFixed(6)}`);
54
+ console.log(`Julian years : ${obsDate.julianYears().toFixed(4)}`);
55
+
56
+ // ─── Arithmetic ───────────────────────────────────────────────────────────
57
+ line('Arithmetic');
58
+ const t0 = JulianDate.fromUtc(2025, 1, 1, 0, 0, 0);
59
+ const t1 = t0.addDays(365.25);
60
+ console.log(`t0 : ${jdToDate(t0.value).toISOString().slice(0, 10)}`);
61
+ console.log(`t1 = t0 + 365.25 d : ${jdToDate(t1.value).toISOString().slice(0, 10)}`);
62
+ console.log(`t1 − t0 (days) : ${t1.difference(t0).toFixed(2)}`);
63
+
64
+ // ─── MJD class ────────────────────────────────────────────────────────────
65
+ line('ModifiedJulianDate');
66
+ const mjd0 = new ModifiedJulianDate(51_544.5);
67
+ console.log(`MJD 51544.5 → JD : ${mjd0.toJd().value}`);
68
+ console.log(`MJD 51544.5 → UTC : ${mjd0.toDate().toISOString()}`);
69
+ const mjd1 = mjd0.addDays(1);
70
+ console.log(`+ 1 day : ${mjd1.value}`);
71
+ console.log(`difference : ${mjd1.difference(mjd0).toFixed(1)} d`);
@@ -0,0 +1,92 @@
1
+ // examples/timescales.mjs
2
+ // Astronomical time contexts: J2000.0, centuries, epoch arithmetic.
3
+ // Run: node examples/timescales.mjs
4
+ import { createRequire } from 'node:module';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { dirname, join } from 'node:path';
7
+
8
+ const require = createRequire(import.meta.url);
9
+ const { JulianDate, ModifiedJulianDate, Period, julianCenturies, julianYears } = require(
10
+ join(dirname(fileURLToPath(import.meta.url)), '..', 'index.js'),
11
+ );
12
+
13
+ const line = (label = '') =>
14
+ console.log(
15
+ label ? `─── ${label} ${'─'.repeat(Math.max(0, 52 - label.length))}` : '─'.repeat(56),
16
+ );
17
+
18
+ // ─── The J2000.0 reference epoch ──────────────────────────────────────────
19
+ line('J2000.0 epoch');
20
+ const J2000 = JulianDate.j2000();
21
+ console.log(`JD : ${J2000.value}`);
22
+ console.log(`MJD : ${J2000.toMjd().value}`);
23
+ // UTC ≈ 2000-01-01T11:58:56Z (J2000.0 is TT, not UTC; ΔT ≈ 63.8 s in 2000)
24
+ console.log(`UTC : ${J2000.toDate().toISOString()} (ΔT ≈ 63.8 s offset from TT noon)`);
25
+
26
+ // ─── Standard astronomical epochs ─────────────────────────────────────────
27
+ line('Standard epochs');
28
+ const epochs = [
29
+ { name: 'J1900.0', jd: 2_415_020.0 },
30
+ { name: 'J1950.0', jd: 2_433_282.5 },
31
+ { name: 'J2000.0', jd: 2_451_545.0 },
32
+ { name: 'J2050.0', jd: 2_469_807.5 },
33
+ ];
34
+
35
+ for (const { name, jd } of epochs) {
36
+ const T = julianCenturies(jd);
37
+ const y = julianYears(jd);
38
+ console.log(`${name} JD = ${jd.toFixed(1)} T = ${T.toFixed(4)} y = ${y.toFixed(2)}`);
39
+ }
40
+
41
+ // ─── Julian centuries as a "clock" ────────────────────────────────────────
42
+ line('Centuries since J2000');
43
+ const observations = [
44
+ new Date('1990-01-01T00:00:00Z'),
45
+ new Date('2000-01-01T12:00:00Z'),
46
+ new Date('2010-06-15T00:00:00Z'),
47
+ new Date('2025-01-01T00:00:00Z'),
48
+ ];
49
+ console.log(`${'Date'.padEnd(26)} ${'T (centuries)'.padStart(15)}`);
50
+ for (const d of observations) {
51
+ const jd = JulianDate.fromDate(d);
52
+ const T = jd.julianCenturies();
53
+ console.log(`${d.toISOString().slice(0, 10).padEnd(26)} ${T.toFixed(6).padStart(15)}`);
54
+ }
55
+
56
+ // ─── Epoch arithmetic ─────────────────────────────────────────────────────
57
+ line('Epoch arithmetic');
58
+ const JULIAN_YEAR = 365.25; // days
59
+ const JULIAN_CENTURY = 36_525.0; // days
60
+
61
+ const jd2000 = JulianDate.j2000();
62
+ const jd2100 = jd2000.addDays(JULIAN_CENTURY);
63
+ console.log(`J2100.0 JD : ${jd2100.value}`);
64
+ console.log(`J2100.0 UTC : ${jd2100.toDate().toISOString().slice(0, 10)}`);
65
+ console.log(`J2100 T : ${jd2100.julianCenturies().toFixed(1)}`);
66
+
67
+ const jd_minus5 = jd2000.addDays(-5 * JULIAN_YEAR);
68
+ console.log(`J1995.0 JD : ${jd_minus5.value.toFixed(1)}`);
69
+ console.log(`T from J2000 : ${jd_minus5.julianCenturies().toFixed(6)}`);
70
+
71
+ // ─── Observation window with T values ─────────────────────────────────────
72
+ line('Observation window');
73
+ const nightStart = new Date('2025-04-15T22:00:00Z');
74
+ const nightEnd = new Date('2025-04-16T04:00:00Z');
75
+ const night = Period.fromDates(nightStart, nightEnd);
76
+
77
+ const midMjd = (night.startMjd + night.endMjd) / 2;
78
+ const midJd = new ModifiedJulianDate(midMjd).toJd();
79
+
80
+ console.log(`Start UTC : ${nightStart.toISOString()}`);
81
+ console.log(`End UTC : ${nightEnd.toISOString()}`);
82
+ console.log(`Duration : ${(night.durationDays() * 24).toFixed(1)} h`);
83
+ console.log(`Mid JD : ${midJd.value.toFixed(5)}`);
84
+ console.log(`Mid T : ${midJd.julianCenturies().toFixed(8)} centuries since J2000`);
85
+
86
+ // ─── MJD as a compact date format ─────────────────────────────────────────
87
+ line('MJD compact dates');
88
+ const today = ModifiedJulianDate.fromDate(new Date());
89
+ console.log(`Today MJD : ${today.value.toFixed(4)}`);
90
+ console.log(`Days since J2000 : ${(today.value - 51_544.5).toFixed(2)}`);
91
+ const formatted = today.format();
92
+ console.log(`Formatted : ${formatted}`);
@@ -0,0 +1,280 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ export interface QuantityLike {
5
+ value: number
6
+ unit: string
7
+ dimension?: string
8
+ }
9
+
10
+ /**
11
+ * UTC bounds of a [`Period`] expressed as millisecond timestamps.
12
+ *
13
+ * Construct JS `Date` objects with `new Date(bounds.startMs)`.
14
+ */
15
+ export interface UtcBounds {
16
+ /** Start instant in milliseconds since Unix epoch. */
17
+ startMs: number
18
+ /** End instant in milliseconds since Unix epoch. */
19
+ endMs: number
20
+ }
21
+
22
+ /* ------------------------------------------------------------------ */
23
+ /* Free functions */
24
+ /* ------------------------------------------------------------------ */
25
+
26
+ /**
27
+ * Convert a Julian Date to a Modified Julian Date value.
28
+ *
29
+ * `mjd = jd − 2 400 000.5`
30
+ */
31
+ export declare function jdToMjd(jd: number): number
32
+ /**
33
+ * Convert a Modified Julian Date to a Julian Date value.
34
+ *
35
+ * `jd = mjd + 2 400 000.5`
36
+ */
37
+ export declare function mjdToJd(mjd: number): number
38
+ /** Compute Julian centuries since J2000.0 for a Julian Date. */
39
+ export declare function julianCenturies(jd: number): number
40
+ /** Compute Julian years since J2000.0 for a Julian Date. */
41
+ export declare function julianYears(jd: number): number
42
+ /** Convert a JavaScript `Date` to a Julian Date value. */
43
+ export declare function jdFromDate(date: Date): number
44
+ /** Convert a JavaScript `Date` to a Modified Julian Date value. */
45
+ export declare function mjdFromDate(date: Date): number
46
+ /**
47
+ * Convert a Julian Date value to a JavaScript `Date`.
48
+ *
49
+ * Throws if the Julian Date is outside the representable UTC range.
50
+ */
51
+ export declare function jdToDate(jd: number): Date
52
+ /**
53
+ * Convert a Modified Julian Date value to a JavaScript `Date`.
54
+ *
55
+ * Throws if the MJD is outside the representable UTC range.
56
+ */
57
+ export declare function mjdToDate(mjd: number): Date
58
+ /** Signed difference `jd1 − jd2` in days. */
59
+ export declare function jdDifference(jd1: number, jd2: number): number
60
+ /** Signed difference `mjd1 − mjd2` in days. */
61
+ export declare function mjdDifference(mjd1: number, mjd2: number): number
62
+ /** Return the tempoch-node version string. */
63
+ export declare function version(): string
64
+
65
+ /* ------------------------------------------------------------------ */
66
+ /* JulianDate */
67
+ /* ------------------------------------------------------------------ */
68
+
69
+ /**
70
+ * A Julian Date — continuous count of days from the Julian Period origin.
71
+ *
72
+ * The Julian Date for J2000.0 is **2 451 545.0** (2000-01-01 12:00:00 TT).
73
+ *
74
+ * ```js
75
+ * const { JulianDate } = require('@siderust/tempoch');
76
+ *
77
+ * // Construct from raw value
78
+ * const jd = new JulianDate(2_451_545.0);
79
+ *
80
+ * // Construct from a JavaScript Date
81
+ * const jd2 = JulianDate.fromDate(new Date('2000-01-01T12:00:00Z'));
82
+ * ```
83
+ */
84
+ export declare class JulianDate {
85
+ /**
86
+ * Create a Julian Date from a raw scalar (days since the Julian Period).
87
+ *
88
+ * Throws if `value` is `NaN` or `±Infinity`.
89
+ */
90
+ constructor(value: number)
91
+ /**
92
+ * Create a Julian Date from a JavaScript `Date` object.
93
+ *
94
+ * The UTC timestamp is interpreted as Universal Time and the ΔT
95
+ * correction is applied automatically.
96
+ */
97
+ static fromDate(date: Date): JulianDate
98
+ /**
99
+ * Create a Julian Date from explicit UTC components.
100
+ *
101
+ * `second` may include a fractional part for sub-second precision.
102
+ * All values are in the proleptic Gregorian calendar (UTC).
103
+ */
104
+ static fromUtc(year: number, month: number, day: number, hour: number, minute: number, second: number): JulianDate
105
+ /** The J2000.0 epoch — JD 2 451 545.0 (2000-01-01T12:00:00 TT). */
106
+ static j2000(): JulianDate
107
+ /** Raw Julian Date value (days since the Julian Period origin). */
108
+ get value(): number
109
+ /** The JD value as a quantity-like object in Days. */
110
+ get days(): QuantityLike
111
+ /** Convert to a `ModifiedJulianDate` (`JD − 2 400 000.5`). */
112
+ toMjd(): ModifiedJulianDate
113
+ /**
114
+ * Convert to a JavaScript `Date` (UTC).
115
+ *
116
+ * Throws if the Julian Date falls outside the range representable by
117
+ * `chrono` (roughly −262 143 to +262 143 CE).
118
+ */
119
+ toDate(): Date
120
+ /**
121
+ * Julian centuries since J2000.0 (T) as a quantity-like object.
122
+ *
123
+ * Used extensively by precession, nutation, and sidereal-time formulae.
124
+ */
125
+ julianCenturies(): QuantityLike
126
+ /** Julian years since J2000.0 as a quantity-like object. */
127
+ julianYears(): QuantityLike
128
+ /**
129
+ * Add a time duration, returning a new `JulianDate`.
130
+ *
131
+ * Accepts a quantity-like object (any supported time unit) or a raw number (days).
132
+ */
133
+ add(duration: QuantityLike | number): JulianDate
134
+ /**
135
+ * Subtract a time duration, returning a new `JulianDate`.
136
+ *
137
+ * Accepts a quantity-like object (any supported time unit) or a raw number (days).
138
+ */
139
+ sub(duration: QuantityLike | number): JulianDate
140
+ /**
141
+ * Add a duration in days, returning a new `JulianDate`.
142
+ * @deprecated Use `add()` instead.
143
+ */
144
+ addDays(days: number): JulianDate
145
+ /** Signed difference `self − other` as a quantity-like object in Days. */
146
+ difference(other: JulianDate): QuantityLike
147
+ /** Human-readable representation (e.g. `"Julian Day: 2451545 d"`). */
148
+ format(): string
149
+ }
150
+
151
+ /* ------------------------------------------------------------------ */
152
+ /* ModifiedJulianDate */
153
+ /* ------------------------------------------------------------------ */
154
+
155
+ /**
156
+ * A Modified Julian Date — `JD − 2 400 000.5`.
157
+ *
158
+ * MJD starts at 1858-11-17T00:00:00 UTC (= JD 2 400 000.5).
159
+ * J2000.0 is MJD **51 544.5**.
160
+ *
161
+ * ```js
162
+ * const { ModifiedJulianDate } = require('@siderust/tempoch');
163
+ *
164
+ * const mjd = new ModifiedJulianDate(51_544.5);
165
+ * const mjd2 = ModifiedJulianDate.fromDate(new Date('2000-01-01T12:00:00Z'));
166
+ * ```
167
+ */
168
+ export declare class ModifiedJulianDate {
169
+ /**
170
+ * Create a Modified Julian Date from a raw scalar.
171
+ *
172
+ * Throws if `value` is `NaN` or `±Infinity`.
173
+ */
174
+ constructor(value: number)
175
+ /** Create a Modified Julian Date from a JavaScript `Date` object. */
176
+ static fromDate(date: Date): ModifiedJulianDate
177
+ /** Create a Modified Julian Date from explicit UTC components. */
178
+ static fromUtc(year: number, month: number, day: number, hour: number, minute: number, second: number): ModifiedJulianDate
179
+ /** Raw MJD value. */
180
+ get value(): number
181
+ /** The MJD value as a quantity-like object in Days. */
182
+ get days(): QuantityLike
183
+ /** Convert to a `JulianDate`. */
184
+ toJd(): JulianDate
185
+ /**
186
+ * Convert to a JavaScript `Date` (UTC).
187
+ *
188
+ * Throws if the MJD falls outside the representable UTC range.
189
+ */
190
+ toDate(): Date
191
+ /**
192
+ * Add a time duration, returning a new `ModifiedJulianDate`.
193
+ *
194
+ * Accepts a quantity-like object (any supported time unit) or a raw number (days).
195
+ */
196
+ add(duration: QuantityLike | number): ModifiedJulianDate
197
+ /**
198
+ * Subtract a time duration, returning a new `ModifiedJulianDate`.
199
+ *
200
+ * Accepts a quantity-like object (any supported time unit) or a raw number (days).
201
+ */
202
+ sub(duration: QuantityLike | number): ModifiedJulianDate
203
+ /**
204
+ * Add a duration in days, returning a new `ModifiedJulianDate`.
205
+ * @deprecated Use `add()` instead.
206
+ */
207
+ addDays(days: number): ModifiedJulianDate
208
+ /** Signed difference `self − other` as a quantity-like object in Days. */
209
+ difference(other: ModifiedJulianDate): QuantityLike
210
+ /** Human-readable representation (e.g. `"MJD 51544.5 d"`). */
211
+ format(): string
212
+ }
213
+
214
+ /* ------------------------------------------------------------------ */
215
+ /* Period */
216
+ /* ------------------------------------------------------------------ */
217
+
218
+ /**
219
+ * A time period (interval) defined by two MJD endpoints.
220
+ *
221
+ * Intervals are half-open `[start, end)`: `start` is included, `end` is
222
+ * excluded from containment tests.
223
+ *
224
+ * ```js
225
+ * const { Period } = require('@siderust/tempoch');
226
+ *
227
+ * const p = new Period(51_544.5, 51_545.5); // one-day period at J2000
228
+ * console.log(p.durationDays()); // 1
229
+ * console.log(p.contains(51_545.0)); // true
230
+ * ```
231
+ */
232
+ export declare class Period {
233
+ /**
234
+ * Create a period from two MJD values or `ModifiedJulianDate` objects.
235
+ *
236
+ * Throws if `start > end`.
237
+ */
238
+ constructor(start: number | ModifiedJulianDate, end: number | ModifiedJulianDate)
239
+ /**
240
+ * Create a period from two JavaScript `Date` objects.
241
+ *
242
+ * Throws if `start > end`.
243
+ */
244
+ static fromDates(start: Date, end: Date): Period
245
+ /** Start of the period as a raw MJD value. */
246
+ get startMjd(): number
247
+ /** End of the period as a raw MJD value. */
248
+ get endMjd(): number
249
+ /** Start as a `ModifiedJulianDate` object. */
250
+ get start(): ModifiedJulianDate
251
+ /** End as a `ModifiedJulianDate` object. */
252
+ get end(): ModifiedJulianDate
253
+ /** Duration of the period as a quantity-like object in Days. */
254
+ duration(): QuantityLike
255
+ /** Duration of the period in days (raw number). */
256
+ durationDays(): number
257
+ /**
258
+ * Return the overlapping sub-period, or `null` if they do not overlap.
259
+ *
260
+ * Periods are half-open `[start, end)`: two periods that share only an
261
+ * endpoint are considered non-overlapping.
262
+ */
263
+ intersection(other: Period): Period | null
264
+ /** Return `true` if the value falls inside `[start, end)`. */
265
+ contains(mjd: number | ModifiedJulianDate): boolean
266
+ /**
267
+ * Return start and end as millisecond timestamps (ms since Unix epoch).
268
+ *
269
+ * Construct JS `Date` objects with:
270
+ * ```js
271
+ * const { startMs, endMs } = period.toUtc();
272
+ * const startDate = new Date(startMs);
273
+ * ```
274
+ *
275
+ * Throws if either endpoint is outside the representable UTC range.
276
+ */
277
+ toUtc(): UtcBounds
278
+ /** Human-readable representation. */
279
+ format(): string
280
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @siderust/tempoch — Astronomical time primitives for Node.js.
3
+ *
4
+ * Public entrypoint. Exposes JS-level façade classes (`JulianDate`,
5
+ * `ModifiedJulianDate`, `Period`) and free functions from the native backend.
6
+ *
7
+ * @module @siderust/tempoch
8
+ */
9
+
10
+ 'use strict';
11
+
12
+ const { JulianDate } = require('./lib/JulianDate.js');
13
+ const { ModifiedJulianDate } = require('./lib/ModifiedJulianDate.js');
14
+ const { Period } = require('./lib/Period.js');
15
+
16
+ // Free functions — pass through from the native backend.
17
+ const backend = require('./lib/backend.js');
18
+
19
+ module.exports.JulianDate = JulianDate;
20
+ module.exports.ModifiedJulianDate = ModifiedJulianDate;
21
+ module.exports.Period = Period;
22
+ module.exports.jdToMjd = backend.jdToMjd;
23
+ module.exports.mjdToJd = backend.mjdToJd;
24
+ module.exports.julianCenturies = backend.julianCenturies;
25
+ module.exports.julianYears = backend.julianYears;
26
+ module.exports.jdFromDate = backend.jdFromDate;
27
+ module.exports.mjdFromDate = backend.mjdFromDate;
28
+ module.exports.jdToDate = backend.jdToDate;
29
+ module.exports.mjdToDate = backend.mjdToDate;
30
+ module.exports.jdDifference = backend.jdDifference;
31
+ module.exports.mjdDifference = backend.mjdDifference;
32
+ module.exports.version = backend.version;