feat: Move from_time to try_from

Moves from_time function to TryFrom<OffsetDateTime>
This commit is contained in:
Kyle Bloom 2022-11-18 20:24:57 +00:00 committed by Marli Frost
parent ac3576c888
commit 5726a07a76
3 changed files with 69 additions and 5 deletions

View file

@ -81,3 +81,20 @@ impl From<ZipError> for io::Error {
io::Error::new(io::ErrorKind::Other, err)
}
}
/// Error type for time parsing
#[derive(Debug)]
pub enum ZipDateTimeError {
/// The date was on or before 1980, or on or after 2107
DateTimeOutOfBounds,
}
impl fmt::Display for ZipDateTimeError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self {
ZipDateTimeError::DateTimeOutOfBounds => write!(fmt, "datetime out of bounds"),
}
}
}
impl Error for ZipDateTimeError {}

View file

@ -1,13 +1,15 @@
//! Types that specify what is contained in a ZIP.
#[cfg(doc)]
use {crate::read::ZipFile, crate::write::FileOptions};
#[cfg(feature = "time")]
use std::convert::TryFrom;
#[cfg(not(any(
all(target_arch = "arm", target_pointer_width = "32"),
target_arch = "mips",
target_arch = "powerpc"
)))]
use std::sync::atomic;
use std::time::SystemTime;
#[cfg(doc)]
use {crate::read::ZipFile, crate::write::FileOptions};
#[cfg(any(
all(target_arch = "arm", target_pointer_width = "32"),
@ -41,6 +43,8 @@ mod atomic {
}
}
#[cfg(feature = "time")]
use crate::result::ZipDateTimeError;
#[cfg(feature = "time")]
use time::{error::ComponentRange, Date, Month, OffsetDateTime, PrimitiveDateTime, Time};
@ -167,6 +171,7 @@ impl DateTime {
///
/// Returns `Err` when this object is out of bounds
#[allow(clippy::result_unit_err)]
#[deprecated(note = "use `DateTime::try_from()`")]
pub fn from_time(dt: OffsetDateTime) -> Result<DateTime, ()> {
if dt.year() >= 1980 && dt.year() <= 2107 {
Ok(DateTime {
@ -195,8 +200,6 @@ impl DateTime {
#[cfg(feature = "time")]
/// Converts the DateTime to a OffsetDateTime structure
pub fn to_time(&self) -> Result<OffsetDateTime, ComponentRange> {
use std::convert::TryFrom;
let date =
Date::from_calendar_date(self.year as i32, Month::try_from(self.month)?, self.day)?;
let time = Time::from_hms(self.hour, self.minute, self.second)?;
@ -254,6 +257,26 @@ impl DateTime {
}
}
#[cfg(feature = "time")]
impl TryFrom<OffsetDateTime> for DateTime {
type Error = ZipDateTimeError;
fn try_from(dt: OffsetDateTime) -> Result<Self, Self::Error> {
if dt.year() >= 1980 && dt.year() <= 2107 {
Ok(DateTime {
year: (dt.year()) as u16,
month: (dt.month()) as u8,
day: dt.day(),
hour: dt.hour(),
minute: dt.minute(),
second: dt.second(),
})
} else {
Err(ZipDateTimeError::DateTimeOutOfBounds)
}
}
}
pub const DEFAULT_VERSION: u8 = 46;
/// A type like `AtomicU64` except it implements `Clone` and has predefined
@ -514,6 +537,27 @@ mod test {
assert!(DateTime::from_time(datetime!(2108-01-01 00:00:00 UTC)).is_err());
}
#[cfg(feature = "time")]
#[test]
fn datetime_try_from_bounds() {
use std::convert::TryFrom;
use super::DateTime;
use time::macros::datetime;
// 1979-12-31 23:59:59
assert!(DateTime::try_from(datetime!(1979-12-31 23:59:59 UTC)).is_err());
// 1980-01-01 00:00:00
assert!(DateTime::try_from(datetime!(1980-01-01 00:00:00 UTC)).is_ok());
// 2107-12-31 23:59:59
assert!(DateTime::try_from(datetime!(2107-12-31 23:59:59 UTC)).is_ok());
// 2108-01-01 00:00:00
assert!(DateTime::try_from(datetime!(2108-01-01 00:00:00 UTC)).is_err());
}
#[test]
fn time_conversion() {
use super::DateTime;
@ -562,10 +606,12 @@ mod test {
#[test]
fn time_at_january() {
use super::DateTime;
use std::convert::TryFrom;
// 2020-01-01 00:00:00
let clock = OffsetDateTime::from_unix_timestamp(1_577_836_800).unwrap();
assert!(DateTime::from_time(clock).is_ok());
assert!(DateTime::try_from(clock).is_ok());
}
}

View file

@ -7,6 +7,7 @@ use crate::spec;
use crate::types::{AtomicU64, DateTime, System, ZipFileData, DEFAULT_VERSION};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use crc32fast::Hasher;
use std::convert::TryInto;
use std::default::Default;
use std::io;
use std::io::prelude::*;