commit b25b0cfc68280e58558d2cca37b92595652bbb27
parent 5fc0a4ff6b7700edd35692f605056afa28aecbdf
Author: Byron Torres <b@torresjrjr.com>
Date: Fri, 12 Nov 2021 22:16:23 +0000
add moment{} stuct and conversion functions
Signed-off-by: Byron Torres <b@torresjrjr.com>
Diffstat:
10 files changed, 207 insertions(+), 128 deletions(-)
diff --git a/chrono/calendar.ha b/chrono/calendar.ha
@@ -1,16 +0,0 @@
-use time;
-
-// Represents a system for ordering days as dates and eras.
-// Allows conversion between [[date]] types.
-export type calendar = struct {
- // TODO
- TODO: bool,
-};
-
-export type localdate = struct {
- nday: i64,
-};
-
-export type localtime = struct {
- ntime: time::duration,
-};
diff --git a/chrono/chronology.ha b/chrono/chronology.ha
@@ -1,17 +1,38 @@
use time;
-// Represents a [[timescale]]-[[calendar]] system for ordering events.
-// Allows conversion between [[datetime]] and [[time::instant]] types.
-//
-// Notes:
-// Needs rethinking. Initially, the idea was to have the possibility of multiple
-// plug-and-plug calendars, but since hare doesn't have objects, we need to
-// deisgn this another way. Probably, datetime:: will be solely ISO 8601
-// Proleptic Gregorian, with TAI, UTC, and UNIX, and then we'll have something
-// like datetime::chrono::* for alternative chronologies. 3rd party libraries
-// would be similar.
+// Represents a chronological system for ordering days as dates and eras
export type chronology = struct {
- timescale: timescale,
- calendar: calendar,
+ // MJD = Modified Julian Date
+ to_mjd: nullable *fn(day: moment) moment,
+ to_moment: nullable *fn(day: moment) moment,
+};
+
+// Represents a calendar system for ordering datea and eras
+export type calendar = struct {
+ // MJDN = Modified Julian Day Number
+ // RD = Rata Die
+ to_mjdn: nullable *fn(dn: daynum) daynum,
+ to_rd: nullable *fn(dn: daynum) daynum,
+};
+
+// Represents a moment in time on a calendar; essentially a datetime
+export type moment = struct {
+ day: daynum,
+ time: time::duration,
};
+// Represents a Rata Die, an ordinal day since a calendar epoch
+//
+// Notes:
+// aka:
+// - epochalday
+// - epochal
+// - nday
+export type daynum = i64;
+
+// Represents the Modified Julian Day Number calendar.
+// Not to be confused with the Julian calendar.
+export const MJDN: calendar = calendar { ... };
+
+// Represents the Modified Julian Date chronology.
+export const MJD: chronology = chronology { ... };
diff --git a/chrono/isocal/calendar.ha b/chrono/isocal/calendar.ha
@@ -0,0 +1,21 @@
+
+// // Represents a calendar system which supports datetimes
+// export type calendar = struct {
+// // chrono::calendar,
+// to_localdate: *conv_daynum_localdate,
+// to_daynum: *conv_localdate_daynum,
+// };
+//
+// export type conv_daynum_localdate = fn(dn: daynum) localdate;
+//
+// export type conv_localdate_daynum = fn(ld: localdate) daynum;
+//
+// export type chronology = struct {
+// // chrono::chronology,
+// to_datetime: *conv_moment_datetime,
+// to_moment: *conv_datetime_moment,
+// };
+//
+// export type conv_moment_datetime = fn(m: moment) datetime;
+//
+// export type conv_datetime_moment = fn(dt: datetime) moment;
diff --git a/chrono/isocal/date.ha b/chrono/isocal/date.ha
@@ -0,0 +1,55 @@
+use chrono;
+
+// Represents a ISO calendar date
+export type localdate = struct {
+ year: i64,
+ month: int,
+ day: int,
+};
+
+export fn conv_daynum_localdate(dn: chrono::daynum) localdate = {
+ const J = dn;
+ const j = 1401;
+ const y = 4716;
+ const B = 274277;
+ const C = -38;
+ const r = 4;
+ const v = 3;
+ const p = 1461;
+ const u = 5;
+ const w = 2;
+ const s = 153;
+ const n = 12;
+ const m = 2;
+
+ const f = J + j + (((4 * J + B) / 146097) * 3) / 4 + C;
+ const e = r * f + v;
+ const g = (e % p) / r;
+ const h = u * g + w;
+
+ const D = (h % s) / u + 1;
+ const M = ((h / s + m) % n) + 1;
+ const Y = (e / p) - y + (n + m - M) / n;
+
+ const ld = localdate {
+ year = Y,
+ month = M: int,
+ day = D: int,
+ };
+ return ld;
+};
+
+export fn conv_localdate_daynum(ld: localdate) chrono::daynum = {
+ const Y = ld.year;
+ const M = ld.month;
+ const D = ld.day;
+ const jdn = (
+ (1461 * (Y + 4000 + (M - 14) / 12)) / 4
+ + (367 * (M - 2 - 12 * ((M - 14) / 12))) / 12
+ - (3 * ((Y + 4900 + (M - 14) / 12) / 100)) / 4
+ + D
+ - 32075
+ );
+ const dn = jdn;
+ return dn;
+};
diff --git a/chrono/isocal/datetime.ha b/chrono/isocal/datetime.ha
@@ -1,20 +1,37 @@
use time;
-// Creates a new datetime, using a [[calendardate]].
+// Represents a ISO datetime
+//
+// Notes:
+// Java has good separation of types: A LocalDatetime, ZonedDatetime,
+// OffsetDatetime. Python instead reasons about datetimes as being
+// timezone-aware/naive. Here's I try to leaverage Hare's type system to combine
+// the two.
+//
+// Putting the date and time related fields into separate typed structs maybe
+// isn't a good idea (see `type localdate` below), but I still put it here
+// because localtime is often used on it's own, and it makes some sense to have
+// a datetime be composed of a date and time.
+export type datetime = struct {
+ date: localdate,
+ time: localtime,
+ loc: locality,
+};
+
+// Creates a new datetime
//
// // 1995 July 18th 09:16:00.000
-// datetime::new(1995, 07, 18, 9, 16, 0, 0, datetime::local)
-// chrono::iso::new(1995, 07, 18, 9, 16, 0, 0, chrono::iso::local)
+// isocal::new(1995, 07, 18, 9, 16, 0, 0, isocal::local)
//
// For alternative forms, assemble a datetime manually using the desired types.
export fn new(
year: i64,
- month: u8,
- day: u8,
- hour: u8,
- min: u8,
- sec: u8,
- nsec: u64,
+ month: int,
+ day: int,
+ hour: int,
+ min: int,
+ sec: int,
+ nsec: int,
loc: locality,
) datetime = datetime {
date = localdate {
@@ -40,34 +57,21 @@ export fn now() datetime = {
// TODO: figure out calendar arithmetics first
year = 1970,
month = 1,
- day = (i.sec / 86400): u8,
+ day = (i.sec / 86400): int,
},
time = localtime {
- hour = (i.sec / 3600): u8 % 24,
- min = (i.sec / 60): u8 % 60,
- sec = i.sec: u8 % 60,
- nsec = i.nsec: u64,
+ hour = (i.sec / 3600): int % 24,
+ min = (i.sec / 60): int % 60,
+ sec = i.sec: int % 60,
+ nsec = i.nsec: int,
},
// TODO: What to do here? How to get the timezone from
- // /etc/localtime? How to determine the system's timescale?
- // Assuming UTC may be sufficient.
+ // /etc/localtime or $TZ? How to determine the system's
+ // timescale? Assuming UTC may be sufficient.
loc = local,
};
return dt;
};
-// Normalizes all fields a datetime
-export fn normalize(dt: datetime) datetime = {
- validate(dt)!;
- // TODO
- return dt;
-};
-
-// Validates a datetime
-export fn validate(dt: datetime) (datetime | error) = {
- // TODO
- return dt;
-};
-
export type error = !void;
diff --git a/chrono/isocal/time.ha b/chrono/isocal/time.ha
@@ -0,0 +1,31 @@
+use time;
+
+// Represents a ISO time of day
+export type localtime = struct {
+ hour: int,
+ min: int,
+ sec: int,
+ nsec: int,
+};
+
+export fn conv_time_localtime(t: time::duration) localtime = {
+ const lt = localtime {
+ hour = (t / time::HOUR): int,
+ min = (t / time::MINUTE): int % 60,
+ sec = (t / time::SECOND): int % 60,
+ nsec = (t % time::SECOND): int,
+ };
+ return lt;
+};
+
+export fn conv_localtime_time(lt: localtime) time::duration = {
+ const t = (
+ (lt.hour * time::HOUR) +
+ (lt.min * time::MINUTE) +
+ (lt.sec * time::SECOND) +
+ (lt.nsec * time::NANOSECOND)
+ );
+ return t;
+};
+
+
diff --git a/chrono/isocal/types.ha b/chrono/isocal/types.ha
@@ -1,58 +1,19 @@
use time;
use chrono;
-// Represents a ISO datetime
-//
-// Notes:
-// Java has good separation of types: A LocalDatetime, ZonedDatetime,
-// OffsetDatetime. Python instead reasons about datetimes as being
-// timezone-aware/naive. Here's I try to leaverage Hare's type system to combine
-// the two.
-//
-// Putting the date and time related fields into separate typed structs maybe
-// isn't a good idea (see `type localdate` below), but I still put it here
-// because localtime is often used on it's own, and it makes some sense to have
-// a datetime be composed of a date and time.
-export type datetime = struct {
- date: localdate,
- time: localtime,
- loc: locality,
-};
-
-// Represents a ISO date
-export type localdate = struct {
- // days since calendar epoch
- epochday: i64,
-
- // ISO calendar date
- year: i64,
- month: u8,
- day: u8,
-
- // ISO week date
- weekyear: i64,
- week: u8,
- weekday: u8,
-
- // ISO ordinal date
- yearday: uint,
-};
-
-// Represents a ISO time of day
-export type localtime = struct {
- hour: u8,
- min: u8,
- sec: u8,
- nsec: u64,
-};
+// // Represents a timezone
+// // Allows conversion between datetimes and instances according to a timescale
+// export type timezone = struct {
+// chrono::timezone,
+// to_tz_utc: nullable *converter,
+// from_tz_utc: nullable *converter,
+// to_tz_tai: nullable *converter,
+// from_tz_tai: nullable *converter,
+// };
+
+export type converter = fn(dt: datetime) datetime;
// Represents the locality of a datetime
-//
-// Notes:
-// `timescale` may not meaningfully belong here. It's here because sometimes ISO
-// datetimes like "1999-05-13T12:30:45.125 UTC" exist as a human-readible form
-// of a UTC instant, using the ISO calendar, and where localtime.sec ranges only
-// from 0-59.
export type locality = (local | zoneoffset | timezone);
// Represents its associated datetime as local
@@ -66,14 +27,8 @@ export type local = void;
export type zoneoffset = time::duration;
// Represents a timezone; a political region with a ruleset regarding offsets
-//
-// Notes:
-// timezone types design needs a lot of thought. Enum is probably not a good
-// idea. Initially this was a `type enum str {}`, which may have been a worse
-// idea. Maybe we need a `fn tzdb(tz: str)` like other langs' libs.
-export type timezone = enum {
- UTC,
- EUROPE_LONDON,
- // ...
+export type timezone = struct {
+ timescale: chrono::timescale,
+ // TODO
+ // func...: *fn...
};
-
diff --git a/chrono/timescales.ha b/chrono/timescales.ha
@@ -2,10 +2,12 @@ use time;
// Represents a linear scale of time, with an epoch.
export type timescale = struct {
- to_tai: *fn(i: time::instant) []time::instant,
- from_tai: *fn(i: time::instant) []time::instant,
+ to_tai: *converter,
+ from_tai: *converter,
};
+export type converter = fn(i: time::instant) []time::instant;
+
// International Atomic Time
//
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -184,15 +184,17 @@ bytes() {
chrono() {
gen_srcs chrono \
chronology.ha \
- timescales.ha \
- calendar.ha
+ timescales.ha
gen_ssa chrono time
}
chrono_isocal() {
gen_srcs chrono::isocal \
+ types.ha \
+ calendar.ha \
datetime.ha \
- types.ha
+ date.ha \
+ time.ha
gen_ssa chrono::isocal chrono time
}
diff --git a/stdlib.mk b/stdlib.mk
@@ -722,8 +722,7 @@ $(HARECACHE)/bytes/bytes-any.ssa: $(stdlib_bytes_any_srcs) $(stdlib_rt) $(stdlib
# chrono (+any)
stdlib_chrono_any_srcs= \
$(STDLIB)/chrono/chronology.ha \
- $(STDLIB)/chrono/timescales.ha \
- $(STDLIB)/chrono/calendar.ha
+ $(STDLIB)/chrono/timescales.ha
$(HARECACHE)/chrono/chrono-any.ssa: $(stdlib_chrono_any_srcs) $(stdlib_rt) $(stdlib_time_$(PLATFORM))
@printf 'HAREC \t$@\n'
@@ -733,8 +732,11 @@ $(HARECACHE)/chrono/chrono-any.ssa: $(stdlib_chrono_any_srcs) $(stdlib_rt) $(std
# chrono::isocal (+any)
stdlib_chrono_isocal_any_srcs= \
+ $(STDLIB)/chrono/isocal/types.ha \
+ $(STDLIB)/chrono/isocal/calendar.ha \
$(STDLIB)/chrono/isocal/datetime.ha \
- $(STDLIB)/chrono/isocal/types.ha
+ $(STDLIB)/chrono/isocal/date.ha \
+ $(STDLIB)/chrono/isocal/time.ha
$(HARECACHE)/chrono/isocal/chrono_isocal-any.ssa: $(stdlib_chrono_isocal_any_srcs) $(stdlib_rt) $(stdlib_chrono_$(PLATFORM)) $(stdlib_time_$(PLATFORM))
@printf 'HAREC \t$@\n'
@@ -2664,8 +2666,7 @@ $(TESTCACHE)/bytes/bytes-any.ssa: $(testlib_bytes_any_srcs) $(testlib_rt) $(test
# chrono (+any)
testlib_chrono_any_srcs= \
$(STDLIB)/chrono/chronology.ha \
- $(STDLIB)/chrono/timescales.ha \
- $(STDLIB)/chrono/calendar.ha
+ $(STDLIB)/chrono/timescales.ha
$(TESTCACHE)/chrono/chrono-any.ssa: $(testlib_chrono_any_srcs) $(testlib_rt) $(testlib_time_$(PLATFORM))
@printf 'HAREC \t$@\n'
@@ -2675,8 +2676,11 @@ $(TESTCACHE)/chrono/chrono-any.ssa: $(testlib_chrono_any_srcs) $(testlib_rt) $(t
# chrono::isocal (+any)
testlib_chrono_isocal_any_srcs= \
+ $(STDLIB)/chrono/isocal/types.ha \
+ $(STDLIB)/chrono/isocal/calendar.ha \
$(STDLIB)/chrono/isocal/datetime.ha \
- $(STDLIB)/chrono/isocal/types.ha
+ $(STDLIB)/chrono/isocal/date.ha \
+ $(STDLIB)/chrono/isocal/time.ha
$(TESTCACHE)/chrono/isocal/chrono_isocal-any.ssa: $(testlib_chrono_isocal_any_srcs) $(testlib_rt) $(testlib_chrono_$(PLATFORM)) $(testlib_time_$(PLATFORM))
@printf 'HAREC \t$@\n'