use std::fmt;
use busylib::model::time::TimezoneInfo;
use busylib::types::timestamp::Timestamp;
use serde::Serialize;
use crate::reporter::events::CliEvent;
use crate::reporter::events::fields::{field, write_fields};
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct TimeNowEvent {
timestamp: Timestamp,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct TimeTimezoneEvent(TimezoneInfo);
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct TimeTzlistEvent {
list: Vec<TimezoneInfo>,
}
impl TimeNowEvent {
pub fn new(timestamp: Timestamp) -> Self {
Self { timestamp }
}
}
impl TimeTimezoneEvent {
pub fn new(timezone: TimezoneInfo) -> Self {
Self(timezone)
}
}
impl TimeTzlistEvent {
pub fn new(list: Vec<TimezoneInfo>) -> Self {
Self { list }
}
}
impl From<TimeNowEvent> for CliEvent {
fn from(event: TimeNowEvent) -> Self {
CliEvent::TimeNow(event)
}
}
impl From<TimeTimezoneEvent> for CliEvent {
fn from(event: TimeTimezoneEvent) -> Self {
CliEvent::TimeTimezone(event)
}
}
impl From<TimeTzlistEvent> for CliEvent {
fn from(event: TimeTzlistEvent) -> Self {
CliEvent::TimeTzlist(event)
}
}
impl fmt::Display for TimeNowEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.timestamp.as_str())
}
}
impl fmt::Display for TimeTimezoneEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let timezone = &self.0;
let fields = vec![
field("name", &timezone.name),
field("offset", &timezone.offset),
field("abbr", &timezone.abbr),
];
write_fields(f, &fields)
}
}
impl fmt::Display for TimeTzlistEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (index, timezone) in self.list.iter().enumerate() {
if index > 0 {
f.write_str("\n")?;
}
write!(f, "{} {} {}", timezone.name, timezone.offset, timezone.abbr)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use serde_json::json;
use super::*;
fn amsterdam() -> TimezoneInfo {
TimezoneInfo {
name: "Amsterdam".to_string(),
offset: "+02:00".to_string(),
abbr: "CEST".to_string(),
}
}
#[test]
fn renders_the_clock_bare() {
let event = TimeNowEvent::new(Timestamp::new("2026-08-02T05:23:32+02:00").unwrap());
assert_eq!(event.to_string(), "2026-08-02T05:23:32+02:00");
assert_eq!(
serde_json::to_value(CliEvent::from(event)).unwrap(),
json!({"event": "time_now", "timestamp": "2026-08-02T05:23:32+02:00"})
);
}
#[test]
fn renders_a_time_zone_and_a_list_of_them() {
assert_eq!(
TimeTimezoneEvent::new(amsterdam()).to_string(),
"name: Amsterdam\noffset: +02:00\nabbr: CEST"
);
assert_eq!(
TimeTzlistEvent::new(vec![amsterdam(), amsterdam()]).to_string(),
"Amsterdam +02:00 CEST\nAmsterdam +02:00 CEST"
);
}
}