Skip to main content

ppoppo_clock/
lib.rs

1//! Universal Clock + Timer port for the ppoppo workspace.
2//!
3//! Single deep-module port hiding the time-source substrate from every consumer.
4//! Three impl arms gated by feature: `native` (Tokio + time-tz), `wasm` (Intl +
5//! Promise + leptos::set_timeout), `mock` (FrozenClock + MockClock + AdvanceableTimer).
6//!
7//! # SSOT relationship
8//!
9//! Standards: `STANDARDS_TIME_MECHANICS.md` §"Universal client + server time port"
10//! (rewritten in RFC_2026-05-10 Slice 9). Engine precedent: `ppoppo-token`
11//! (1st-party-consumed primitive, surface via SDK re-export). External Developer
12//! Apps consume via `pas_external::clock::*` — never path-dep this crate.
13//!
14//! # Dart mirror (CFC)
15//!
16//! `apps/cfc/lib/clock.dart` is the hand-maintained Dart shape mirror. Drift
17//! detection deferred to a follow-up RFC. When changing trait shape here,
18//! update the Dart mirror in the same commit.
19//!
20//! # Temporal API readiness
21//!
22//! Trait shape is deliberately Temporal-aligned. When `js_sys::Temporal::*`
23//! lands in upstream, only `src/wasm.rs` changes — public traits unchanged.
24//! See RFC §5.
25
26#![cfg_attr(not(test), warn(clippy::unwrap_used, clippy::panic))]
27
28use futures::future::BoxFuture;
29use std::sync::Arc;
30use time::{Date, Duration, OffsetDateTime};
31
32mod tz;
33mod zoned;
34pub use tz::{Tz, TzParseError};
35pub use zoned::{LocalParts, ZonedDateTime};
36
37#[cfg(feature = "native")]
38pub mod native;
39#[cfg(feature = "wasm")]
40pub mod wasm;
41#[cfg(feature = "mock")]
42pub mod mock;
43
44/// Wall-clock readouts. Single port for "what time is it?" across all surfaces.
45pub trait Clock: Send + Sync + 'static {
46    fn now_utc(&self) -> OffsetDateTime;
47    fn now_in(&self, tz: &Tz) -> ZonedDateTime;
48    fn today_in(&self, tz: &Tz) -> Date;
49    fn now_unix_millis(&self) -> i64;
50}
51
52/// Async scheduling primitive. Single port for "wait N ms" / "yield event-loop tick".
53pub trait Timer: Send + Sync + 'static {
54    fn sleep(&self, dur: Duration) -> BoxFuture<'static, ()>;
55    fn next_tick(&self) -> BoxFuture<'static, ()>;
56}
57
58/// Convenience aliases for the common injection shape.
59pub type ArcClock = Arc<dyn Clock>;
60pub type ArcTimer = Arc<dyn Timer>;