Files
cell/scripts/modules/time.js
John Alanbrook 600fbfd3b7
Some checks failed
Build and Deploy / package-dist (push) Has been cancelled
Build and Deploy / build-linux (push) Has been cancelled
Build and Deploy / deploy-itch (push) Has been cancelled
Build and Deploy / deploy-gitea (push) Has been cancelled
Build and Deploy / build-windows (CLANG64) (push) Has been cancelled
fast sprite render
2025-05-01 01:35:05 -05:00

233 lines
7.6 KiB
JavaScript

var time = this;
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.hour2minute = function() {
return this.hour / this.minute;
};
time.day2hour = function() {
return this.day / this.hour;
};
time.minute2second = function() {
return this.minute / this.second;
};
time.week2day = function() {
return this.week / this.day;
};
time.strparse = {
yyyy: "year",
mm: "month",
m: "month",
eee: "yday",
dd: "day",
d: "day",
v: "weekday",
hh: "hour",
h: "hour",
nn: "minute",
n: "minute",
ss: "second",
s: "second",
};
time.isleap = function isleap(year) {
return this.yearsize(year) === 366;
};
time.yearsize = function yearsize(y) {
if (y % 4 === 0 && (y % 100 !== 0 || y % 400 === 0)) return 366;
return 365;
};
time.timecode = function timecode(t, fps = 24) {
var s = Math.trunc(t);
t -= s;
return `${s}:${Math.trunc(fps * s)}`;
};
time.monthdays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
time.zones = { "-12": "IDLW" };
time.record = function record(num, zone = this.computer_zone()) {
if (typeof num === "object") {
return num;
} else if (typeof num === "number") {
var monthdays = this.monthdays.slice();
var rec = {
second: 0,
minute: 0,
hour: 0,
yday: 0,
year: 0,
zone: 0,
};
rec.zone = zone;
num += zone * this.hour;
var hms = num % this.day;
var day = Math.floor(num / this.day);
if (hms < 0) {
hms += this.day;
day--;
}
rec.second = hms % this.minute;
var d1 = Math.floor(hms / this.minute);
rec.minute = d1 % this.minute;
rec.hour = Math.floor(d1 / this.minute);
rec.weekday = (day + 4503599627370496 + 2) % 7;
var yIter = this.epoch;
if (day >= 0) {
for (yIter = this.epoch; day >= this.yearsize(yIter); yIter++) {
day -= this.yearsize(yIter);
}
} else {
for (yIter = this.epoch; day < 0; yIter--) {
day += this.yearsize(yIter - 1);
}
}
rec.year = yIter;
rec.ce = (rec.year <= 0) ? "BC" : "AD";
rec.yday = day;
if (this.yearsize(yIter) === 366) {
monthdays[1] = 29;
}
var d0 = day;
for (d1 = 0; d0 >= monthdays[d1]; d1++) {
d0 -= monthdays[d1];
}
monthdays[1] = 28;
rec.day = d0 + 1;
rec.month = d1;
return rec;
}
};
time.number = function number(rec) {
if (typeof rec === "number") {
return rec;
} else if (typeof rec === "object") {
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 yday = rec.yday || 0;
if (year > this.epoch) {
for (var i = this.epoch; i < year; i++) {
c += this.day * this.yearsize(i);
}
} else if (year < this.epoch) {
for (var i = this.epoch - 1; i > year; i--) {
c += this.day * this.yearsize(i);
}
c += (this.yearsize(year) - yday - 1) * this.day;
c += (this.day2hour() - hour - 1) * this.hour;
c += (this.hour2minute() - minute - 1) * this.minute;
c += this.minute2second() - second;
c += zone * this.hour;
c *= -1;
return c;
}
c += second;
c += minute * this.minute;
c += hour * this.hour;
c += yday * this.day;
c -= zone * this.hour;
return c;
}
};
time.fmt = "vB mB d h:nn:ss TZz a y c";
time.text = function text(num, fmt = this.fmt, zone) {
var rec = (typeof num === "number") ? time.record(num, zone) : num;
zone = rec.zone;
if (fmt.match("a")) {
if (rec.hour >= 13) {
rec.hour -= 12;
fmt = fmt.replaceAll("a", "PM");
} else if (rec.hour === 12) {
fmt = fmt.replaceAll("a", "PM");
} else if (rec.hour === 0) {
rec.hour = 12;
fmt = fmt.replaceAll("a", "AM");
} else {
fmt = fmt.replaceAll("a", "AM");
}
}
var year = rec.year > 0 ? rec.year : (rec.year - 1);
if (fmt.match("c")) {
if (year < 0) {
year = Math.abs(year);
fmt = fmt.replaceAll("c", "BC");
} else {
fmt = fmt.replaceAll("c", "AD");
}
}
fmt = fmt.replaceAll("yyyy", year.toString().padStart(4, "0"));
fmt = fmt.replaceAll("y", year);
fmt = fmt.replaceAll("eee", rec.yday + 1);
fmt = fmt.replaceAll("dd", rec.day.toString().padStart(2, "0"));
fmt = fmt.replaceAll("d", rec.day);
fmt = fmt.replaceAll("hh", rec.hour.toString().padStart(2, "0"));
fmt = fmt.replaceAll("h", rec.hour);
fmt = fmt.replaceAll("nn", rec.minute.toString().padStart(2, "0"));
fmt = fmt.replaceAll("n", rec.minute);
fmt = fmt.replaceAll("ss", rec.second.toFixed(2).padStart(2, "0"));
fmt = fmt.replaceAll("s", rec.second);
fmt = fmt.replaceAll("z", zone >= 0 ? "+" + zone : zone);
fmt = fmt.replaceAll(/mm[^bB]/g, rec.month + 1);
fmt = fmt.replaceAll(/m[^bB]/g, rec.month + 1);
fmt = fmt.replaceAll(/v[^bB]/g, rec.weekday);
fmt = fmt.replaceAll("mb", this.monthstr[rec.month].slice(0, 3));
fmt = fmt.replaceAll("mB", this.monthstr[rec.month]);
fmt = fmt.replaceAll("vB", this.weekdays[rec.weekday]);
fmt = fmt.replaceAll("vb", this.weekdays[rec.weekday].slice(0, 3));
return fmt;
};
time[prosperon.DOC] = {
doc: `The main time object, handling date/time utilities in earth-seconds.`,
second: `Number of seconds in a (real) second (always 1).`,
minute: `Number of seconds in a minute (60).`,
hour: `Number of seconds in an hour (3600).`,
day: `Number of seconds in a day (86400).`,
week: `Number of seconds in a week (604800).`,
weekdays: `Names of the days of the week, Sunday through Saturday.`,
monthstr: `Full names of the months of the year, January through December.`,
epoch: `Base epoch year, from which day 0 is calculated (default 1970).`,
hour2minute: `Return the ratio of hour to minute in seconds, e.g. 3600 / 60 => 60.`,
day2hour: `Return the ratio of day to hour in seconds, e.g. 86400 / 3600 => 24.`,
minute2second: `Return the ratio of minute to second in seconds, e.g. 60 / 1 => 60.`,
week2day: `Return the ratio of week to day in seconds, e.g. 604800 / 86400 => 7.`,
strparse: `Mapping of format tokens (yyyy, mm, dd, etc.) to time fields (year, month, day...).`,
isleap: `Return true if a given year is leap, based on whether it has 366 days.`,
yearsize: `Given a year, return 365 or 366 depending on leap-year rules.`,
timecode: `Convert seconds into a "S:frames" timecode string, with optional FPS (default 24).`,
monthdays: `An array of days in each month for a non-leap year.`,
zones: `Table of recognized time zone abbreviations, with offsets (e.g., "-12" -> "IDLW").`,
record: `Convert a timestamp (in seconds) into a record with fields like day, month, year, etc.`,
number: `Convert a record back into a numeric timestamp (seconds).`,
fmt: `Default format string for time.text(), containing tokens like 'yyyy', 'dd', 'hh', etc.`,
text: `Format a numeric or record time into a string using a format pattern, e.g. 'hh:nn:ss'.`,
now: `Return the current system time in seconds (implemented in C extension).`,
computer_dst: `Return true if local system time is currently in DST (implemented in C extension).`,
computer_zone: `Return local time zone offset from UTC in hours (implemented in C extension).`
};
return time;