# `time_scales`

The `time_scales` library provides predicates for converting instants between UTC, TAI, TT, UT1, TDB, GPS, GST, TCG, and TCB using bundled reference data and optional user-provided override files.

The library is designed to complement (not replace) the `dates` and `iso8601` libraries:

- Use `dates` for civil date-time arithmetic and Unix epoch conversions.

- Use `iso8601` for string parsing and formatting.

- Use `time_scales` for physical time-scale conversions.

## API documentation

Open the ../../apis/library_index.html#time_scales link in a web browser.

## Loading

To load all entities in this library, load the `loader.lgt` file:

    | ?- logtalk_load(time_scales(loader)).

## Testing

To test this library predicates, load the `tester.lgt` file:

    | ?- logtalk_load(time_scales(tester)).

## Features

Current feature set:

- Supported scales: `utc`, `tai`, `tt`, `ut1`, `tdb`, `gps`, `gst`, `tcg`, and `tcb`.

- UTC support starts at `1972-01-01T00:00:00Z`.

- Leap seconds are provided by a bundled static table with optional override file.

- DUT1 (`UT1-UTC`) is provided by bundled data with optional override file.

- Active leap-second and DUT1 tables can be queried as ordered term lists for reproducibility.

- Active leap-second and DUT1 tables can be saved to deterministic term files and reloaded as overrides.

- Fail- and error-based validation predicates for validating and type-checking instant terms and conversion requests.

- TDB conversions use a practical TT/TDB approximation suitable for application-level use.

- Real-valued approximation offsets converted to rationals using high-resolution nanosecond scaling.

## Limitations

Current non-implemented features:

- UTC coverage before 1972-01-01T00:00:00Z is not implemented.

- network-driven leap-second and DUT1 data updates are not implemented.

- high-precision ephemeris-based relativistic modeling (beyond the current practical approximation formulas) is not implemented.

For full functionality (including all high-precision conversion paths and their corresponding tests), a Prolog backend with support for unbounded integer arithmetic is required.

## Representation

Instants are represented as:

    instant(Scale, Seconds, fraction(Numerator, Denominator))

Where:

- `Scale` is one of `utc`, `tai`, `tt`, `ut1`, `tdb`, `gps`, `gst`, `tcg`, or `tcb`;

- `Seconds` is integer epoch seconds;

- `fraction(Numerator, Denominator)` is a normalized fraction in the `[0,1[` interval.

Offsets are returned as:

    rational(Numerator, Denominator)

## Examples

Convert UTC to TAI:

    | ?- time_scales::convert(instant(utc, 1483228800, fraction(0,1)), utc, tai, TAI).

Strictly validate an instant term (throws on invalid input):

    | ?- time_scales::check_instant(instant(utc, 1483228800, fraction(0,1))).

Strict conversion (throws on invalid scale or mismatched instant scale):

    | ?- time_scales::check_convert(instant(utc, 1483228800, fraction(0,1)), utc, tai, TAI).

Convert TAI to TT:

    | ?- time_scales::convert(instant(tai, 1483228837, fraction(0,1)), tai, tt, TT).

Convert UTC to UT1:

    | ?- time_scales::convert(instant(utc, 1483228800, fraction(0,1)), utc, ut1, UT1).

Convert TT to TDB:

    | ?- time_scales::convert(instant(tt, 1483228869, fraction(0,1)), tt, tdb, TDB).

Convert UTC to GPS:

    | ?- time_scales::convert(instant(utc, 1483228800, fraction(0,1)), utc, gps, GPS).

Convert UTC to GST:

    | ?- time_scales::convert(instant(utc, 1483228800, fraction(0,1)), utc, gst, GST).

Convert UTC to TCG:

    | ?- time_scales::convert(instant(utc, 1483228800, fraction(0,1)), utc, tcg, TCG).

Convert UTC to TCB:

    | ?- time_scales::convert(instant(utc, 1483228800, fraction(0,1)), utc, tcb, TCB).

Lookup an effective leap-second date:

    | ?- time_scales::leap_second_date(Date, Offset).

Load leap-second and DUT1 override files:

    | ?- time_scales::load_leap_seconds_override('test_files/leap_seconds_override.pl').

    | ?- time_scales::load_dut1_override('test_files/dut1_override.pl').

Query active leap-second and DUT1 data tables:

    | ?- time_scales::leap_seconds_entries(LeapEntries).

    | ?- time_scales::dut1_entries(DUT1Entries).

Save active leap-second and DUT1 data tables:

    | ?- time_scales::save_leap_seconds_entries('/tmp/logtalk_time_scales_leap_snapshot.pl').

    | ?- time_scales::save_dut1_entries('/tmp/logtalk_time_scales_dut1_snapshot.pl').

Validate an instant or conversion request:

    | ?- time_scales::valid_instant(instant(utc, 1483228800, fraction(0,1))).

    | ?- time_scales::valid_conversion(instant(tai, 1483228837, fraction(0,1)), tai, tdb).