use super::Timestamp;
use serde::{Serialize, Serializer};
use std::fmt::{Display, Formatter, Result as FmtResult};
#[derive(Debug)]
pub struct TimestampIso8601Display {
timestamp: Timestamp,
with_microseconds: bool,
}
impl TimestampIso8601Display {
pub(super) const fn new(timestamp: Timestamp) -> Self {
Self {
timestamp,
with_microseconds: true,
}
}
pub const fn get(self) -> Timestamp {
self.timestamp
}
#[must_use]
pub const fn with_microseconds(mut self, with_microseconds: bool) -> Self {
self.with_microseconds = with_microseconds;
self
}
}
impl Display for TimestampIso8601Display {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
let year = self.timestamp.0.year();
Display::fmt(&(year / 1000), f)?;
Display::fmt(&(year / 100 % 10), f)?;
Display::fmt(&(year / 10 % 10), f)?;
Display::fmt(&(year % 10), f)?;
f.write_str("-")?;
let month = self.timestamp.0.month() as u8;
Display::fmt(&(month / 10), f)?;
Display::fmt(&(month % 10), f)?;
f.write_str("-")?;
let day = self.timestamp.0.day();
Display::fmt(&(day / 10), f)?;
Display::fmt(&(day % 10), f)?;
f.write_str("T")?;
let hour = self.timestamp.0.hour();
Display::fmt(&(hour / 10), f)?;
Display::fmt(&(hour % 10), f)?;
f.write_str(":")?;
let minute = self.timestamp.0.minute();
Display::fmt(&(minute / 10 % 6), f)?;
Display::fmt(&(minute % 10), f)?;
f.write_str(":")?;
let second = self.timestamp.0.second();
Display::fmt(&(second / 10 % 6), f)?;
Display::fmt(&(second % 10), f)?;
if self.with_microseconds {
f.write_str(".")?;
let microsecond = self.timestamp.0.microsecond();
Display::fmt(&(microsecond / 100_000), f)?;
Display::fmt(&(microsecond / 10_000 % 10), f)?;
Display::fmt(&(microsecond / 1_000 % 10), f)?;
Display::fmt(&(microsecond / 100 % 10), f)?;
Display::fmt(&(microsecond / 10 % 10), f)?;
Display::fmt(&(microsecond % 10), f)?;
}
f.write_str("+00:00")
}
}
impl Serialize for TimestampIso8601Display {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.collect_str(self)
}
}
#[cfg(test)]
mod tests {
use super::{super::Timestamp, TimestampIso8601Display};
use serde::Serialize;
use static_assertions::assert_impl_all;
use std::fmt::Debug;
assert_impl_all!(TimestampIso8601Display: Debug, Send, Serialize, Sync);
#[test]
fn display() {
const LONG: &str = "2020-02-02T02:02:02.020000+00:00";
const SHORT: &str = "2020-02-02T02:02:02+00:00";
const TIME: i64 = 1_580_608_922_020_000;
let mut formatter = Timestamp::from_micros(TIME).expect("non zero").iso_8601();
assert_eq!(LONG, formatter.to_string());
formatter = formatter.with_microseconds(true);
assert_eq!(LONG, formatter.to_string());
formatter = formatter.with_microseconds(false);
assert_eq!(SHORT, formatter.to_string());
}
}