ppoppo-clock 0.1.0

Universal Clock + Timer port for ppoppo workspace — chat-as-infrastructure primitive
Documentation
//! Universal Clock + Timer port for the ppoppo workspace.
//!
//! Single deep-module port hiding the time-source substrate from every consumer.
//! Three impl arms gated by feature: `native` (Tokio + time-tz), `wasm` (Intl +
//! Promise + leptos::set_timeout), `mock` (FrozenClock + MockClock + AdvanceableTimer).
//!
//! # SSOT relationship
//!
//! Standards: `STANDARDS_TIME_MECHANICS.md` §"Universal client + server time port"
//! (rewritten in RFC_2026-05-10 Slice 9). Engine precedent: `ppoppo-token`
//! (1st-party-consumed primitive, surface via SDK re-export). External Developer
//! Apps consume via `pas_external::clock::*` — never path-dep this crate.
//!
//! # Dart mirror (CFC)
//!
//! `apps/cfc/lib/clock.dart` is the hand-maintained Dart shape mirror. Drift
//! detection deferred to a follow-up RFC. When changing trait shape here,
//! update the Dart mirror in the same commit.
//!
//! # Temporal API readiness
//!
//! Trait shape is deliberately Temporal-aligned. When `js_sys::Temporal::*`
//! lands in upstream, only `src/wasm.rs` changes — public traits unchanged.
//! See RFC §5.

#![cfg_attr(not(test), warn(clippy::unwrap_used, clippy::panic))]

use futures::future::BoxFuture;
use std::sync::Arc;
use time::{Date, Duration, OffsetDateTime};

mod tz;
mod zoned;
pub use tz::{Tz, TzParseError};
pub use zoned::{LocalParts, ZonedDateTime};

#[cfg(feature = "native")]
pub mod native;
#[cfg(feature = "wasm")]
pub mod wasm;
#[cfg(feature = "mock")]
pub mod mock;

/// Wall-clock readouts. Single port for "what time is it?" across all surfaces.
pub trait Clock: Send + Sync + 'static {
    fn now_utc(&self) -> OffsetDateTime;
    fn now_in(&self, tz: &Tz) -> ZonedDateTime;
    fn today_in(&self, tz: &Tz) -> Date;
    fn now_unix_millis(&self) -> i64;
}

/// Async scheduling primitive. Single port for "wait N ms" / "yield event-loop tick".
pub trait Timer: Send + Sync + 'static {
    fn sleep(&self, dur: Duration) -> BoxFuture<'static, ()>;
    fn next_tick(&self) -> BoxFuture<'static, ()>;
}

/// Convenience aliases for the common injection shape.
pub type ArcClock = Arc<dyn Clock>;
pub type ArcTimer = Arc<dyn Timer>;