CelestialCalendar Documentation
On this page

UTC and JDE(TT) conversions

The C, Python and JavaScript interfaces expose the existing C++ conversions from 1.1.0 onward. They convert time scales; adding a timezone offset is a separate display operation.

Interface UTC civil fields to JDE(TT) JDE(TT) to UTC civil fields
C++ astro::julian_day::utc_to_jde(utc_dt) astro::julian_day::jde_to_utc(jde_tt)
C celestial_utc_to_jde(y, m, d, fraction) celestial_jde_to_utc(jde_tt)
Python utc_to_jde(CivilDateTime(...)) jde_to_utc(jde)
JavaScript time.utcToJde(civil) time.jdeToUtc(jde)

The C forward result is CelestialJulianDay; the inverse returns a CelestialUTCTime record by value. Check valid, then read celestial_last_error_kind() and celestial_last_error() on failure; neither reader clears the recorded error. Python returns a float or a frozen CivilDateTime. JavaScript returns a number or an owned CivilDateTimeResult, including derived hour, minute and fractional second fields; call await init() first. Civil records do not carry a time scale themselves: the conversion name specifies it.

Domains and inherited limits

  • Forward input uses a valid Gregorian date in years [1, 32767] and a finite day fraction in [0, 1). The shifted TT date must also be representable. At the upper end TT is 69.184 seconds ahead of UTC, so the final 69.184 seconds of year 32767 are rejected.
  • The inverse accepts finite JDE(TT) in [1867522.5, 13689325.5). Its lower endpoint returns 400-12-31, after subtracting fixed Algo5's modelled TT minus UT1 (ΔT). Forward dates before this inverse window can succeed without having an admitted inverse.
  • Before 1972-01-01, UTC-labelled civil fields use the UT1 substitute with fixed Algo5. This does not model historical UTC, including the variable-length seconds of 1960–1971. Chart and civil-house queries retain their stricter policy and reject pre-1972 UTC input.
  • From 1972 onward the existing leap-second table applies. Its final row is 2017-01-01; later dates retain TT minus UTC = 69.184 seconds. This is a library policy, not a forecast of future UTC.
  • 23:59:60 cannot be represented. A JDE inside the TT interval corresponding to that leap second converts to the next civil second. Converting that result back to JDE does not recover the original input. Julian-day rounding at midnight when the leap-table offset steps can also make a UTC → JDE → UTC result one second later than its input.
  • The historical/modern seam is about 68 ms and is non-monotone: stepping forward across the last millisecond of 1971 can move JDE backward. Do not assume exact roundtrips at the seam or leap steps.

These functions do not supply a whole-domain accuracy or reversibility guarantee. See Time scales for the models.

Invalid civil values and non-finite/out-of-domain JDEs produce CELESTIAL_ERROR_INVALID_INPUT in C, ValueError in Python and RangeError in JavaScript. Wrong binding types produce TypeError. Computation/resource/internal failures and malformed native success records produce the binding's CelestialError; the normal failure contract is unchanged.

Next Jieqi from a UTC input, displayed at UTC+8

Copy the Python program or the JavaScript program into an application with the matching package installed. Run it as python example.py or node example.mjs. For an unreleased checkout, build the local wheel or npm packages first; a published 1.0 package does not have these methods.

Both programs use the fixed input 2026-10-28T19:35:37Z and print with seconds omitted:

立冬
UTC: 2026-11-07 09:52
UTC+8: 2026-11-07 17:52

The input goes through UTC-to-JDE. Existing Jieqi queries return UT1, so each event goes through UT1-to-JDE before comparison. Only the selected JDE goes through JDE-to-UTC; then the application formats it with a fixed +8-hour offset. The examples use the library's leap table, with no chart query, location or house computation.

The examples enumerate both the input year and the following year and select by moment, since the Jieqi enum starts at Lichun, not January. This is a contemporary example. The public Jieqi result is derived from a TT instant via UT1; converting it back to TT is not guaranteed to reproduce that instant in remote eras. Jieqi queries accept years [401, 32766], so a two-year scan's first query year must be in [401, 32765].