Skip to content

Commit 888bcff

Browse files
Pr0metheanmass10
authored andcommitted
fix: Restore original file timestamp when unzipping with chrono (#46)
* Set filetime * Add chrono * fix: Duplicate "chrono" entry in Cargo.toml Signed-off-by: Chris Hennick <4961925+Pr0methean@users.noreply.github.com> * fix: typo in read.rs Signed-off-by: Chris Hennick <4961925+Pr0methean@users.noreply.github.com> * fix: missing feature gate Signed-off-by: Chris Hennick <4961925+Pr0methean@users.noreply.github.com> * Set filetime * Add chrono * fix: Duplicate "chrono" entry in Cargo.toml Signed-off-by: Chris Hennick <4961925+Pr0methean@users.noreply.github.com> * fix: typo in read.rs Signed-off-by: Chris Hennick <4961925+Pr0methean@users.noreply.github.com> * fix: Errors due to missing chrono feature gate * fix: bad merge * style: cargo fmt --all * fix: chrono has renamed method to from_utc * Revert "fix: chrono has renamed method to from_utc" This reverts commit 38cc3ca. * fix: from_utc is deprecated, but from_naive_utc_and_offset doesn't exist before 0.4.27 --------- Signed-off-by: Chris Hennick <4961925+Pr0methean@users.noreply.github.com> Co-authored-by: mass10 <irisawa.masaru@gmail.com>
1 parent fb2e708 commit 888bcff

2 files changed

Lines changed: 40 additions & 1 deletion

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ time = { version = "0.3.37", default-features = false }
2929
[dependencies]
3030
aes = { version = "0.8", optional = true }
3131
bzip2 = { version = "0.6.0", optional = true }
32-
chrono = { version = "0.4", optional = true }
32+
chrono = { version = "^0.4.27", optional = true }
3333
constant_time_eq = { version = "0.3.1", optional = true }
3434
crc32fast = "1.4"
3535
flate2 = { version = "1.1.1", default-features = false, optional = true }

src/read.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,7 @@ impl<R: Read + Seek> ZipArchive<R> {
919919
}
920920
let mut file = self.by_index(i)?;
921921
let mut outfile = fs::File::create(&outpath)?;
922+
922923
io::copy(&mut file, &mut outfile)?;
923924
#[cfg(unix)]
924925
{
@@ -927,6 +928,15 @@ impl<R: Read + Seek> ZipArchive<R> {
927928
files_by_unix_mode.push((outpath.clone(), mode));
928929
}
929930
}
931+
#[cfg(feature = "chrono")]
932+
{
933+
// Set original timestamp.
934+
if let Some(last_modified) = file.last_modified() {
935+
if let Some(t) = datetime_to_systemtime(&last_modified) {
936+
outfile.set_modified(t)?;
937+
}
938+
}
939+
}
930940
}
931941
#[cfg(unix)]
932942
{
@@ -2033,6 +2043,35 @@ pub fn root_dir_common_filter(path: &Path) -> bool {
20332043
true
20342044
}
20352045

2046+
#[cfg(feature = "chrono")]
2047+
/// Generate a `SystemTime` from a `DateTime`.
2048+
fn datetime_to_systemtime(datetime: &DateTime) -> Option<std::time::SystemTime> {
2049+
if let Some(t) = generate_chrono_datetime(datetime) {
2050+
let time = chrono::DateTime::<chrono::Utc>::from_naive_utc_and_offset(t, chrono::Utc);
2051+
return Some(time.into());
2052+
}
2053+
None
2054+
}
2055+
2056+
#[cfg(feature = "chrono")]
2057+
/// Generate a `NaiveDateTime` from a `DateTime`.
2058+
fn generate_chrono_datetime(datetime: &DateTime) -> Option<chrono::NaiveDateTime> {
2059+
if let Some(d) = chrono::NaiveDate::from_ymd_opt(
2060+
datetime.year().into(),
2061+
datetime.month().into(),
2062+
datetime.day().into(),
2063+
) {
2064+
if let Some(d) = d.and_hms_opt(
2065+
datetime.hour().into(),
2066+
datetime.minute().into(),
2067+
datetime.second().into(),
2068+
) {
2069+
return Some(d);
2070+
}
2071+
}
2072+
None
2073+
}
2074+
20362075
#[cfg(test)]
20372076
mod test {
20382077
use crate::result::ZipResult;

0 commit comments

Comments
 (0)