Use the browser clock for now_iso on wasm (comment and tracked-change dates) (#214)

Fixes #188.

Co-authored-by: Fabio Lussi <198260595+itrycodinganditsbad@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
Fabio Lussi
2026-10-10 09:27:02 -04:00
committed by GitHub
co-authored by Fabio Lussi Claude Opus 5.5 Brandon Thomas
parent 24388e2c24
commit 58ae1d5685
3 changed files with 35 additions and 5 deletions
Generated
+1
View File
@@ -4939,6 +4939,7 @@ name = "wordcraft-engine"
version = "0.4.0"
dependencies = [
"image",
"js-sys",
"log",
"regex",
"regex-automata",
+4
View File
@@ -27,5 +27,9 @@ regex = { workspace = true }
regex-automata = { workspace = true }
image = { workspace = true }
[target.'cfg(target_arch = "wasm32")'.dependencies]
# The browser clock for `now_iso` (`SystemTime::now()` panics on wasm32).
js-sys = "0.3"
[dev-dependencies]
zip = { workspace = true }
+30 -5
View File
@@ -212,19 +212,26 @@ pub fn split_para(s: &mut Session, at: &Pos) -> Result<Pos, CmdError> {
Ok(new)
}
/// ISO-8601 timestamp (UTC, seconds) for `secs` since the Unix epoch.
fn iso_from_unix_secs(secs: u64) -> String {
let (y, m, d) = civil_from_days((secs / 86_400) as i64);
let t = secs % 86_400;
format!("{y:04}-{m:02}-{d:02}T{:02}:{:02}:{:02}Z", t / 3600, t / 60 % 60, t % 60)
}
/// ISO-8601 timestamp (UTC, seconds).
pub fn now_iso() -> String {
#[cfg(not(target_arch = "wasm32"))]
{
let secs = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).map(|d| d.as_secs()).unwrap_or(0);
let days = (secs / 86_400) as i64;
let (y, m, d) = civil_from_days(days);
let t = secs % 86_400;
format!("{y:04}-{m:02}-{d:02}T{:02}:{:02}:{:02}Z", t / 3600, t / 60 % 60, t % 60)
iso_from_unix_secs(secs)
}
// `SystemTime::now()` panics on wasm32-unknown-unknown, so ask the browser's clock.
#[cfg(target_arch = "wasm32")]
{
"2026-01-01T00:00:00Z".to_string()
let ms = js_sys::Date::now();
// Clamp a NaN or pre-epoch clock to 0 rather than fail.
iso_from_unix_secs(if ms.is_finite() && ms > 0.0 { (ms / 1000.0) as u64 } else { 0 })
}
}
@@ -246,3 +253,21 @@ pub fn civil_from_days(z: i64) -> (i64, u32, u32) {
pub fn story_param(s: &Session, v: &Value) -> StoryRef {
v.get("story").and_then(|x| serde_json::from_value(x.clone()).ok()).unwrap_or(s.sel.focus.story)
}
#[cfg(test)]
mod iso_tests {
use super::iso_from_unix_secs;
#[test]
fn formats_epoch_and_known_timestamps() {
assert_eq!(iso_from_unix_secs(0), "1970-01-01T00:00:00Z");
assert_eq!(iso_from_unix_secs(1_760_082_785), "2025-10-10T07:53:05Z");
}
#[test]
fn formats_leap_day_and_year_end() {
assert_eq!(iso_from_unix_secs(1_709_164_800), "2024-02-29T00:00:00Z");
assert_eq!(iso_from_unix_secs(951_782_400), "2000-02-29T00:00:00Z");
assert_eq!(iso_from_unix_secs(1_735_689_599), "2024-12-31T23:59:59Z");
}
}