Jiff provides integration with the system timezone, and provides better integration with ICU4X crates. Since it doesn't make sense to have multiple datetime dependencies, Jiff seems like the best overall choice. This patch also removes dateparser
, as Jiff integrates that functionality directly.
N26HD5PFUNVDSEXAQVOTMSMNPWFHQSZ5PHMGEF2ACC23OWFHTGQQC
HKHMES6TWN5F7VTIC6GRV7ZBUCZ7KQUCSCKIA7PV2T5HKK4FD2FAC
5IABX6JGQF24EZW75KLV3LMTLMB2N35QPHXZUSH533OW7AO6JF7QC
TCXM4WIJPHMB3QX2QYGVKOFSTETGTB6EXKMYFM6C6PIXLGUGJX3QC
QAS4VLXUNSYY53SSYJECRM6JSKTM47SCSKLJANRNXOROFWVE7UJAC
HJVWPKWVSL5ZXALZOT4BOQUWWNGH62OU6YLSZQQEIOB37QQGHK6AC
A3RM526Y7LUXNYW4TL56YKQ5GVOK2R5D7JJVTSQ6TT5MEXIR6YAAC
4OJWMSOWWNT5N4W4FDMKBZB5UARCLGV3SRZVKGR4EFAYFUMUHM7AC
SXEYMYF7P4RZMZ46WPL4IZUTSQ2ATBWYZX7QNVMS3SGOYXYOHAGQC
4RV7T4SRYIQLBW3EZFWBO5G65QAVG2GHPI4KMDDZERCX65KQWSPQC
4KJ45IJLTIE35KQZUSFMFS67RNENG4P2FZMKMULJLGGYMKJUVRSQC
32G3GOK752NTSULBH6KYGD3ZC2YC4B2X7O73G7BT3AJVMIUIFHXQC
Y6TBQN7MFWX4SKJM2UGDGR4UMMDEO4TPNNJZKZWHEBTW7MPX4WWQC
2MKP7CB7FKQUNEAV3YPEJ7FNFW75VGGQIYPQRI54BFXGCUOQESPAC
SU3JX6SEW6MLREX6CCM4V3353YC3IQD4JOZW2KEIHYTHOI2AJKPQC
FOCBVLOUXYA7ZCUZA2CU3JU2QGF3ZOXW6EAVL5KZINN43GXNL7CQC
QL6K2ZM35B3NIXEMMCJWUSFXOBQHAGXRDMO7ID5DCKTJH4QJVY7QC
BPCAJCLTVK2GVWYURWJTPQ6XA34JUJZNZHG6ONX4ARM3QPJJ6UPQC
QQS7LII4MKQWKPYJXSZVOKLZ2ZSWQOMHHE6T22DJ4CL5I6YRGJLQC
3FTEGCMRMELPIJRUKNKRTA5TDBXEOTOOVRUTZJ7DWD27ZTKKMV3QC
QWIYNMI5SOTLRPYE4O3AG7R75JXM2TB3ZADU646PG6ACPBGSYUYAC
2TWWWCU4C3DLAECGKC43PYYVWC6DABSGKVXI25QZO5INZHVBZ5LAC
Q3UD2OLQNCBH7AQOH4M3R75KER5GLG2SAB2O2UDAMMBRUEKQMCXAC
OU243LABJJZ3MQHYW2A2MYKW7KZLTZGHJJXDR2BIIIHXT5BSYN3AC
ZHABNS3S6FSINO74FOI5KHYXYDTBPO4FQTTYTUS7NNKEVVNLYC4AC
L4JXJHWXYNCL4QGJXNKKTOKKTAXKKXBJUUY7HFZGEUZ5A2V5H34QC
4H2XTVJ2BNXDNHQ3RQTMOG3I4NRGZT7JDLC2GRINS56TIYTYTO4QC
NS36CJCO6E2FS65JRHHMOK4GTL7CLNOOLQZZAAAIZI2CQYNPAYRQC
C6SOSQCVVNBHQ67TUEJ5XQ4WEA4HPWHMVKECC3RD3LCKWHRI7S5QC
5QB3HZFV5FLU7BBWRIX4F5DC4RDERS6ZJ6LO7J7IEEQ33OH6S7RQC
GUL4M5FIE7JYXJHR7MCTQS3543HIQXGPLBWZKASBAWWEA4SZ75CAC
TFPETWTVADLG2DL7WERHJPGMJVOY4WOKCRWB3NZ3YOOQ4CVAUHBAC
DDJO7X2P2BAJSXPOE6ODKAJM7GRWKPT36WWTUZ373ZWQRYU4CFIAC
2RXOCWUWOGHEKHT5W73LAHJSOZVRTOGS7BWLSIGEEEBJGMCZBXQAC
F2S6XETO6DQ4447O4WPAHISGTBRVWW2WZYJ633KKYWWYKW5GXBPQC
WMS44NF5MTERTAK6KKJNLH5O463DNOQAK5BSBJAPMSRP44TKHHCQC
USQMBKTPHQBNFPDJ3RQWGTAJBLQUCVNE2JERIPFVYBS6MTCSYL6AC
AAAMZY4V64NAAMAXTSPUU7SAYLBJRISICA7RBWXWFMXHVFZQRHPAC
FAOGX7G362OSLMKTQLQ3S3XMGKACNRAIV2VRURS5QJRHDF577BHQC
NO2QPRFLGCYUDXYJTOY3S3NZJCCLAFOQUHITKDZ7LSZLRLOV5W3QC
OEKRRU6OMDAHD3UT2L56WTAVYMJUZM7JBTRJBJR6MAV7EXBPTHYQC
YN63NUZO4LVJ7XPMURDULTXBVJKW5MVCTZ24R7Z52QMHO3HPDUVQC
27PYHR6LO4M4RMSMLVMUKSYNQ72V6RRMRXLYQI3JA3LBHJO747YAC
EEBKW7VTILH6AGGV57ZIJ3DJGYHDSYBWGU3C7Q4WWAKSVNUGIYMQC
SMMBFECLGSUKRZW5YPOQPOQCOY2CH2OTZXBSZ3KG2N3J3HQZ5PSAC
FXEDPLRI7PXLDXV634ZA6D5Q3ZWG3ESTKJTMRPJ4MAHI7PKU3M6AC
XR7MNOMU5PMOOEY2EPPUABZ7NOP432RDCWUET23ONPXTT3JQIFIAC
RRCSHAYZ6RLWVPNYHF2F5FSRL2KKJNPQUQRIJYLJGB23BZQQ7JLQC
RDQYEED2LELS3HDSZA23JBLTHE6L5YXIXOKXQF6LSGYQ3O47H63QC
EJ7TFFOWLM5EXYX57NJZZX3NLPBLLMRX7CGJYC75DJZ5LYXOQPJAC
DVBSW7SICQMTYIC4NOLA3CBRU5OWPAWX3MYEOZ7UWXF3IJLLJDYQC
PNJL5TPZLQ3VXAASTLUX7462RCRPO7TV3GKOTTHDZABDQCBMXPRQC
RIZ4IP76N4PNGXMMZSFPOQIUQICFMGSHJNJMYZGHM4WODM45QOHAC
STG7MO5MLMKFJYJQDAXL6YSUJE2BTXOMWUQHXBWFHDFJNNJRP5AQC
HWYGVLP5M3H46XDLLUPXI5H2K35LHJPILMR3SPD7QKOULN5OSAKQC
ABPFWGKH24JK7TLAGDVENTA5VSVRANPBVRD555WCQMNW56BL7SZQC
RVAH6PXA7H7NUDTF7Q52I7EXGXVJVMGI2LTNN6L3MVEDEMAXVH4AC
.with_validator(move |input: &String| -> Result<(), &str> {
let parsed_date = dateparser::parse_with_timezone(input, &chrono::offset::Utc);
if parsed_date.is_err() {
return Err("Invalid date");
}
.with_validator(move |input: &String| -> Result<(), String> {
let expiry_date: Timestamp = input
.parse()
.map_err(|error| format!("Unable to parse date: {error:#?}"))?;
timestamp: if let Some(t) = timestamp {
chrono::DateTime::from_naive_utc_and_offset(
chrono::NaiveDateTime::from_timestamp_opt(t, 0).unwrap(),
chrono::Utc,
)
} else {
chrono::Utc::now()
},
timestamp: timestamp.unwrap_or_else(Timestamp::now),
pub(crate) fn parse_datetime_rfc2822(s: &str) -> Result<i64, &'static str> {
if let Ok(ts) = chrono::DateTime::parse_from_rfc2822(s) {
return Ok(ts.timestamp());
}
if let Ok(t) = s.parse() {
return Ok(t);
}
Err("Could not parse timestamp")
}
timestamp: if let Some(t) = self.timestamp {
chrono::DateTime::from_naive_utc_and_offset(
chrono::NaiveDateTime::from_timestamp_opt(t, 0).unwrap(),
chrono::Utc,
)
} else {
Utc::now()
},
timestamp: self.timestamp.unwrap_or_else(Timestamp::now),
fn parse_expiry(input: &str) -> Result<DateTime<Utc>, anyhow::Error> {
let parsed_date = dateparser::parse_with_timezone(input, &chrono::offset::Utc);
if parsed_date.is_err() {
bail!("Invalid date");
}
fn parse_expiry(input: &str) -> Result<Timestamp, anyhow::Error> {
let parsed_date: Timestamp = input
.parse()
.map_err(|error| anyhow!("Error parsing date: {error:#?}"))?;
timestamp: chrono::DateTime::from_naive_utc_and_offset(
chrono::NaiveDateTime::from_timestamp_opt(signature.when().seconds(), 0)
.expect("seconds and nanos are within bounds"),
chrono::Utc,
),
timestamp: jiff::Timestamp::from_second(signature.when().seconds()),
c.timestamp.timestamp() as u64
// Since jiff::Timestamp can represent negative values before the Unix epoch,
// clamp all unrepresentable (negative) values to 0
match u64::try_from(c.timestamp.as_second()) {
Ok(value) => value,
Err(_) => 0,
}
use chrono::Datelike;
let expires = chrono::Utc::now();
let expires = expires.with_year(expires.year() + 1).unwrap();
let sk = SKey::generate(Some(expires));
use jiff::ToSpan;
let expiry_date = jiff::Timestamp::now().checked_add(1.year()).unwrap();
let sk = SKey::generate(Some(expiry_date));
use chrono::Datelike;
let expires = chrono::Utc::now();
let expires = expires.with_year(expires.year() + 1).unwrap();
let sk = SKey::generate(Some(expires));
use jiff::ToSpan;
let expiry_date = jiff::Timestamp::now().checked_add(1.year()).unwrap();
let sk = SKey::generate(Some(expiry_date));
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
name = "chrono"
version = "0.4.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"serde",
"wasm-bindgen",
"windows-targets 0.52.0",
]
[[package]]
[[package]]
name = "dateparser"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9e12a21fe97a29f5ae9cb6770419711f180d3715a039b500b5ff7ab45bb00c4"
dependencies = [
"anyhow",
"chrono",
"lazy_static 1.4.0",
"regex",
]
name = "iana-time-zone"
version = "0.1.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
[[package]]
name = "jiff"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f02000660d30638906021176af16b17498bd0d12813dbfe7b276d8bc7f3c0806"
dependencies = [
"jiff-static",
"jiff-tzdb-platform",
"log",
"portable-atomic",
"portable-atomic-util",
"serde",
"windows-sys 0.52.0",
]
[[package]]
name = "jiff-static"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3c30758ddd7188629c6713fc45d1188af4f44c90582311d0c8d8c9907f60c48"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
]
[[package]]
name = "jiff-tzdb"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1283705eb0a21404d2bfd6eef2a7593d240bc42a0bdb39db0ad6fa2ec026524"
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets 0.52.0",
]
[[package]]