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:
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