commit 95933b0482f4b61613ff3b21878c4d65c09b9f31
parent e787950a7c64864630eee109dd5bcd5fa7aa2963
Author: Curtis Arthaud <uku82@gmx.fr>
Date: Wed, 10 Apr 2024 11:04:04 +0200
time::date: add v.century, v.year100
Parsing something like "%y-%m-%d" is now easier.
Co-authored-by: Byron Torres <b@torresjrjr.com>
Signed-off-by: Byron Torres <b@torresjrjr.com>
Signed-off-by: Curtis Arthaud <uku82@gmx.fr>
Diffstat:
3 files changed, 72 insertions(+), 37 deletions(-)
diff --git a/time/date/format.ha b/time/date/format.ha
@@ -128,6 +128,8 @@ fn fmtout(out: io::handle, r: rune, d: *date) (size | io::error) = {
return fmt::fprint(out, MONTHS_SHORT[_month(d) - 1]);
case 'B' =>
return fmt::fprint(out, MONTHS[_month(d) - 1]);
+ case 'C' =>
+ return fmt::fprintf(out, "{:.2}", _year(d) / 100);
case 'd' =>
return fmt::fprintf(out, "{:.2}", _day(d));
case 'e' =>
@@ -197,6 +199,7 @@ fn fmtout(out: io::handle, r: rune, d: *date) (size | io::error) = {
// %A -- The full name of the day of the week.
// %b -- The abbreviated name of the month.
// %B -- The full name of the month.
+// %C -- The century digits (all but the last two digits of the year).
// %d -- The day of the month (decimal, range 01 to 31).
// %e -- The day of the month (decimal, range 1 to 31), left-padded space.
// %F -- The full date, equivalent to %Y-%m-%d
@@ -272,6 +275,7 @@ export fn format(
// year
("%Y", "1994"),
("%y", "94"),
+ ("%C", "19"),
// month name
("%b", "Jan"),
("%B", "January"),
diff --git a/time/date/parse.ha b/time/date/parse.ha
@@ -74,6 +74,8 @@ fn parse_specifier(
v.month = scan_for(iter, MONTHS_SHORT...)? + 1;
case 'B' =>
v.month = scan_for(iter, MONTHS...)? + 1;
+ case 'C' =>
+ v.century = scan_int(iter, 2)?;
case 'd', 'e' =>
v.day = scan_int(iter, 2)?;
case 'F' =>
@@ -118,6 +120,8 @@ fn parse_specifier(
v.weekday = scan_int(iter, 1)? - 1;
case 'W' =>
v.week = scan_int(iter, 2)?;
+ case 'y' =>
+ v.year100 = scan_int(iter, 2)?;
case 'Y' =>
v.year = scan_int(iter, 4)?;
case 'z' =>
diff --git a/time/date/virtual.ha b/time/date/virtual.ha
@@ -52,6 +52,10 @@ export type virtual = struct {
zoff: (void | time::duration),
// zone abbreviation
zabbr: (void | str),
+ // all but the last two digits of the year
+ century: (void | int),
+ // the last two digits of the year
+ year100: (void | int),
// hour of 12 hour clock
hour12: (void | int),
// AM/PM (false/true)
@@ -89,6 +93,8 @@ export fn newvirtual() virtual = virtual {
locname = void,
zoff = void,
zabbr = void,
+ century = void,
+ year100 = void,
hour12 = void,
ampm = void,
};
@@ -133,15 +139,19 @@ export fn newvirtual() virtual = virtual {
//
// An empty .daydate depends on:
//
-// - .year, .month, .day
-// - .year, .yearday
-// - .year, .week, .weekday
+// - .year*, .month, .day
+// - .year*, .yearday
+// - .year*, .week, .weekday
// - .isoweekyear, .isoweek, .weekday
//
// An empty .daytime depends on:
//
// - .hour*, .minute, .second, .nanosecond
//
+// An empty .year depends on:
+//
+// - .century, .year100
+//
// An empty .hour depends on:
//
// - .hour12, .ampm
@@ -190,40 +200,57 @@ export fn realize(
// determine .daydate
if (v.daydate is i64) {
void;
- } else if (
- v.year is int &&
- v.month is int &&
- v.day is int
- ) {
- v.daydate = calc_daydate__ymd(
- v.year as int,
- v.month as int,
- v.day as int,
- )?;
- } else if (
- v.year is int &&
- v.yearday is int
- ) {
- v.daydate = calc_daydate__yd(
- v.year as int,
- v.yearday as int,
- )?;
- } else if (
- v.year is int &&
- v.week is int &&
- v.weekday is int
- ) {
- v.daydate = calc_daydate__ywd(
- v.year as int,
- v.week as int,
- v.weekday as int,
- )?;
- } else if (false) {
- // TODO: calendar.ha: calc_daydate__isoywd()
- void;
- } else {
- // cannot deduce daydate
- lacking |= insufficient::DAYDATE;
+ } else :daydate {
+ const year =
+ if (v.year is int) {
+ yield v.year as int;
+ } else if (v.century is int && v.year100 is int) {
+ let cc = v.century as int;
+ let yy = v.year100 as int;
+ if (yy < 0 || yy > 99) {
+ return invalid;
+ };
+ yield cc * 100 + yy;
+ } else {
+ lacking |= lack::DAYDATE;
+ yield :daydate;
+ };
+
+ if (
+ v.year is int &&
+ v.month is int &&
+ v.day is int
+ ) {
+ v.daydate = calc_daydate__ymd(
+ v.year as int,
+ v.month as int,
+ v.day as int,
+ )?;
+ } else if (
+ v.year is int &&
+ v.yearday is int
+ ) {
+ v.daydate = calc_daydate__yd(
+ v.year as int,
+ v.yearday as int,
+ )?;
+ } else if (
+ v.year is int &&
+ v.week is int &&
+ v.weekday is int
+ ) {
+ v.daydate = calc_daydate__ywd(
+ v.year as int,
+ v.week as int,
+ v.weekday as int,
+ )?;
+ } else if (false) {
+ // TODO: calendar.ha: calc_daydate__isoywd()
+ void;
+ } else {
+ // cannot deduce daydate
+ lacking |= insufficient::DAYDATE;
+ };
};
// determine .daytime