intrinsics rewritten without ++, --, etc
This commit is contained in:
343
time.cm
343
time.cm
@@ -1,204 +1,211 @@
|
||||
// epoch = 0000-01-01 00:00:00 +0000
|
||||
var time = this;
|
||||
var time = this
|
||||
|
||||
/* -------- host helpers -------------------------------------------------- */
|
||||
var now = time.now; // seconds since Misty epoch (C stub)
|
||||
var computer_zone = time.computer_zone; // integral hours, no DST
|
||||
var computer_dst = time.computer_dst; // true ↔ DST in effect
|
||||
var now = time.now
|
||||
var computer_zone = time.computer_zone
|
||||
var computer_dst = time.computer_dst
|
||||
|
||||
delete time.now;
|
||||
delete time.computer_zone;
|
||||
delete time.computer_dst;
|
||||
delete time.now
|
||||
delete time.computer_zone
|
||||
delete time.computer_dst
|
||||
|
||||
/* -------- units & static tables ----------------------------------------- */
|
||||
|
||||
time.second = 1;
|
||||
time.minute = 60;
|
||||
time.hour = 3_600;
|
||||
time.day = 86_400;
|
||||
time.week = 604_800;
|
||||
time.second = 1
|
||||
time.minute = 60
|
||||
time.hour = 3600
|
||||
time.day = 86400
|
||||
time.week = 604800
|
||||
|
||||
time.weekdays = [
|
||||
"Sunday", "Monday", "Tuesday",
|
||||
"Wednesday", "Thursday", "Friday", "Saturday"
|
||||
];
|
||||
]
|
||||
|
||||
time.monthstr = [
|
||||
"January", "February", "March", "April", "May", "June",
|
||||
"July", "August", "September", "October", "November", "December"
|
||||
];
|
||||
]
|
||||
|
||||
time.epoch = 1970;
|
||||
time.epoch = 1970
|
||||
|
||||
/* ratios (kept K&R-style) */
|
||||
time.hour2minute = function() { return time.hour / time.minute; };
|
||||
time.day2hour = function() { return time.day / time.hour; };
|
||||
time.minute2second = function() { return time.minute / time.second; };
|
||||
time.week2day = function() { return time.week / time.day; };
|
||||
time.hour2minute = function() { return time.hour / time.minute }
|
||||
time.day2hour = function() { return time.day / time.hour }
|
||||
time.minute2second = function() { return time.minute / time.second }
|
||||
time.week2day = function() { return time.week / time.day }
|
||||
|
||||
/* leap-year helpers */
|
||||
time.yearsize = function yearsize(y)
|
||||
{
|
||||
if (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) return 366;
|
||||
return 365;
|
||||
};
|
||||
time.isleap = function(y) { return time.yearsize(y) == 366; };
|
||||
time.yearsize = function yearsize(y) {
|
||||
if (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) return 366
|
||||
return 365
|
||||
}
|
||||
time.isleap = function(y) { return time.yearsize(y) == 366 }
|
||||
|
||||
/* timecode utility */
|
||||
time.timecode = function(t, fps = 24)
|
||||
{
|
||||
var s = whole(t);
|
||||
var frac = t - s;
|
||||
return `${s}:${whole(frac * fps)}`;
|
||||
};
|
||||
|
||||
/* per-month day counts (non-leap) */
|
||||
time.monthdays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
||||
|
||||
// convert seconds-since-epoch → broken-down record
|
||||
function time_record(num = now(),
|
||||
zone = computer_zone(),
|
||||
dst = computer_dst())
|
||||
{
|
||||
if (is_object(num)) return num;
|
||||
|
||||
var monthdays = array(time.monthdays);
|
||||
var rec = {
|
||||
second : 0, minute : 0, hour : 0,
|
||||
yday : 0, year : 0,
|
||||
weekday: 0, month : 0, day : 0,
|
||||
zone : zone, dst : !!dst,
|
||||
ce : "AD"
|
||||
};
|
||||
|
||||
/* include DST in the effective offset */
|
||||
var offset = zone + (dst ? 1 : 0);
|
||||
num += offset * time.hour;
|
||||
|
||||
/* split into day + seconds-of-day */
|
||||
var hms = num % time.day;
|
||||
var day = floor(num / time.day);
|
||||
if (hms < 0) { hms += time.day; day--; }
|
||||
|
||||
rec.second = hms % time.minute;
|
||||
var tmp = floor(hms / time.minute);
|
||||
rec.minute = tmp % time.minute;
|
||||
rec.hour = floor(tmp / time.minute);
|
||||
rec.weekday = (day + 4_503_599_627_370_496 + 2) % 7; /* 2 → 1970-01-01 was Thursday */
|
||||
|
||||
/* year & day-of-year */
|
||||
var y = time.epoch;
|
||||
if (day >= 0) {
|
||||
for (y = time.epoch; day >= time.yearsize(y); y++)
|
||||
day -= time.yearsize(y);
|
||||
} else {
|
||||
for (y = time.epoch; day < 0; y--)
|
||||
day += time.yearsize(y - 1);
|
||||
}
|
||||
rec.year = y;
|
||||
rec.ce = (y <= 0) ? "BC" : "AD";
|
||||
rec.yday = day;
|
||||
|
||||
/* month & month-day */
|
||||
if (time.yearsize(y) == 366) monthdays[1] = 29;
|
||||
var m = 0;
|
||||
for (; day >= monthdays[m]; m++) day -= monthdays[m];
|
||||
rec.month = m;
|
||||
rec.day = day + 1;
|
||||
|
||||
return rec;
|
||||
time.timecode = function(t) {
|
||||
var fps = 24
|
||||
var s = whole(t)
|
||||
var frac = t - s
|
||||
return `${s}:${whole(frac * fps)}`
|
||||
}
|
||||
|
||||
function time_number(rec = now())
|
||||
{
|
||||
if (is_number(rec)) return rec;
|
||||
time.monthdays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
||||
|
||||
log.console(rec)
|
||||
log.console(rec.minute)
|
||||
// convert seconds-since-epoch -> broken-down record
|
||||
function time_record(_num, _zone, _dst) {
|
||||
var n = _num
|
||||
var z = _zone
|
||||
var d = _dst
|
||||
if (n == null) n = now()
|
||||
if (z == null) z = computer_zone()
|
||||
if (d == null) d = computer_dst()
|
||||
|
||||
var c = 0;
|
||||
var year = rec.year || 0;
|
||||
var hour = rec.hour || 0;
|
||||
var minute = rec.minute || 0;
|
||||
var second = rec.second || 0;
|
||||
var zone = rec.zone || 0;
|
||||
var dst = rec.dst ? 1 : 0;
|
||||
var yday = rec.yday || 0;
|
||||
if (is_object(n)) return n
|
||||
|
||||
if (year > time.epoch) {
|
||||
for (var i = time.epoch; i < year; i++)
|
||||
c += time.day * time.yearsize(i);
|
||||
} else if (year < time.epoch) {
|
||||
for (var i = time.epoch - 1; i > year; i--)
|
||||
c += time.day * time.yearsize(i);
|
||||
c += (time.yearsize(year) - yday - 1) * time.day;
|
||||
c += (time.day2hour() - hour - 1) * time.hour;
|
||||
c += (time.hour2minute() - minute - 1) * time.minute;
|
||||
c += time.minute2second() - second;
|
||||
c += (zone + dst) * time.hour;
|
||||
return -c; /* BCE */
|
||||
var monthdays = array(time.monthdays)
|
||||
var rec = {
|
||||
second: 0, minute: 0, hour: 0,
|
||||
yday: 0, year: 0,
|
||||
weekday: 0, month: 0, day: 0,
|
||||
zone: z, dst: !!d,
|
||||
ce: "AD"
|
||||
}
|
||||
|
||||
c = second;
|
||||
c += minute * time.minute;
|
||||
c += hour * time.hour;
|
||||
c += yday * time.day;
|
||||
c -= (zone + dst) * time.hour;
|
||||
var offset = z + (d ? 1 : 0)
|
||||
n = n + offset * time.hour
|
||||
|
||||
return c;
|
||||
var hms = n % time.day
|
||||
var day = floor(n / time.day)
|
||||
if (hms < 0) { hms = hms + time.day; day = day - 1 }
|
||||
|
||||
rec.second = hms % time.minute
|
||||
var tmp = floor(hms / time.minute)
|
||||
rec.minute = tmp % time.minute
|
||||
rec.hour = floor(tmp / time.minute)
|
||||
rec.weekday = (day + 4503599627370496 + 2) % 7
|
||||
|
||||
var y = time.epoch
|
||||
if (day >= 0) {
|
||||
y = time.epoch
|
||||
while (day >= time.yearsize(y)) {
|
||||
day = day - time.yearsize(y)
|
||||
y = y + 1
|
||||
}
|
||||
} else {
|
||||
y = time.epoch
|
||||
while (day < 0) {
|
||||
y = y - 1
|
||||
day = day + time.yearsize(y)
|
||||
}
|
||||
}
|
||||
rec.year = y
|
||||
rec.ce = (y <= 0) ? "BC" : "AD"
|
||||
rec.yday = day
|
||||
|
||||
if (time.yearsize(y) == 366) monthdays[1] = 29
|
||||
var m = 0
|
||||
while (day >= monthdays[m]) {
|
||||
day = day - monthdays[m]
|
||||
m = m + 1
|
||||
}
|
||||
rec.month = m
|
||||
rec.day = day + 1
|
||||
|
||||
return rec
|
||||
}
|
||||
|
||||
function time_number(_rec) {
|
||||
var r = _rec
|
||||
if (r == null) r = now()
|
||||
if (is_number(r)) return r
|
||||
|
||||
var c = 0
|
||||
var year = r.year || 0
|
||||
var hour = r.hour || 0
|
||||
var minute = r.minute || 0
|
||||
var second = r.second || 0
|
||||
var zone = r.zone || 0
|
||||
var dst = r.dst ? 1 : 0
|
||||
var yday = r.yday || 0
|
||||
|
||||
if (year > time.epoch) {
|
||||
var i = time.epoch
|
||||
while (i < year) {
|
||||
c = c + time.day * time.yearsize(i)
|
||||
i = i + 1
|
||||
}
|
||||
} else if (year < time.epoch) {
|
||||
var i = time.epoch - 1
|
||||
while (i > year) {
|
||||
c = c + time.day * time.yearsize(i)
|
||||
i = i - 1
|
||||
}
|
||||
c = c + (time.yearsize(year) - yday - 1) * time.day
|
||||
c = c + (time.day2hour() - hour - 1) * time.hour
|
||||
c = c + (time.hour2minute() - minute - 1) * time.minute
|
||||
c = c + time.minute2second() - second
|
||||
c = c + (zone + dst) * time.hour
|
||||
return -c
|
||||
}
|
||||
|
||||
c = second
|
||||
c = c + minute * time.minute
|
||||
c = c + hour * time.hour
|
||||
c = c + yday * time.day
|
||||
c = c - (zone + dst) * time.hour
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// text formatting
|
||||
var default_fmt = "vB mB d hh:nn:ss a z y c"; /* includes new DST token */
|
||||
var default_fmt = "vB mB d hh:nn:ss a z y c"
|
||||
|
||||
function time_text(num = now(),
|
||||
fmt = default_fmt,
|
||||
zone = computer_zone(),
|
||||
dst = computer_dst())
|
||||
{
|
||||
var rec = is_number(num) ? time_record(num, zone, dst) : num;
|
||||
zone = rec.zone;
|
||||
dst = rec.dst;
|
||||
function time_text(_num, _fmt, _zone, _dst) {
|
||||
var n = _num
|
||||
var f = _fmt
|
||||
var z = _zone
|
||||
var d = _dst
|
||||
if (n == null) n = now()
|
||||
if (f == null) f = default_fmt
|
||||
if (z == null) z = computer_zone()
|
||||
if (d == null) d = computer_dst()
|
||||
|
||||
/* am/pm */
|
||||
if (search(fmt, "a") != null) {
|
||||
if (rec.hour >= 13) { rec.hour -= 12; fmt = replace(fmt, "a", "PM"); }
|
||||
else if (rec.hour == 12) { fmt = replace(fmt, "a", "PM"); }
|
||||
else if (rec.hour == 0) { rec.hour = 12; fmt = replace(fmt, "a", "AM"); }
|
||||
else fmt = replace(fmt, "a", "AM");
|
||||
var rec = is_number(n) ? time_record(n, z, d) : n
|
||||
z = rec.zone
|
||||
d = rec.dst
|
||||
|
||||
if (search(f, "a") != null) {
|
||||
if (rec.hour >= 13) { rec.hour = rec.hour - 12; f = replace(f, "a", "PM") }
|
||||
else if (rec.hour == 12) { f = replace(f, "a", "PM") }
|
||||
else if (rec.hour == 0) { rec.hour = 12; f = replace(f, "a", "AM") }
|
||||
else f = replace(f, "a", "AM")
|
||||
}
|
||||
|
||||
/* BCE/CE */
|
||||
var year = rec.year > 0 ? rec.year : rec.year - 1;
|
||||
if (search(fmt, "c") != null) {
|
||||
if (year < 0) { year = abs(year); fmt = replace(fmt, "c", "BC"); }
|
||||
else fmt = replace(fmt, "c", "AD");
|
||||
var year = rec.year > 0 ? rec.year : rec.year - 1
|
||||
if (search(f, "c") != null) {
|
||||
if (year < 0) { year = abs(year); f = replace(f, "c", "BC") }
|
||||
else f = replace(f, "c", "AD")
|
||||
}
|
||||
|
||||
/* substitutions */
|
||||
var full_offset = zone + (dst ? 1 : 0);
|
||||
fmt = replace(fmt, "yyyy", text(year, "i4"))
|
||||
fmt = replace(fmt, "y", year);
|
||||
fmt = replace(fmt, "eee", rec.yday + 1);
|
||||
fmt = replace(fmt, "dd", text(rec.day, "i2"))
|
||||
fmt = replace(fmt, "d", rec.day);
|
||||
fmt = replace(fmt, "hh", text(rec.hour, "i2"));
|
||||
fmt = replace(fmt, "h", rec.hour);
|
||||
fmt = replace(fmt, "nn", text(rec.minute, "i2"));
|
||||
fmt = replace(fmt, "n", rec.minute);
|
||||
fmt = replace(fmt, "ss", text(rec.second, "i2"));
|
||||
fmt = replace(fmt, "s", rec.second);
|
||||
fmt = replace(fmt, "x", dst ? "DST" : ""); /* new */
|
||||
fmt = replace(fmt, "z", (full_offset >= 0 ? "+" : "") + text(full_offset));
|
||||
fmt = replace(fmt, /mm[^bB]/g, rec.month + 1);
|
||||
fmt = replace(fmt, /m[^bB]/g, rec.month + 1);
|
||||
fmt = replace(fmt, /v[^bB]/g, rec.weekday);
|
||||
fmt = replace(fmt, "mb", text(time.monthstr[rec.month], 0, 3));
|
||||
fmt = replace(fmt, "mB", time.monthstr[rec.month]);
|
||||
fmt = replace(fmt, "vB", time.weekdays[rec.weekday]);
|
||||
fmt = replace(fmt, "vb", text(time.weekdays[rec.weekday], 0, 3));
|
||||
var full_offset = z + (d ? 1 : 0)
|
||||
f = replace(f, "yyyy", text(year, "i4"))
|
||||
f = replace(f, "y", year)
|
||||
f = replace(f, "eee", rec.yday + 1)
|
||||
f = replace(f, "dd", text(rec.day, "i2"))
|
||||
f = replace(f, "d", rec.day)
|
||||
f = replace(f, "hh", text(rec.hour, "i2"))
|
||||
f = replace(f, "h", rec.hour)
|
||||
f = replace(f, "nn", text(rec.minute, "i2"))
|
||||
f = replace(f, "n", rec.minute)
|
||||
f = replace(f, "ss", text(rec.second, "i2"))
|
||||
f = replace(f, "s", rec.second)
|
||||
f = replace(f, "x", d ? "DST" : "")
|
||||
f = replace(f, "z", (full_offset >= 0 ? "+" : "") + text(full_offset))
|
||||
f = replace(f, /mm[^bB]/g, rec.month + 1)
|
||||
f = replace(f, /m[^bB]/g, rec.month + 1)
|
||||
f = replace(f, /v[^bB]/g, rec.weekday)
|
||||
f = replace(f, "mb", text(time.monthstr[rec.month], 0, 3))
|
||||
f = replace(f, "mB", time.monthstr[rec.month])
|
||||
f = replace(f, "vB", time.weekdays[rec.weekday])
|
||||
f = replace(f, "vb", text(time.weekdays[rec.weekday], 0, 3))
|
||||
|
||||
return fmt;
|
||||
return f
|
||||
}
|
||||
|
||||
return { record: time_record, number: time_number, text: time_text };
|
||||
return { record: time_record, number: time_number, text: time_text }
|
||||
|
||||
Reference in New Issue
Block a user