זמןzman

Method

How the counter is computed, what is verified, and what remains to be done.

The unit and the epoch

The fundamental counter is a signed 64-bit integer: the number of rega’im elapsed since the epoch. The structural constants are set by definition and depend on no measurement:

UnitValueSource
1 hour1,080 chalakimRambam, Hilkhot Kiddush ha-Chodesh 6:2
1 chelek76 rega’imibid. 10:1
1 day24 hours = 25,920 chalakim = 1,969,920 rega’imby definition
Start of the day18:00Jerusalem mean time, fixed-calendar convention

The epoch (rega 0) is the Saturday evening 18:00 that opens the week of the molad Tohu. Day 0 is that Sunday; day 1 is the Monday, which is also 1 Tishrei of year 1. The molad Tohu, ב״ד ר״ד, falls on day 2 of the week (Monday), 5 hours, 204 chalakim, that is:

1 × 25,920 + 5 × 1,080 + 204 = 31,524 chalakim
31,524 × 76                  = 2,395,824 rega’im

This point is checked by a unit test, as is the identity “day 1 = 1 Tishrei 1 = Monday”. The day number d is related to the Reingold–Dershowitz fixed date by RD = d − 1,373,428; that relation calibrates the bridge to the machine clock, and it is verified by cross-tests on known instants.

The fixed calendar

The calendar is implemented without any external library, from the classical rules. The molad of Tishrei of year N is the molad Tohu plus ⌊(235 N − 234) / 19⌋ mean lunations of 29 days, 12 hours, 793 chalakim. 1 Tishrei follows after applying the four דחיות, in this order:

DechiyahConditionEffect
מולד זקןmolad at 18 hours or laterpostponed to the next day
גטר״דcommon year, molad on a Tuesday at 9 h 204 ch or laterpostponed (to Thursday, via the next rule)
בט״ו תקפ״טyear following a leap year, molad on a Monday at 15 h 589 ch or laterpostponed to Tuesday
לא אד״ו ראשresult on a Sunday, Wednesday or Fridaypostponed to the next day

The length of the year is the difference between two consecutive Rosh Hashanahs; Cheshvan and Kislev absorb the variation (353, 354, 355 days; 383, 384, 385 for leap years, years 3, 6, 8, 11, 14, 17 and 19 of the cycle). Months are numbered by the biblical convention: Nisan = 1 … Adar = 12, Adar II = 13.

The measurement chain

System clock UTC (atom) + DUT1 UT1 Earth rotation IERS finals2000A.all interpolated UT1−UTC + 35.2137° E Jerusalem mean time + 2 h 20 min 51.288 s − epoch, × 1,969,920 / 86,400 Rega (integer) rega’im since the epoch Pure arithmetic day · hour · chelek · rega · date · weekday Above this line: SI second, UTC, MJD. One package (pkg/clock + pkg/iers). The API never sees them.
From the machine clock to the counter. The second exists only in the first two boxes.

In detail:

  1. The server reads the machine clock, in UTC, synchronised by NTP.
  2. It computes the modified Julian date of the instant and linearly interpolates UT1−UTC (DUT1) between the two neighbouring lines of the IERS finals2000A.all file. A leap-second jump between two lines is not interpolated: the value on the nearer side is taken.
  3. UT1 = UTC + DUT1. This is the actual rotation of the Earth, to the precision of the measurements (a few tens of microseconds for final values, a few milliseconds for predictions one month out).
  4. Jerusalem mean time is UT1 shifted by the longitude, 35.2137° E, that is + 8,451.288 s. No time zone, no daylight saving.
  5. The time elapsed since the epoch is converted into rega’im by integer arithmetic: rega = ⌊nanoseconds × 1,969,920 / 86,400 × 10⁹⌋. The computation uses arbitrary-precision integers; no floating point enters the result.

From there on everything is integer: division by 1,969,920 for the day, by 82,080 for the hour, by 76 for the chelek.

Predictions

The IERS publishes measured values a few days late, then a year of predictions marked P. When the current instant is past the last measurement, the server uses the prediction and says so: the field clock.predicted becomes true and clock.dut1_age_days gives the age of the last measurement. Beyond the last line of the file, the last known value is kept. The file is reloaded weekly; if it is unreachable, the disk cache, then the shared cache, serve as fallbacks. If no data is available at startup, the server runs in fallback mode with DUT1 = 0 — an error under one second, about twenty rega’im — and announces it in every response.

What is verified

What is not done yet

The server does not measure the Earth’s rotation; it reads it from the IERS. The planned local sensor — gnomon and camera by day, astrometric solution of the sky by night — does not exist yet. The Clock interface (Now() rega.Rega, Quality()) is the replacement point; nothing in the API depends on it. The server does no holidays, no zmanim by location, no readings: for those, hebcal and KosherJava exist and are excellent.

The code is public: https://github.com/materligmann/zman.