1#![deny(missing_docs)]
10
11pub mod admin;
12pub mod audit;
13pub mod bootstrap;
14pub mod config;
15pub mod merge;
16pub mod server;
17pub mod store;
18
19pub use config::{Config, ConfigError, TlsMode};
20pub use merge::Merger;
21pub use server::Server;
22pub use store::Store;
23
24use time::OffsetDateTime;
25
26pub fn now() -> String {
34 format_timestamp(OffsetDateTime::now_utc())
35}
36
37pub(crate) fn format_timestamp(at: OffsetDateTime) -> String {
42 let fmt = time::macros::format_description!(
45 "[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond digits:3]Z"
46 );
47 at.to_offset(time::UtcOffset::UTC)
48 .format(&fmt)
49 .expect("the timestamp format is a compile-time constant")
50}
51
52pub(crate) fn parse_timestamp(text: &str) -> Option<OffsetDateTime> {
54 OffsetDateTime::parse(text, &time::format_description::well_known::Rfc3339).ok()
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60
61 #[test]
62 fn timestamps_read_back_to_the_same_moment() {
63 let at = OffsetDateTime::from_unix_timestamp_nanos(1_788_472_195_191_000_000).unwrap();
64 assert_eq!(parse_timestamp(&format_timestamp(at)), Some(at));
65 assert_eq!(parse_timestamp("yesterday"), None);
66 }
67
68 #[test]
69 fn timestamps_match_javascripts_toisostring() {
70 let t = now();
71 assert_eq!(t.len(), 24, "got {t}");
72 assert!(t.ends_with('Z'), "got {t}");
73 assert_eq!(&t[10..11], "T", "got {t}");
74 assert_eq!(&t[19..20], ".", "got {t}");
75 assert!(
76 t[20..23].chars().all(|c| c.is_ascii_digit()),
77 "milliseconds must be digits, got {t}"
78 );
79 }
80
81 #[test]
84 fn renders_real_milliseconds_not_literal_zeroes() {
85 let at = OffsetDateTime::from_unix_timestamp_nanos(1_788_472_195_191_000_000).unwrap();
86 assert_eq!(format_timestamp(at), "2026-09-03T21:49:55.191Z");
87 }
88}