#![allow(clippy::unwrap_used, clippy::expect_used)]
use timeglyph::{format, interpret};
fn assert_int(id: &str, value: i64, prefix: &str) {
let f = format(id).unwrap();
let inst = f.decode_int(value).unwrap();
let rendered = inst.to_rfc3339().unwrap_or_default();
assert!(
rendered.starts_with(prefix),
"{id}({value}) = {rendered:?}, expected to start {prefix:?}"
);
}
fn assert_float(id: &str, value: f64, prefix: &str) {
let f = format(id).unwrap();
let inst = f.decode_float(value).unwrap();
let rendered = inst.to_rfc3339().unwrap_or_default();
assert!(
rendered.starts_with(prefix),
"{id}({value}) = {rendered:?}, expected to start {prefix:?}"
);
}
fn assert_form(cands: &[interpret::Candidate], id: &str, prefix: &str) {
let c = cands
.iter()
.find(|c| c.format_id == id)
.unwrap_or_else(|| panic!("no {id} candidate among {cands:?}"));
let r = c.rendered.as_deref().unwrap_or("");
assert!(r.starts_with(prefix), "{id} = {r:?}, expected {prefix:?}");
}
#[test]
fn active_directory_filetime() {
assert_int("active", 0, "1601-01-01T00:00:00");
assert_int("active", 133_908_455_300_649_390, "2025-05-04T15:18:50");
}
#[test]
fn mozilla_prtime_micros_since_1970() {
assert_int("prtime", 0, "1970-01-01T00:00:00");
assert_int("prtime", 1_746_371_930_064_939, "2025-05-04T15:18:50");
}
#[test]
fn ios_nsdate_nanos_since_2001() {
assert_int("iostime", 0, "2001-01-01T00:00:00");
assert_int("iostime", 768_064_730_064_939_008, "2025-05-04T15:18:50");
}
#[test]
fn ksuid_seconds_since_2014() {
assert_int("ksuid", 0, "2014-05-13T16:53:20");
assert_int("ksuid", 346_371_930, "2025-05-04T15:18:50");
}
#[test]
fn excel_1904_float_days() {
assert_float("excel1904", 0.0, "1904-01-01T00:00:00");
assert_float("excel1904", 44_319.638_079_455_3, "2025-05-04T15:18:50");
}
#[test]
fn mastodon_embedded_millis_shift16() {
assert_int("mastodon", 0, "1970-01-01T00:00:00");
assert_int("mastodon", 114_450_230_804_480_000, "2025-05-04T15:18:50");
}
#[test]
fn linkedin_embedded_millis_shift22() {
assert_int("linkedin", 7_324_176_984_442_343_424, "2025-05-02T21:04:29");
}
#[test]
fn tiktok_embedded_seconds_shift32() {
assert_int("tiktok", 1 << 32, "1970-01-01T00:00:01");
assert_int("tiktok", 7_228_142_017_547_750_661, "2023-05-01T09:22:38");
}
#[test]
fn ulid_string_first_48_bits_are_unix_millis() {
let cands = interpret::interpret_string("01JTDY1SYGCZWCBPCSEBHV1DW2");
assert_form(&cands, "ulid", "2025-05-04T15:18:50.064");
}
#[test]
fn uuid_v1_100ns_since_1582() {
let cands = interpret::interpret_string("d93026f0-e857-11ed-a05b-0242ac120003");
assert_form(&cands, "uuid_v1", "2023-05-01T19:39:12");
}
#[test]
fn rfc2822_email_date() {
let cands = interpret::interpret_string("Sun, 04 May 2025 15:18:50 +0000");
assert_form(&cands, "rfc2822", "2025-05-04T15:18:50");
}
#[test]
fn exif_datetime_colon_separated() {
let cands = interpret::interpret_string("2025:05:04 15:18:50");
assert_form(&cands, "exif", "2025-05-04T15:18:50");
}
#[test]
fn systemtime_128bit_struct() {
let groups = interpret::interpret_hex("e9070500000004000f00120032004000").unwrap();
let all: Vec<_> = groups.iter().flat_map(|(_, c)| c.clone()).collect();
assert_form(&all, "systemtime", "2025-05-04T15:18:50");
}
#[test]
fn google_ei_url_parameter_first_4_bytes_le_unix_seconds() {
let cands = interpret::interpret_string("ei=Yx1sYw");
assert_form(&cands, "google_ei", "2022-11-09T21:36:35");
let url = interpret::interpret_string("https://www.google.com/search?q=x&ei=Yx1sYw&oq=x");
assert_form(&url, "google_ei", "2022-11-09T21:36:35");
assert!(
!interpret::interpret_string("Yx1sYw")
.iter()
.any(|c| c.format_id == "google_ei"),
"a bare base64 token must not be blindly read as a Google ei timestamp"
);
}
#[test]
fn apache_clf_datetime() {
assert_form(
&interpret::interpret_string("10/Oct/2000:13:55:36 -0700"),
"clf",
"2000-10-10T20:55:36",
);
assert_form(
&interpret::interpret_string("[10/Oct/2000:13:55:36 -0700]"),
"clf",
"2000-10-10T20:55:36",
);
}
#[test]
fn pdf_date_string() {
assert_form(
&interpret::interpret_string("D:20260709123456+08'00'"),
"pdf_date",
"2026-07-09T04:34:56",
);
}
#[test]
fn dmtf_cim_datetime() {
assert_form(
&interpret::interpret_string("20260709123456.123456+480"),
"dmtf_cim",
"2026-07-09T04:34:56",
);
}
#[test]
fn f64_bit_reinterpret_lane_decodes_a_double_timestamp() {
let little = interpret::interpret_hex("ec4f086ddee3c641").unwrap();
let from_little: Vec<_> = little.iter().flat_map(|(_, c)| c.clone()).collect();
assert_form(&from_little, "cocoa_float", "2025-05-04T15:18:50");
let big = interpret::interpret_hex("41c6e3de6d084fec").unwrap();
let from_big: Vec<_> = big.iter().flat_map(|(_, c)| c.clone()).collect();
assert_form(&from_big, "cocoa_float", "2025-05-04T15:18:50");
}
#[test]
fn jwt_payload_claims_decode_as_unix_seconds() {
let jwt = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJpYXQiOiAxNTc3ODM2ODAwLCAiZXhwIjogMTU3NzkyMzIwMCwgInN1YiI6ICJ4In0.SIGNATURE";
let cands = interpret::interpret_string(jwt);
assert_form(&cands, "jwt_iat", "2020-01-01T00:00:00");
assert_form(&cands, "jwt_exp", "2020-01-02T00:00:00");
}