commit 2eab33f08315016a6d5edaf5021555cf6b68aa0b
parent eb62889ab2cdea07360fb16db1c10a9ea981fc7e
Author: Bor Grošelj Simić <bgs@turminal.net>
Date: Sun, 30 Apr 2023 00:35:08 +0200
datetime: parse: fix %z scanning, add test
(rune | void) was incorrectly compared to rune and harec didn't complain
because of #787.
References: https://todo.sr.ht/~sircmpwn/hare/787
Signed-off-by: Bor Grošelj Simić <bgs@turminal.net>
Diffstat:
1 file changed, 24 insertions(+), 12 deletions(-)
diff --git a/datetime/parse.ha b/datetime/parse.ha
@@ -197,25 +197,33 @@ fn scan_int(iter: *strings::iterator, n: size, pad: bool) (int | failure) = {
// Z
// z
// +nn:nn
+// +nnnn
// -nn:nn
+// -nnnn
//
fn scan_zo(iter: *strings::iterator) (time::duration | failure) = {
- const rest = strings::iterstr(iter);
- if (strings::hasprefix(rest, 'Z') || strings::hasprefix(rest, 'z')) {
+ const r = match (strings::next(iter)) {
+ case void =>
+ return failure;
+ case let r: rune =>
+ yield r;
+ };
+ if (r == 'Z' || r == 'z') {
return 0;
- } else {
- const prefix = strings::next(iter);
- let zo = scan_int(iter, 2, false)? * time::HOUR;
- const rest = strings::iterstr(iter);
- if (strings::hasprefix(rest, ":")) {
+ };
+ let zo = scan_int(iter, 2, false)? * time::HOUR;
+ match (strings::next(iter)) {
+ case void => void;
+ case let r: rune =>
+ if (r == ':') {
strings::next(iter);
};
- zo += scan_int(iter, 2, false)? * time::MINUTE;
- if (prefix == '-') {
- zo *= -1;
- };
- return zo;
};
+ zo += scan_int(iter, 2, false)? * time::MINUTE;
+ if (r == '-') {
+ zo *= -1;
+ };
+ return zo;
};
// Scans and parses locality names, made of printable characters.
@@ -364,6 +372,10 @@ fn scan_str(iter: *strings::iterator) (str | failure) = {
assert(parse(&v, "%z", "+0100") is void , "%z: parsefail");
assert(v.zoff is i64 , "%z: void");
assert(v.zoff as i64 == 1 * time::HOUR , "%z: incorrect");
+ let v = newvirtual();
+ assert(parse(&v, "%z", "+01:00") is void , "%z: parsefail");
+ assert(v.zoff is i64 , "%z: void");
+ assert(v.zoff as i64 == 1 * time::HOUR , "%z: incorrect");
let v = newvirtual();
assert(parse(&v, "%Z", "CET") is void , "%Z: parsefail");