improve time
This commit is contained in:
@@ -22,12 +22,10 @@ function caller_data(depth = 0)
|
|||||||
function console_rec(line, file, msg) {
|
function console_rec(line, file, msg) {
|
||||||
return `[${prosperon.id.slice(0,5)}] [${file}:${line}]: ${msg}\n`
|
return `[${prosperon.id.slice(0,5)}] [${file}:${line}]: ${msg}\n`
|
||||||
|
|
||||||
var now = time.now()
|
|
||||||
|
|
||||||
var id = prosperon.name ? prosperon.name : prosperon.id
|
var id = prosperon.name ? prosperon.name : prosperon.id
|
||||||
id = id.substring(0,6)
|
id = id.substring(0,6)
|
||||||
|
|
||||||
return `[${id}] [${time.text(now, "mb d yyyy h:nn:ss")}] ${file}:${line}: ${msg}\n`
|
return `[${id}] [${time.text("mb d yyyy h:nn:ss")}] ${file}:${line}: ${msg}\n`
|
||||||
}
|
}
|
||||||
|
|
||||||
var console_mod = prosperon.hidden.console
|
var console_mod = prosperon.hidden.console
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ graphics.Image = function(surfaceData) {
|
|||||||
this[CPU] = surfaceData || undefined;
|
this[CPU] = surfaceData || undefined;
|
||||||
this[GPU] = undefined;
|
this[GPU] = undefined;
|
||||||
this[LOADING] = false;
|
this[LOADING] = false;
|
||||||
this[LASTUSE] = time.now();
|
this[LASTUSE] = time.number();
|
||||||
this.rect = {x:0, y:0, width:1, height:1};
|
this.rect = {x:0, y:0, width:1, height:1};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ graphics.Image = function(surfaceData) {
|
|||||||
Object.defineProperties(graphics.Image.prototype, {
|
Object.defineProperties(graphics.Image.prototype, {
|
||||||
gpu: {
|
gpu: {
|
||||||
get: function() {
|
get: function() {
|
||||||
this[LASTUSE] = time.now();
|
this[LASTUSE] = time.number();
|
||||||
if (!this[GPU] && !this[LOADING]) {
|
if (!this[GPU] && !this[LOADING]) {
|
||||||
this[LOADING] = true;
|
this[LOADING] = true;
|
||||||
var self = this;
|
var self = this;
|
||||||
@@ -69,7 +69,7 @@ Object.defineProperties(graphics.Image.prototype, {
|
|||||||
|
|
||||||
cpu: {
|
cpu: {
|
||||||
get: function() {
|
get: function() {
|
||||||
this[LASTUSE] = time.now();
|
this[LASTUSE] = time.number();
|
||||||
// Note: Reading texture back from GPU requires async operation
|
// Note: Reading texture back from GPU requires async operation
|
||||||
// For now, return the CPU data if available
|
// For now, return the CPU data if available
|
||||||
return this[CPU]
|
return this[CPU]
|
||||||
|
|||||||
@@ -1,183 +1,191 @@
|
|||||||
|
/* time.js – exports: {record, number, text} */
|
||||||
|
|
||||||
var time = this;
|
var time = this;
|
||||||
|
|
||||||
time.second = 1;
|
/* -------- host helpers -------------------------------------------------- */
|
||||||
time.minute = 60;
|
|
||||||
time.hour = 3600;
|
var now = time.now; // seconds since Misty epoch (C stub)
|
||||||
time.day = 86400;
|
var computer_zone = time.computer_zone; // integral hours, no DST
|
||||||
time.week = 604800;
|
var computer_dst = time.computer_dst; // true ↔ DST in effect
|
||||||
time.weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
|
||||||
time.monthstr = ["January", "February", "March", "April", "May", "June",
|
delete time.now;
|
||||||
"July", "August", "September", "October", "November", "December"];
|
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.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;
|
||||||
|
|
||||||
time.hour2minute = function() {
|
/* ratios (kept K&R-style) */
|
||||||
return this.hour / this.minute;
|
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.day2hour = function() {
|
/* leap-year helpers */
|
||||||
return this.day / this.hour;
|
time.yearsize = function yearsize(y)
|
||||||
};
|
{
|
||||||
|
|
||||||
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;
|
if (y % 4 === 0 && (y % 100 !== 0 || y % 400 === 0)) return 366;
|
||||||
return 365;
|
return 365;
|
||||||
};
|
};
|
||||||
|
time.isleap = function(y) { return time.yearsize(y) === 366; };
|
||||||
|
|
||||||
time.timecode = function timecode(t, fps = 24) {
|
/* timecode utility */
|
||||||
|
time.timecode = function(t, fps = 24)
|
||||||
|
{
|
||||||
var s = Math.trunc(t);
|
var s = Math.trunc(t);
|
||||||
t -= s;
|
var frac = t - s;
|
||||||
return `${s}:${Math.trunc(fps * s)}`;
|
return `${s}:${Math.trunc(frac * fps)}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* per-month day counts (non-leap) */
|
||||||
time.monthdays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
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()) {
|
/* -------- core converters ----------------------------------------------- */
|
||||||
if (typeof num === "object") {
|
|
||||||
return num;
|
function record(num = now(),
|
||||||
} else if (typeof num === "number") {
|
zone = computer_zone(),
|
||||||
var monthdays = this.monthdays.slice();
|
dst = computer_dst())
|
||||||
var rec = {
|
{
|
||||||
second: 0,
|
/* caller passed an existing record → return it verbatim */
|
||||||
minute: 0,
|
if (typeof num === "object") return num;
|
||||||
hour: 0,
|
|
||||||
yday: 0,
|
/* -------------------------------------------------------------------- */
|
||||||
year: 0,
|
/* convert seconds-since-epoch → broken-down record */
|
||||||
zone: 0,
|
|
||||||
};
|
var monthdays = time.monthdays.slice();
|
||||||
rec.zone = zone;
|
var rec = {
|
||||||
num += zone * this.hour;
|
second : 0, minute : 0, hour : 0,
|
||||||
var hms = num % this.day;
|
yday : 0, year : 0,
|
||||||
var day = Math.floor(num / this.day);
|
weekday: 0, month : 0, day : 0,
|
||||||
if (hms < 0) {
|
zone : zone, dst : !!dst,
|
||||||
hms += this.day;
|
ce : "AD"
|
||||||
day--;
|
};
|
||||||
}
|
|
||||||
rec.second = hms % this.minute;
|
/* include DST in the effective offset */
|
||||||
var d1 = Math.floor(hms / this.minute);
|
var offset = zone + (dst ? 1 : 0);
|
||||||
rec.minute = d1 % this.minute;
|
num += offset * time.hour;
|
||||||
rec.hour = Math.floor(d1 / this.minute);
|
|
||||||
rec.weekday = (day + 4503599627370496 + 2) % 7;
|
/* split into day + seconds-of-day */
|
||||||
var yIter = this.epoch;
|
var hms = num % time.day;
|
||||||
if (day >= 0) {
|
var day = Math.floor(num / time.day);
|
||||||
for (yIter = this.epoch; day >= this.yearsize(yIter); yIter++) {
|
if (hms < 0) { hms += time.day; day--; }
|
||||||
day -= this.yearsize(yIter);
|
|
||||||
}
|
rec.second = hms % time.minute;
|
||||||
} else {
|
var tmp = Math.floor(hms / time.minute);
|
||||||
for (yIter = this.epoch; day < 0; yIter--) {
|
rec.minute = tmp % time.minute;
|
||||||
day += this.yearsize(yIter - 1);
|
rec.hour = Math.floor(tmp / time.minute);
|
||||||
}
|
rec.weekday = (day + 4_503_599_627_370_496 + 2) % 7; /* 2 → 1970-01-01 was Thursday */
|
||||||
}
|
|
||||||
rec.year = yIter;
|
/* year & day-of-year */
|
||||||
rec.ce = (rec.year <= 0) ? "BC" : "AD";
|
var y = time.epoch;
|
||||||
rec.yday = day;
|
if (day >= 0) {
|
||||||
if (this.yearsize(yIter) === 366) {
|
for (y = time.epoch; day >= time.yearsize(y); y++)
|
||||||
monthdays[1] = 29;
|
day -= time.yearsize(y);
|
||||||
}
|
} else {
|
||||||
var d0 = day;
|
for (y = time.epoch; day < 0; y--)
|
||||||
for (d1 = 0; d0 >= monthdays[d1]; d1++) {
|
day += time.yearsize(y - 1);
|
||||||
d0 -= monthdays[d1];
|
|
||||||
}
|
|
||||||
monthdays[1] = 28;
|
|
||||||
rec.day = d0 + 1;
|
|
||||||
rec.month = d1;
|
|
||||||
return rec;
|
|
||||||
}
|
}
|
||||||
};
|
rec.year = y;
|
||||||
|
rec.ce = (y <= 0) ? "BC" : "AD";
|
||||||
|
rec.yday = day;
|
||||||
|
|
||||||
time.number = function number(rec) {
|
/* month & month-day */
|
||||||
if (typeof rec === "number") {
|
if (time.yearsize(y) === 366) monthdays[1] = 29;
|
||||||
return rec;
|
var m = 0;
|
||||||
} else if (typeof rec === "object") {
|
for (; day >= monthdays[m]; m++) day -= monthdays[m];
|
||||||
var c = 0;
|
rec.month = m;
|
||||||
var year = rec.year || 0;
|
rec.day = day + 1;
|
||||||
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) {
|
return rec;
|
||||||
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;
|
function number(rec = now())
|
||||||
c += minute * this.minute;
|
{
|
||||||
c += hour * this.hour;
|
/* fall through for numeric input or implicit “now” */
|
||||||
c += yday * this.day;
|
if (typeof rec === "number") return rec;
|
||||||
c -= zone * this.hour;
|
|
||||||
return c;
|
/* -------------------------------------------------------------------- */
|
||||||
|
/* record → seconds-since-epoch */
|
||||||
|
|
||||||
|
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 (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 */
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
time.fmt = "vB mB d h:nn:ss TZz a y c";
|
c = second;
|
||||||
|
c += minute * time.minute;
|
||||||
|
c += hour * time.hour;
|
||||||
|
c += yday * time.day;
|
||||||
|
c -= (zone + dst) * time.hour;
|
||||||
|
|
||||||
time.text = function text(num, fmt = this.fmt, zone) {
|
return c;
|
||||||
var rec = (typeof num === "number") ? time.record(num, zone) : num;
|
}
|
||||||
zone = rec.zone;
|
|
||||||
if (fmt.match("a")) {
|
/* -------- text formatting ----------------------------------------------- */
|
||||||
if (rec.hour >= 13) {
|
|
||||||
rec.hour -= 12;
|
var default_fmt = "vB mB d hh:nn:ss a z y c"; /* includes new DST token */
|
||||||
fmt = fmt.replaceAll("a", "PM");
|
|
||||||
} else if (rec.hour === 12) {
|
function text(num = now(),
|
||||||
fmt = fmt.replaceAll("a", "PM");
|
fmt = default_fmt,
|
||||||
} else if (rec.hour === 0) {
|
zone = computer_zone(),
|
||||||
rec.hour = 12;
|
dst = computer_dst())
|
||||||
fmt = fmt.replaceAll("a", "AM");
|
{
|
||||||
} else {
|
var rec = (typeof num === "number") ? record(num, zone, dst) : num;
|
||||||
fmt = fmt.replaceAll("a", "AM");
|
zone = rec.zone;
|
||||||
}
|
dst = rec.dst;
|
||||||
|
|
||||||
|
/* am/pm */
|
||||||
|
if (fmt.includes("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")) {
|
/* BCE/CE */
|
||||||
if (year < 0) {
|
var year = rec.year > 0 ? rec.year : rec.year - 1;
|
||||||
year = Math.abs(year);
|
if (fmt.includes("c")) {
|
||||||
fmt = fmt.replaceAll("c", "BC");
|
if (year < 0) { year = Math.abs(year); fmt = fmt.replaceAll("c", "BC"); }
|
||||||
} else {
|
else fmt = fmt.replaceAll("c", "AD");
|
||||||
fmt = fmt.replaceAll("c", "AD");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* substitutions */
|
||||||
|
var full_offset = zone + (dst ? 1 : 0);
|
||||||
fmt = fmt.replaceAll("yyyy", year.toString().padStart(4, "0"));
|
fmt = fmt.replaceAll("yyyy", year.toString().padStart(4, "0"));
|
||||||
fmt = fmt.replaceAll("y", year);
|
fmt = fmt.replaceAll("y", year);
|
||||||
fmt = fmt.replaceAll("eee", rec.yday + 1);
|
fmt = fmt.replaceAll("eee", rec.yday + 1);
|
||||||
@@ -189,44 +197,28 @@ time.text = function text(num, fmt = this.fmt, zone) {
|
|||||||
fmt = fmt.replaceAll("n", rec.minute);
|
fmt = fmt.replaceAll("n", rec.minute);
|
||||||
fmt = fmt.replaceAll("ss", rec.second.toFixed(2).padStart(2, "0"));
|
fmt = fmt.replaceAll("ss", rec.second.toFixed(2).padStart(2, "0"));
|
||||||
fmt = fmt.replaceAll("s", rec.second);
|
fmt = fmt.replaceAll("s", rec.second);
|
||||||
fmt = fmt.replaceAll("z", zone >= 0 ? "+" + zone : zone);
|
fmt = fmt.replaceAll("x", dst ? "DST" : ""); /* new */
|
||||||
|
fmt = fmt.replaceAll("z", (full_offset >= 0 ? "+" : "") + full_offset);
|
||||||
fmt = fmt.replaceAll(/mm[^bB]/g, rec.month + 1);
|
fmt = fmt.replaceAll(/mm[^bB]/g, rec.month + 1);
|
||||||
fmt = fmt.replaceAll(/m[^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(/v[^bB]/g, rec.weekday);
|
||||||
fmt = fmt.replaceAll("mb", this.monthstr[rec.month].slice(0, 3));
|
fmt = fmt.replaceAll("mb", time.monthstr[rec.month].slice(0, 3));
|
||||||
fmt = fmt.replaceAll("mB", this.monthstr[rec.month]);
|
fmt = fmt.replaceAll("mB", time.monthstr[rec.month]);
|
||||||
fmt = fmt.replaceAll("vB", this.weekdays[rec.weekday]);
|
fmt = fmt.replaceAll("vB", time.weekdays[rec.weekday]);
|
||||||
fmt = fmt.replaceAll("vb", this.weekdays[rec.weekday].slice(0, 3));
|
fmt = fmt.replaceAll("vb", time.weekdays[rec.weekday].slice(0, 3));
|
||||||
|
|
||||||
return fmt;
|
return fmt;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
/* -------- docs ---------------------------------------------------------- */
|
||||||
|
|
||||||
time[prosperon.DOC] = {
|
time[prosperon.DOC] = {
|
||||||
doc: `The main time object, handling date/time utilities in earth-seconds.`,
|
doc : "Time utilities; epoch = 0000-01-01 00:00:00 +0000.",
|
||||||
second: `Number of seconds in a (real) second (always 1).`,
|
record : "time.record([num | rec], [zone], [dst]) → detailed record (adds .dst).",
|
||||||
minute: `Number of seconds in a minute (60).`,
|
number : "time.number([rec]) → numeric seconds since epoch.",
|
||||||
hour: `Number of seconds in an hour (3600).`,
|
text : "time.text([val], [fmt], [zone], [dst]) → formatted string (token Z = DST)."
|
||||||
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;
|
/* -------- public exports ------------------------------------------------ */
|
||||||
|
|
||||||
|
return { record, number, text };
|
||||||
|
|||||||
@@ -1,45 +1,81 @@
|
|||||||
#include "qjs_time.h"
|
#include "qjs_time.h"
|
||||||
#include "quickjs.h"
|
#include "quickjs.h"
|
||||||
#include <time.h> // For time() calls, localtime, etc.
|
#include <time.h>
|
||||||
#include <sys/time.h> // For gettimeofday, if needed
|
#include <sys/time.h>
|
||||||
|
|
||||||
// Example stubs for your time-related calls
|
/* ---------------------------------------------------------------- *\
|
||||||
|
Helpers
|
||||||
|
\* ---------------------------------------------------------------- */
|
||||||
|
|
||||||
static JSValue js_time_now(JSContext *ctx, JSValueConst this_val,
|
/* Seconds from Misty epoch (year-0) so JS “number()” stays consistent.
|
||||||
int argc, JSValueConst *argv) {
|
62167219200 = seconds between 0000-01-01 00:00 UTC and 1970-01-01 00:00 UTC. */
|
||||||
// time_now
|
static inline double misty_now(void)
|
||||||
|
{
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
double now = (double)tv.tv_sec + (tv.tv_usec / 1000000.0);
|
return (double)tv.tv_sec + tv.tv_usec / 1000000.0;
|
||||||
return JS_NewFloat64(ctx, now);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSValue js_time_computer_dst(JSContext *ctx, JSValueConst this_val,
|
/* ---------------------------------------------------------------- *\
|
||||||
int argc, JSValueConst *argv) {
|
JS bindings
|
||||||
|
\* ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static JSValue
|
||||||
|
js_time_now(JSContext *ctx, JSValueConst this_val,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
return JS_NewFloat64(ctx, misty_now());
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue
|
||||||
|
js_time_computer_dst(JSContext *ctx, JSValueConst this_val,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
time_t t = time(NULL);
|
time_t t = time(NULL);
|
||||||
struct tm *lt = localtime(&t);
|
struct tm *lt = localtime(&t);
|
||||||
int is_dst = (lt ? lt->tm_isdst : -1);
|
return JS_NewBool(ctx, lt && lt->tm_isdst > 0);
|
||||||
return JS_NewBool(ctx, (is_dst > 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSValue js_time_computer_zone(JSContext *ctx, JSValueConst this_val,
|
static JSValue
|
||||||
int argc, JSValueConst *argv) {
|
js_time_computer_zone(JSContext *ctx, JSValueConst this_val,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
time_t t = time(NULL);
|
time_t t = time(NULL);
|
||||||
time_t local_t = mktime(localtime(&t));
|
|
||||||
double diff = difftime(t, local_t); // difference in seconds from local time
|
#ifdef __USE_BSD /* tm_gmtoff / tm_zone available */
|
||||||
return JS_NewFloat64(ctx, diff / 3600.0);
|
struct tm lt = *localtime(&t);
|
||||||
|
long offset_sec = lt.tm_gmtoff; /* seconds east of UTC */
|
||||||
|
#else /* portable fallback */
|
||||||
|
struct tm gmt = *gmtime(&t);
|
||||||
|
|
||||||
|
/* Trick: encode the *same* calendar fields as “local” and see
|
||||||
|
how many seconds they represent. */
|
||||||
|
gmt.tm_isdst = 0; /* mktime expects valid flag */
|
||||||
|
time_t local_view = mktime(&gmt); /* same Y-M-D H:M:S but local */
|
||||||
|
|
||||||
|
long offset_sec = t - local_view; /* negative west of UTC */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return JS_NewFloat64(ctx, (double)offset_sec / 3600.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------- *\
|
||||||
|
registration
|
||||||
|
\* ---------------------------------------------------------------- */
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_time_funcs[] = {
|
static const JSCFunctionListEntry js_time_funcs[] = {
|
||||||
// name, prop flags, #args, etc.
|
JS_CFUNC_DEF("now", 0, js_time_now),
|
||||||
JS_CFUNC_DEF("now", 0, js_time_now),
|
JS_CFUNC_DEF("computer_dst", 0, js_time_computer_dst),
|
||||||
JS_CFUNC_DEF("computer_dst", 0, js_time_computer_dst),
|
JS_CFUNC_DEF("computer_zone", 0, js_time_computer_zone),
|
||||||
JS_CFUNC_DEF("computer_zone", 0, js_time_computer_zone),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
JSValue js_time_use(JSContext *ctx) {
|
JSValue
|
||||||
|
js_time_use(JSContext *ctx)
|
||||||
|
{
|
||||||
JSValue obj = JS_NewObject(ctx);
|
JSValue obj = JS_NewObject(ctx);
|
||||||
JS_SetPropertyFunctionList(ctx, obj, js_time_funcs,
|
JS_SetPropertyFunctionList(ctx, obj,
|
||||||
sizeof(js_time_funcs)/sizeof(js_time_funcs[0]));
|
js_time_funcs,
|
||||||
|
sizeof(js_time_funcs) /
|
||||||
|
sizeof(js_time_funcs[0]));
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
var parseq = use('parseq', $_.delay)
|
var parseq = use('parseq', $_.delay)
|
||||||
|
var time = use('time')
|
||||||
|
|
||||||
function load_comment_from_api_requestor(id) {
|
function load_comment_from_api_requestor(id) {
|
||||||
return function(cb) {
|
return function(cb) {
|
||||||
@@ -23,6 +24,6 @@ $_.receiver(tree => {
|
|||||||
send(tree, reason)
|
send(tree, reason)
|
||||||
}
|
}
|
||||||
|
|
||||||
send(tree, { ...result.comment, children: result.children })
|
send(tree, { ...result.comment, children: result.children, time: time.text() })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user