hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 3d3b1b2d34e1ed8fc4d9719efeb8032ec0ca3715
parent c5f72d0cb5a18f3bdbe63cb8cdf2beb69a5fe376
Author: Byron Torres <b@torresjrjr.com>
Date:   Fri, 28 Jan 2022 19:16:40 +0000

make new() use given zoffset

Signed-off-by: Byron Torres <b@torresjrjr.com>

Diffstat:
Mdatetime/chronology.ha | 86++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Mdatetime/datetime.ha | 37++++++++++++++++++++++++++++++-------
Mtime/chrono/chronology.ha | 4++++
Mtime/chrono/timezone.ha | 2+-
4 files changed, 94 insertions(+), 35 deletions(-)

diff --git a/datetime/chronology.ha b/datetime/chronology.ha @@ -2,14 +2,58 @@ use errors; use time; use time::chrono; +// Fucntions renamed here to avoid namespace conflict, like in the parameters of +// the [[new]] function. + // Returns a [[datetime]]'s number of days since the calendar epoch 0000-01-01 -export fn epochal(dt: *datetime) chrono::epochal = { +export fn epochal(dt: *datetime) chrono::epochal = _epochal(dt); + +// Returns a [[datetime]]'s era +export fn era(dt: *datetime) int = _era(dt); + +// Returns a [[datetime]]'s year +export fn year(dt: *datetime) int = _year(dt); + +// Returns a [[datetime]]'s month of the year +export fn month(dt: *datetime) int = _month(dt); + +// Returns a [[datetime]]'s day of the month +export fn day(dt: *datetime) int = _day(dt); + +// Returns a [[datetime]]'s day of the week +export fn weekday(dt: *datetime) int = _weekday(dt); + +// Returns a [[datetime]]'s ordinal day of the year +export fn yearday(dt: *datetime) int = _yearday(dt); + +// Returns a [[datetime]]'s ISO week-numbering year +export fn isoweekyear(dt: *datetime) int = _isoweekyear(dt); + +// Returns a [[datetime]]'s Gregorian week +export fn week(dt: *datetime) int = _week(dt); + +// Returns a [[datetime]]'s ISO week +export fn isoweek(dt: *datetime) int = _isoweek(dt); + +// Returns a [[datetime]]'s hour of the day +export fn hour(dt: *datetime) int = _hour(dt); + +// Returns a [[datetime]]'s minute of the hour +export fn min(dt: *datetime) int = _min(dt); + +// Returns a [[datetime]]'s second of the minute +export fn sec(dt: *datetime) int = _sec(dt); + +// Returns a [[datetime]]'s nanosecond of the second +export fn nsec(dt: *datetime) int = _nsec(dt); + + +fn _epochal(dt: *datetime) chrono::epochal = { const ldt = transform(*dt, dt.zone.zoffset); return ldt.date - EPOCHAL_GREGORIAN; }; -// Returns a [[datetime]]'s era -export fn era(dt: *datetime) int = { +fn _era(dt: *datetime) int = { match (dt.era) { case void => if (dt.year is void) { @@ -22,8 +66,7 @@ export fn era(dt: *datetime) int = { }; }; -// Returns a [[datetime]]'s year -export fn year(dt: *datetime) int = { +fn _year(dt: *datetime) int = { const ldt = transform(*dt, dt.zone.zoffset); match (dt.year) { case void => @@ -37,8 +80,7 @@ export fn year(dt: *datetime) int = { }; }; -// Returns a [[datetime]]'s month of the year -export fn month(dt: *datetime) int = { +fn _month(dt: *datetime) int = { const ldt = transform(*dt, dt.zone.zoffset); match (dt.month) { case void => @@ -52,8 +94,7 @@ export fn month(dt: *datetime) int = { }; }; -// Returns a [[datetime]]'s day of the month -export fn day(dt: *datetime) int = { +fn _day(dt: *datetime) int = { const ldt = transform(*dt, dt.zone.zoffset); match (dt.day) { case void => @@ -67,8 +108,7 @@ export fn day(dt: *datetime) int = { }; }; -// Returns a [[datetime]]'s day of the week -export fn weekday(dt: *datetime) int = { +fn _weekday(dt: *datetime) int = { const ldt = transform(*dt, dt.zone.zoffset); match (dt.weekday) { case void => @@ -79,8 +119,7 @@ export fn weekday(dt: *datetime) int = { }; }; -// Returns a [[datetime]]'s ordinal day of the year -export fn yearday(dt: *datetime) int = { +fn _yearday(dt: *datetime) int = { match (dt.yearday) { case void => if (dt.year is void) { @@ -103,8 +142,7 @@ export fn yearday(dt: *datetime) int = { }; }; -// Returns a [[datetime]]'s ISO week-numbering year -export fn isoweekyear(dt: *datetime) int = { +fn _isoweekyear(dt: *datetime) int = { match (dt.isoweekyear) { case void => if (dt.year is void) { @@ -131,8 +169,7 @@ export fn isoweekyear(dt: *datetime) int = { }; }; -// Returns a [[datetime]]'s Gregorian week -export fn week(dt: *datetime) int = { +fn _week(dt: *datetime) int = { match (dt.week) { case void => if (dt.yearday is void) { @@ -151,8 +188,7 @@ export fn week(dt: *datetime) int = { }; }; -// Returns a [[datetime]]'s ISO week -export fn isoweek(dt: *datetime) int = { +fn _isoweek(dt: *datetime) int = { match (dt.isoweek) { case void => if (dt.year is void) { @@ -179,8 +215,7 @@ export fn isoweek(dt: *datetime) int = { }; }; -// Returns a [[datetime]]'s hour of the day -export fn hour(dt: *datetime) int = { +fn _hour(dt: *datetime) int = { const ldt = transform(*dt, dt.zone.zoffset); match (dt.hour) { case void => @@ -195,8 +230,7 @@ export fn hour(dt: *datetime) int = { }; }; -// Returns a [[datetime]]'s minute of the hour -export fn min(dt: *datetime) int = { +fn _min(dt: *datetime) int = { const ldt = transform(*dt, dt.zone.zoffset); match (dt.min) { case void => @@ -211,8 +245,7 @@ export fn min(dt: *datetime) int = { }; }; -// Returns a [[datetime]]'s second of the minute -export fn sec(dt: *datetime) int = { +fn _sec(dt: *datetime) int = { const ldt = transform(*dt, dt.zone.zoffset); match (dt.sec) { case void => @@ -227,8 +260,7 @@ export fn sec(dt: *datetime) int = { }; }; -// Returns a [[datetime]]'s nanosecond of the second -export fn nsec(dt: *datetime) int = { +fn _nsec(dt: *datetime) int = { const ldt = transform(*dt, dt.zone.zoffset); match (dt.nsec) { case void => diff --git a/datetime/datetime.ha b/datetime/datetime.ha @@ -81,7 +81,9 @@ fn init() datetime = datetime { // the local time 02:30 was observed twice (00:30 UTC & 01:30 UTC), // as the clock jumped back 1 hour from 03:00 CEST to 02:00 CET. // -// TODO: implement as described. +// TODO: Implement as described. +// TODO: Allow and correct for overflowing units like Golang? Most likely not. +// Defeats the purpose of validation at creation. I see little benefit. export fn new( year: int, month: int, @@ -101,10 +103,14 @@ export fn new( // TODO: should this be `nullable *chrono::timezone`? // would interface better with other code, i presume. loc: (*chrono::timezone | void), + +// TODO: improve variety of errors. +// `invaliddatetime = !void` ? +// `invaliddatetime = !datetime::builder` ? ) (datetime | errors::invalid) = { // TODO: set the correct values according to the given zoffset and // locality/timezone. - const m = chrono::new( + let m = chrono::new( calc_epochal_from_ymd(year, month, day)?, calc_time_from_hmsn(hour, min, sec, nsec)?, if (loc is void) chrono::local else loc: *chrono::timezone, @@ -112,16 +118,33 @@ export fn new( // figuring out what zone this moment observes if (zoffset is time::duration) { - // transform inversely to the moment that would transform to the - // current moment, then perform a zone lookup. - void; + // transform inversely to the moment that would transform back + // to the current moment, then perform a zone lookup. + m = chrono::transform(m, -(zoffset as time::duration)); + chrono::lookupzone(&m); } else { // just perform a zone lookup, then try that zone and the - // neighboring zones. + // zones that are observed before and after. + //const z0 = chrono::lookupzone(*m); + //m = chrono::transform(m, -z0.zoffset); void; }; - return from_moment(m); + const dt = from_moment(m); + if ( + year == _year(&dt) + && month == _month(&dt) + && day == _day(&dt) + && hour == _hour(&dt) + && min == _min(&dt) + && sec == _sec(&dt) + && nsec == _nsec(&dt) + ) { + void; + } else { + return errors::invalid; + }; + return dt; }; // Returns a [[datetime]] of the immediate system time diff --git a/time/chrono/chronology.ha b/time/chrono/chronology.ha @@ -26,6 +26,10 @@ export type moment = struct { export type epochal = i64; // Creates a new [[moment]] +// +// TODO: Check for `time` value bounds overflow. Should we: +// a. Return an error? +// b. "Correct" by overflowing? See datetime::new(); export fn new(date: epochal, time: time::duration, loc: locality) moment = { const m = moment { date = date, diff --git a/time/chrono/timezone.ha b/time/chrono/timezone.ha @@ -129,7 +129,7 @@ export fn lookupzone(m: *moment) zone = { // if we've reached the end of the locality's transitions, try its // posix_extend string // - // TODO: important + // TODO: Unfinished; complete. if (lo == len(m.loc.transitions) - 1 && m.loc.posix_extend != "") { void; };