commit 0f8c679a2a43df23ed3074466df048c173553831
parent 96a3c04ddb1201e7e13cb51d40f3e6bf1e41f79c
Author: Byron Torres <b@torresjrjr.com>
Date: Sat, 8 Jan 2022 02:05:33 +0000
etch new timezone functions
Signed-off-by: Byron Torres <b@torresjrjr.com>
Diffstat:
5 files changed, 78 insertions(+), 37 deletions(-)
diff --git a/datetime/calendar.ha b/datetime/calendar.ha
@@ -226,6 +226,10 @@ export fn min(dt: *datetime) int = {
// Evaluates a [[datetime]]'s second of the minute
export fn sec(dt: *datetime) int = {
+ // TODO: localize datetimes for all functions here. Use localised date
+ // and time in place of the given datetime's date and time.
+ const ldt = chrono::localize(to_moment(*dt));
+
match (dt.sec) {
case void =>
const hmsn = calc_hmsn(dt.time: time::duration);
diff --git a/datetime/datetime.ha b/datetime/datetime.ha
@@ -31,7 +31,6 @@ export type datetime = struct {
fn init() datetime = datetime {
date = 0,
time = 0,
- zone = chrono::zone{ ... },
loc = chrono::local,
era = void,
@@ -63,13 +62,12 @@ export fn new(
min: int,
sec: int,
nsec: int,
- zoffset: chrono::zoffset,
+ zoffset: time::duration,
loc: (*chrono::timezone | void),
) (datetime | errors::invalid) = {
const dt = datetime {
date = calc_epochal_from_ymd(year, month, day)?,
time = calc_time_from_hmsn(hour, min, sec, nsec)?,
- zone = chrono::zone{ zoffset = zoffset, ... },
loc = if (loc is void) chrono::local else loc: *chrono::timezone,
era = void,
@@ -95,7 +93,6 @@ export fn clone(dt: datetime) datetime = {
return datetime {
date = dt.date,
time = dt.time,
- zone = dt.zone,
loc = dt.loc,
era = dt.era,
@@ -140,7 +137,6 @@ export fn now() datetime = {
// TODO: What to do here? How to get the timezone from
// /etc/localtime or $TZ? How to determine the system's
// timescale? Assuming UTC may be sufficient.
- zone = chrono::zone{ ... },
loc = chrono::local,
era = void,
@@ -257,3 +253,11 @@ export type method = enum uint {
// all methods, in order as presented here
ALL = YMD | YD | YWD | ISOYWD,
};
+
+export fn to_moment(dt: datetime) chrono::moment = {
+ return chrono::moment {
+ date = dt.date,
+ time = dt.time,
+ loc = dt.loc,
+ };
+};
diff --git a/datetime/timezone.ha b/datetime/timezone.ha
@@ -15,7 +15,8 @@ export fn tzdb(name: str) chrono::timezone = {
// "CET", "Central European Time" timezone
export const TZ_CET: chrono::timezone = chrono::timezone {
name = "CET",
- scale = &chrono::UTC,
+ timescale = &chrono::UTC,
+ daylength = chrono::EARTH_DAY,
zones = [
chrono::zone {
zoffset = 1 * time::HOUR,
@@ -30,5 +31,5 @@ export const TZ_CET: chrono::timezone = chrono::timezone {
dst = true,
},
],
- trans = [],
+ transitions = [],
};
diff --git a/time/chrono/chronology.ha b/time/chrono/chronology.ha
@@ -4,10 +4,11 @@ use time;
export type moment = struct {
date: epochal,
time: time::duration,
- zone: zone,
loc: locality,
};
// An ordinal day (on Earth or otherwise) since the Hare epoch (zeroth day)
// 1970-01-01
export type epochal = i64;
+
+export def EARTH_DAY: time::duration = 86400 * time::SECOND;
diff --git a/time/chrono/timezone.ha b/time/chrono/timezone.ha
@@ -2,33 +2,45 @@ use time;
export type locality = *timezone;
-// The zoneinfo of a datetime
-export type zoneinfo = struct {
- zabbrev: str, // %Z
- zoffset: zoffset, // %z
-};
+// A timezone; a political region with a ruleset regarding offsets for
+// calculating localized civil time
+export type timezone = struct {
+ // The textual identifier ("Europe/Amsterdam")
+ name: str,
-// A simple, constant zone offset
-export type zoffset = time::duration;
+ // The base timescale (chrono::UTC)
+ timescale: *timescale,
-// A timezone; a political region with a ruleset regarding offsets
-export type timezone = struct {
- name: str, // "Europe/Amsterdam"
- scale: *timescale,
+ // The duration of a day in this timezone (24 * time::HOUR)
+ // TODO: Make this a function? Some planets may have greater rotational
+ // acceleration, meaning daylength would change over time.
+ daylength: time::duration,
+
+ // The possible temporal zones a locality with this timezone can observe
+ // (CET, CEST, ...)
zones: []zone,
- trans: []zonetran,
+
+ // The transitions between this timezone's zones
+ transitions: []transition,
};
-// A conditional offset, dependant on the time of year
+// A timezone state, with an offset for calculating localized civil time
export type zone = struct {
- zoffset: zoffset, // 2 * time::HOUR
- name: str, // "Central European Summer Time"
- abbrev: str, // "CEST"
+ // The offset from the normal timezone (2 * time::HOUR)
+ zoffset: time::duration,
+
+ // The full descriptive name ("Central European Summer Time")
+ name: str,
+
+ // The abbreviated name ("CEST")
+ abbrev: str,
+
+ // Indicator of Daylight Saving Time
dst: bool, // true
};
-// A timezone transition
-export type zonetran = struct {
+// A timezone transition between two zones
+export type transition = struct {
when: time::instant,
zoneindex: int,
};
@@ -36,15 +48,31 @@ export type zonetran = struct {
// A destructured dual std/dst POSIX timezone. See tzset(3).
type tzname = struct {
std_name: str,
- std_offset: zoffset,
+ std_offset: time::duration,
dst_name: str,
- dst_offset: zoffset,
+ dst_offset: time::duration,
dst_start: str,
dst_starttime: str,
dst_end: str,
dst_endtime: str,
};
+// Returns a fictitious moment which assumes it's own locality is the normal
+// locality. The given timezone is consulted to find the current zone, and its
+// offset is applied to the new .date and .time fields.
+export fn localize(m: moment) moment = {
+ const zone = lookupzone(m);
+ const newtime = m.time + zone.zoffset;
+ m.time = newtime % m.loc.daylength;
+ m.date += (newtime / m.loc.daylength);
+ return m;
+};
+
+export fn lookupzone(m: moment) zone = {
+ // TODO: search through m.loc.trans using m.date and m.time
+ return zone{ ... };
+};
+
// The system's local timezone, set during initialisation
export const local: *timezone = &TZ_local;
@@ -53,7 +81,9 @@ export const local: *timezone = &TZ_local;
return;
};
const TZ_local: timezone = timezone {
- scale = &UTC,
+ name = "",
+ timescale = &UTC,
+ daylength = EARTH_DAY,
zones = [
zone {
zoffset = 0 * time::SECOND,
@@ -62,15 +92,16 @@ const TZ_local: timezone = timezone {
dst = false,
},
],
- trans = [],
- name = "",
+ transitions = [],
};
// The UTC "Zulu" timezone
export const UTC_Z: *timezone = &TZ_UTC;
const TZ_UTC: timezone = timezone {
- scale = &UTC,
+ name = "Etc/UTC",
+ timescale = &UTC,
+ daylength = EARTH_DAY,
zones = [
zone {
zoffset = 0 * time::SECOND,
@@ -79,15 +110,16 @@ const TZ_UTC: timezone = timezone {
dst = false,
},
],
- trans = [],
- name = "Etc/UTC",
+ transitions = [],
};
// The TAI "Zulu" timezone
export const TAI_Z: *timezone = &TZ_TAI;
const TZ_TAI: timezone = timezone {
- scale = &TAI,
+ name = "",
+ timescale = &TAI,
+ daylength = EARTH_DAY,
zones = [
zone {
zoffset = 0 * time::SECOND,
@@ -96,6 +128,5 @@ const TZ_TAI: timezone = timezone {
dst = false,
},
],
- trans = [],
- name = "",
+ transitions = [],
};