diff --git a/Cargo.toml b/Cargo.toml index 0576c5f0c..304678e5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ time = { version = "0.3.37", default-features = false } [dependencies] aes = { version = "0.8", optional = true } bzip2 = { version = "0.6.0", optional = true } -chrono = { version = "0.4", optional = true } +chrono = { version = "^0.4.27", optional = true } constant_time_eq = { version = "0.3.1", optional = true } crc32fast = "1.4" flate2 = { version = "1.1.1", default-features = false, optional = true } diff --git a/src/read.rs b/src/read.rs index 4643ca04f..68f6331f7 100644 --- a/src/read.rs +++ b/src/read.rs @@ -910,6 +910,7 @@ impl ZipArchive { } let mut file = self.by_index(i)?; let mut outfile = fs::File::create(&outpath)?; + io::copy(&mut file, &mut outfile)?; #[cfg(unix)] { @@ -918,6 +919,15 @@ impl ZipArchive { files_by_unix_mode.push((outpath.clone(), mode)); } } + #[cfg(feature = "chrono")] + { + // Set original timestamp. + if let Some(last_modified) = file.last_modified() { + if let Some(t) = datetime_to_systemtime(&last_modified) { + outfile.set_modified(t)?; + } + } + } } #[cfg(unix)] { @@ -2024,6 +2034,35 @@ pub fn root_dir_common_filter(path: &Path) -> bool { true } +#[cfg(feature = "chrono")] +/// 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 +} + +#[cfg(feature = "chrono")] +/// 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 { use crate::result::ZipResult;