use super::components::extract_components;
use crate::time_units::TimeUnit;
pub fn format_iso8601(timestamp: i64, time_unit: TimeUnit) -> String {
let comp = extract_components(timestamp, time_unit);
match time_unit {
TimeUnit::Seconds => format!(
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02}Z",
comp.year, comp.month, comp.day, comp.hour, comp.minute, comp.second
),
TimeUnit::Milliseconds => format!(
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02}.{:03}Z",
comp.year,
comp.month,
comp.day,
comp.hour,
comp.minute,
comp.second,
comp.nanosecond / 1_000_000
),
TimeUnit::Microseconds => format!(
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02}.{:06}Z",
comp.year,
comp.month,
comp.day,
comp.hour,
comp.minute,
comp.second,
comp.nanosecond / 1_000
),
TimeUnit::Nanoseconds => format!(
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02}.{:09}Z",
comp.year, comp.month, comp.day, comp.hour, comp.minute, comp.second, comp.nanosecond
),
TimeUnit::Days => format!("{:04}-{:02}-{:02}", comp.year, comp.month, comp.day),
}
}
pub fn format_rfc3339(timestamp: i64, time_unit: TimeUnit) -> String {
format_iso8601(timestamp, time_unit)
}
pub fn format_date_only(timestamp: i64, time_unit: TimeUnit) -> String {
let comp = extract_components(timestamp, time_unit);
format!("{:04}-{:02}-{:02}", comp.year, comp.month, comp.day)
}
pub fn format_time_only(timestamp: i64, time_unit: TimeUnit) -> String {
let comp = extract_components(timestamp, time_unit);
match time_unit {
TimeUnit::Seconds => format!(
"{:02}:{:02}:{:02}",
comp.hour, comp.minute, comp.second
),
TimeUnit::Milliseconds => format!(
"{:02}:{:02}:{:02}.{:03}",
comp.hour,
comp.minute,
comp.second,
comp.nanosecond / 1_000_000
),
TimeUnit::Microseconds => format!(
"{:02}:{:02}:{:02}.{:06}",
comp.hour,
comp.minute,
comp.second,
comp.nanosecond / 1_000
),
TimeUnit::Nanoseconds => format!(
"{:02}:{:02}:{:02}.{:09}",
comp.hour, comp.minute, comp.second, comp.nanosecond
),
TimeUnit::Days => String::from("00:00:00"),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_format_iso8601_epoch() {
assert_eq!(
format_iso8601(0, TimeUnit::Seconds),
"1970-01-01T00:00:00Z"
);
}
#[test]
fn test_format_iso8601_with_time() {
let ts = 946730096;
assert_eq!(
format_iso8601(ts, TimeUnit::Seconds),
"2000-01-01T12:34:56Z"
);
}
#[test]
fn test_format_iso8601_milliseconds() {
assert_eq!(
format_iso8601(123, TimeUnit::Milliseconds),
"1970-01-01T00:00:00.123Z"
);
}
#[test]
fn test_format_iso8601_microseconds() {
assert_eq!(
format_iso8601(123456, TimeUnit::Microseconds),
"1970-01-01T00:00:00.123456Z"
);
}
#[test]
fn test_format_iso8601_nanoseconds() {
assert_eq!(
format_iso8601(123456789, TimeUnit::Nanoseconds),
"1970-01-01T00:00:00.123456789Z"
);
}
#[test]
fn test_format_date_only() {
assert_eq!(format_date_only(0, TimeUnit::Seconds), "1970-01-01");
assert_eq!(format_date_only(946684800, TimeUnit::Seconds), "2000-01-01");
}
#[test]
fn test_format_time_only() {
assert_eq!(format_time_only(0, TimeUnit::Seconds), "00:00:00");
let ts = 12 * 3600 + 34 * 60 + 56;
assert_eq!(format_time_only(ts, TimeUnit::Seconds), "12:34:56");
}
#[test]
fn test_roundtrip() {
use super::super::parse::parse_iso8601;
let test_cases = vec![
"1970-01-01T00:00:00Z",
"2000-01-01T12:34:56Z",
"2020-02-29T23:59:59Z",
];
for expected in test_cases {
let (ts, unit) = parse_iso8601(expected).unwrap();
let formatted = format_iso8601(ts, unit);
assert_eq!(formatted, expected);
}
}
}