nx_civil_date.nx
buildroot/runtime/nx_civil_date.nx
about
civil_date.nx -- Gregorian civil date from unix seconds.
Pairs with ntp.nx (returns unix seconds) to convert seconds
into (year, month, day, hour, minute, second, weekday) without
depending on glibc strftime or the OS tzdata. UTC only;
timezone handling is a separate concern.
Uses Howard Hinnant's "civil_from_days" algorithm (the
<chrono> library implementation used by libc++). Correct for
all years in i64 range (billions of years past and future).
Algorithm:
z = days since 1970-01-01
Shift epoch to 0000-03-01 so Feb is last: z += 719468
era = z / 146097 (146097 days = 400 years)
doe = z % 146097
yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365
y = yoe + era*400
doy = doe - (365*yoe + yoe/4 - yoe/100)
mp = (5*doy + 2) / 153
d = doy - (153*mp + 2)/5 + 1
m = mp < 10 ? mp + 3 : mp - 9
y += m <= 2 ? 1 : 0
Invariants:
CD1 1970-01-01 00:00:00 UTC <-> unix_sec = 0, all fields
returned accordingly (year=1970, month=1, day=1, ...).
CD2 Negative unix_sec works (dates before 1970).
CD3 Weekday: 0 = Sunday, 1 = Monday, ..., 6 = Saturday
(Unix convention; struct tm compatible).
dependencies 1 imports · 3 importers
imports: nx_syscalls.nx
imported by: nx_http_date.nxnx_iso8601.nxnx_sitemap.nx
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| 50 | struct CivilDate |
consts
| 39 | const SECONDS_MAGIC_3600: i64 = 3600 |
| 40 | const SECONDS_MAGIC_719468: i64 = 719468 |
| 41 | const SECONDS_MAGIC_146097: i64 = 146097 |
| 42 | const SECONDS_MAGIC_1460: i64 = 1460 |
| 43 | const SECONDS_MAGIC_36524: i64 = 36524 |
| 44 | const SECONDS_MAGIC_146096: i64 = 146096 |
| 45 | const SECONDS_MAGIC_1970: i64 = 1970 |
| 46 | const SECONDS_MAGIC_946684800: i64 = 946684800 |
| 47 | const SECONDS_MAGIC_2000: i64 = 2000 |
| 48 | const SECONDS_MAGIC_2026: i64 = 2026 |
| 60 | const SECONDS_PER_DAY: i64 = 86400 |
functions
| 65 | func cd_fdiv(a: i64, b: i64) -> i64 |
| 74 | func cd_fmod(a: i64, b: i64) -> i64 |
| 80 | func civil_from_unix(unix_sec: i64, out: *CivilDate) -> i64 |
| 113 | func unix_from_civil(y: i64, m: i64, d: i64, |
| 128 | func main() -> i64 |