Switch from chrono to time

This commit is contained in:
Roderick van Domburg 2022-01-14 23:28:09 +01:00
parent 7fe13be564
commit dbeeb0f991
No known key found for this signature in database
GPG key ID: A9EF5222A26F0451
12 changed files with 78 additions and 75 deletions

14
Cargo.lock generated
View file

@ -237,7 +237,7 @@ dependencies = [
"libc", "libc",
"num-integer", "num-integer",
"num-traits", "num-traits",
"time", "time 0.1.43",
"winapi", "winapi",
] ]
@ -1369,7 +1369,6 @@ dependencies = [
"base64", "base64",
"byteorder", "byteorder",
"bytes", "bytes",
"chrono",
"dns-sd", "dns-sd",
"env_logger", "env_logger",
"form_urlencoded", "form_urlencoded",
@ -1400,6 +1399,7 @@ dependencies = [
"sha-1 0.10.0", "sha-1 0.10.0",
"shannon", "shannon",
"thiserror", "thiserror",
"time 0.3.5",
"tokio", "tokio",
"tokio-stream", "tokio-stream",
"tokio-tungstenite", "tokio-tungstenite",
@ -1441,7 +1441,6 @@ dependencies = [
"async-trait", "async-trait",
"byteorder", "byteorder",
"bytes", "bytes",
"chrono",
"librespot-core", "librespot-core",
"librespot-protocol", "librespot-protocol",
"log", "log",
@ -2737,6 +2736,15 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "time"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41effe7cfa8af36f439fac33861b66b049edc6f9a32331e2312660529c1c24ad"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "tinyvec" name = "tinyvec"
version = "1.5.1" version = "1.5.1"

View file

@ -17,7 +17,6 @@ aes = "0.7"
base64 = "0.13" base64 = "0.13"
byteorder = "1.4" byteorder = "1.4"
bytes = "1" bytes = "1"
chrono = "0.4"
dns-sd = { version = "0.1", optional = true } dns-sd = { version = "0.1", optional = true }
form_urlencoded = "1.0" form_urlencoded = "1.0"
futures-core = "0.3" futures-core = "0.3"
@ -46,6 +45,7 @@ serde_json = "1.0"
sha-1 = "0.10" sha-1 = "0.10"
shannon = "0.2" shannon = "0.2"
thiserror = "1.0" thiserror = "1.0"
time = "0.3"
tokio = { version = "1", features = ["io-util", "macros", "net", "parking_lot", "rt", "sync", "time"] } tokio = { version = "1", features = ["io-util", "macros", "net", "parking_lot", "rt", "sync", "time"] }
tokio-stream = "0.1" tokio-stream = "0.1"
tokio-tungstenite = { version = "*", default-features = false, features = ["rustls-tls-native-roots"] } tokio-tungstenite = { version = "*", default-features = false, features = ["rustls-tls-native-roots"] }

View file

@ -3,7 +3,6 @@ use std::{
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
}; };
use chrono::Local;
use protobuf::Message; use protobuf::Message;
use thiserror::Error; use thiserror::Error;
use url::Url; use url::Url;
@ -84,9 +83,9 @@ impl CdnUrl {
return Err(CdnUrlError::Unresolved.into()); return Err(CdnUrlError::Unresolved.into());
} }
let now = Local::now(); let now = Date::now_utc();
let url = self.urls.iter().find(|url| match url.1 { let url = self.urls.iter().find(|url| match url.1 {
Some(expiry) => now < expiry.as_utc(), Some(expiry) => now < expiry,
None => true, None => true,
}); });

View file

@ -1,30 +1,27 @@
use std::{convert::TryFrom, fmt::Debug, ops::Deref}; use std::{
convert::{TryFrom, TryInto},
fmt::Debug,
ops::Deref,
};
use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, Utc}; use time::{error::ComponentRange, Date as _Date, OffsetDateTime, PrimitiveDateTime, Time};
use thiserror::Error;
use crate::Error; use crate::Error;
use librespot_protocol as protocol; use librespot_protocol as protocol;
use protocol::metadata::Date as DateMessage; use protocol::metadata::Date as DateMessage;
#[derive(Debug, Error)] impl From<ComponentRange> for Error {
pub enum DateError { fn from(err: ComponentRange) -> Self {
#[error("item has invalid timestamp {0}")] Error::out_of_range(err)
Timestamp(i64),
}
impl From<DateError> for Error {
fn from(err: DateError) -> Self {
Error::invalid_argument(err)
} }
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Date(pub DateTime<Utc>); pub struct Date(pub OffsetDateTime);
impl Deref for Date { impl Deref for Date {
type Target = DateTime<Utc>; type Target = OffsetDateTime;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.0 &self.0
} }
@ -32,42 +29,43 @@ impl Deref for Date {
impl Date { impl Date {
pub fn as_timestamp(&self) -> i64 { pub fn as_timestamp(&self) -> i64 {
self.0.timestamp() self.0.unix_timestamp()
} }
pub fn from_timestamp(timestamp: i64) -> Result<Self, Error> { pub fn from_timestamp(timestamp: i64) -> Result<Self, Error> {
if let Some(date_time) = NaiveDateTime::from_timestamp_opt(timestamp, 0) { let date_time = OffsetDateTime::from_unix_timestamp(timestamp)?;
Ok(Self::from_utc(date_time)) Ok(Self(date_time))
} else {
Err(DateError::Timestamp(timestamp).into())
}
} }
pub fn as_utc(&self) -> DateTime<Utc> { pub fn as_utc(&self) -> OffsetDateTime {
self.0 self.0
} }
pub fn from_utc(date_time: NaiveDateTime) -> Self { pub fn from_utc(date_time: PrimitiveDateTime) -> Self {
Self(DateTime::<Utc>::from_utc(date_time, Utc)) Self(date_time.assume_utc())
}
pub fn now_utc() -> Self {
Self(OffsetDateTime::now_utc())
} }
} }
impl From<&DateMessage> for Date { impl TryFrom<&DateMessage> for Date {
fn from(date: &DateMessage) -> Self { type Error = crate::Error;
let naive_date = NaiveDate::from_ymd( fn try_from(msg: &DateMessage) -> Result<Self, Self::Error> {
date.get_year() as i32, let date = _Date::from_calendar_date(
date.get_month() as u32, msg.get_year(),
date.get_day() as u32, (msg.get_month() as u8).try_into()?,
); msg.get_day() as u8,
let naive_time = NaiveTime::from_hms(date.get_hour() as u32, date.get_minute() as u32, 0); )?;
let naive_datetime = NaiveDateTime::new(naive_date, naive_time); let time = Time::from_hms(msg.get_hour() as u8, msg.get_minute() as u8, 0)?;
Self(DateTime::<Utc>::from_utc(naive_datetime, Utc)) Ok(Self::from_utc(PrimitiveDateTime::new(date, time)))
} }
} }
impl From<DateTime<Utc>> for Date { impl From<OffsetDateTime> for Date {
fn from(date: DateTime<Utc>) -> Self { fn from(datetime: OffsetDateTime) -> Self {
Self(date) Self(datetime)
} }
} }

View file

@ -11,7 +11,6 @@ edition = "2018"
async-trait = "0.1" async-trait = "0.1"
byteorder = "1" byteorder = "1"
bytes = "1" bytes = "1"
chrono = "0.4"
log = "0.4" log = "0.4"
protobuf = "2" protobuf = "2"
thiserror = "1" thiserror = "1"

View file

@ -101,7 +101,7 @@ impl TryFrom<&<Self as Metadata>::Message> for Album {
artists: album.get_artist().try_into()?, artists: album.get_artist().try_into()?,
album_type: album.get_field_type(), album_type: album.get_field_type(),
label: album.get_label().to_owned(), label: album.get_label().to_owned(),
date: album.get_date().into(), date: album.get_date().try_into()?,
popularity: album.get_popularity(), popularity: album.get_popularity(),
genres: album.get_genre().to_vec(), genres: album.get_genre().to_vec(),
covers: album.get_cover().into(), covers: album.get_cover().into(),
@ -111,12 +111,12 @@ impl TryFrom<&<Self as Metadata>::Message> for Album {
copyrights: album.get_copyright().into(), copyrights: album.get_copyright().into(),
restrictions: album.get_restriction().into(), restrictions: album.get_restriction().into(),
related: album.get_related().try_into()?, related: album.get_related().try_into()?,
sale_periods: album.get_sale_period().into(), sale_periods: album.get_sale_period().try_into()?,
cover_group: album.get_cover_group().get_image().into(), cover_group: album.get_cover_group().get_image().into(),
original_title: album.get_original_title().to_owned(), original_title: album.get_original_title().to_owned(),
version_title: album.get_version_title().to_owned(), version_title: album.get_version_title().to_owned(),
type_str: album.get_type_str().to_owned(), type_str: album.get_type_str().to_owned(),
availability: album.get_availability().into(), availability: album.get_availability().try_into()?,
}) })
} }
} }

View file

@ -1,7 +1,5 @@
use std::fmt::Debug; use std::fmt::Debug;
use chrono::Local;
use crate::{ use crate::{
availability::{AudioItemAvailability, Availabilities, UnavailabilityReason}, availability::{AudioItemAvailability, Availabilities, UnavailabilityReason},
episode::Episode, episode::Episode,
@ -12,7 +10,7 @@ use crate::{
use super::file::AudioFiles; use super::file::AudioFiles;
use librespot_core::{session::UserData, spotify_id::SpotifyItemType, Error, Session, SpotifyId}; use librespot_core::{session::UserData, date::Date, spotify_id::SpotifyItemType, Error, Session, SpotifyId};
pub type AudioItemResult = Result<AudioItem, Error>; pub type AudioItemResult = Result<AudioItem, Error>;
@ -93,7 +91,7 @@ pub trait InnerAudioItem {
if !(availability if !(availability
.iter() .iter()
.any(|availability| Local::now() >= availability.start.as_utc())) .any(|availability| Date::now_utc() >= availability.start))
{ {
return Err(UnavailabilityReason::Embargo); return Err(UnavailabilityReason::Embargo);
} }

View file

@ -1,8 +1,8 @@
use std::{fmt::Debug, ops::Deref}; use std::{convert::{TryFrom, TryInto}, fmt::Debug, ops::Deref};
use thiserror::Error; use thiserror::Error;
use crate::util::from_repeated_message; use crate::util::try_from_repeated_message;
use librespot_core::date::Date; use librespot_core::date::Date;
@ -39,13 +39,14 @@ pub enum UnavailabilityReason {
NotWhitelisted, NotWhitelisted,
} }
impl From<&AvailabilityMessage> for Availability { impl TryFrom<&AvailabilityMessage> for Availability {
fn from(availability: &AvailabilityMessage) -> Self { type Error = librespot_core::Error;
Self { fn try_from(availability: &AvailabilityMessage) -> Result<Self, Self::Error> {
Ok(Self {
catalogue_strs: availability.get_catalogue_str().to_vec(), catalogue_strs: availability.get_catalogue_str().to_vec(),
start: availability.get_start().into(), start: availability.get_start().try_into()?,
} })
} }
} }
from_repeated_message!(AvailabilityMessage, Availabilities); try_from_repeated_message!(AvailabilityMessage, Availabilities);

View file

@ -108,7 +108,7 @@ impl TryFrom<&<Self as Metadata>::Message> for Episode {
audio: episode.get_audio().into(), audio: episode.get_audio().into(),
description: episode.get_description().to_owned(), description: episode.get_description().to_owned(),
number: episode.get_number(), number: episode.get_number(),
publish_time: episode.get_publish_time().into(), publish_time: episode.get_publish_time().try_into()?,
covers: episode.get_cover_image().get_image().into(), covers: episode.get_cover_image().get_image().into(),
language: episode.get_language().to_owned(), language: episode.get_language().to_owned(),
is_explicit: episode.get_explicit().to_owned(), is_explicit: episode.get_explicit().to_owned(),
@ -120,7 +120,7 @@ impl TryFrom<&<Self as Metadata>::Message> for Episode {
freeze_frames: episode.get_freeze_frame().get_image().into(), freeze_frames: episode.get_freeze_frame().get_image().into(),
keywords: episode.get_keyword().to_vec(), keywords: episode.get_keyword().to_vec(),
allow_background_playback: episode.get_allow_background_playback(), allow_background_playback: episode.get_allow_background_playback(),
availability: episode.get_availability().into(), availability: episode.get_availability().try_into()?,
external_url: episode.get_external_url().to_owned(), external_url: episode.get_external_url().to_owned(),
episode_type: episode.get_field_type(), episode_type: episode.get_field_type(),
has_music_and_talk: episode.get_music_and_talk(), has_music_and_talk: episode.get_music_and_talk(),

View file

@ -1,6 +1,6 @@
use std::{fmt::Debug, ops::Deref}; use std::{convert::{TryFrom, TryInto}, fmt::Debug, ops::Deref};
use crate::{restriction::Restrictions, util::from_repeated_message}; use crate::{restriction::Restrictions, util::try_from_repeated_message};
use librespot_core::date::Date; use librespot_core::date::Date;
@ -24,14 +24,15 @@ impl Deref for SalePeriods {
} }
} }
impl From<&SalePeriodMessage> for SalePeriod { impl TryFrom<&SalePeriodMessage> for SalePeriod {
fn from(sale_period: &SalePeriodMessage) -> Self { type Error = librespot_core::Error;
Self { fn try_from(sale_period: &SalePeriodMessage) -> Result<Self, Self::Error> {
Ok(Self {
restrictions: sale_period.get_restriction().into(), restrictions: sale_period.get_restriction().into(),
start: sale_period.get_start().into(), start: sale_period.get_start().try_into()?,
end: sale_period.get_end().into(), end: sale_period.get_end().try_into()?,
} })
} }
} }
from_repeated_message!(SalePeriodMessage, SalePeriods); try_from_repeated_message!(SalePeriodMessage, SalePeriods);

View file

@ -65,7 +65,7 @@ impl TryFrom<&<Self as Metadata>::Message> for Show {
keywords: show.get_keyword().to_vec(), keywords: show.get_keyword().to_vec(),
media_type: show.get_media_type(), media_type: show.get_media_type(),
consumption_order: show.get_consumption_order(), consumption_order: show.get_consumption_order(),
availability: show.get_availability().into(), availability: show.get_availability().try_into()?,
trailer_uri: SpotifyId::from_uri(show.get_trailer_uri())?, trailer_uri: SpotifyId::from_uri(show.get_trailer_uri())?,
has_music_and_talk: show.get_music_and_talk(), has_music_and_talk: show.get_music_and_talk(),
is_audiobook: show.get_is_audiobook(), is_audiobook: show.get_is_audiobook(),

View file

@ -4,7 +4,6 @@ use std::{
ops::Deref, ops::Deref,
}; };
use chrono::Local;
use uuid::Uuid; use uuid::Uuid;
use crate::{ use crate::{
@ -77,7 +76,7 @@ impl InnerAudioItem for Track {
}; };
// TODO: check meaning of earliest_live_timestamp in // TODO: check meaning of earliest_live_timestamp in
let availability = if Local::now() < track.earliest_live_timestamp.as_utc() { let availability = if Date::now_utc() < track.earliest_live_timestamp {
Err(UnavailabilityReason::Embargo) Err(UnavailabilityReason::Embargo)
} else { } else {
Self::available_for_user( Self::available_for_user(
@ -130,12 +129,12 @@ impl TryFrom<&<Self as Metadata>::Message> for Track {
restrictions: track.get_restriction().into(), restrictions: track.get_restriction().into(),
files: track.get_file().into(), files: track.get_file().into(),
alternatives: track.get_alternative().try_into()?, alternatives: track.get_alternative().try_into()?,
sale_periods: track.get_sale_period().into(), sale_periods: track.get_sale_period().try_into()?,
previews: track.get_preview().into(), previews: track.get_preview().into(),
tags: track.get_tags().to_vec(), tags: track.get_tags().to_vec(),
earliest_live_timestamp: track.get_earliest_live_timestamp().try_into()?, earliest_live_timestamp: track.get_earliest_live_timestamp().try_into()?,
has_lyrics: track.get_has_lyrics(), has_lyrics: track.get_has_lyrics(),
availability: track.get_availability().into(), availability: track.get_availability().try_into()?,
licensor: Uuid::from_slice(track.get_licensor().get_uuid()) licensor: Uuid::from_slice(track.get_licensor().get_uuid())
.unwrap_or_else(|_| Uuid::nil()), .unwrap_or_else(|_| Uuid::nil()),
language_of_performance: track.get_language_of_performance().to_vec(), language_of_performance: track.get_language_of_performance().to_vec(),