commit a3a879bcc37bca30406782da8bf32ab11182068c
parent 4cc6365d9adcc291e7352e652e035371cd9b9cec
Author: Byron Torres <b@torresjrjr.com>
Date: Thu, 22 Feb 2024 23:44:03 +0000
time::date: make type insufficient an enum
Signed-off-by: Byron Torres <b@torresjrjr.com>
Diffstat:
2 files changed, 32 insertions(+), 8 deletions(-)
diff --git a/time/date/error.ha b/time/date/error.ha
@@ -2,6 +2,7 @@
// (c) Hare authors <https://harelang.org>
use fmt;
+use strings;
// All possible errors returned from [[date]].
export type error = !(insufficient | invalid | parsefail);
@@ -10,8 +11,17 @@ export type error = !(insufficient | invalid | parsefail);
// statically allocated.
export fn strerror(err: error) const str = {
match (err) {
- case insufficient =>
- return "Insufficient date information";
+ case let lack: insufficient =>
+ static let buf: [92]u8 = [0...];
+ return strings::rtrim(fmt::bsprint(buf,
+ "Insufficient date information, could not calculate:",
+ if (lack & insufficient::DAYDATE: u8 == 0) "" else
+ "daydate",
+ if (lack & insufficient::DAYTIME: u8 == 0) "" else
+ "time-of-day",
+ if (lack & insufficient::ZOFF: u8 == 0) "" else
+ "zone-offset",
+ ));
case invalid =>
return "Invalid date information";
case let rn: parsefail =>
diff --git a/time/date/virtual.ha b/time/date/virtual.ha
@@ -5,7 +5,13 @@ use time;
use time::chrono;
// A [[virtual]] does not have enough information to create a valid [[date]].
-export type insufficient = !void;
+export type insufficient = !lack; // TODO: drop alias workaround
+
+export type lack = enum u8 {
+ DAYDATE = 1 << 0, // could not infer daydate
+ DAYTIME = 1 << 1, // could not infer time-of-day
+ ZOFF = 1 << 2, // could not infer zone offset
+};
// A virtual date; a [[date]] wrapper interface, which represents a date of
// uncertain validity. Its fields need not be valid observed chronological
@@ -118,6 +124,8 @@ export fn realize(
v: virtual,
locs: chrono::locality...
) (date | insufficient | invalid) = {
+ let lacking = 0u8;
+
// determine .daydate
if (v.daydate is i64) {
void;
@@ -154,13 +162,13 @@ export fn realize(
void;
} else {
// cannot deduce daydate
- return insufficient;
+ lacking |= insufficient::DAYDATE;
};
// determine .daytime
if (v.daytime is i64) {
void;
- } else {
+ } else :nodaytime {
const hour = if (v.hour is int) {
yield v.hour as int;
} else if (v.halfhour is int && v.ampm is bool) {
@@ -168,7 +176,8 @@ export fn realize(
const pm = v.ampm as bool;
yield if (pm) hr * 2 else hr;
} else {
- return insufficient;
+ lacking |= insufficient::DAYTIME;
+ yield :nodaytime;
};
if (
@@ -182,8 +191,9 @@ export fn realize(
v.second as int,
v.nanosecond as int,
)?;
+ lacking |= 0u8;
} else {
- return insufficient;
+ lacking |= insufficient::DAYTIME;
};
};
@@ -191,7 +201,7 @@ export fn realize(
if (v.zoff is i64) {
void;
} else {
- return insufficient;
+ lacking |= insufficient::ZOFF;
};
// determine .loc (defaults to time::chrono::UTC)
@@ -208,6 +218,10 @@ export fn realize(
};
};
+ if (lacking != 0u8) {
+ return lacking: insufficient;
+ };
+
// determine .sec, .nsec
const d = from_moment(chrono::from_datetime(
v.loc,