Skip to content

Commit

Permalink
Prepare the merge of ParsingError
Browse files Browse the repository at this point in the history
  • Loading branch information
Zomtir committed Feb 5, 2024
1 parent dd8e32e commit 9ca9a91
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 27 deletions.
57 changes: 50 additions & 7 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ pub enum Error {
///
/// An example is a date for the year 500.000, which is out of the range supported by chrono's
/// types.
OutOfRange,
DateOutOfRange,

/// A date or datetime does not exist.
/// A date or datetime does is invalid.
///
/// Examples are:
/// - April 31,
/// - February 29 in a non-leap year,
/// - a time that falls in the gap created by moving the clock forward during a DST transition,
/// - a leap second on a non-minute boundary.
DoesNotExist,
InvalidDate,

/// Some of the date or time components are not consistent with each other.
///
Expand All @@ -50,14 +50,42 @@ pub enum Error {
///
/// Contains the byte index of the formatting specifier within the format string.
UnsupportedSpecifier(u32),

/// Given field is out of permitted range.
FieldOutOfRange,

/// There is no possible date and time value with given set of fields.
///
/// This does not include the out-of-range conditions, which are trivially invalid.
/// It includes the case that there are one or more fields that are inconsistent to each other.
FieldImpossible,

/// Given set of fields is not enough to make a requested date and time value.
///
/// Note that there *may* be a case that given fields constrain the possible values so much
/// that there is a unique possible value. Chrono only tries to be correct for
/// most useful sets of fields however, as such constraint solving can be expensive.
FieldNotEnough,

/// The input string has some invalid character sequence for given formatting items.
InvalidInput,

/// The input string has been prematurely ended.
InputTooShort,

/// All formatting items have been read but there is a remaining input.
InputTooLong,

/// There was an error on the formatting string, or there were non-supported formating items.
BadFormat,
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::InvalidParameter => write!(f, "invalid parameter"),
Error::OutOfRange => write!(f, "date outside of the supported range"),
Error::DoesNotExist => write!(f, "date or datetime does not exist"),
Error::DateOutOfRange => write!(f, "date outside of the supported range"),
Error::InvalidDate => write!(f, "date or datetime does not exist"),
Error::Inconsistent => {
write!(f, "some of the date or time components are not consistent with each other")
}
Expand All @@ -70,12 +98,27 @@ impl fmt::Display for Error {
Error::UnsupportedSpecifier(_) => {
write!(f, "format string contains a formatting specifier that is not supported")
}
Error::FieldOutOfRange => write!(f, "input is out of range"),
Error::FieldImpossible => write!(f, "no possible date and time matching input"),
Error::FieldNotEnough => write!(f, "input is not enough for unique date and time"),
Error::InvalidInput => write!(f, "input contains invalid characters"),
Error::InputTooShort => write!(f, "premature end of input"),
Error::InputTooLong => write!(f, "trailing input"),
Error::BadFormat => write!(f, "bad or unsupported format string"),
}
}
}

#[cfg(feature = "std")]
impl std::error::Error for Error {}

pub(crate) const INVALID: Error = Error::InvalidParameter;
pub(crate) const DOES_NOT_EXIST: Error = Error::DoesNotExist;
pub(crate) const INVALID_PARAM: Error = Error::InvalidParameter;
pub(crate) const INVALID_DATE: Error = Error::InvalidDate;

pub(crate) const FIELD_OUT_OF_RANGE: Error = Error::FieldOutOfRange;
pub(crate) const FIELD_IMPOSSIBLE: Error = Error::FieldImpossible;
pub(crate) const FIELD_NOT_ENOUGH: Error = Error::FieldNotEnough;
pub(crate) const INVALID_INPUT: Error = Error::InvalidInput;
pub(crate) const INPUT_TOO_SHORT: Error = Error::InputTooShort;
pub(crate) const INPUT_TOO_LONG: Error = Error::InputTooLong;
pub(crate) const BAD_FORMAT: Error = Error::BadFormat;
6 changes: 3 additions & 3 deletions src/naive/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -780,7 +780,7 @@ impl NaiveDate {
///
/// Returns [`Error::InvalidParameter`] on invalid hour, minute, second and/or millisecond.
///
/// Returns [`Error::DoesNotExist`] if the millisecond part to represent a leap second is not on
/// Returns [`Error::InvalidDate`] if the millisecond part to represent a leap second is not on
/// a minute boundary.
///
/// # Example
Expand Down Expand Up @@ -817,7 +817,7 @@ impl NaiveDate {
///
/// Returns [`Error::InvalidParameter`] on invalid hour, minute, second and/or microsecond.
///
/// Returns [`Error::DoesNotExist`] if the microsecond part to represent a leap second is not on
/// Returns [`Error::InvalidDate`] if the microsecond part to represent a leap second is not on
/// a minute boundary.
///
/// # Example
Expand Down Expand Up @@ -854,7 +854,7 @@ impl NaiveDate {
///
/// Returns [`Error::InvalidParameter`] on invalid hour, minute, second and/or nanosecond.
///
/// Returns [`Error::DoesNotExist`] if the nanosecond part to represent a leap second is not on
/// Returns [`Error::InvalidDate`] if the nanosecond part to represent a leap second is not on
/// a minute boundary.
///
/// # Example
Expand Down
30 changes: 15 additions & 15 deletions src/naive/time/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use core::{fmt, str};
#[cfg(any(feature = "rkyv", feature = "rkyv-16", feature = "rkyv-32", feature = "rkyv-64"))]
use rkyv::{Archive, Deserialize, Serialize};

use crate::error::{Error, DOES_NOT_EXIST, INVALID};
use crate::error::{Error, INVALID_PARAM, INVALID_DATE};
use crate::expect;
#[cfg(feature = "alloc")]
use crate::format::DelayedFormat;
Expand Down Expand Up @@ -265,7 +265,7 @@ impl NaiveTime {
///
/// Returns [`Error::InvalidParameter`] on invalid hour, minute, second and/or millisecond.
///
/// Returns [`Error::DoesNotExist`] if the millisecond part to represent a leap second is not on
/// Returns [`Error::InvalidDate`] if the millisecond part to represent a leap second is not on
/// a minute boundary.
///
/// # Example
Expand All @@ -282,7 +282,7 @@ impl NaiveTime {
/// assert_eq!(from_hms_milli(23, 60, 0, 0), Err(Error::InvalidParameter));
/// assert_eq!(from_hms_milli(23, 59, 60, 0), Err(Error::InvalidParameter));
/// assert_eq!(from_hms_milli(23, 59, 59, 2_000), Err(Error::InvalidParameter));
/// assert_eq!(from_hms_milli(23, 59, 30, 1_999), Err(Error::DoesNotExist));
/// assert_eq!(from_hms_milli(23, 59, 30, 1_999), Err(Error::InvalidDate));
/// ```
#[inline]
pub const fn from_hms_milli(
Expand All @@ -293,7 +293,7 @@ impl NaiveTime {
) -> Result<NaiveTime, Error> {
let nano = match milli.checked_mul(1_000_000) {
Some(nano) => nano,
None => return Err(INVALID),
None => return Err(INVALID_PARAM),
};
NaiveTime::from_hms_nano(hour, min, sec, nano)
}
Expand All @@ -307,7 +307,7 @@ impl NaiveTime {
///
/// Returns [`Error::InvalidParameter`] on invalid hour, minute, second and/or microsecond.
///
/// Returns [`Error::DoesNotExist`] if the microsecond part to represent a leap second is not on
/// Returns [`Error::InvalidDate`] if the microsecond part to represent a leap second is not on
/// a minute boundary.
///
/// # Example
Expand All @@ -324,7 +324,7 @@ impl NaiveTime {
/// assert_eq!(from_hms_micro(23, 60, 0, 0), Err(Error::InvalidParameter));
/// assert_eq!(from_hms_micro(23, 59, 60, 0), Err(Error::InvalidParameter));
/// assert_eq!(from_hms_micro(23, 59, 59, 2_000_000), Err(Error::InvalidParameter));
/// assert_eq!(from_hms_micro(23, 59, 30, 1_999_999), Err(Error::DoesNotExist));
/// assert_eq!(from_hms_micro(23, 59, 30, 1_999_999), Err(Error::InvalidDate));
/// ```
#[inline]
pub const fn from_hms_micro(
Expand All @@ -335,7 +335,7 @@ impl NaiveTime {
) -> Result<NaiveTime, Error> {
let nano = match micro.checked_mul(1_000) {
Some(nano) => nano,
None => return Err(INVALID),
None => return Err(INVALID_PARAM),
};
NaiveTime::from_hms_nano(hour, min, sec, nano)
}
Expand All @@ -349,7 +349,7 @@ impl NaiveTime {
///
/// Returns [`Error::InvalidParameter`] on invalid hour, minute, second and/or nanosecond.
///
/// Returns [`Error::DoesNotExist`] if the nanosecond part to represent a leap second is not on
/// Returns [`Error::InvalidDate`] if the nanosecond part to represent a leap second is not on
/// a minute boundary.
///
/// # Example
Expand All @@ -366,7 +366,7 @@ impl NaiveTime {
/// assert_eq!(from_hms_nano(23, 60, 0, 0), Err(Error::InvalidParameter));
/// assert_eq!(from_hms_nano(23, 59, 60, 0), Err(Error::InvalidParameter));
/// assert_eq!(from_hms_nano(23, 59, 59, 2_000_000_000), Err(Error::InvalidParameter));
/// assert_eq!(from_hms_nano(23, 59, 30, 1_999_999_999), Err(Error::DoesNotExist));
/// assert_eq!(from_hms_nano(23, 59, 30, 1_999_999_999), Err(Error::InvalidDate));
/// ```
#[inline]
pub const fn from_hms_nano(
Expand All @@ -376,9 +376,9 @@ impl NaiveTime {
nano: u32,
) -> Result<NaiveTime, Error> {
if hour >= 24 || min >= 60 || sec >= 60 || nano >= 2_000_000_000 {
return Err(INVALID);
return Err(INVALID_PARAM);
} else if nano >= 1_000_000_000 && sec != 59 {
return Err(DOES_NOT_EXIST);
return Err(INVALID_DATE);
}
let secs = hour * 3600 + min * 60 + sec;
Ok(NaiveTime { secs, frac: nano })
Expand All @@ -393,7 +393,7 @@ impl NaiveTime {
///
/// Returns `[`Error::InvalidParameter`]` on invalid number of seconds and/or nanosecond.
///
/// Returns [`Error::DoesNotExist`] if the nanosecond part to represent a leap second is not on
/// Returns [`Error::InvalidDate`] if the nanosecond part to represent a leap second is not on
/// a minute boundary.
///
/// # Example
Expand All @@ -408,14 +408,14 @@ impl NaiveTime {
/// assert!(from_nsecs(86399, 1_999_999_999).is_ok()); // a leap second after 23:59:59
/// assert_eq!(from_nsecs(86_400, 0), Err(Error::InvalidParameter));
/// assert_eq!(from_nsecs(86399, 2_000_000_000), Err(Error::InvalidParameter));
/// assert_eq!(from_nsecs(1, 1_999_999_999), Err(Error::DoesNotExist));
/// assert_eq!(from_nsecs(1, 1_999_999_999), Err(Error::InvalidDate));
/// ```
#[inline]
pub const fn from_num_seconds_from_midnight(secs: u32, nano: u32) -> Result<NaiveTime, Error> {
if secs >= 86_400 || nano >= 2_000_000_000 {
return Err(INVALID);
return Err(INVALID_PARAM);
} else if nano >= 1_000_000_000 && secs % 60 != 59 {
return Err(DOES_NOT_EXIST);
return Err(INVALID_DATE);
}
Ok(NaiveTime { secs, frac: nano })
}
Expand Down
4 changes: 2 additions & 2 deletions src/offset/local/tz_info/rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1033,11 +1033,11 @@ mod tests {

assert!(matches!(
transition_rule_1.find_local_time_type(min_unix_time),
Err(Error::OutOfRange(_))
Err(Error::DateOutOfRange(_))
));
assert!(matches!(
transition_rule_2.find_local_time_type(max_unix_time),
Err(Error::OutOfRange(_))
Err(Error::DateOutOfRange(_))
));

Ok(())
Expand Down

0 comments on commit 9ca9a91

Please sign in to comment.