#![allow(dead_code)]
use std::time::SystemTime;
use time::{OffsetDateTime, Time};
pub(crate) fn truncate_subsecs(time: SystemTime) -> SystemTime {
let date_time = OffsetDateTime::from(time);
let time = date_time.time();
date_time
.replace_time(
Time::from_hms(time.hour(), time.minute(), time.second()).expect("was already a time"),
)
.into()
}
pub(crate) fn format_date(time: SystemTime) -> String {
let time = OffsetDateTime::from(time);
format!(
"{:04}{:02}{:02}",
time.year(),
u8::from(time.month()),
time.day()
)
}
pub(crate) fn format_date_time(time: SystemTime) -> String {
let time = OffsetDateTime::from(time);
format!(
"{:04}{:02}{:02}T{:02}{:02}{:02}Z",
time.year(),
u8::from(time.month()),
time.day(),
time.hour(),
time.minute(),
time.second()
)
}
#[cfg(test)]
pub(crate) mod test_parsers {
use std::{borrow::Cow, error::Error, fmt, time::SystemTime};
use time::format_description;
use time::{Date, PrimitiveDateTime, Time};
const DATE_TIME_FORMAT: &str = "[year][month][day]T[hour][minute][second]Z";
const DATE_FORMAT: &str = "[year][month][day]";
pub(crate) fn parse_date_time(date_time_str: &str) -> Result<SystemTime, ParseError> {
let date_time = PrimitiveDateTime::parse(
date_time_str,
&format_description::parse(DATE_TIME_FORMAT).unwrap(),
)
.map_err(|err| ParseError(err.to_string().into()))?
.assume_utc();
Ok(date_time.into())
}
pub(crate) fn parse_date(date_str: &str) -> Result<SystemTime, ParseError> {
let date_time = PrimitiveDateTime::new(
Date::parse(date_str, &format_description::parse(DATE_FORMAT).unwrap())
.map_err(|err| ParseError(err.to_string().into()))?,
Time::from_hms(0, 0, 0).unwrap(),
)
.assume_utc();
Ok(date_time.into())
}
#[derive(Debug)]
pub(crate) struct ParseError(Cow<'static, str>);
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "failed to parse time: {}", self.0)
}
}
impl Error for ParseError {}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::date_time::test_parsers::{parse_date, parse_date_time};
use time::format_description::well_known::Rfc3339;
#[cfg(not(any(target_arch = "powerpc", target_arch = "x86")))]
#[test]
fn date_format() {
let time: SystemTime = OffsetDateTime::parse("2039-02-04T23:01:09.104Z", &Rfc3339)
.unwrap()
.into();
assert_eq!("20390204", format_date(time));
let time: SystemTime = OffsetDateTime::parse("0100-01-02T00:00:00.000Z", &Rfc3339)
.unwrap()
.into();
assert_eq!("01000102", format_date(time));
}
#[cfg(not(any(target_arch = "powerpc", target_arch = "x86")))]
#[test]
fn date_time_format() {
let time: SystemTime = OffsetDateTime::parse("2039-02-04T23:01:09.104Z", &Rfc3339)
.unwrap()
.into();
assert_eq!("20390204T230109Z", format_date_time(time));
let time: SystemTime = OffsetDateTime::parse("0100-01-02T00:00:00.000Z", &Rfc3339)
.unwrap()
.into();
assert_eq!("01000102T000000Z", format_date_time(time));
}
#[test]
fn date_time_roundtrip() {
let time = parse_date_time("20150830T123600Z").unwrap();
assert_eq!("20150830T123600Z", format_date_time(time));
}
#[test]
fn date_roundtrip() {
let time = parse_date("20150830").unwrap();
assert_eq!("20150830", format_date(time));
}
#[cfg(not(any(target_arch = "powerpc", target_arch = "x86")))]
#[test]
fn test_truncate_subsecs() {
let time: SystemTime = OffsetDateTime::parse("2039-02-04T23:01:09.104Z", &Rfc3339)
.unwrap()
.into();
let expected: SystemTime = OffsetDateTime::parse("2039-02-04T23:01:09.000Z", &Rfc3339)
.unwrap()
.into();
assert_eq!(expected, truncate_subsecs(time));
}
}