hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 6cdaa5d1ba754586f64e962ae4cc8fee8a464f31
parent 189e10f061f7fc5e38caa6948e272b4493115f93
Author: Byron Torres <b@torresjrjr.com>
Date:   Wed,  8 Dec 2021 18:15:36 +0000

reorganize time, chrono, datetime, isocal modules

Moves chrono:: to time::chrono::
Moves chrono::isocal:: to datetime::

Signed-off-by: Byron Torres <b@torresjrjr.com>

Diffstat:
Dchrono/chronology.ha | 26--------------------------
Dchrono/isocal/calendar.ha | 173-------------------------------------------------------------------------------
Dchrono/isocal/date.ha | 65-----------------------------------------------------------------
Dchrono/isocal/datetime.ha | 137-------------------------------------------------------------------------------
Rchrono/isocal/README -> datetime/README | 0
Adatetime/calendar.ha | 173+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adatetime/date.ha | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adatetime/datetime.ha | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rchrono/isocal/time.ha -> datetime/time.ha | 0
Mscripts/gen-stdlib | 26+++++++++++++-------------
Mstdlib.mk | 148++++++++++++++++++++++++++++++++++++++++----------------------------------------
Rchrono/README -> time/chrono/README | 0
Atime/chrono/chronology.ha | 25+++++++++++++++++++++++++
Rchrono/timescales.ha -> time/chrono/timescales.ha | 0
Rchrono/timezone.ha -> time/chrono/timezone.ha | 0
15 files changed, 487 insertions(+), 488 deletions(-)

diff --git a/chrono/chronology.ha b/chrono/chronology.ha @@ -1,26 +0,0 @@ -use time; - -// // A chronological system for ordering days as dates and eras -// export type chronology = struct { -// to_taidate: nullable *fn(n: moment) moment, -// from_taidate: nullable *fn(n: moment) moment, -// -// scale: timescale, -// }; - -// A date & time within a chronology -export type moment = struct { - date: epochal, - time: time::duration, - loc: locality, -}; - -// An ordinal day on earth since the calendar epoch (zeroth day) 1970-01-01 -// -// Notes: -// 1970-01-01 is "the Hare date-epoch". It was chosen out of simplicity to match -// the UNIX timescale epoch. This shouldn't affect performance in calendar -// implementations because they can convert to other epochs if they so desire. -// (as of writing) chrono::isocal:: converts to the Julian epoch for -// calculations. -export type epochal = i64; diff --git a/chrono/isocal/calendar.ha b/chrono/isocal/calendar.ha @@ -1,173 +0,0 @@ -use time; -use chrono; - - -// The epoch of the Julian Day Number -export def EPOCH_JULIAN: i64 = -2440588; - -// The epoch of the Common Era -export def EPOCH_COMMONERA: i64 = -719164; - - -export fn conv_datetime_moment(dt: datetime) chrono::moment = { - const d = conv_localdate_epochal(dt.date); - const t = conv_localtime_time(dt.time); - const m = chrono::moment { - date = d, - time = t, - loc = dt.loc, - }; - return m; -}; - -export fn conv_moment_datetime(m: chrono::moment) datetime = { - const ld = conv_epochal_localdate(m.date); - const lt = conv_time_localtime(m.time); - const dt = datetime { - date = ld, - time = lt, - loc = m.loc, - }; - return dt; -}; - - -// -// date-like -// - -// Calculates a moment's number of days since the calendar epoch 0001-01-01 -export fn epocal(m: chrono::moment) int = { - return (EPOCH_COMMONERA + m.date): int; -}; - -// Calculates a moment's era -export fn era(m: chrono::moment) int = { - if (m.date > EPOCH_COMMONERA) { - return 0; // CE, Common Era - } else { - return -1; // BCE, Before Common Era - }; -}; - -// Calculates a moment's year -export fn year(m: chrono::moment) int = { - const ld = conv_epochal_localdate(m.date); - return ld.year as int; -}; - -// Calculates a moment's month -export fn month(m: chrono::moment) int = { - const ld = conv_epochal_localdate(m.date); - return ld.month as int; -}; - -// Calculates a moment's day of the month -export fn day(m: chrono::moment) int = { - const ld = conv_epochal_localdate(m.date); - return ld.day as int; -}; - -// Calculates a moment's ISO week calendar year -export fn weekyear(m: chrono::moment) int = { - // TODO - return 0; -}; - -// Calculates a moment's ISO week -export fn week(m: chrono::moment) int = { - // TODO - return 0; -}; - -// Calculates a moment's ordinal day of the year -export fn yearday(m: chrono::moment) int = { - // TODO - return 0; -}; - -// -// time-like -// - -// Calculates a moment's hour of the day -export fn hour(m: chrono::moment) int = { - return (m.time / time::HOUR): int; -}; - -// Calculates a moment's minute of the hour -export fn min(m: chrono::moment) int = { - return ((m.time / time::MINUTE) % 60): int; -}; - -// Calculates a moment's second of the minute -export fn sec(m: chrono::moment) int = { - return ((m.time / time::SECOND) % 60): int; -}; - -// Calculates a moment's nanosecond of the second -export fn nsec(m: chrono::moment) int = { - return (m.time % time::SECOND): int; -}; - - -// A contextual span of time in the proleptic Gregorian calendar. -// Used for calendar arithmetic. -export type period = struct { - eras: int, - years: int, - - // Can be 28, 29, 30, or 31 days long - months: int, - - // Weeks start on Monday - weeks: int, - - days: int, - hours: int, - minutes: int, - seconds: int, - nanoseconds: int, -}; - -// Hops along the calendar from a moment, according to the given periods -// sequencially, consulting period's units from largest to smallest. -// -// // m := 1999-05-13 12:30:45 -// isocal::hop(m, isocal::period { -// years = 22, // 2021-01-01 00:00:00 -// months = -1, // 2020-11-01 00:00:00 -// days = -4, // 2020-10-27 00:00:00 -// }); -// -export fn hop(m: chrono::moment, pp: period...) chrono::moment = { - // TODO - for (let i = 0z; i < len(pp); i += 1) { - const p = pp[i]; - }; - return m; -}; - -// Adds a calindrical period of time to a moment, largest units first. -// Tries to conserve relative distance from cyclical points on the calendar. -// -// // m := 1999-05-13 12:30:45 -// isocal::hop(m, isocal::period { -// years = 22, // 2021-05-13 00:00:00 -// months = -1, // 2021-04-13 00:00:00 -// days = -4, // 2020-04-09 00:00:00 -// }); -// -// When units overflow, such as when adding a month to Jan 31st inaccurately -// results to Feb 31th, the flag is consulted on how to handle this. -// -// TODO: -// How to handle overflows and predictability with cal-arithm in general? -export fn add(m: chrono::moment, flag: int, pp: period...) chrono::moment = { - // TODO - for (let i = 0z; i < len(pp); i += 1) { - const p = pp[i]; - }; - return m; -}; - diff --git a/chrono/isocal/date.ha b/chrono/isocal/date.ha @@ -1,65 +0,0 @@ -use chrono; - -// Represents an ISO calendar date. -// Instances created from isocal:: functions are guaranteed to be valid. -export type localdate = struct { - era: (void | int), - year: (void | int), - month: (void | int), - day: (void | int), - weekyear: (void | int), - week: (void | int), - weekday: (void | int), - yearday: (void | int), -}; - -export fn conv_epochal_localdate(epochal: chrono::epochal) localdate = { - // Algorithm adapted from: - // https://en.wikipedia.org/wiki/Julian_day#Julian_or_Gregorian_calendar_from_Julian_day_number - // - // Alternate methods of date calculation should be explored. - const J = epochal - EPOCH_JULIAN; - const j = 1401; - const y = 4716; - const B = 274277; - const C = -38; - const r = 4; - const v = 3; - const p = 1461; - const u = 5; - const w = 2; - const s = 153; - const n = 12; - const m = 2; - - const f = J + j + (((4 * J + B) / 146097) * 3) / 4 + C; - const e = r * f + v; - const g = (e % p) / r; - const h = u * g + w; - - const D = (h % s) / u + 1; - const M = ((h / s + m) % n) + 1; - const Y = (e / p) - y + (n + m - M) / n; - - const ld = localdate { - year = Y: int, - month = M: int, - day = D: int, - }; - return ld; -}; - -export fn conv_localdate_epochal(ld: localdate) chrono::epochal = { - const Y = ld.year as int; - const M = ld.month as int; - const D = ld.day as int; - const jdn = ( - (1461 * (Y + 4800 + (M - 14) / 12)) / 4 - + (367 * (M - 2 - 12 * ((M - 14) / 12))) / 12 - - (3 * ((Y + 4900 + (M - 14) / 12) / 100)) / 4 - + D - - 32075 - ); - const epochal = jdn + EPOCH_JULIAN; - return epochal; -}; diff --git a/chrono/isocal/datetime.ha b/chrono/isocal/datetime.ha @@ -1,137 +0,0 @@ -use time; -use chrono; -use errors; - -// Represents a ISO datetime -// -// Notes: -// Java has good separation of types: A LocalDatetime, ZonedDatetime, -// OffsetDatetime. Python instead reasons about datetimes as being -// timezone-aware/naive. Here's I try to leaverage Hare's type system to combine -// the two. -// -// Putting the date and time related fields into separate typed structs maybe -// isn't a good idea (see `type localdate` below), but I still put it here -// because localtime is often used on it's own, and it makes some sense to have -// a datetime be composed of a date and time. -export type datetime = struct { - date: localdate, - time: localtime, - loc: locality, -}; - -export type locality = chrono::locality; - -// Creates a new moment -// -// // 1995 July 18th 09:16:00.000 -// isocal::new_moment(1995, 07, 18, 9, 16, 0, 0, isocal::local) -// -// For alternative forms, assemble a datetime manually using the desired types. -export fn new_moment( - year: int, - month: int, - day: int, - hour: int, - min: int, - sec: int, - nsec: int, - loc: locality, -) chrono::moment = { - const dt = datetime { - date = localdate { - year = year, - month = month, - day = day, - }, - time = localtime { - hour = hour, - min = min, - sec = sec, - nsec = nsec, - }, - loc = loc, - }; - const m = conv_datetime_moment(dt); - return m; -}; - -// Creates a new datetime -// -// // 1995 July 18th 09:16:00.000 -// isocal::new(1995, 07, 18, 9, 16, 0, 0, isocal::local) -// -// For alternative forms, assemble a datetime manually using the desired types. -export fn new_datetime( - year: int, - month: int, - day: int, - hour: int, - min: int, - sec: int, - nsec: int, - loc: locality, -) (datetime | errors::invalid) = { - const dt = datetime { - date = localdate { - year = year, - month = month, - day = day, - }, - time = localtime { - hour = hour, - min = min, - sec = sec, - nsec = nsec, - }, - loc = loc, - }; - if (!validate(dt)) { - return errors::invalid; - }; - return dt; -}; - -// Returns the current moment -export fn now_moment() chrono::moment = { - const i = time::now(time::clock::REALTIME); - const u = time::unix(i); - const d = (u / 86400); - const t = ( - (i.sec * time::SECOND) + (i.nsec * time::NANOSECOND) - ) % (24 * time::HOUR); - const m = chrono::moment { - date = d, - time = t, - loc = chrono::local, - }; - return m; -}; - -// Returns the current datetime -export fn now_datetime() datetime = { - const i = time::now(time::clock::REALTIME); - const u = time::unix(i); - const d = (u / 86400); - const ld = conv_epochal_localdate(d); - const dt = datetime { - date = ld, - time = localtime { - hour = (i.sec / 3600): int % 24, - min = (i.sec / 60): int % 60, - sec = i.sec: int % 60, - nsec = i.nsec: int, - }, - - // TODO: What to do here? How to get the timezone from - // /etc/localtime or $TZ? How to determine the system's - // timescale? Assuming UTC may be sufficient. - loc = chrono::local, - }; - return dt; -}; - -export fn validate(dt: datetime) bool = { - // TODO - return true; -}; diff --git a/chrono/isocal/README b/datetime/README diff --git a/datetime/calendar.ha b/datetime/calendar.ha @@ -0,0 +1,173 @@ +use time; +use time::chrono; + + +// The epoch of the Julian Day Number +export def EPOCH_JULIAN: i64 = -2440588; + +// The epoch of the Common Era +export def EPOCH_COMMONERA: i64 = -719164; + + +export fn conv_datetime_moment(dt: datetime) chrono::moment = { + const d = conv_localdate_epochal(dt.date); + const t = conv_localtime_time(dt.time); + const m = chrono::moment { + date = d, + time = t, + loc = dt.loc, + }; + return m; +}; + +export fn conv_moment_datetime(m: chrono::moment) datetime = { + const ld = conv_epochal_localdate(m.date); + const lt = conv_time_localtime(m.time); + const dt = datetime { + date = ld, + time = lt, + loc = m.loc, + }; + return dt; +}; + + +// +// date-like +// + +// Calculates a moment's number of days since the calendar epoch 0001-01-01 +export fn epocal(m: chrono::moment) int = { + return (EPOCH_COMMONERA + m.date): int; +}; + +// Calculates a moment's era +export fn era(m: chrono::moment) int = { + if (m.date > EPOCH_COMMONERA) { + return 0; // CE, Common Era + } else { + return -1; // BCE, Before Common Era + }; +}; + +// Calculates a moment's year +export fn year(m: chrono::moment) int = { + const ld = conv_epochal_localdate(m.date); + return ld.year as int; +}; + +// Calculates a moment's month +export fn month(m: chrono::moment) int = { + const ld = conv_epochal_localdate(m.date); + return ld.month as int; +}; + +// Calculates a moment's day of the month +export fn day(m: chrono::moment) int = { + const ld = conv_epochal_localdate(m.date); + return ld.day as int; +}; + +// Calculates a moment's ISO week calendar year +export fn weekyear(m: chrono::moment) int = { + // TODO + return 0; +}; + +// Calculates a moment's ISO week +export fn week(m: chrono::moment) int = { + // TODO + return 0; +}; + +// Calculates a moment's ordinal day of the year +export fn yearday(m: chrono::moment) int = { + // TODO + return 0; +}; + +// +// time-like +// + +// Calculates a moment's hour of the day +export fn hour(m: chrono::moment) int = { + return (m.time / time::HOUR): int; +}; + +// Calculates a moment's minute of the hour +export fn min(m: chrono::moment) int = { + return ((m.time / time::MINUTE) % 60): int; +}; + +// Calculates a moment's second of the minute +export fn sec(m: chrono::moment) int = { + return ((m.time / time::SECOND) % 60): int; +}; + +// Calculates a moment's nanosecond of the second +export fn nsec(m: chrono::moment) int = { + return (m.time % time::SECOND): int; +}; + + +// A contextual span of time in the proleptic Gregorian calendar. +// Used for calendar arithmetic. +export type period = struct { + eras: int, + years: int, + + // Can be 28, 29, 30, or 31 days long + months: int, + + // Weeks start on Monday + weeks: int, + + days: int, + hours: int, + minutes: int, + seconds: int, + nanoseconds: int, +}; + +// Hops along the calendar from a moment, according to the given periods +// sequencially, consulting period's units from largest to smallest. +// +// // m := 1999-05-13 12:30:45 +// isocal::hop(m, isocal::period { +// years = 22, // 2021-01-01 00:00:00 +// months = -1, // 2020-11-01 00:00:00 +// days = -4, // 2020-10-27 00:00:00 +// }); +// +export fn hop(m: chrono::moment, pp: period...) chrono::moment = { + // TODO + for (let i = 0z; i < len(pp); i += 1) { + const p = pp[i]; + }; + return m; +}; + +// Adds a calindrical period of time to a moment, largest units first. +// Tries to conserve relative distance from cyclical points on the calendar. +// +// // m := 1999-05-13 12:30:45 +// isocal::hop(m, isocal::period { +// years = 22, // 2021-05-13 00:00:00 +// months = -1, // 2021-04-13 00:00:00 +// days = -4, // 2020-04-09 00:00:00 +// }); +// +// When units overflow, such as when adding a month to Jan 31st inaccurately +// results to Feb 31th, the flag is consulted on how to handle this. +// +// TODO: +// How to handle overflows and predictability with cal-arithm in general? +export fn add(m: chrono::moment, flag: int, pp: period...) chrono::moment = { + // TODO + for (let i = 0z; i < len(pp); i += 1) { + const p = pp[i]; + }; + return m; +}; + diff --git a/datetime/date.ha b/datetime/date.ha @@ -0,0 +1,65 @@ +use time::chrono; + +// Represents an ISO calendar date. +// Instances created from isocal:: functions are guaranteed to be valid. +export type localdate = struct { + era: (void | int), + year: (void | int), + month: (void | int), + day: (void | int), + weekyear: (void | int), + week: (void | int), + weekday: (void | int), + yearday: (void | int), +}; + +export fn conv_epochal_localdate(epochal: chrono::epochal) localdate = { + // Algorithm adapted from: + // https://en.wikipedia.org/wiki/Julian_day#Julian_or_Gregorian_calendar_from_Julian_day_number + // + // Alternate methods of date calculation should be explored. + const J = epochal - EPOCH_JULIAN; + const j = 1401; + const y = 4716; + const B = 274277; + const C = -38; + const r = 4; + const v = 3; + const p = 1461; + const u = 5; + const w = 2; + const s = 153; + const n = 12; + const m = 2; + + const f = J + j + (((4 * J + B) / 146097) * 3) / 4 + C; + const e = r * f + v; + const g = (e % p) / r; + const h = u * g + w; + + const D = (h % s) / u + 1; + const M = ((h / s + m) % n) + 1; + const Y = (e / p) - y + (n + m - M) / n; + + const ld = localdate { + year = Y: int, + month = M: int, + day = D: int, + }; + return ld; +}; + +export fn conv_localdate_epochal(ld: localdate) chrono::epochal = { + const Y = ld.year as int; + const M = ld.month as int; + const D = ld.day as int; + const jdn = ( + (1461 * (Y + 4800 + (M - 14) / 12)) / 4 + + (367 * (M - 2 - 12 * ((M - 14) / 12))) / 12 + - (3 * ((Y + 4900 + (M - 14) / 12) / 100)) / 4 + + D + - 32075 + ); + const epochal = jdn + EPOCH_JULIAN; + return epochal; +}; diff --git a/datetime/datetime.ha b/datetime/datetime.ha @@ -0,0 +1,137 @@ +use time; +use time::chrono; +use errors; + +// Represents a ISO datetime +// +// Notes: +// Java has good separation of types: A LocalDatetime, ZonedDatetime, +// OffsetDatetime. Python instead reasons about datetimes as being +// timezone-aware/naive. Here's I try to leaverage Hare's type system to combine +// the two. +// +// Putting the date and time related fields into separate typed structs maybe +// isn't a good idea (see `type localdate` below), but I still put it here +// because localtime is often used on it's own, and it makes some sense to have +// a datetime be composed of a date and time. +export type datetime = struct { + date: localdate, + time: localtime, + loc: locality, +}; + +export type locality = chrono::locality; + +// Creates a new moment +// +// // 1995 July 18th 09:16:00.000 +// isocal::new_moment(1995, 07, 18, 9, 16, 0, 0, isocal::local) +// +// For alternative forms, assemble a datetime manually using the desired types. +export fn new_moment( + year: int, + month: int, + day: int, + hour: int, + min: int, + sec: int, + nsec: int, + loc: locality, +) chrono::moment = { + const dt = datetime { + date = localdate { + year = year, + month = month, + day = day, + }, + time = localtime { + hour = hour, + min = min, + sec = sec, + nsec = nsec, + }, + loc = loc, + }; + const m = conv_datetime_moment(dt); + return m; +}; + +// Creates a new datetime +// +// // 1995 July 18th 09:16:00.000 +// isocal::new(1995, 07, 18, 9, 16, 0, 0, isocal::local) +// +// For alternative forms, assemble a datetime manually using the desired types. +export fn new_datetime( + year: int, + month: int, + day: int, + hour: int, + min: int, + sec: int, + nsec: int, + loc: locality, +) (datetime | errors::invalid) = { + const dt = datetime { + date = localdate { + year = year, + month = month, + day = day, + }, + time = localtime { + hour = hour, + min = min, + sec = sec, + nsec = nsec, + }, + loc = loc, + }; + if (!validate(dt)) { + return errors::invalid; + }; + return dt; +}; + +// Returns the current moment +export fn now_moment() chrono::moment = { + const i = time::now(time::clock::REALTIME); + const u = time::unix(i); + const d = (u / 86400); + const t = ( + (i.sec * time::SECOND) + (i.nsec * time::NANOSECOND) + ) % (24 * time::HOUR); + const m = chrono::moment { + date = d, + time = t, + loc = chrono::local, + }; + return m; +}; + +// Returns the current datetime +export fn now_datetime() datetime = { + const i = time::now(time::clock::REALTIME); + const u = time::unix(i); + const d = (u / 86400); + const ld = conv_epochal_localdate(d); + const dt = datetime { + date = ld, + time = localtime { + hour = (i.sec / 3600): int % 24, + min = (i.sec / 60): int % 60, + sec = i.sec: int % 60, + nsec = i.nsec: int, + }, + + // TODO: What to do here? How to get the timezone from + // /etc/localtime or $TZ? How to determine the system's + // timescale? Assuming UTC may be sufficient. + loc = chrono::local, + }; + return dt; +}; + +export fn validate(dt: datetime) bool = { + // TODO + return true; +}; diff --git a/chrono/isocal/time.ha b/datetime/time.ha diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib @@ -181,21 +181,13 @@ bytes() { gen_ssa bytes types } -chrono() { - gen_srcs chrono \ - chronology.ha \ - timescales.ha \ - timezone.ha - gen_ssa chrono time -} - -chrono_isocal() { - gen_srcs chrono::isocal \ +datetime() { + gen_srcs datetime \ calendar.ha \ datetime.ha \ date.ha \ time.ha - gen_ssa chrono::isocal chrono time + gen_ssa datetime time time::chrono } compress_flate() { @@ -1180,6 +1172,14 @@ time() { gen_ssa -pfreebsd time } +time_chrono() { + gen_srcs time::chrono \ + chronology.ha \ + timescales.ha \ + timezone.ha + gen_ssa time::chrono time +} + types() { gen_srcs types \ limits.ha \ @@ -1271,8 +1271,6 @@ uuid() { modules="ascii bufio bytes -chrono -chrono::isocal compress::flate compress::zlib crypto @@ -1292,6 +1290,7 @@ crypto::sha1 crypto::sha256 crypto::sha512 crypto::curve25519 +datetime dirs encoding::base64 encoding::base32 @@ -1348,6 +1347,7 @@ strings strio temp linux freebsd time linux freebsd +time::chrono types unix linux freebsd unix::hosts diff --git a/stdlib.mk b/stdlib.mk @@ -148,18 +148,6 @@ stdlib_deps_any+=$(stdlib_bytes_any) stdlib_bytes_linux=$(stdlib_bytes_any) stdlib_bytes_freebsd=$(stdlib_bytes_any) -# gen_lib chrono (any) -stdlib_chrono_any=$(HARECACHE)/chrono/chrono-any.o -stdlib_deps_any+=$(stdlib_chrono_any) -stdlib_chrono_linux=$(stdlib_chrono_any) -stdlib_chrono_freebsd=$(stdlib_chrono_any) - -# gen_lib chrono::isocal (any) -stdlib_chrono_isocal_any=$(HARECACHE)/chrono/isocal/chrono_isocal-any.o -stdlib_deps_any+=$(stdlib_chrono_isocal_any) -stdlib_chrono_isocal_linux=$(stdlib_chrono_isocal_any) -stdlib_chrono_isocal_freebsd=$(stdlib_chrono_isocal_any) - # gen_lib compress::flate (any) stdlib_compress_flate_any=$(HARECACHE)/compress/flate/compress_flate-any.o stdlib_deps_any+=$(stdlib_compress_flate_any) @@ -276,6 +264,12 @@ stdlib_deps_any+=$(stdlib_crypto_curve25519_any) stdlib_crypto_curve25519_linux=$(stdlib_crypto_curve25519_any) stdlib_crypto_curve25519_freebsd=$(stdlib_crypto_curve25519_any) +# gen_lib datetime (any) +stdlib_datetime_any=$(HARECACHE)/datetime/datetime-any.o +stdlib_deps_any+=$(stdlib_datetime_any) +stdlib_datetime_linux=$(stdlib_datetime_any) +stdlib_datetime_freebsd=$(stdlib_datetime_any) + # gen_lib dirs (any) stdlib_dirs_any=$(HARECACHE)/dirs/dirs-any.o stdlib_deps_any+=$(stdlib_dirs_any) @@ -622,6 +616,12 @@ stdlib_deps_linux+=$(stdlib_time_linux) stdlib_time_freebsd=$(HARECACHE)/time/time-freebsd.o stdlib_deps_freebsd+=$(stdlib_time_freebsd) +# gen_lib time::chrono (any) +stdlib_time_chrono_any=$(HARECACHE)/time/chrono/time_chrono-any.o +stdlib_deps_any+=$(stdlib_time_chrono_any) +stdlib_time_chrono_linux=$(stdlib_time_chrono_any) +stdlib_time_chrono_freebsd=$(stdlib_time_chrono_any) + # gen_lib types (any) stdlib_types_any=$(HARECACHE)/types/types-any.o stdlib_deps_any+=$(stdlib_types_any) @@ -719,31 +719,6 @@ $(HARECACHE)/bytes/bytes-any.ssa: $(stdlib_bytes_any_srcs) $(stdlib_rt) $(stdlib @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Nbytes \ -t$(HARECACHE)/bytes/bytes.td $(stdlib_bytes_any_srcs) -# chrono (+any) -stdlib_chrono_any_srcs= \ - $(STDLIB)/chrono/chronology.ha \ - $(STDLIB)/chrono/timescales.ha \ - $(STDLIB)/chrono/timezone.ha - -$(HARECACHE)/chrono/chrono-any.ssa: $(stdlib_chrono_any_srcs) $(stdlib_rt) $(stdlib_time_$(PLATFORM)) - @printf 'HAREC \t$@\n' - @mkdir -p $(HARECACHE)/chrono - @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Nchrono \ - -t$(HARECACHE)/chrono/chrono.td $(stdlib_chrono_any_srcs) - -# chrono::isocal (+any) -stdlib_chrono_isocal_any_srcs= \ - $(STDLIB)/chrono/isocal/calendar.ha \ - $(STDLIB)/chrono/isocal/datetime.ha \ - $(STDLIB)/chrono/isocal/date.ha \ - $(STDLIB)/chrono/isocal/time.ha - -$(HARECACHE)/chrono/isocal/chrono_isocal-any.ssa: $(stdlib_chrono_isocal_any_srcs) $(stdlib_rt) $(stdlib_chrono_$(PLATFORM)) $(stdlib_time_$(PLATFORM)) - @printf 'HAREC \t$@\n' - @mkdir -p $(HARECACHE)/chrono/isocal - @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Nchrono::isocal \ - -t$(HARECACHE)/chrono/isocal/chrono_isocal.td $(stdlib_chrono_isocal_any_srcs) - # compress::flate (+any) stdlib_compress_flate_any_srcs= \ $(STDLIB)/compress/flate/inflate.ha @@ -952,6 +927,19 @@ $(HARECACHE)/crypto/curve25519/crypto_curve25519-any.ssa: $(stdlib_crypto_curve2 @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Ncrypto::curve25519 \ -t$(HARECACHE)/crypto/curve25519/crypto_curve25519.td $(stdlib_crypto_curve25519_any_srcs) +# datetime (+any) +stdlib_datetime_any_srcs= \ + $(STDLIB)/datetime/calendar.ha \ + $(STDLIB)/datetime/datetime.ha \ + $(STDLIB)/datetime/date.ha \ + $(STDLIB)/datetime/time.ha + +$(HARECACHE)/datetime/datetime-any.ssa: $(stdlib_datetime_any_srcs) $(stdlib_rt) $(stdlib_time_$(PLATFORM)) $(stdlib_time_chrono_$(PLATFORM)) + @printf 'HAREC \t$@\n' + @mkdir -p $(HARECACHE)/datetime + @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Ndatetime \ + -t$(HARECACHE)/datetime/datetime.td $(stdlib_datetime_any_srcs) + # dirs (+any) stdlib_dirs_any_srcs= \ $(STDLIB)/dirs/xdg.ha @@ -1797,6 +1785,18 @@ $(HARECACHE)/time/time-freebsd.ssa: $(stdlib_time_freebsd_srcs) $(stdlib_rt) @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Ntime \ -t$(HARECACHE)/time/time.td $(stdlib_time_freebsd_srcs) +# time::chrono (+any) +stdlib_time_chrono_any_srcs= \ + $(STDLIB)/time/chrono/chronology.ha \ + $(STDLIB)/time/chrono/timescales.ha \ + $(STDLIB)/time/chrono/timezone.ha + +$(HARECACHE)/time/chrono/time_chrono-any.ssa: $(stdlib_time_chrono_any_srcs) $(stdlib_rt) $(stdlib_time_$(PLATFORM)) + @printf 'HAREC \t$@\n' + @mkdir -p $(HARECACHE)/time/chrono + @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Ntime::chrono \ + -t$(HARECACHE)/time/chrono/time_chrono.td $(stdlib_time_chrono_any_srcs) + # types (+any) stdlib_types_any_srcs= \ $(STDLIB)/types/limits.ha \ @@ -2092,18 +2092,6 @@ testlib_deps_any+=$(testlib_bytes_any) testlib_bytes_linux=$(testlib_bytes_any) testlib_bytes_freebsd=$(testlib_bytes_any) -# gen_lib chrono (any) -testlib_chrono_any=$(TESTCACHE)/chrono/chrono-any.o -testlib_deps_any+=$(testlib_chrono_any) -testlib_chrono_linux=$(testlib_chrono_any) -testlib_chrono_freebsd=$(testlib_chrono_any) - -# gen_lib chrono::isocal (any) -testlib_chrono_isocal_any=$(TESTCACHE)/chrono/isocal/chrono_isocal-any.o -testlib_deps_any+=$(testlib_chrono_isocal_any) -testlib_chrono_isocal_linux=$(testlib_chrono_isocal_any) -testlib_chrono_isocal_freebsd=$(testlib_chrono_isocal_any) - # gen_lib compress::flate (any) testlib_compress_flate_any=$(TESTCACHE)/compress/flate/compress_flate-any.o testlib_deps_any+=$(testlib_compress_flate_any) @@ -2220,6 +2208,12 @@ testlib_deps_any+=$(testlib_crypto_curve25519_any) testlib_crypto_curve25519_linux=$(testlib_crypto_curve25519_any) testlib_crypto_curve25519_freebsd=$(testlib_crypto_curve25519_any) +# gen_lib datetime (any) +testlib_datetime_any=$(TESTCACHE)/datetime/datetime-any.o +testlib_deps_any+=$(testlib_datetime_any) +testlib_datetime_linux=$(testlib_datetime_any) +testlib_datetime_freebsd=$(testlib_datetime_any) + # gen_lib dirs (any) testlib_dirs_any=$(TESTCACHE)/dirs/dirs-any.o testlib_deps_any+=$(testlib_dirs_any) @@ -2566,6 +2560,12 @@ testlib_deps_linux+=$(testlib_time_linux) testlib_time_freebsd=$(TESTCACHE)/time/time-freebsd.o testlib_deps_freebsd+=$(testlib_time_freebsd) +# gen_lib time::chrono (any) +testlib_time_chrono_any=$(TESTCACHE)/time/chrono/time_chrono-any.o +testlib_deps_any+=$(testlib_time_chrono_any) +testlib_time_chrono_linux=$(testlib_time_chrono_any) +testlib_time_chrono_freebsd=$(testlib_time_chrono_any) + # gen_lib types (any) testlib_types_any=$(TESTCACHE)/types/types-any.o testlib_deps_any+=$(testlib_types_any) @@ -2663,31 +2663,6 @@ $(TESTCACHE)/bytes/bytes-any.ssa: $(testlib_bytes_any_srcs) $(testlib_rt) $(test @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nbytes \ -t$(TESTCACHE)/bytes/bytes.td $(testlib_bytes_any_srcs) -# chrono (+any) -testlib_chrono_any_srcs= \ - $(STDLIB)/chrono/chronology.ha \ - $(STDLIB)/chrono/timescales.ha \ - $(STDLIB)/chrono/timezone.ha - -$(TESTCACHE)/chrono/chrono-any.ssa: $(testlib_chrono_any_srcs) $(testlib_rt) $(testlib_time_$(PLATFORM)) - @printf 'HAREC \t$@\n' - @mkdir -p $(TESTCACHE)/chrono - @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nchrono \ - -t$(TESTCACHE)/chrono/chrono.td $(testlib_chrono_any_srcs) - -# chrono::isocal (+any) -testlib_chrono_isocal_any_srcs= \ - $(STDLIB)/chrono/isocal/calendar.ha \ - $(STDLIB)/chrono/isocal/datetime.ha \ - $(STDLIB)/chrono/isocal/date.ha \ - $(STDLIB)/chrono/isocal/time.ha - -$(TESTCACHE)/chrono/isocal/chrono_isocal-any.ssa: $(testlib_chrono_isocal_any_srcs) $(testlib_rt) $(testlib_chrono_$(PLATFORM)) $(testlib_time_$(PLATFORM)) - @printf 'HAREC \t$@\n' - @mkdir -p $(TESTCACHE)/chrono/isocal - @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nchrono::isocal \ - -t$(TESTCACHE)/chrono/isocal/chrono_isocal.td $(testlib_chrono_isocal_any_srcs) - # compress::flate (+any) testlib_compress_flate_any_srcs= \ $(STDLIB)/compress/flate/inflate.ha @@ -2913,6 +2888,19 @@ $(TESTCACHE)/crypto/curve25519/crypto_curve25519-any.ssa: $(testlib_crypto_curve @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ncrypto::curve25519 \ -t$(TESTCACHE)/crypto/curve25519/crypto_curve25519.td $(testlib_crypto_curve25519_any_srcs) +# datetime (+any) +testlib_datetime_any_srcs= \ + $(STDLIB)/datetime/calendar.ha \ + $(STDLIB)/datetime/datetime.ha \ + $(STDLIB)/datetime/date.ha \ + $(STDLIB)/datetime/time.ha + +$(TESTCACHE)/datetime/datetime-any.ssa: $(testlib_datetime_any_srcs) $(testlib_rt) $(testlib_time_$(PLATFORM)) $(testlib_time_chrono_$(PLATFORM)) + @printf 'HAREC \t$@\n' + @mkdir -p $(TESTCACHE)/datetime + @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ndatetime \ + -t$(TESTCACHE)/datetime/datetime.td $(testlib_datetime_any_srcs) + # dirs (+any) testlib_dirs_any_srcs= \ $(STDLIB)/dirs/xdg.ha @@ -3786,6 +3774,18 @@ $(TESTCACHE)/time/time-freebsd.ssa: $(testlib_time_freebsd_srcs) $(testlib_rt) @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ntime \ -t$(TESTCACHE)/time/time.td $(testlib_time_freebsd_srcs) +# time::chrono (+any) +testlib_time_chrono_any_srcs= \ + $(STDLIB)/time/chrono/chronology.ha \ + $(STDLIB)/time/chrono/timescales.ha \ + $(STDLIB)/time/chrono/timezone.ha + +$(TESTCACHE)/time/chrono/time_chrono-any.ssa: $(testlib_time_chrono_any_srcs) $(testlib_rt) $(testlib_time_$(PLATFORM)) + @printf 'HAREC \t$@\n' + @mkdir -p $(TESTCACHE)/time/chrono + @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ntime::chrono \ + -t$(TESTCACHE)/time/chrono/time_chrono.td $(testlib_time_chrono_any_srcs) + # types (+any) testlib_types_any_srcs= \ $(STDLIB)/types/limits.ha \ diff --git a/chrono/README b/time/chrono/README diff --git a/time/chrono/chronology.ha b/time/chrono/chronology.ha @@ -0,0 +1,25 @@ +use time; + +// // A chronological system for ordering days as dates and eras +// export type chronology = struct { +// to_taidate: nullable *fn(n: moment) moment, +// from_taidate: nullable *fn(n: moment) moment, +// +// scale: timescale, +// }; + +// A date & time within a chronology +export type moment = struct { + date: epochal, + time: time::duration, + loc: locality, +}; + +// An ordinal day on earth since the calendar epoch (zeroth day) 1970-01-01 +// +// Notes: +// 1970-01-01 is "the Hare date-epoch". It was chosen out of simplicity to match +// the UNIX timescale epoch. This shouldn't affect performance in calendar +// implementations because they can convert to other epochs if they so desire. +// (as of writing) datetime:: converts to the Julian epoch for calculations. +export type epochal = i64; diff --git a/chrono/timescales.ha b/time/chrono/timescales.ha diff --git a/chrono/timezone.ha b/time/chrono/timezone.ha