commit 19e380ccb7dfe2bcab5f94e6bd03004e3e2c6005
parent 4d909ad613a6d2c8552ab14ed0c8639439c348cd
Author: Byron Torres <b@torresjrjr.com>
Date: Tue, 24 May 2022 04:00:29 +0100
time::chrono: make in() handle multiple timescales
The following now works properly:
const earth = datetime::now();
const mars = datetime::in(chrono::MTC, earth);
Fixes: https://todo.sr.ht/~sircmpwn/hare/618
Signed-off-by: Byron Torres <b@torresjrjr.com>
Diffstat:
1 file changed, 23 insertions(+), 0 deletions(-)
diff --git a/time/chrono/timezone.ha b/time/chrono/timezone.ha
@@ -71,7 +71,30 @@ type tzname = struct {
};
// Creates an equivalent [[moment]] with a different [[locality]].
+//
+// If the old and new localities have different timescales, a direct conversion
+// between them will be tried, and will abort if unsuccessful. To avoid this,
+// consider manually converting moments to instants, and those instants between
+// timescales.
export fn in(loc: locality, m: moment) moment = {
+ if (m.loc.timescale != loc.timescale) {
+ const i = to_instant(m);
+ const i = match (m.loc.timescale.to_tai(i)) {
+ case let i: time::instant =>
+ yield i;
+ case time::error =>
+ abort("time::chrono::in(): direct timescale conversion failed");
+ };
+ const i = match (loc.timescale.from_tai(i)) {
+ case let i: time::instant =>
+ yield i;
+ case time::error =>
+ abort("time::chrono::in(): direct timescale conversion failed");
+ };
+ const m = from_instant(i, loc);
+ return m;
+ };
+
assert(m.time < loc.daylength, "Internal error: time excedes daylength");
return new(loc, m.date, m.time)!; // resets .zone
};