refactor: replace chrono with time-rs

This commit is contained in:
ThetaDev 2022-10-18 22:53:09 +02:00
parent b5f6b7a174
commit 3c1cc92461
16 changed files with 195 additions and 112 deletions

View file

@ -13,7 +13,7 @@ include = ["/src", "README.md", "LICENSE", "!snapshots"]
members = [".", "codegen", "cli"]
[features]
default = ["default-tls"]
default = ["default-tls", "rss"]
all = ["rss", "html"]
rss = ["quick-xml"]
@ -38,8 +38,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.82"
serde_with = {version = "2.0.0", features = ["json"] }
rand = "0.8.5"
chrono = {version = "0.4.19", default-features = false, features = ["clock", "serde"]}
chronoutil = "0.2.3"
time = {version = "0.3.15", features = ["macros", "serde", "serde-well-known"]}
futures = "0.3.21"
indicatif = "0.17.0"
filenamify = "0.1.0"

View file

@ -1,6 +1,7 @@
use std::borrow::Cow;
use serde::Serialize;
use time::OffsetDateTime;
use url::Url;
use crate::{
@ -191,7 +192,8 @@ impl MapResponse<Channel<ChannelInfo>> for response::Channel {
lang,
&meta.joined_date_text,
&mut warnings,
),
)
.map(OffsetDateTime::date),
view_count: meta
.view_count_text
.and_then(|txt| util::parse_numeric_or_warn(&txt, &mut warnings)),

View file

@ -18,13 +18,13 @@ mod channel_rss;
use std::sync::Arc;
use std::{borrow::Cow, fmt::Debug};
use chrono::{DateTime, Duration, Utc};
use fancy_regex::Regex;
use log::{debug, error, warn};
use once_cell::sync::Lazy;
use rand::Rng;
use reqwest::{header, Client, ClientBuilder, Request, RequestBuilder, Response};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use time::{Duration, OffsetDateTime};
use tokio::sync::RwLock;
use crate::{
@ -240,7 +240,8 @@ enum CacheEntry<T> {
#[default]
None,
Some {
last_update: DateTime<Utc>,
#[serde(with = "time::serde::rfc3339")]
last_update: OffsetDateTime,
data: T,
},
}
@ -254,7 +255,7 @@ impl<T> CacheEntry<T> {
fn get(&self) -> Option<&T> {
match self {
CacheEntry::Some { last_update, data } => {
if last_update < &(Utc::now() - Duration::hours(24)) {
if last_update < &(OffsetDateTime::now_utc() - Duration::hours(24)) {
None
} else {
Some(data)
@ -268,7 +269,7 @@ impl<T> CacheEntry<T> {
impl<T> From<T> for CacheEntry<T> {
fn from(f: T) -> Self {
Self::Some {
last_update: Utc::now(),
last_update: OffsetDateTime::now_utc(),
data: f,
}
}

View file

@ -1,5 +1,7 @@
use std::{borrow::Cow, convert::TryFrom};
use time::OffsetDateTime;
use crate::{
deobfuscate::Deobfuscator,
error::{Error, ExtractionError},
@ -152,9 +154,9 @@ impl MapResponse<Playlist> for response::Playlist {
.and_then(|link| ChannelId::try_from(link).ok());
let mut warnings = video_items.warnings;
let last_update = last_update_txt
.as_ref()
.and_then(|txt| timeago::parse_textual_date_or_warn(lang, txt, &mut warnings));
let last_update = last_update_txt.as_ref().and_then(|txt| {
timeago::parse_textual_date_or_warn(lang, txt, &mut warnings).map(OffsetDateTime::date)
});
Ok(MapResult {
c: Playlist {

View file

@ -1,5 +1,5 @@
use chrono::{DateTime, Utc};
use serde::Deserialize;
use time::OffsetDateTime;
use super::Thumbnail;
@ -9,8 +9,8 @@ pub(crate) struct ChannelRss {
pub channel_id: String,
#[serde(rename = "$unflatten=title")]
pub title: String,
#[serde(rename = "$unflatten=published")]
pub create_date: DateTime<Utc>,
#[serde(rename = "$unflatten=published", with = "time::serde::rfc3339")]
pub create_date: OffsetDateTime,
pub entry: Vec<Entry>,
}
@ -20,10 +20,10 @@ pub(crate) struct Entry {
pub video_id: String,
#[serde(rename = "$unflatten=title")]
pub title: String,
#[serde(rename = "$unflatten=published")]
pub published: DateTime<Utc>,
#[serde(rename = "$unflatten=updated")]
pub updated: DateTime<Utc>,
#[serde(rename = "$unflatten=published", with = "time::serde::rfc3339")]
pub published: OffsetDateTime,
#[serde(rename = "$unflatten=updated", with = "time::serde::rfc3339")]
pub updated: OffsetDateTime,
#[serde(rename = "$unflatten=media:group")]
pub media_group: MediaGroup,
}

View file

@ -1,6 +1,6 @@
use chrono::TimeZone;
use serde::Deserialize;
use serde_with::{json::JsonString, serde_as, DefaultOnError, VecSkipError};
use time::OffsetDateTime;
use super::{ChannelBadge, ContinuationEndpoint, Thumbnails};
use crate::{
@ -342,12 +342,7 @@ impl<T> YouTubeListMapper<T> {
publish_date: video
.upcoming_event_data
.as_ref()
.map(|upc| {
chrono::Local.from_utc_datetime(&chrono::NaiveDateTime::from_timestamp(
upc.start_time,
0,
))
})
.and_then(|upc| OffsetDateTime::from_unix_timestamp(upc.start_time).ok())
.or_else(|| {
video
.published_time_text

View file

@ -143,7 +143,7 @@ Channel(
),
],
content: ChannelInfo(
create_date: Some("2009-04-04T00:00:00+02:00"),
create_date: Some("2009-04-04"),
view_count: Some(186854342),
links: [
("EEVblog Web Site", "http://www.eevblog.com/"),

View file

@ -160,7 +160,7 @@ Channel(
),
],
channel: None,
publish_date: Some("2022-09-27T18:00:00+02:00"),
publish_date: Some("2022-09-27T16:00:00Z"),
publish_date_txt: None,
view_count: Some(237),
is_live: false,

View file

@ -5,13 +5,14 @@ mod paginator;
pub mod richtext;
pub use paginator::Paginator;
use serde_with::serde_as;
use std::ops::Range;
use chrono::{DateTime, Local, Utc};
use serde::{Deserialize, Serialize};
use time::{Date, OffsetDateTime};
use crate::{error::Error, util};
use crate::{error::Error, serializer::DateYmd, util};
use self::richtext::RichText;
@ -437,6 +438,7 @@ pub struct Subtitle {
*/
/// YouTube playlist
#[serde_as]
#[derive(Clone, Debug, Serialize, Deserialize)]
#[non_exhaustive]
pub struct Playlist {
@ -455,7 +457,8 @@ pub struct Playlist {
/// Channel of the playlist
pub channel: Option<ChannelId>,
/// Last update date
pub last_update: Option<DateTime<Local>>,
#[serde_as(as = "Option<DateYmd>")]
pub last_update: Option<Date>,
/// Textual last update date
pub last_update_txt: Option<String>,
}
@ -512,7 +515,8 @@ pub struct VideoDetails {
/// Video publishing date. Start date in case of a livestream.
///
/// [`None`] if the date could not be parsed.
pub publish_date: Option<DateTime<Local>>,
#[serde(with = "time::serde::rfc3339::option")]
pub publish_date: Option<OffsetDateTime>,
/// Textual video publishing date (e.g. `Aug 2, 2013`, depends on language)
pub publish_date_txt: String,
/// Is the video a livestream?
@ -616,7 +620,8 @@ pub struct Comment {
/// Comment publishing date.
///
/// [`None`] if the date could not be parsed.
pub publish_date: Option<DateTime<Local>>,
#[serde(with = "time::serde::rfc3339::option")]
pub publish_date: Option<OffsetDateTime>,
/// Textual comment publish date (e.g. `14 hours ago`), depends on language setting
pub publish_date_txt: String,
/// Number of comment likes
@ -675,11 +680,13 @@ pub struct Channel<T> {
}
/// Additional channel metadata fetched from the "About" tab.
#[serde_as]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive]
pub struct ChannelInfo {
/// Channel creation date
pub create_date: Option<DateTime<Local>>,
#[serde_as(as = "Option<DateYmd>")]
pub create_date: Option<Date>,
/// Channel view count
pub view_count: Option<u64>,
/// Links to other websites or social media profiles
@ -697,7 +704,8 @@ pub struct ChannelRss {
/// List of the latest channel videos
pub videos: Vec<ChannelRssVideo>,
/// Channel creation date (second-accurate).
pub create_date: DateTime<Utc>,
#[serde(with = "time::serde::rfc3339")]
pub create_date: OffsetDateTime,
}
/// YouTube video fetched from a channel's RSS feed
@ -713,9 +721,11 @@ pub struct ChannelRssVideo {
/// Video thumbnail
pub thumbnail: Thumbnail,
/// Video publishing date (second-accurate).
pub publish_date: DateTime<Utc>,
#[serde(with = "time::serde::rfc3339")]
pub publish_date: OffsetDateTime,
/// Date and time when the RSS feed entry was last updated.
pub update_date: DateTime<Utc>,
#[serde(with = "time::serde::rfc3339")]
pub update_date: OffsetDateTime,
/// Number of views / current viewers in case of a livestream.
pub view_count: u64,
/// Number of likes
@ -767,7 +777,8 @@ pub struct VideoItem {
/// Video publishing date.
///
/// [`None`] if the date could not be parsed.
pub publish_date: Option<DateTime<Local>>,
#[serde(with = "time::serde::rfc3339::option")]
pub publish_date: Option<OffsetDateTime>,
/// Textual video publish date (e.g. `11 months ago`, depends on language)
///
/// Is [`None`] for livestreams.

View file

@ -6,13 +6,17 @@ use std::{
path::{Path, PathBuf},
};
use chrono::{DateTime, Local};
use log::error;
use serde::{Deserialize, Serialize};
use time::macros::format_description;
use time::OffsetDateTime;
use crate::deobfuscate::DeobfData;
use crate::error::Error;
const FILENAME_FORMAT: &[time::format_description::FormatItem] =
format_description!("[year]-[month]-[day]_[hour]-[minute]-[second]");
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct Report {
@ -40,7 +44,8 @@ pub struct Info {
/// Package version (`0.1.0`)
pub version: String,
/// Date/Time when the event occurred
pub date: DateTime<Local>,
#[serde(with = "time::serde::rfc3339")]
pub date: OffsetDateTime,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@ -76,7 +81,7 @@ impl Default for Info {
Self {
package: "rustypipe".to_owned(),
version: "0.1.0".to_owned(),
date: chrono::Local::now(),
date: OffsetDateTime::now_utc(),
}
}
}
@ -126,7 +131,7 @@ fn get_report_path(root: &Path, report: &Report, ext: &str) -> Result<PathBuf, E
let filename_prefix = format!(
"{}_{:?}",
report.info.date.format("%F_%H-%M-%S"),
report.info.date.format(FILENAME_FORMAT).unwrap_or_default(),
report.level
);

50
src/serializer/date.rs Normal file
View file

@ -0,0 +1,50 @@
use serde::{
de::{self, Visitor},
ser, Serialize,
};
use serde_with::{DeserializeAs, SerializeAs};
use time::{macros::format_description, Date};
const YMD_FORMAT: &[time::format_description::FormatItem] =
format_description!("[year]-[month]-[day]");
pub struct DateYmd;
impl SerializeAs<Date> for DateYmd {
fn serialize_as<S>(date: &Date, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
date.format(YMD_FORMAT)
.map_err(ser::Error::custom)?
.serialize(serializer)
}
}
impl<'de> DeserializeAs<'de, Date> for DateYmd {
fn deserialize_as<D>(deserializer: D) -> Result<Date, D::Error>
where
D: serde::Deserializer<'de>,
{
struct DateYmdVisitor;
impl<'de> Visitor<'de> for DateYmdVisitor {
type Value = Date;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a YYYY-MM-DD formatted date")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Date::parse(v, YMD_FORMAT).map_err(|_| {
de::Error::invalid_value(de::Unexpected::Str(v), &"a YYYY-MM-DD formatted date")
})
}
}
deserializer.deserialize_str(DateYmdVisitor)
}
}

View file

@ -1,8 +1,10 @@
pub mod text;
mod date;
mod range;
mod vec_log_err;
pub use date::DateYmd;
pub use range::Range;
pub use vec_log_err::VecLogError;

View file

@ -17,8 +17,8 @@
use std::ops::Mul;
use chrono::{DateTime, Duration, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone};
use serde::{Deserialize, Serialize};
use time::{Date, Duration, OffsetDateTime};
use crate::{
param::Language,
@ -42,7 +42,7 @@ pub struct TimeAgo {
/// - "2 months ago" => `ParsedDate::Relative(TimeAgo {n: 2, unit: TimeUnit::Month})`
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ParsedDate {
Absolute(NaiveDate),
Absolute(Date),
Relative(TimeAgo),
}
@ -82,27 +82,25 @@ impl Mul<u8> for TimeAgo {
}
}
impl From<TimeAgo> for DateTime<Local> {
impl From<TimeAgo> for OffsetDateTime {
fn from(ta: TimeAgo) -> Self {
let ts = Local::now();
let ts = OffsetDateTime::now_utc();
match ta.unit {
TimeUnit::Second => ts - Duration::seconds(ta.n as i64),
TimeUnit::Minute => ts - Duration::minutes(ta.n as i64),
TimeUnit::Hour => ts - Duration::hours(ta.n as i64),
TimeUnit::Day => ts - Duration::days(ta.n as i64),
TimeUnit::Week => ts - Duration::weeks(ta.n as i64),
TimeUnit::Month => chronoutil::shift_months(ts, -(ta.n as i32)),
TimeUnit::Year => chronoutil::shift_years(ts, -(ta.n as i32)),
TimeUnit::Month => ts.replace_date(util::shift_months(ts.date(), -(ta.n as i32))),
TimeUnit::Year => ts.replace_date(util::shift_years(ts.date(), -(ta.n as i32))),
}
}
}
impl From<ParsedDate> for DateTime<Local> {
impl From<ParsedDate> for OffsetDateTime {
fn from(date: ParsedDate) -> Self {
match date {
ParsedDate::Absolute(date) => Local
.from_local_datetime(&NaiveDateTime::new(date, NaiveTime::from_hms(0, 0, 0)))
.unwrap(),
ParsedDate::Absolute(date) => date.with_hms(0, 0, 0).unwrap().assume_utc(),
ParsedDate::Relative(timeago) => timeago.into(),
}
}
@ -180,7 +178,7 @@ pub fn parse_timeago(lang: Language, textual_date: &str) -> Option<TimeAgo> {
/// Parse a TimeAgo string (e.g. "29 minutes ago") into a Chrono DateTime object.
///
/// Returns None if the date could not be parsed.
pub fn parse_timeago_to_dt(lang: Language, textual_date: &str) -> Option<DateTime<Local>> {
pub fn parse_timeago_to_dt(lang: Language, textual_date: &str) -> Option<OffsetDateTime> {
parse_timeago(lang, textual_date).map(|ta| ta.into())
}
@ -219,10 +217,9 @@ pub fn parse_textual_date(lang: Language, textual_date: &str) -> Option<ParsedDa
}
match (y, m, d) {
(Some(y), Some(m), Some(d)) => {
NaiveDate::from_ymd_opt(y.into(), m.into(), d.into())
.map(ParsedDate::Absolute)
}
(Some(y), Some(m), Some(d)) => util::month_from_n(m as u8)
.and_then(|m| Date::from_calendar_date(y.into(), m, d as u8).ok())
.map(ParsedDate::Absolute),
_ => None,
}
} else {
@ -236,7 +233,7 @@ pub fn parse_textual_date(lang: Language, textual_date: &str) -> Option<ParsedDa
/// Parse a textual date (e.g. "29 minutes ago" or "Jul 2, 2014") into a Chrono DateTime object.
///
/// Returns None if the date could not be parsed.
pub fn parse_textual_date_to_dt(lang: Language, textual_date: &str) -> Option<DateTime<Local>> {
pub fn parse_textual_date_to_dt(lang: Language, textual_date: &str) -> Option<OffsetDateTime> {
parse_textual_date(lang, textual_date).map(|ta| ta.into())
}
@ -244,7 +241,7 @@ pub(crate) fn parse_textual_date_or_warn(
lang: Language,
textual_date: &str,
warnings: &mut Vec<String>,
) -> Option<DateTime<Local>> {
) -> Option<OffsetDateTime> {
let res = parse_textual_date_to_dt(lang, textual_date);
if res.is_none() {
warnings.push(format!("could not parse timeago `{}`", textual_date));
@ -256,8 +253,8 @@ pub(crate) fn parse_textual_date_or_warn(
mod tests {
use std::{collections::BTreeMap, fs::File, io::BufReader, path::Path};
use chrono::Datelike;
use rstest::rstest;
use time::macros::{date, datetime};
use super::*;
@ -494,7 +491,7 @@ mod tests {
#[case(
Language::En,
"Last updated on Jun 04, 2003",
Some(ParsedDate::Absolute(NaiveDate::from_ymd(2003, 6, 4)))
Some(ParsedDate::Absolute(date!(2003-6-4)))
)]
fn t_parse_date(
#[case] lang: Language,
@ -546,73 +543,73 @@ mod tests {
);
assert_eq!(
parse_textual_date(*lang, samples.get("Jan").unwrap()),
Some(ParsedDate::Absolute(NaiveDate::from_ymd(2020, 1, 3))),
Some(ParsedDate::Absolute(date!(2020 - 1 - 3))),
"lang: {}",
lang
);
assert_eq!(
parse_textual_date(*lang, samples.get("Feb").unwrap()),
Some(ParsedDate::Absolute(NaiveDate::from_ymd(2016, 2, 7))),
Some(ParsedDate::Absolute(date!(2016 - 2 - 7))),
"lang: {}",
lang
);
assert_eq!(
parse_textual_date(*lang, samples.get("Mar").unwrap()),
Some(ParsedDate::Absolute(NaiveDate::from_ymd(2015, 3, 9))),
Some(ParsedDate::Absolute(date!(2015 - 3 - 9))),
"lang: {}",
lang
);
assert_eq!(
parse_textual_date(*lang, samples.get("Apr").unwrap()),
Some(ParsedDate::Absolute(NaiveDate::from_ymd(2017, 4, 2))),
Some(ParsedDate::Absolute(date!(2017 - 4 - 2))),
"lang: {}",
lang
);
assert_eq!(
parse_textual_date(*lang, samples.get("May").unwrap()),
Some(ParsedDate::Absolute(NaiveDate::from_ymd(2014, 5, 22))),
Some(ParsedDate::Absolute(date!(2014 - 5 - 22))),
"lang: {}",
lang
);
assert_eq!(
parse_textual_date(*lang, samples.get("Jun").unwrap()),
Some(ParsedDate::Absolute(NaiveDate::from_ymd(2014, 6, 28))),
Some(ParsedDate::Absolute(date!(2014 - 6 - 28))),
"lang: {}",
lang
);
assert_eq!(
parse_textual_date(*lang, samples.get("Jul").unwrap()),
Some(ParsedDate::Absolute(NaiveDate::from_ymd(2014, 7, 2))),
Some(ParsedDate::Absolute(date!(2014 - 7 - 2))),
"lang: {}",
lang
);
assert_eq!(
parse_textual_date(*lang, samples.get("Aug").unwrap()),
Some(ParsedDate::Absolute(NaiveDate::from_ymd(2015, 8, 23))),
Some(ParsedDate::Absolute(date!(2015 - 8 - 23))),
"lang: {}",
lang
);
assert_eq!(
parse_textual_date(*lang, samples.get("Sep").unwrap()),
Some(ParsedDate::Absolute(NaiveDate::from_ymd(2018, 9, 16))),
Some(ParsedDate::Absolute(date!(2018 - 9 - 16))),
"lang: {}",
lang
);
assert_eq!(
parse_textual_date(*lang, samples.get("Oct").unwrap()),
Some(ParsedDate::Absolute(NaiveDate::from_ymd(2014, 10, 31))),
Some(ParsedDate::Absolute(date!(2014 - 10 - 31))),
"lang: {}",
lang
);
assert_eq!(
parse_textual_date(*lang, samples.get("Nov").unwrap()),
Some(ParsedDate::Absolute(NaiveDate::from_ymd(2016, 11, 3))),
Some(ParsedDate::Absolute(date!(2016 - 11 - 3))),
"lang: {}",
lang
);
assert_eq!(
parse_textual_date(*lang, samples.get("Dec").unwrap()),
Some(ParsedDate::Absolute(NaiveDate::from_ymd(2021, 12, 24))),
Some(ParsedDate::Absolute(date!(2021 - 12 - 24))),
"lang: {}",
lang
);
@ -623,19 +620,11 @@ mod tests {
fn t_to_datetime() {
// Absolute date
let date = parse_textual_date_to_dt(Language::En, "Last updated on Jan 3, 2020").unwrap();
assert_eq!(
date,
Local
.from_local_datetime(&NaiveDateTime::new(
NaiveDate::from_ymd(2020, 1, 3),
NaiveTime::from_hms(0, 0, 0)
))
.unwrap()
);
assert_eq!(date, datetime!(2020-1-3 0:00 +0));
// Relative date
let date = parse_textual_date_to_dt(Language::En, "1 year ago").unwrap();
let now = Local::now();
let now = OffsetDateTime::now_utc();
assert_eq!(date.year(), now.year() - 1);
}
}

44
src/util/date.rs Normal file
View file

@ -0,0 +1,44 @@
use time::{Date, Month};
pub const fn month_from_n(n: u8) -> Option<Month> {
match n {
1 => Some(Month::January),
2 => Some(Month::February),
3 => Some(Month::March),
4 => Some(Month::April),
5 => Some(Month::May),
6 => Some(Month::June),
7 => Some(Month::July),
8 => Some(Month::August),
9 => Some(Month::September),
10 => Some(Month::October),
11 => Some(Month::November),
12 => Some(Month::December),
_ => None,
}
}
/// Shift a date by the given number of months.
/// Ambiguous month-ends are shifted backwards as necessary.
pub fn shift_months(date: Date, months: i32) -> Date {
let mut year = date.year() + (date.month() as i32 + months) / 12;
let mut month = (date.month() as i32 + months) % 12;
let mut day = date.day();
if month < 1 {
year -= 1;
month += 12;
}
let month = month_from_n(month as u8).unwrap();
let month_days = time::util::days_in_year_month(year, month);
day = day.min(month_days);
Date::from_calendar_date(year, month, day).unwrap()
}
/// Shift a date by the given number of years.
/// Ambiguous month-ends are shifted backwards as necessary.
pub fn shift_years(date: Date, years: i32) -> Date {
shift_months(date, years * 12)
}

View file

@ -1,7 +1,9 @@
mod date;
mod protobuf;
pub mod dictionary;
pub use date::{month_from_n, shift_months, shift_years};
pub use protobuf::ProtoBuilder;
use std::{

View file

@ -1,7 +1,8 @@
use std::collections::HashSet;
use chrono::Datelike;
use rstest::rstest;
use time::macros::{date, datetime};
use time::OffsetDateTime;
use rustypipe::client::{ClientType, RustyPipe};
use rustypipe::error::{Error, ExtractionError};
@ -417,9 +418,7 @@ async fn get_video_details() {
);
let date = details.publish_date.unwrap();
assert_eq!(date.year(), 2020);
assert_eq!(date.month(), 11);
assert_eq!(date.day(), 17);
assert_eq!(date.date(), date!(2020 - 11 - 17));
assert!(!details.is_live);
assert!(!details.is_ccommons);
@ -470,9 +469,7 @@ async fn get_video_details_music() {
);
let date = details.publish_date.unwrap();
assert_eq!(date.year(), 2020);
assert_eq!(date.month(), 8);
assert_eq!(date.day(), 6);
assert_eq!(date.date(), date!(2020 - 8 - 6));
assert!(!details.is_live);
assert!(!details.is_ccommons);
@ -528,9 +525,7 @@ async fn get_video_details_ccommons() {
);
let date = details.publish_date.unwrap();
assert_eq!(date.year(), 2019);
assert_eq!(date.month(), 12);
assert_eq!(date.day(), 29);
assert_eq!(date.date(), date!(2019 - 12 - 29));
assert!(!details.is_live);
assert!(details.is_ccommons);
@ -585,9 +580,7 @@ async fn get_video_details_chapters() {
);
let date = details.publish_date.unwrap();
assert_eq!(date.year(), 2022);
assert_eq!(date.month(), 9);
assert_eq!(date.day(), 15);
assert_eq!(date.date(), date!(2022 - 9 - 15));
assert!(!details.is_live);
assert!(!details.is_ccommons);
@ -728,9 +721,7 @@ async fn get_video_details_live() {
);
let date = details.publish_date.unwrap();
assert_eq!(date.year(), 2021);
assert_eq!(date.month(), 9);
assert_eq!(date.day(), 23);
assert_eq!(date.date(), date!(2021 - 9 - 23));
assert!(details.is_live);
assert!(!details.is_ccommons);
@ -777,9 +768,7 @@ async fn get_video_details_agegate() {
assert!(details.like_count.is_none(), "like count not hidden");
let date = details.publish_date.unwrap();
assert_eq!(date.year(), 2019);
assert_eq!(date.month(), 1);
assert_eq!(date.day(), 2);
assert_eq!(date.date(), date!(2019 - 1 - 2));
assert!(!details.is_live);
assert!(!details.is_ccommons);
@ -885,7 +874,7 @@ async fn channel_videos(#[case] order: ChannelOrder) {
let first_video = &channel.content.items[0];
let first_video_date = first_video.publish_date.unwrap();
let age_days = (chrono::Local::now() - first_video_date).num_days();
let age_days = (OffsetDateTime::now_utc() - first_video_date).whole_days();
match order {
ChannelOrder::Latest => {
@ -946,9 +935,7 @@ async fn channel_info() {
assert_channel_eevblog(&channel);
let created = channel.content.create_date.unwrap();
assert_eq!(created.year(), 2009);
assert_eq!(created.month(), 4);
assert_eq!(created.day(), 4);
assert_eq!(created, date!(2009 - 4 - 4));
assert!(
channel.content.view_count.unwrap() > 186854340,
@ -1072,8 +1059,6 @@ async fn channel_not_found(#[case] id: &str) {
mod channel_rss {
use super::*;
use chrono::Timelike;
#[tokio::test]
async fn get_channel_rss() {
let rp = RustyPipe::builder().strict().build();
@ -1085,11 +1070,7 @@ mod channel_rss {
assert_eq!(channel.id, "UCHnyfMqiRRG1u-2MsSQLbXA");
assert_eq!(channel.name, "Veritasium");
assert_eq!(channel.create_date.year(), 2010);
assert_eq!(channel.create_date.month(), 7);
assert_eq!(channel.create_date.day(), 21);
assert_eq!(channel.create_date.hour(), 7);
assert_eq!(channel.create_date.minute(), 18);
assert_eq!(channel.create_date, datetime!(2010-07-21 7:18:02 +0));
assert!(!channel.videos.is_empty());
}