diff --git a/Cargo.toml b/Cargo.toml index 510df9ca2..31b9cfce9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ pbkdf2 = {version = "0.11.0", optional = true } sha1 = {version = "0.10.1", optional = true } time = { version = "0.3.7", optional = true, default-features = false, features = ["std"] } zstd = { version = "0.11.2", optional = true } +chrono = { version = "0.4.34" } [target.'cfg(any(all(target_arch = "arm", target_pointer_width = "32"), target_arch = "mips", target_arch = "powerpc"))'.dependencies] crossbeam-utils = "0.8.8" diff --git a/src/read.rs b/src/read.rs index b702b4f21..481033a35 100644 --- a/src/read.rs +++ b/src/read.rs @@ -466,6 +466,11 @@ impl ZipArchive { } let mut outfile = fs::File::create(&outpath)?; io::copy(&mut file, &mut outfile)?; + + // Set original timestamp. + if let Some(t) = datetime_to_systemtime(&file.last_modified()) { + outfile.set_modified(t)?; + } } // Get and Set permissions #[cfg(unix)] @@ -1129,6 +1134,33 @@ pub fn read_zipfile_from_stream<'a, R: io::Read>( })) } +/// Generate a `SystemTime` from a `DateTime`. +fn datetime_to_systemtime(datetime: &DateTime) -> Option { + if let Some(t) = generate_chrono_datetime(datetime) { + let time = chrono::DateTime::::from_naive_utc_and_offset(t, chrono::Utc); + return Some(time.into()); + } + None +} + +/// Generate a `NaiveDateTime` from a `DateTime`. +fn generate_chrono_datetime(datetime: &DateTime) -> Option { + if let Some(d) = chrono::NaiveDate::from_ymd_opt( + datetime.year().into(), + datetime.month().into(), + datetime.day().into(), + ) { + if let Some(d) = d.and_hms_opt( + datetime.hour().into(), + datetime.minute().into(), + datetime.second().into(), + ) { + return Some(d); + } + } + None +} + #[cfg(test)] mod test { #[test]