Files
el/lang/tests/suite/src/test_time.el
2026-05-05 01:38:51 -05:00

280 lines
12 KiB
EmacsLisp

// tests/suite/test_time.el comprehensive tests for runtime/time.el
//
// Covers time_now, now_millis, unix_timestamp, now_ns, time_format, time_to_parts,
// time_add, time_diff, duration helpers, and uuid_new.
// time_now / now_millis / unix_timestamp_ms
fn test_time_now_basic(_: String) -> String {
let t: Int = time_now()
// Milliseconds since epoch: must be well past year 2020 (1577836800000)
assert_true(t > 1577836800000, "time_now is past 2020-01-01")
// Must be before year 2100 (4102444800000)
assert_true(t < 4102444800000, "time_now is before 2100-01-01")
return ""
}
fn test_now_millis_basic(_: String) -> String {
let t: Int = now_millis()
assert_true(t > 1577836800000, "now_millis is past 2020-01-01")
assert_true(t < 4102444800000, "now_millis is before 2100-01-01")
return ""
}
fn test_unix_timestamp_ms_basic(_: String) -> String {
let t: Int = unix_timestamp_ms()
assert_true(t > 1577836800000, "unix_timestamp_ms is past 2020-01-01")
assert_true(t < 4102444800000, "unix_timestamp_ms is before 2100-01-01")
return ""
}
fn test_time_now_ms_alias(_: String) -> String {
let t: Int = time_now_ms()
assert_true(t > 1577836800000, "time_now_ms is past 2020-01-01")
assert_true(t < 4102444800000, "time_now_ms is before 2100-01-01")
return ""
}
// monotonicity
fn test_time_monotonic_now_millis(_: String) -> String {
let t1: Int = now_millis()
let t2: Int = now_millis()
assert_true(t2 >= t1, "second call >= first call (monotonic)")
return ""
}
fn test_time_monotonic_time_now(_: String) -> String {
let t1: Int = time_now()
let t2: Int = time_now()
assert_true(t2 >= t1, "time_now is monotonic across calls")
return ""
}
fn test_time_monotonic_now_ns(_: String) -> String {
let t1: Int = now_ns()
let t2: Int = now_ns()
assert_true(t2 >= t1, "now_ns is monotonic across calls")
// ns should be much larger than ms (9 digits difference)
assert_true(t1 > 1000000000000000000, "now_ns is in nanosecond scale")
return ""
}
// unix_timestamp (seconds)
fn test_unix_timestamp_basic(_: String) -> String {
let secs: Int = unix_timestamp()
// Must be past 2020-01-01 in seconds (1577836800)
assert_true(secs > 1577836800, "unix_timestamp is past 2020-01-01")
// Must be before 2100-01-01 in seconds (4102444800)
assert_true(secs < 4102444800, "unix_timestamp is before 2100-01-01")
// seconds are about 1000x smaller than millis
let ms: Int = time_now()
assert_true(ms > secs, "milliseconds > seconds")
return ""
}
// time_to_parts
fn test_time_to_parts_basic(_: String) -> String {
// Known timestamp: 2024-01-15 12:30:45.123 UTC
// 2024-01-15 00:00:00 UTC = epoch + (54 * 365 + 14 leaps) days approximately
// Use a precisely known value: 2024-01-15T12:30:45.123Z
// epoch_ms = 1705320645123
let ts: Int = 1705320645123
let parts: String = time_to_parts(ts)
assert_eq(json_get(parts, "year"), "2024", "year is 2024")
assert_eq(json_get(parts, "month"), "1", "month is 1 (January)")
assert_eq(json_get(parts, "day"), "15", "day is 15")
assert_eq(json_get(parts, "hour"), "12", "hour is 12")
assert_eq(json_get(parts, "minute"), "30", "minute is 30")
assert_eq(json_get(parts, "second"), "45", "second is 45")
assert_eq(json_get(parts, "ms"), "123", "milliseconds is 123")
return ""
}
fn test_time_to_parts_epoch(_: String) -> String {
// Unix epoch: 1970-01-01T00:00:00.000Z = timestamp 0
let parts: String = time_to_parts(0)
assert_eq(json_get(parts, "year"), "1970", "epoch year is 1970")
assert_eq(json_get(parts, "month"), "1", "epoch month is 1")
assert_eq(json_get(parts, "day"), "1", "epoch day is 1")
assert_eq(json_get(parts, "hour"), "0", "epoch hour is 0")
assert_eq(json_get(parts, "minute"), "0", "epoch minute is 0")
assert_eq(json_get(parts, "second"), "0", "epoch second is 0")
return ""
}
fn test_time_to_parts_current(_: String) -> String {
let ts: Int = time_now()
let parts: String = time_to_parts(ts)
let year: Int = str_to_int(json_get(parts, "year"))
let month: Int = str_to_int(json_get(parts, "month"))
let day: Int = str_to_int(json_get(parts, "day"))
let hour: Int = str_to_int(json_get(parts, "hour"))
let minute: Int = str_to_int(json_get(parts, "minute"))
let second: Int = str_to_int(json_get(parts, "second"))
assert_true(year >= 2024, "current year >= 2024")
assert_true(year < 2100, "current year < 2100")
assert_true(month >= 1, "month >= 1")
assert_true(month <= 12, "month <= 12")
assert_true(day >= 1, "day >= 1")
assert_true(day <= 31, "day <= 31")
assert_true(hour >= 0, "hour >= 0")
assert_true(hour <= 23, "hour <= 23")
assert_true(minute >= 0, "minute >= 0")
assert_true(minute <= 59, "minute <= 59")
assert_true(second >= 0, "second >= 0")
assert_true(second <= 59, "second <= 59")
return ""
}
// time_format
fn test_time_format_iso(_: String) -> String {
let ts: Int = 1705320645123
let iso: String = time_format(ts, "ISO")
assert_starts_with(iso, "2024-01-15", "ISO format starts with correct date")
assert_contains(iso, "T12:30:45", "ISO format has correct time")
assert_ends_with(iso, "Z", "ISO format ends with Z")
assert_contains(iso, "123", "ISO format includes milliseconds")
return ""
}
fn test_time_format_empty(_: String) -> String {
let ts: Int = 1705320645123
let iso: String = time_format(ts, "")
assert_starts_with(iso, "2024-01-15", "empty fmt gives ISO format")
assert_ends_with(iso, "Z", "empty fmt gives ISO format ending in Z")
return ""
}
fn test_time_format_strftime(_: String) -> String {
let ts: Int = 1705320645123
let formatted: String = time_format(ts, "%Y-%m-%d")
assert_eq(formatted, "2024-01-15", "strftime %Y-%m-%d")
let formatted2: String = time_format(ts, "%H:%M:%S")
assert_eq(formatted2, "12:30:45", "strftime %H:%M:%S")
return ""
}
// time_add
fn test_time_add_basic(_: String) -> String {
let base: Int = 1000000000000
assert_int_eq(time_add(base, 1000, "ms"), base + 1000, "add milliseconds")
assert_int_eq(time_add(base, 1, "sec"), base + 1000, "add 1 second")
assert_int_eq(time_add(base, 1, "min"), base + 60000, "add 1 minute")
assert_int_eq(time_add(base, 1, "hour"), base + 3600000, "add 1 hour")
assert_int_eq(time_add(base, 1, "day"), base + 86400000, "add 1 day")
return ""
}
fn test_time_add_multiple(_: String) -> String {
let base: Int = 1000000000000
assert_int_eq(time_add(base, 60, "sec"), base + 60000, "add 60 seconds")
assert_int_eq(time_add(base, 24, "hour"), base + 86400000, "add 24 hours = 1 day")
assert_int_eq(time_add(base, 0, "sec"), base, "add 0 seconds")
assert_int_eq(time_add(base, -1, "sec"), base - 1000, "add negative seconds")
return ""
}
// time_diff
fn test_time_diff_basic(_: String) -> String {
let t1: Int = 1000000000000
let t2: Int = t1 + 5000
assert_int_eq(time_diff(t1, t2, "ms"), 5000, "diff in ms")
assert_int_eq(time_diff(t1, t2, "sec"), 5, "diff in seconds")
return ""
}
fn test_time_diff_larger(_: String) -> String {
let t1: Int = 1000000000000
let t2: Int = t1 + 3600000
assert_int_eq(time_diff(t1, t2, "min"), 60, "diff of 1 hour in minutes")
assert_int_eq(time_diff(t1, t2, "hour"), 1, "diff of 1 hour in hours")
assert_int_eq(time_diff(t1, t2, "ms"), 3600000, "diff of 1 hour in ms")
return ""
}
fn test_time_diff_zero(_: String) -> String {
let t: Int = 1000000000000
assert_int_eq(time_diff(t, t, "ms"), 0, "same timestamp: diff is 0")
assert_int_eq(time_diff(t, t, "sec"), 0, "same timestamp: diff in sec is 0")
return ""
}
// Duration helpers
fn test_duration_helpers_basic(_: String) -> String {
assert_int_eq(duration_seconds(1), 1000000000, "1 second = 1e9 ns")
assert_int_eq(duration_millis(1), 1000000, "1 ms = 1e6 ns")
assert_int_eq(duration_nanos(42), 42, "nanos identity")
assert_int_eq(duration_to_seconds(1000000000), 1, "1e9 ns = 1 second")
assert_int_eq(duration_to_millis(1000000), 1, "1e6 ns = 1 ms")
assert_int_eq(duration_to_nanos(42), 42, "nanos identity roundtrip")
return ""
}
fn test_instant_helpers_basic(_: String) -> String {
let i: Int = unix_seconds(1000)
assert_int_eq(i, 1000000000000, "unix_seconds(1000) = 1e12 ns")
let ms_i: Int = unix_millis(5000)
assert_int_eq(ms_i, 5000000000, "unix_millis(5000) = 5e9 ns")
assert_int_eq(instant_to_unix_seconds(1000000000000), 1000, "instant to seconds")
assert_int_eq(instant_to_unix_millis(5000000000), 5000, "instant to millis")
return ""
}
// uuid_new / uuid_v4
fn test_uuid_new_basic(_: String) -> String {
let u: String = uuid_new()
assert_int_eq(str_len(u), 36, "UUID has 36 characters")
assert_eq(str_char_at(u, 8), "-", "UUID has dash at position 8")
assert_eq(str_char_at(u, 13), "-", "UUID has dash at position 13")
assert_eq(str_char_at(u, 18), "-", "UUID has dash at position 18")
assert_eq(str_char_at(u, 23), "-", "UUID has dash at position 23")
return ""
}
fn test_uuid_uniqueness(_: String) -> String {
let u1: String = uuid_new()
let u2: String = uuid_new()
let u3: String = uuid_v4()
assert_false(str_eq(u1, u2), "consecutive UUIDs are different")
assert_false(str_eq(u1, u3), "uuid_new and uuid_v4 produce different values")
assert_false(str_eq(u2, u3), "three consecutive UUIDs are all different")
assert_int_eq(str_len(u3), 36, "uuid_v4 also produces 36-char UUID")
return ""
}
// time_from_parts
fn test_time_from_parts_basic(_: String) -> String {
// time_from_parts(secs, ns, tz) = secs * 1000 + ns / 1000000
let ts: Int = time_from_parts(1000, 0, "UTC")
assert_int_eq(ts, 1000000, "1000 secs = 1000000 ms")
let ts2: Int = time_from_parts(0, 500000000, "UTC")
assert_int_eq(ts2, 500, "500ms in nanoseconds -> 500ms")
let ts3: Int = time_from_parts(1705320645, 123000000, "UTC")
assert_int_eq(ts3, 1705320645123, "known timestamp with ms component")
return ""
}
// instant_to_iso8601
fn test_instant_to_iso8601_basic(_: String) -> String {
let ts_ms: Int = 1705320645123
let ts_ns: Int = ts_ms * 1000000
let iso: String = instant_to_iso8601(ts_ns)
assert_starts_with(iso, "2024-01-15", "instant_to_iso8601 correct date")
assert_ends_with(iso, "Z", "instant_to_iso8601 ends with Z")
return ""
}