2024-03-31 16:33:28 +00:00
|
|
|
use std::{fmt::Debug, ops::Deref};
|
2021-12-07 22:22:24 +00:00
|
|
|
|
2022-09-01 20:35:03 +00:00
|
|
|
use time::{
|
|
|
|
error::ComponentRange, format_description::well_known::Iso8601, Date as _Date, OffsetDateTime,
|
|
|
|
PrimitiveDateTime, Time,
|
|
|
|
};
|
2021-12-07 22:22:24 +00:00
|
|
|
|
2021-12-26 20:18:42 +00:00
|
|
|
use crate::Error;
|
|
|
|
|
2021-12-07 22:22:24 +00:00
|
|
|
use librespot_protocol as protocol;
|
|
|
|
use protocol::metadata::Date as DateMessage;
|
|
|
|
|
2022-01-14 22:28:09 +00:00
|
|
|
impl From<ComponentRange> for Error {
|
|
|
|
fn from(err: ComponentRange) -> Self {
|
|
|
|
Error::out_of_range(err)
|
2021-12-26 20:18:42 +00:00
|
|
|
}
|
2021-12-16 21:42:37 +00:00
|
|
|
}
|
|
|
|
|
2021-12-07 22:22:24 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
2022-01-14 22:28:09 +00:00
|
|
|
pub struct Date(pub OffsetDateTime);
|
2021-12-07 22:22:24 +00:00
|
|
|
|
|
|
|
impl Deref for Date {
|
2022-01-14 22:28:09 +00:00
|
|
|
type Target = OffsetDateTime;
|
2021-12-07 22:22:24 +00:00
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Date {
|
2022-07-28 16:46:16 +00:00
|
|
|
pub fn as_timestamp_ms(&self) -> i64 {
|
|
|
|
(self.0.unix_timestamp_nanos() / 1_000_000) as i64
|
2021-12-07 22:22:24 +00:00
|
|
|
}
|
|
|
|
|
2022-07-28 16:46:16 +00:00
|
|
|
pub fn from_timestamp_ms(timestamp: i64) -> Result<Self, Error> {
|
|
|
|
let date_time = OffsetDateTime::from_unix_timestamp_nanos(timestamp as i128 * 1_000_000)?;
|
2022-01-14 22:28:09 +00:00
|
|
|
Ok(Self(date_time))
|
2021-12-07 22:22:24 +00:00
|
|
|
}
|
|
|
|
|
2022-01-14 22:28:09 +00:00
|
|
|
pub fn as_utc(&self) -> OffsetDateTime {
|
2021-12-07 22:22:24 +00:00
|
|
|
self.0
|
|
|
|
}
|
|
|
|
|
2022-01-14 22:28:09 +00:00
|
|
|
pub fn from_utc(date_time: PrimitiveDateTime) -> Self {
|
|
|
|
Self(date_time.assume_utc())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn now_utc() -> Self {
|
|
|
|
Self(OffsetDateTime::now_utc())
|
2021-12-07 22:22:24 +00:00
|
|
|
}
|
2022-09-01 20:35:03 +00:00
|
|
|
|
|
|
|
pub fn from_iso8601(input: &str) -> Result<Self, Error> {
|
|
|
|
let date_time = OffsetDateTime::parse(input, &Iso8601::DEFAULT)?;
|
|
|
|
Ok(Self(date_time))
|
|
|
|
}
|
2021-12-07 22:22:24 +00:00
|
|
|
}
|
|
|
|
|
2022-01-14 22:28:09 +00:00
|
|
|
impl TryFrom<&DateMessage> for Date {
|
|
|
|
type Error = crate::Error;
|
|
|
|
fn try_from(msg: &DateMessage) -> Result<Self, Self::Error> {
|
2022-01-25 19:02:41 +00:00
|
|
|
// Some metadata contains a year, but no month. In that case just set January.
|
|
|
|
let month = if msg.has_month() {
|
2023-01-17 20:46:14 +00:00
|
|
|
msg.month() as u8
|
2022-01-25 19:02:41 +00:00
|
|
|
} else {
|
|
|
|
1
|
|
|
|
};
|
|
|
|
|
|
|
|
// Having no day will work, but may be unexpected: it will imply the last day
|
|
|
|
// of the month before. So prevent that, and just set day 1.
|
2023-01-17 20:46:14 +00:00
|
|
|
let day = if msg.has_day() { msg.day() as u8 } else { 1 };
|
2022-01-25 19:02:41 +00:00
|
|
|
|
2023-01-17 20:46:14 +00:00
|
|
|
let date = _Date::from_calendar_date(msg.year(), month.try_into()?, day)?;
|
|
|
|
let time = Time::from_hms(msg.hour() as u8, msg.minute() as u8, 0)?;
|
2022-01-14 22:28:09 +00:00
|
|
|
Ok(Self::from_utc(PrimitiveDateTime::new(date, time)))
|
2021-12-07 22:22:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-14 22:28:09 +00:00
|
|
|
impl From<OffsetDateTime> for Date {
|
|
|
|
fn from(datetime: OffsetDateTime) -> Self {
|
|
|
|
Self(datetime)
|
2021-12-07 22:22:24 +00:00
|
|
|
}
|
|
|
|
}
|