~turminal/hare

95933b0482f4b61613ff3b21878c4d65c09b9f31 — Curtis Arthaud 6 months ago e787950
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>
3 files changed, 72 insertions(+), 37 deletions(-)

M time/date/format.ha
M time/date/parse.ha
M time/date/virtual.ha
M time/date/format.ha => time/date/format.ha +4 -0
@@ 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"),

M time/date/parse.ha => time/date/parse.ha +4 -0
@@ 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' =>

M time/date/virtual.ha => time/date/virtual.ha +64 -37
@@ 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