use crate::{Context, Localize};
use fixed_decimal::Decimal;
use jiff::{SpanRound, Timestamp, Unit, tz::TimeZone};
use writeable::Writeable;
impl Localize for Timestamp {
fn localize(&self, context: &Context, buffer: &mut String) {
let current_timestamp = Self::now();
let current_datetime = current_timestamp.to_zoned(TimeZone::UTC).datetime();
let unformatted_span = current_timestamp
.until(*self)
.unwrap()
.round(
SpanRound::new()
.largest(Unit::Year)
.relative(current_datetime),
)
.unwrap();
let units: [(Unit, i64); 7] = [
(Unit::Year, i64::from(unformatted_span.get_years())),
(Unit::Month, i64::from(unformatted_span.get_months())),
(Unit::Week, i64::from(unformatted_span.get_weeks())),
(Unit::Day, i64::from(unformatted_span.get_days())),
(Unit::Hour, i64::from(unformatted_span.get_hours())),
(Unit::Minute, unformatted_span.get_minutes()),
(Unit::Second, unformatted_span.get_seconds()),
];
let selected_unit = units
.iter()
.find(|(_unit, value)| value.abs() > 0)
.map_or(Unit::Second, |(unit, _value)| *unit);
let rounding_options = SpanRound::new()
.smallest(selected_unit)
.largest(selected_unit)
.relative(current_datetime);
let formatted_span = current_timestamp
.until(*self)
.unwrap()
.round(rounding_options)
.unwrap();
let selected_value = match selected_unit {
Unit::Year => i64::from(formatted_span.get_years()),
Unit::Month => i64::from(formatted_span.get_months()),
Unit::Week => i64::from(formatted_span.get_weeks()),
Unit::Day => i64::from(formatted_span.get_days()),
Unit::Hour => i64::from(formatted_span.get_hours()),
Unit::Minute => formatted_span.get_minutes(),
Unit::Second => formatted_span.get_seconds(),
_ => unreachable!(),
};
let formatter = context.relative_time_formatter(selected_unit).unwrap();
let decimal = Decimal::from(selected_value);
let formatted_text = formatter.format(decimal);
formatted_text.write_to(buffer).unwrap();
}
}