/*----------------------------------------------------------------------------
   Copyright 2012-2021, Microsoft Research, Daan Leijen

   Licensed under the Apache License, Version 2.0 ("The Licence"). You may not
   use this file except in compliance with the License. A copy of the License
   can be found in the LICENSE file at the root of this distribution.
----------------------------------------------------------------------------*/

/* Time scales for astronomy (TT, TCG, TDB, and TCB).

Internally all computations use high precision `:ddouble` numbers.
The different time scales relate as follows:

* **TAI**, `ts-tai`, `cal-tai`: International Atomic Time. The atomic time standard
  measuring SI seconds on the Earth's geoid.

* **GPS**, `ts-gps`, `cal-gps`: Global Positioning System time. Runs at the same rate as
  TAI but with a 19 second offset: GPS = TAI - 19s.

* **UT1**, [`cal-ut1-load`](std_time_ut1.html): Universal Time: A time scale based
  on the rotation of the earth where one rotation is 86400 (solar) seconds.
  Defined to be a linear function of the rotation angle of the Earth.
  See the [``std/time/ut1``](std_time_ut1.html) module for more information.

* **UTC**, `ts-utc-create`, `cal-utc-load`:
  Coordinated Universal Time: A hybrid of UT1 and TAI: uses
  SI seconds as its unit, but inserts (or deletes) periodically leap
  seconds in order to stay within 0.9s of UT1. See the [`std/time/utc`](std_time_utc.html)
  module for more information.

* **TI**, `ts-ti`, `cal-iso`: International Time: this was a
  [proposed][TIpropose] time scale at the 2004 ITU-R meeting as a replacement of UTC
  without future leap seconds. In this library, we define TI to match
  exactly UTC up to the compiler release date (currently 2017) but ignore any
  possible future leap seconds after that date. This is the preferred time scale
  in this library as it guarantees deterministic time calculations for any
  future date, i.e. before 2017-01-01Z, TI == UTC, while after that, TI == TAI - 37s.

* **[TT]**, `ts-tt`, `cal-tt`: Terrestrial time. This is an ideal time scale defined to
  run slower at a constant rate from TCG such that TT runs at the same rate as a
  time scale based on SI seconds on the Earth's geoid. Since TCG
  is a theoretical time scale, TT can be considered an idealized form
  of TAI and is currently realized by defining:\
  TT = TAI + 32.184s.\
  Terrestrial time replaces (and preserves continuity with) the older Terrestrial
  Dynamic Time (TDT) and Ephemeris Time (ET).

* **TCG**, `ts-tcg`, `cal-tcg`: Geocentric Coordinate Time. Theoretical clock using
  SI seconds in a coordinate reference frame at the center of the Earth.
  It is in a linear relationship with TT where TCG runs faster
  than TT at a constant rate. By definition, TCG and TT were equal on 1977-01-01Z.
  Computed from TT using IAU 1991 recommendation [IV][IAU-IV]
   (and updated to currently known [precision][IERS-2010])):\
  TCG = TT + L~g~×(JD~TCG~ - 2443144.5003725)×86400, with L~g~ = 6.969290134×10^-10^.

* **TCB**, `ts-tcb`, `cal-tcb`: Barycentric Coordinate Time. Theoretical clock using SI
   seconds in a coordinate reference frame at the gravitational center of the solar
   system. TCB and TCG are related by a coordinate transformation taking
   into account relativistic effects (see IAU 2000 resolution
   [B1.5](https://syrte.obspm.fr/IAU_resolutions/Resol-UAIEng.ps)). In the
   library, instead of transforming TCG, we compute TCB from (the
   approximated) TDB (`ts-tdb`) using the IAU 2006 resolution [B3][IAU-B3]:\
   TDB = TCB - L~b~ × (JD~TCB~ - T~0~) × 86400 + TDB~0~,
   with T~0~ = 2443144.5003725, L~b~ = 1.55051976772×10^-8^, TDB~0~
   = -6.55×10^-5^.

* **TDB**, `ts-tdb`, `cal-tdb`: Barycentric Dynamical Time. Defined to run slower at a
   constant rate from TCB in order to be approximately equal to TT These
   relativistic corrections ensure a difference to TT of less then 2
   milli-seconds and are periodic with an average of zero. In the
   library, TDB is approximated from TT using an initial set of
   coefficients by Fairhead & Bretagnon [@Fairhead:tt] assuming the geo
   center (longitude and latitude of 0 degrees), and corrected for JPL
   planetary masses. See also USNO circular 179 [@Kaplan:circ],
   equation 2.6). The approximation is within 10μs precision in the
   time span 1600 to 2200 (and probably a bit less).

Note that theoretically the definition of TT is based on TCG which is
based on TCB, but in practice we define TT on the basis of an actual clock (TAI)
and derive TCG from TT. Moreover, TDB is approximated from TT, and TCB
is derived from the approximated TDB.

Since TDB (and in turn TCB) are approximated, it is possible to create
your own time scale which uses a potentially more precise approximation using
`ts-tdb-create` and `ts-tcb-create`.

~ Figure { #fig-timescales; caption:"Relation between different time scales relative to TAI between 1950 and 2000. \
    The periodic terms of TCB and TDB are magnified by 100 to make them visible. \
    Figure from Seidelmann and Fukushima [@Seidelmann:why]." }
![timescales]
~

[timescales]: timescales.png { width:70%; }

## References {-}

~ Bibliography { caption:"0" }

~~ BibItem { #Fairhead:tt; bibitem-label:"[1]"; searchterm:"Fairhead+Bretagnon+An+analytical+formula+for+the+time+transformation" }
L.\ Fairhead and P.\ Bretagnon.
_An analytical formula for the time transformation TB-TT_.
Astronomy and Astrophysics, vol. 229, no. 1, March 1990, p. 240--247.
[ADS](https://articles.adsabs.harvard.edu/cgi-bin/nph-iarticle_query?1990A%26A...229..240F)
~~

~~ BibItem { #Kaplan:circ; bibitem-label:"[2]"; searchterm:"Kaplan+The+IAU+Resolutions+on+Astronomical+Reference+Systems" }
George H.\ Kaplan.
_The IAU Resolutions on Astronomical Reference Systems,
Time Scales, and Earth Rotation Models -- Explanation and Implementation_.
USNO Circular [179](https://aa.usno.navy.mil/pubations/docs/Circular_179.pdf)
~~

~~ BibItem { #Seidelmann:why; bibitem-label:"[3]"; searchterm:"Seidelmann+Fukushima+Why+new+time+scales" }
P.K.\ Seidelmann and T.\ Fukushima.
_Why new time scales?_
Astronomy and Astrophysics, vol. 265, no. 2, p. 833--838.
[ADS](https://adsabs.harvard.edu/full/1992A%26A...265..833S)
~~

~

[IAU-B3]: https://www.iau.org/static/resolutions/IAU2006_Resol3.pdf
[IAU-IV]: https://www.iers.org/IERS/EN/Science/Recommendations/recommendation4.html?nn=12932
[IERS-2010]: https://www.iers.org/SharedDocs/Publikationen/EN/IERS/pubations/tn/TechnNote36/tn36.pdf?__blob=pubationFile&v=1
[TIpropose]: https://syrte.obspm.fr/journees2004/pdf/McCarthy2.pdf#page=4
[Java time]: https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html
[UTC]: https://en.wikipedia.org/wiki/Coordinated_Universal_Time
[TAI]: https://en.wikipedia.org/wiki/International_Atomic_Time
[UT1]: https://en.wikipedia.org/wiki/Universal_Time
[TT]: https://en.wikipedia.org/wiki/Terrestrial_Time
\/

*/
module std/time/astrostd/time/astro

import std/num/float64std/num/float64
import std/num/ddoublestd/num/ddouble
import std/time/timestampstd/time/timestamp
import std/time/durationstd/time/duration
import std/time/instantstd/time/instant
import std/time/calendarstd/time/calendar

// for documentation
import std/time/utcstd/time/utc        // ts-ti
import std/time/calendarsstd/time/calendars  // cal-tai, cal-gps
// import std/time/download   // cal-utc-load

/*
// The TCG (Geometric coordinate time) calendar, i.e. an ISO calendar but using the `ts-tcg` time scale.
pub val cal-tcg  = iso-calendar( ts-tcg )//, fixed(32184,3) )

// The TDB (Barycentric dynamical time) calendar, i.e. an ISO calendar but using the `ts-tdb` time scale. Always within 2ms of TT (`cal-tt`).
pub val cal-tdb  = iso-calendar( ts-tdb )//, fixed(32184,3) )

// The TCB (Barycentric coordinate time) calendar, i.e. an ISO calendar but using the `ts-tcb` time scale.
pub val cal-tcb  = iso-calendar( ts-tcb )//, fixed(32184,3) )
*/


val secs-per-daystd/time/astro/secs-per-day: ddouble    = ddoublestd/num/ddouble/int/ddouble: (i : int) -> ddouble(86400literal: int
dec = 86400
hex32= 0x00015180
bit32= 0b00000000000000010101000110000000
) val offset-j2000std/time/astro/offset-j2000: ddouble = ddoublestd/num/ddouble/int/ddouble: (i : int) -> ddouble(43200literal: int
dec = 43200
hex32= 0x0000A8C0
bit32= 0b00000000000000001010100011000000
) // The [J2000] epoch is defined as 2000-01-01T12:00:00 TT (Terrestrial time). // // [J2000]: https://en.wikipedia.org/wiki/Equinox_(celestial_coordinates)#J2000.0 pub val epoch-j2000std/time/astro/epoch-j2000: instant = instant-at-j2000std/time/astro/instant-at-j2000: (jd : ddouble) -> instant(zerostd/num/ddouble/zero: ddouble) // Return the J2000 julian date for an instant. This is the number of days, and // the fraction of the day since J2000 (`epoch-j2000`) in terrestrial time (`ts-tt`).\ // `instant(2000,1,1,12,0,0).j2000.show == "0.00074287037037"`\ // `instant(2000,1,1,12,0,0,cal=cal-tt).j2000.show == "0"` pub fun j2000std/time/astro/j2000: (i : instant) -> ddouble( ii: instant : instantstd/time/instant/instant: V )result: -> total ddouble : ddoublestd/num/ddouble/ddouble: V divstd/time/timestamp/div: (x : timespan, y : timespan, prec : ? int) -> timespan( (ii: instant.timestamp-instd/time/instant/timestamp-in: (i : instant, tscale : timescale) -> timestamp(ts-ttstd/time/instant/ts-tt: timescale) -std/time/timestamp/(-): (ts : timestamp, t : timespan) -> timestamp offset-j2000std/time/astro/offset-j2000: ddouble).timespan-noleapstd/time/timestamp/timespan-noleap: (ts : timestamp) -> timespan, secs-per-daystd/time/astro/secs-per-day: ddouble, 18literal: int
dec = 18
hex8 = 0x12
bit8 = 0b00010010
) // div( (i.-in(ts-tt).timespan - offset-j2000), secs-per-day, 18 ) // atto-second precision // Return the instant corresponding to a J2000 julian date: this is the number of days, and // the fraction of the day since J2000 (`epoch-j2000`) in terrestrial time (`ts-tt`).\ // `instant-at-j2000(zero).time.show == "2000-01-01T11:58:55.816Z"`\ // `instant-at-j2000(zero).time(cal=cal-tt).show == "2000-01-01T12:00:00Z TT"` pub fun instant-at-j2000std/time/astro/instant-at-j2000: (jd : ddouble) -> instant( jdjd: ddouble : ddoublestd/num/ddouble/ddouble: V )result: -> total instant : instantstd/time/instant/instant: V ts-ttstd/time/instant/ts-tt: timescale.instantstd/time/instant/timescale/instant: (ts : timescale, t : timestamp) -> instant( timestampstd/time/timestamp/timestamp: (t : timespan, leap : ? int) -> timestamp( (jdjd: ddouble *std/num/ddouble/(*): (x : ddouble, y : ddouble) -> ddouble secs-per-daystd/time/astro/secs-per-day: ddouble) +std/num/ddouble/(+): (x : ddouble, y : ddouble) -> ddouble offset-j2000std/time/astro/offset-j2000: ddouble) ) /*---------------------------------------------------------------------------- TCG: Geocentric coordinate time ----------------------------------------------------------------------------*/ val lgstd/time/astro/lg: ddouble : ddoublestd/num/ddouble/ddouble: V = ddouble-expstd/num/ddouble/int/ddouble-exp: (i : int, exp : int) -> ddouble(6969290134literal: int
dec = 6969290134
hex64= 0x000000019F66ED96
bit64= 0b0000000000000000000000000000000110011111011001101110110110010110
,~std/core/int/(~): (i : int) -> int19literal: int
dec = 19
hex8 = 0x13
bit8 = 0b00010011
) // 6.969290134e-10 // 1991: 6.969291e-10 // now: 6.969290134 val tcg-epoch-deltastd/time/astro/tcg-epoch-delta: ddouble = ddouble-expstd/num/ddouble/int/ddouble-exp: (i : int, exp : int) -> ddouble(~std/core/int/(~): (i : int) -> int725759967816literal: int
dec = 725759967816
hex64= 0x000000A8FAAA4248
bit64= 0b0000000000000000000000001010100011111010101010100100001001001000
,~std/core/int/(~): (i : int) -> int3literal: int
dec = 3
hex8 = 0x03
bit8 = 0b00000011
) // 1977-01-01T00:00:32.184 TT, 2443144.5003725 JD~TT~ // IAU 1991 recommendation IV :\ // TCG - TT = L~g~&times;(JD~TT~ - TCG~epoch~) // => // TCG = TT + Lg*(TT - TCG~epoch~) fun tcg-from-taistd/time/astro/tcg-from-tai: (tai : duration) -> timestamp( taitai: duration : durationstd/time/duration/duration: V )result: -> total timestamp : timestampstd/time/timestamp/timestamp: V val tttt: timestamp = ts-ttstd/time/instant/ts-tt: timescale.from-taistd/time/instant/from-tai: (ts : timescale, d : duration) -> timestamp(taitai: duration) tttt: timestamp +std/time/timestamp/(+): (ts : timestamp, t : timespan) -> timestamp (lgstd/time/astro/lg: ddouble*std/num/ddouble/(*): (x : ddouble, y : ddouble) -> ddouble(tttt: timestamp -std/time/timestamp/(-): (ts : timestamp, t : timespan) -> timestamp tcg-epoch-deltastd/time/astro/tcg-epoch-delta: ddouble).timespan-noleapstd/time/timestamp/timespan-noleap: (ts : timestamp) -> timespan) // IAU 1991 recommendation [IV](https://www.iers.org/IERS/EN/Science/Recommendations/recommendation4.html?nn=12932):\ // TCG - TT = L~g~&times;(JD~TT~ - TCG~epoch~) // => // TT = TCG - Lg*(TCG - TCG~epoch~) fun tcg-to-taistd/time/astro/tcg-to-tai: (t : timestamp) -> duration( tt: timestamp : timestampstd/time/timestamp/timestamp: V )result: -> total duration : durationstd/time/duration/duration: V val tttt: timestamp = tt: timestamp -std/time/timestamp/(-): (ts : timestamp, t : timespan) -> timestamp (lgstd/time/astro/lg: ddouble*std/num/ddouble/(*): (x : ddouble, y : ddouble) -> ddouble(tt: timestamp -std/time/timestamp/(-): (ts : timestamp, t : timespan) -> timestamp tcg-epoch-deltastd/time/astro/tcg-epoch-delta: ddouble).timespan-noleapstd/time/timestamp/timespan-noleap: (ts : timestamp) -> timespan) ts-ttstd/time/instant/ts-tt: timescale.to-taistd/time/instant/to-tai: (ts : timescale, t : timestamp) -> duration(tttt: timestamp) // The [TCG](https://en.wikipedia.org/wiki/Geocentric_Coordinate_Time) (Geocentric coordinate time) time scale. // The unit of TCG is the SI second in a coordinate reference frame at the center of the Earth. pub val ts-tcgstd/time/astro/ts-tcg: timescale : timescalestd/time/instant/timescale: V = timescalestd/time/instant/timescale: (name : string, from-tai : (duration) -> timestamp, to-tai : (timestamp) -> duration, unit : ? string, seconds-in-day : ? (maybe<(timestamp) -> timespan>), to-mjd2000 : ? (maybe<(t : timestamp, tzdelta : timespan) -> ddouble>), from-mjd2000 : ? (maybe<(days : int, frac : ddouble) -> timestamp>)) -> timescale( "TCG"literal: string
count= 3
, tcg-from-taistd/time/astro/tcg-from-tai: (tai : duration) -> timestamp, tcg-to-taistd/time/astro/tcg-to-tai: (t : timestamp) -> duration
) /*---------------------------------------------------------------------------- TDB: Barycentric dynamical time ----------------------------------------------------------------------------*/ val j2k-epochstd/time/astro/j2k-epoch: timespan = timespanstd/time/timestamp/int/timespan: (seconds : int, frac : ? float64) -> timespan(43200literal: int
dec = 43200
hex32= 0x0000A8C0
bit32= 0b00000000000000001010100011000000
) // 2000-01-01T12:00:00 TT val secs-per-julian-yearstd/time/astro/secs-per-julian-year: float64 = 31557600.0literal: float64
hex64= 0x1.e187ep24
// 365.25 * 86400.0 // Compute tdb-delta(TT) = TDB - TT. This is the default function used for `ts-tdb`. // Fairhead & Bretagnon (1990) initial coefficents. // See also USNO circular 179 ([@Kaplan:circ], section 2.6). // The error in this approximation is a maximum of 10 micro-seconds in the time period 1600 to 2200. // (and probably less as we expanded to more terms and do JPL planetary mass adjustment) fun tdb-deltastd/time/astro/tdb-delta: (tt : timestamp) -> timespan( tttt: timestamp : timestampstd/time/timestamp/timestamp: V )result: -> total timespan : timespanstd/time/timestamp/timespan: V val tt: float64 = (tttt: timestamp -std/time/timestamp/(-): (ts : timestamp, t : timespan) -> timestamp j2k-epochstd/time/astro/j2k-epoch: timespan).timespan-noleapstd/time/timestamp/timespan-noleap: (ts : timestamp) -> timespan.float64std/num/ddouble/float64: (x : ddouble) -> float64 /std/num/float64/(/): (x : float64, y : float64) -> float64 (secs-per-julian-yearstd/time/astro/secs-per-julian-year: float64 *std/num/float64/(*): (x : float64, y : float64) -> float64 1000.0literal: float64
hex64= 0x1.f4p9
) // fraction of Julian millenia since J2000 // First terms of Fairhead et al. model val wfwf: float64 : float64std/core/types/float64: V =(1656.6746e-6literal: float64
hex64= 0x1.b2498ce8908a9p-10
*std/num/float64/(*): (x : float64, y : float64) -> float64sinstd/num/float64/sin: (d : float64) -> float64( 6283.0758literal: float64
hex64= 0x1.88b1367a0f909p12
*std/num/float64/(*): (x : float64, y : float64) -> float64tt: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 6.2401literal: float64
hex64= 0x1.8f5dcc63f1412p2
) +std/num/float64/(+): (x : float64, y : float64) -> float64 ( 22.4175e-6literal: float64
hex64= 0x1.781a6dea693fep-16
*std/num/float64/(*): (x : float64, y : float64) -> float64sinstd/num/float64/sin: (d : float64) -> float64( 5753.3859literal: float64
hex64= 0x1.67962ca57a787p12
*std/num/float64/(*): (x : float64, y : float64) -> float64tt: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 4.2970literal: float64
hex64= 0x1.13020c49ba5e3p2
) +std/num/float64/(+): (x : float64, y : float64) -> float64 13.8398e-6literal: float64
hex64= 0x1.d062fa0d5c3aep-17
*std/num/float64/(*): (x : float64, y : float64) -> float64sinstd/num/float64/sin: (d : float64) -> float64(12566.1527literal: float64
hex64= 0x1.88b138bac710dp13
*std/num/float64/(*): (x : float64, y : float64) -> float64tt: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 6.1969literal: float64
hex64= 0x1.8c9a027525461p2
) +std/num/float64/(+): (x : float64, y : float64) -> float64 4.7701e-6literal: float64
hex64= 0x1.401db1a9a147cp-18
*std/num/float64/(*): (x : float64, y : float64) -> float64sinstd/num/float64/sin: (d : float64) -> float64( 529.6910literal: float64
hex64= 0x1.08d872b020c4ap9
*std/num/float64/(*): (x : float64, y : float64) -> float64tt: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 0.4444literal: float64
hex64= 0x1.c710cb295e9e2p-2
) +std/num/float64/(+): (x : float64, y : float64) -> float64 4.6767e-6literal: float64
hex64= 0x1.39d9181e54b5dp-18
*std/num/float64/(*): (x : float64, y : float64) -> float64sinstd/num/float64/sin: (d : float64) -> float64( 6069.7768literal: float64
hex64= 0x1.7b5c6dc5d6388p12
*std/num/float64/(*): (x : float64, y : float64) -> float64tt: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 4.0212literal: float64
hex64= 0x1.015b573eab368p2
)) ) +std/num/float64/(+): (x : float64, y : float64) -> float64 ( 2.2567e-6literal: float64
hex64= 0x1.2ee39f1f8b22cp-19
*std/num/float64/(*): (x : float64, y : float64) -> float64sinstd/num/float64/sin: (d : float64) -> float64( 213.2991literal: float64
hex64= 0x1.aa9923a29c77ap7
*std/num/float64/(*): (x : float64, y : float64) -> float64tt: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 5.5431literal: float64
hex64= 0x1.62c226809d495p2
) +std/num/float64/(+): (x : float64, y : float64) -> float64 1.6942e-6literal: float64
hex64= 0x1.c6c88998b0eb9p-20
*std/num/float64/(*): (x : float64, y : float64) -> float64sinstd/num/float64/sin: (d : float64) -> float64( ~std/num/float64/(~): (f : float64) -> float643.5232literal: float64
hex64= 0x1.c2f837b4a233ap1
*std/num/float64/(*): (x : float64, y : float64) -> float64tt: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 5.0251literal: float64
hex64= 0x1.419b3d07c84b6p2
) +std/num/float64/(+): (x : float64, y : float64) -> float64 1.5549e-6literal: float64
hex64= 0x1.a163ea14992fbp-20
*std/num/float64/(*): (x : float64, y : float64) -> float64sinstd/num/float64/sin: (d : float64) -> float64(77713.7715literal: float64
hex64= 0x1.2f91c5810624ep16
*std/num/float64/(*): (x : float64, y : float64) -> float64tt: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 5.1985literal: float64
hex64= 0x1.4cb4395810625p2
) +std/num/float64/(+): (x : float64, y : float64) -> float64 1.2768e-6literal: float64
hex64= 0x1.56bd07243a05bp-20
*std/num/float64/(*): (x : float64, y : float64) -> float64sinstd/num/float64/sin: (d : float64) -> float64( 7860.4194literal: float64
hex64= 0x1.eb46b5dcc63f1p12
*std/num/float64/(*): (x : float64, y : float64) -> float64tt: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 5.9888literal: float64
hex64= 0x1.7f487fcb923a3p2
) +std/num/float64/(+): (x : float64, y : float64) -> float64 1.1934e-6literal: float64
hex64= 0x1.4059d2d34dcfbp-20
*std/num/float64/(*): (x : float64, y : float64) -> float64sinstd/num/float64/sin: (d : float64) -> float64( 5223.6939literal: float64
hex64= 0x1.467b1a36e2eb2p12
*std/num/float64/(*): (x : float64, y : float64) -> float64tt: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 3.6498literal: float64
hex64= 0x1.d32ca57a786c2p1
) ) +std/num/float64/(+): (x : float64, y : float64) -> float64 tt: float64*std/num/float64/(*): (x : float64, y : float64) -> float64(102.1567e-6literal: float64
hex64= 0x1.ac79ebe055992p-14
*std/num/float64/(*): (x : float64, y : float64) -> float64sinstd/num/float64/sin: (d : float64) -> float64( 6283.0758literal: float64
hex64= 0x1.88b1367a0f909p12
*std/num/float64/(*): (x : float64, y : float64) -> float64tt: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 4.2490literal: float64
hex64= 0x1.0fef9db22d0e5p2
)) // Adjustments to use JPL planetary masses instead of IAU. val wjwj: float64 : float64std/core/types/float64: V = 0.00065e-6literal: float64
hex64= 0x1.65575e0ff4a28p-31
*std/num/float64/(*): (x : float64, y : float64) -> float64sinstd/num/float64/sin: (d : float64) -> float64(6069.776754literal: float64
hex64= 0x1.7b5c6d959a30ap12
*std/num/float64/(*): (x : float64, y : float64) -> float64tt: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 4.021194literal: float64
hex64= 0x1.015b3e1437c57p2
) +std/num/float64/(+): (x : float64, y : float64) -> float64 0.00033e-6literal: float64
hex64= 0x1.6ad6be0852fbap-32
*std/num/float64/(*): (x : float64, y : float64) -> float64sinstd/num/float64/sin: (d : float64) -> float64( 213.299095literal: float64
hex64= 0x1.aa9922fad6cb5p7
*std/num/float64/(*): (x : float64, y : float64) -> float64tt: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 5.543132literal: float64
hex64= 0x1.62c2acb85a4fp2
) +std/num/float64/(+): (x : float64, y : float64) -> float64 (~std/num/float64/(~): (f : float64) -> float640.00196e-6literal: float64
hex64= 0x1.0d615e8a0f102p-29
*std/num/float64/(*): (x : float64, y : float64) -> float64sinstd/num/float64/sin: (d : float64) -> float64(6208.294251literal: float64
hex64= 0x1.8404b540895d1p12
*std/num/float64/(*): (x : float64, y : float64) -> float64tt: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 5.696701literal: float64
hex64= 0x1.6c96bfca85cabp2
)) +std/num/float64/(+): (x : float64, y : float64) -> float64 (~std/num/float64/(~): (f : float64) -> float640.00173e-6literal: float64
hex64= 0x1.db89ed6be11f2p-30
*std/num/float64/(*): (x : float64, y : float64) -> float64sinstd/num/float64/sin: (d : float64) -> float64( 74.781599literal: float64
hex64= 0x1.2b205b7cfe586p6
*std/num/float64/(*): (x : float64, y : float64) -> float64tt: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 2.435900literal: float64
hex64= 0x1.37cb923a29c78p1
)) +std/num/float64/(+): (x : float64, y : float64) -> float64 0.03638e-6literal: float64
hex64= 0x1.3880774e331b6p-25
*std/num/float64/(*): (x : float64, y : float64) -> float64tt: float64*std/num/float64/(*): (x : float64, y : float64) -> float64tt: float64; // Topo centric adjustments val wtwt: float64 = 0.0literal: float64
hex64= 0x0p+0
// tdb-topocentric(t,0.5,~155.933222,10000.0,5000.0) ddoublestd/num/ddouble/float64/ddouble: (d : float64) -> ddouble( wfwf: float64+std/num/float64/(+): (x : float64, y : float64) -> float64wjwj: float64+std/num/float64/(+): (x : float64, y : float64) -> float64wtwt: float64
) val pi2std/time/astro/pi2: float64 = 6.283185307179586476925287literal: float64
hex64= 0x1.921fb54442d18p2
// 2pi val dd2rstd/time/astro/dd2r: float64 = 1.745329251994329576923691e-2literal: float64
hex64= 0x1.1df46a2529d39p-6
// degree to radians // From the ERFA routines fun tdb-topocentricstd/time/astro/tdb-topocentric: (t : float64, ut : ? float64, elong : ? float64, u : ? float64, v : ? float64) -> float64( tt: float64 : float64std/core/types/float64: V, // fractional julian millennia utut: ? float64 : float64std/core/types/float64: V = 0.0literal: float64
hex64= 0x0p+0
, // UT1 (fraction of one day) elongelong: ? float64 : float64std/core/types/float64: V = 0.0literal: float64
hex64= 0x0p+0
, // east positive degrees uu: ? float64 : float64std/core/types/float64: V = 0.0literal: float64
hex64= 0x0p+0
, // distance earth spin axis in km vv: ? float64 : float64std/core/types/float64: V = 0.0literal: float64
hex64= 0x0p+0
// distance north of eq. plane in km )result: -> total float64 // Convert UT to local solar time in radians. val tsoltsol: float64 = utut: float64.fractionstd/num/float64/fraction: (d : float64) -> float64*std/num/float64/(*): (x : float64, y : float64) -> float64pi2std/time/astro/pi2: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 elongelong: float64*std/num/float64/(*): (x : float64, y : float64) -> float64dd2rstd/time/astro/dd2r: float64 // Combine time argument (millennia) with deg/arcsec factor. val ww: float64 = tt: float64 /std/num/float64/(/): (x : float64, y : float64) -> float64 3600.0literal: float64
hex64= 0x1.c2p11
// Sun Mean Longitude. val elsunelsun: float64 = ((280.46645683literal: float64
hex64= 0x1.187769b6fdd89p8
+std/num/float64/(+): (x : float64, y : float64) -> float64 1296027711.03429literal: float64
hex64= 0x1.34ff40fc231cfp30
*std/num/float64/(*): (x : float64, y : float64) -> float64 ww: float64) %std/num/float64/(%): (x : float64, y : float64) -> float64 360.0literal: float64
hex64= 0x1.68p8
) *std/num/float64/(*): (x : float64, y : float64) -> float64 dd2rstd/time/astro/dd2r: float64 // Sun Mean Anomaly. val emsunemsun: float64 = ((357.52910918literal: float64
hex64= 0x1.658773b3001dp8
+std/num/float64/(+): (x : float64, y : float64) -> float64 1295965810.481literal: float64
hex64= 0x1.34fb79c9ec8b4p30
*std/num/float64/(*): (x : float64, y : float64) -> float64 ww: float64) %std/num/float64/(%): (x : float64, y : float64) -> float64 360.0literal: float64
hex64= 0x1.68p8
) *std/num/float64/(*): (x : float64, y : float64) -> float64 dd2rstd/time/astro/dd2r: float64 // Mean Elongation of Moon from Sun. val dd: float64 = ((297.85019547literal: float64
hex64= 0x1.29d9a6690adb8p8
+std/num/float64/(+): (x : float64, y : float64) -> float64 16029616012.090literal: float64
hex64= 0x1.ddb843c60b852p33
*std/num/float64/(*): (x : float64, y : float64) -> float64 ww: float64) %std/num/float64/(%): (x : float64, y : float64) -> float64 360.0literal: float64
hex64= 0x1.68p8
) *std/num/float64/(*): (x : float64, y : float64) -> float64 dd2rstd/time/astro/dd2r: float64 // Mean Longitude of Jupiter. val eljelj: float64 = ((34.35151874literal: float64
hex64= 0x1.12cfe90ea1d96p5
+std/num/float64/(+): (x : float64, y : float64) -> float64 109306899.89453literal: float64
hex64= 0x1.a0f904f93ffacp26
*std/num/float64/(*): (x : float64, y : float64) -> float64 ww: float64) %std/num/float64/(%): (x : float64, y : float64) -> float64 360.0literal: float64
hex64= 0x1.68p8
) *std/num/float64/(*): (x : float64, y : float64) -> float64 dd2rstd/time/astro/dd2r: float64 // Mean Longitude of Saturn. val elsels: float64 = ((50.07744430literal: float64
hex64= 0x1.909e9b1dfe17dp5
+std/num/float64/(+): (x : float64, y : float64) -> float64 44046398.47038literal: float64
hex64= 0x1.500c1f3c35697p25
*std/num/float64/(*): (x : float64, y : float64) -> float64 ww: float64) %std/num/float64/(%): (x : float64, y : float64) -> float64 360.0literal: float64
hex64= 0x1.68p8
) *std/num/float64/(*): (x : float64, y : float64) -> float64 dd2rstd/time/astro/dd2r: float64 // Moyer 1981 and Murray 1983. val wtwt: float64 : float64std/core/types/float64: V =( 0.00029e-10literal: float64
hex64= 0x1.053572801a604p-45
*std/num/float64/(*): (x : float64, y : float64) -> float64 uu: float64 *std/num/float64/(*): (x : float64, y : float64) -> float64 sinstd/num/float64/sin: (d : float64) -> float64(tsoltsol: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 elsunelsun: float64 -std/num/float64/(-): (x : float64, y : float64) -> float64 elsels: float64) +std/num/float64/(+): (x : float64, y : float64) -> float64 (0.00100e-10literal: float64
hex64= 0x1.c25c268497682p-44
*std/num/float64/(*): (x : float64, y : float64) -> float64 uu: float64 *std/num/float64/(*): (x : float64, y : float64) -> float64 sinstd/num/float64/sin: (d : float64) -> float64(tsoltsol: float64 -std/num/float64/(-): (x : float64, y : float64) -> float64 2.0literal: float64
hex64= 0x1p1
*std/num/float64/(*): (x : float64, y : float64) -> float64 emsunemsun: float64) +std/num/float64/(+): (x : float64, y : float64) -> float64 0.00133e-10literal: float64
hex64= 0x1.2b7d47b1c5f72p-43
*std/num/float64/(*): (x : float64, y : float64) -> float64 uu: float64 *std/num/float64/(*): (x : float64, y : float64) -> float64 sinstd/num/float64/sin: (d : float64) -> float64(tsoltsol: float64 -std/num/float64/(-): (x : float64, y : float64) -> float64 dd: float64) +std/num/float64/(+): (x : float64, y : float64) -> float64 0.00133e-10literal: float64
hex64= 0x1.2b7d47b1c5f72p-43
*std/num/float64/(*): (x : float64, y : float64) -> float64 uu: float64 *std/num/float64/(*): (x : float64, y : float64) -> float64 sinstd/num/float64/sin: (d : float64) -> float64(tsoltsol: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 (elsunelsun: float64 -std/num/float64/(-): (x : float64, y : float64) -> float64 eljelj: float64)) -std/num/float64/(-): (x : float64, y : float64) -> float64 0.00229e-10literal: float64
hex64= 0x1.01d4c1924f001p-42
*std/num/float64/(*): (x : float64, y : float64) -> float64 uu: float64 *std/num/float64/(*): (x : float64, y : float64) -> float64 sinstd/num/float64/sin: (d : float64) -> float64(tsoltsol: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 (2.0literal: float64
hex64= 0x1p1
*std/num/float64/(*): (x : float64, y : float64) -> float64 elsunelsun: float64) +std/num/float64/(+): (x : float64, y : float64) -> float64 emsunemsun: float64) -std/num/float64/(-): (x : float64, y : float64) -> float64 0.02200e-10literal: float64
hex64= 0x1.359f5a7b28179p-39
*std/num/float64/(*): (x : float64, y : float64) -> float64 vv: float64 *std/num/float64/(*): (x : float64, y : float64) -> float64 cosstd/num/float64/cos: (d : float64) -> float64(elsunelsun: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 emsunemsun: float64)) ) +std/num/float64/(+): (x : float64, y : float64) -> float64 ( 0.05312e-10literal: float64
hex64= 0x1.75cc7c21403a4p-38
*std/num/float64/(*): (x : float64, y : float64) -> float64 uu: float64 *std/num/float64/(*): (x : float64, y : float64) -> float64 sinstd/num/float64/sin: (d : float64) -> float64(tsoltsol: float64 -std/num/float64/(-): (x : float64, y : float64) -> float64 emsunemsun: float64) -std/num/float64/(-): (x : float64, y : float64) -> float64 0.13677e-10literal: float64
hex64= 0x1.e13776d646a91p-37
*std/num/float64/(*): (x : float64, y : float64) -> float64 uu: float64 *std/num/float64/(*): (x : float64, y : float64) -> float64 sinstd/num/float64/sin: (d : float64) -> float64(tsoltsol: float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 2.0literal: float64
hex64= 0x1p1
*std/num/float64/(*): (x : float64, y : float64) -> float64 elsunelsun: float64) -std/num/float64/(-): (x : float64, y : float64) -> float64 1.31840e-10literal: float64
hex64= 0x1.21eb52655b117p-33
*std/num/float64/(*): (x : float64, y : float64) -> float64 vv: float64 *std/num/float64/(*): (x : float64, y : float64) -> float64 cosstd/num/float64/cos: (d : float64) -> float64(elsunelsun: float64) +std/num/float64/(+): (x : float64, y : float64) -> float64 3.17679e-10literal: float64
hex64= 0x1.5d4ab06a978bdp-32
*std/num/float64/(*): (x : float64, y : float64) -> float64 uu: float64 *std/num/float64/(*): (x : float64, y : float64) -> float64 sinstd/num/float64/sin: (d : float64) -> float64(tsoltsol: float64) ); wtwt: float64
fun tai-to-tdbstd/time/astro/tai-to-tdb: (tai : duration, delta : ? ((timestamp) -> timespan)) -> timestamp( taitai: duration : durationstd/time/duration/duration: V, deltadelta: ? ((timestamp) -> timespan) : timestampstd/time/timestamp/timestamp: V -> timespanstd/time/timestamp/timespan: V = tdb-deltastd/time/astro/tdb-delta: (tt : timestamp) -> timespan )result: -> total timestamp : timestampstd/time/timestamp/timestamp: V val tttt: timestamp = ts-ttstd/time/instant/ts-tt: timescale.from-taistd/time/instant/from-tai: (ts : timescale, d : duration) -> timestamp(taitai: duration) tttt: timestamp +std/time/timestamp/(+): (ts : timestamp, t : timespan) -> timestamp deltadelta: (timestamp) -> timespan(tttt: timestamp) fun tdb-to-taistd/time/astro/tdb-to-tai: (tdb : timestamp, delta : ? ((timestamp) -> timespan)) -> duration( tdbtdb: timestamp : timestampstd/time/timestamp/timestamp: V, deltadelta: ? ((timestamp) -> timespan) : timestampstd/time/timestamp/timestamp: V -> timespanstd/time/timestamp/timespan: V = tdb-deltastd/time/astro/tdb-delta: (tt : timestamp) -> timespan )result: -> total duration : durationstd/time/duration/duration: V ts-ttstd/time/instant/ts-tt: timescale.to-taistd/time/instant/to-tai: (ts : timescale, t : timestamp) -> duration( tdbtdb: timestamp -std/time/timestamp/(-): (ts : timestamp, t : timespan) -> timestamp deltadelta: (timestamp) -> timespan(tdbtdb: timestamp) ) // The [TDB](https://en.wikipedia.org/wiki/Barycentric_Coordinate_Time) (Barycentric dynamical time) time scale // (which can be considered equivalent T~eph~). // // TDB is approximated from TT using an initial set of coefficients by // Fairhead &amp; Bretagnon [@Fairhead:tt] assuming the geo center (longitude and latitude of 0 degrees). // See also USNO circular 179 ([@Kaplan:circ], equation 2.6). // The approximation is within 10&mu;s precision in the time span 1600 to 2200 (and probably a bit less). pub val ts-tdbstd/time/astro/ts-tdb: timescale : timescalestd/time/instant/timescale: V = ts-tdb-createstd/time/astro/ts-tdb-create: (tdb-minus-tt : (timestamp) -> timespan) -> timescale(tdb-deltastd/time/astro/tdb-delta: (tt : timestamp) -> timespan) // Creates a new TDB timescale given a user provided function to calculate TDB-TT. // The default function used for `ts-tdb` uses the Fairhead &amp; Bretagnon approximation // corrected for JPL planetary masses but assumes the geo center. Use this function // to create a new TDB timescale if you need more precision. pub fun ts-tdb-createstd/time/astro/ts-tdb-create: (tdb-minus-tt : (timestamp) -> timespan) -> timescale( tdb-minus-tttdb-minus-tt: (timestamp) -> timespan : timestampstd/time/timestamp/timestamp: V -> timespanstd/time/timestamp/timespan: V )result: -> total timescale : timescalestd/time/instant/timescale: V timescalestd/time/instant/timescale: (name : string, from-tai : (duration) -> timestamp, to-tai : (timestamp) -> duration, unit : ? string, seconds-in-day : ? (maybe<(timestamp) -> timespan>), to-mjd2000 : ? (maybe<(t : timestamp, tzdelta : timespan) -> ddouble>), from-mjd2000 : ? (maybe<(days : int, frac : ddouble) -> timestamp>)) -> timescale("TDB"literal: string
count= 3
, fnfn: (tai : duration) -> timestamp(taitai: duration:durationstd/time/duration/duration: V) { tai-to-tdbstd/time/astro/tai-to-tdb: (tai : duration, delta : ? ((timestamp) -> timespan)) -> timestamp(taitai: duration,tdb-minus-tttdb-minus-tt: (timestamp) -> timespan) }, fnfn: (tdb : timestamp) -> duration(tdbtdb: timestamp:timestampstd/time/timestamp/timestamp: V) { tdb-to-taistd/time/astro/tdb-to-tai: (tdb : timestamp, delta : ? ((timestamp) -> timespan)) -> duration(tdbtdb: timestamp,tdb-minus-tttdb-minus-tt: (timestamp) -> timespan) }
) /*---------------------------------------------------------------------------- TCB: Barycentric coordinate time ----------------------------------------------------------------------------*/ val lbstd/time/astro/lb: ddouble : ddoublestd/num/ddouble/ddouble: V = ddouble-expstd/num/ddouble/int/ddouble-exp: (i : int, exp : int) -> ddouble(155051976772literal: int
dec = 155051976772
hex64= 0x0000002419D16844
bit64= 0b0000000000000000000000000010010000011001110100010110100001000100
,~std/core/int/(~): (i : int) -> int19literal: int
dec = 19
hex8 = 0x13
bit8 = 0b00010011
) // 1.55051976772e-8 val tdb0std/time/astro/tdb0: ddouble : ddoublestd/num/ddouble/ddouble: V = ddouble-expstd/num/ddouble/int/ddouble-exp: (i : int, exp : int) -> ddouble(~std/core/int/(~): (i : int) -> int655literal: int
dec = 655
hex16= 0x028F
bit16= 0b0000001010001111
,~std/core/int/(~): (i : int) -> int7literal: int
dec = 7
hex8 = 0x07
bit8 = 0b00000111
) // ~6.55e-5 fun tai-to-tcbstd/time/astro/tai-to-tcb: (tai : duration, tstdb : timescale) -> timestamp( taitai: duration : durationstd/time/duration/duration: V, tstdbtstdb: timescale : timescalestd/time/instant/timescale: V )result: -> total timestamp : timestampstd/time/timestamp/timestamp: V val tdbtdb: timestamp = tstdbtstdb: timescale.from-taistd/time/instant/from-tai: (ts : timescale, d : duration) -> timestamp(taitai: duration) val adjadj: ddouble = lbstd/time/astro/lb: ddouble*std/num/ddouble/(*): (x : ddouble, y : ddouble) -> ddouble(tdbtdb: timestamp -std/time/timestamp/(-): (ts : timestamp, t : timespan) -> timestamp tcg-epoch-deltastd/time/astro/tcg-epoch-delta: ddouble).timespan-noleapstd/time/timestamp/timespan-noleap: (ts : timestamp) -> timespan tdbtdb: timestamp +std/time/timestamp/(+): (ts : timestamp, t : timespan) -> timestamp (adjadj: ddouble -std/num/ddouble/(-): (x : ddouble, y : ddouble) -> ddouble tdb0std/time/astro/tdb0: ddouble) fun tcb-to-taistd/time/astro/tcb-to-tai: (tcb : timestamp, tstdb : timescale) -> duration( tcbtcb: timestamp : timestampstd/time/timestamp/timestamp: V, tstdbtstdb: timescale : timescalestd/time/instant/timescale: V )result: -> total duration : durationstd/time/duration/duration: V val adjadj: ddouble = lbstd/time/astro/lb: ddouble*std/num/ddouble/(*): (x : ddouble, y : ddouble) -> ddouble(tcbtcb: timestamp -std/time/timestamp/(-): (ts : timestamp, t : timespan) -> timestamp tcg-epoch-deltastd/time/astro/tcg-epoch-delta: ddouble).timespan-noleapstd/time/timestamp/timespan-noleap: (ts : timestamp) -> timespan val tdbtdb: timestamp = tcbtcb: timestamp -std/time/timestamp/(-): (ts : timestamp, t : timespan) -> timestamp (adjadj: ddouble -std/num/ddouble/(-): (x : ddouble, y : ddouble) -> ddouble tdb0std/time/astro/tdb0: ddouble) tstdbtstdb: timescale.to-taistd/time/instant/to-tai: (ts : timescale, t : timestamp) -> duration(tdbtdb: timestamp) // The [TCB](https://en.wikipedia.org/wiki/Geocentric_Coordinate_Time) // (Barycentric coordinate time) time scale.\ The unit of TCB is the SI // second, but in a coordinate reference frame at the barycenter of the solar // system. pub val ts-tcbstd/time/astro/ts-tcb: timescale : timescalestd/time/instant/timescale: V = ts-tcb-createstd/time/astro/ts-tcb-create: (tstdb : timescale) -> timescale(ts-tdbstd/time/astro/ts-tdb: timescale) // Create a new TCB timescale given a TDB timescale (`tstdb`). The default // `ts-tcb` uses the default `ts-tdb` timescale, but if you created // a different TCB time scale (using `ts-tdb-create`) you can use // this function to create a TCB time scale from it. It computes // TCB from the provided TDB using the IAU 2006 resolution // [B3](https://www.iau.org/static/resolutions/IAU2006_Resol3.pdf):\ TDB = TCB - // L~b~ &times; (JD~TCB~ - T~0~) &times; 86400 + TDB~0~, with T~0~ = // 2443144.5003725, L~b~ = 1.55051976772&times;10^-8^, TDB~0~ = // -6.55&times;10^-5^. pub fun ts-tcb-createstd/time/astro/ts-tcb-create: (tstdb : timescale) -> timescale( tstdbtstdb: timescale : timescalestd/time/instant/timescale: V )result: -> total timescale : timescalestd/time/instant/timescale: V timescalestd/time/instant/timescale: (name : string, from-tai : (duration) -> timestamp, to-tai : (timestamp) -> duration, unit : ? string, seconds-in-day : ? (maybe<(timestamp) -> timespan>), to-mjd2000 : ? (maybe<(t : timestamp, tzdelta : timespan) -> ddouble>), from-mjd2000 : ? (maybe<(days : int, frac : ddouble) -> timestamp>)) -> timescale( "TCB"literal: string
count= 3
, fnfn: (tai : duration) -> timestamp(taitai: duration:durationstd/time/duration/duration: V) { tai-to-tcbstd/time/astro/tai-to-tcb: (tai : duration, tstdb : timescale) -> timestamp(taitai: duration, tstdbtstdb: timescale) }, fnfn: (tcb : timestamp) -> duration(tcbtcb: timestamp:timestampstd/time/timestamp/timestamp: V) { tcb-to-taistd/time/astro/tcb-to-tai: (tcb : timestamp, tstdb : timescale) -> duration(tcbtcb: timestamp, tstdbtstdb: timescale) }
)