mirror of
https://github.com/chronotope/chrono.git
synced 2025-10-02 15:26:12 +00:00
Remove dependency on num-traits
Co-authored-by: Dirkjan Ochtman <dirkjan@ochtman.nl>
This commit is contained in:
parent
eb927846b6
commit
b0983c25d9
@ -4,7 +4,7 @@
|
|||||||
//! A collection of parsed date and time items.
|
//! A collection of parsed date and time items.
|
||||||
//! They can be constructed incrementally while being checked for consistency.
|
//! They can be constructed incrementally while being checked for consistency.
|
||||||
|
|
||||||
use num_traits::ToPrimitive;
|
use core::convert::TryFrom;
|
||||||
|
|
||||||
use super::{ParseResult, IMPOSSIBLE, NOT_ENOUGH, OUT_OF_RANGE};
|
use super::{ParseResult, IMPOSSIBLE, NOT_ENOUGH, OUT_OF_RANGE};
|
||||||
use crate::naive::{NaiveDate, NaiveDateTime, NaiveTime};
|
use crate::naive::{NaiveDate, NaiveDateTime, NaiveTime};
|
||||||
@ -136,7 +136,7 @@ impl Parsed {
|
|||||||
/// Tries to set the [`year`](#structfield.year) field from given value.
|
/// Tries to set the [`year`](#structfield.year) field from given value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_year(&mut self, value: i64) -> ParseResult<()> {
|
pub fn set_year(&mut self, value: i64) -> ParseResult<()> {
|
||||||
set_if_consistent(&mut self.year, value.to_i32().ok_or(OUT_OF_RANGE)?)
|
set_if_consistent(&mut self.year, i32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to set the [`year_div_100`](#structfield.year_div_100) field from given value.
|
/// Tries to set the [`year_div_100`](#structfield.year_div_100) field from given value.
|
||||||
@ -145,7 +145,7 @@ impl Parsed {
|
|||||||
if value < 0 {
|
if value < 0 {
|
||||||
return Err(OUT_OF_RANGE);
|
return Err(OUT_OF_RANGE);
|
||||||
}
|
}
|
||||||
set_if_consistent(&mut self.year_div_100, value.to_i32().ok_or(OUT_OF_RANGE)?)
|
set_if_consistent(&mut self.year_div_100, i32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to set the [`year_mod_100`](#structfield.year_mod_100) field from given value.
|
/// Tries to set the [`year_mod_100`](#structfield.year_mod_100) field from given value.
|
||||||
@ -154,13 +154,13 @@ impl Parsed {
|
|||||||
if value < 0 {
|
if value < 0 {
|
||||||
return Err(OUT_OF_RANGE);
|
return Err(OUT_OF_RANGE);
|
||||||
}
|
}
|
||||||
set_if_consistent(&mut self.year_mod_100, value.to_i32().ok_or(OUT_OF_RANGE)?)
|
set_if_consistent(&mut self.year_mod_100, i32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to set the [`isoyear`](#structfield.isoyear) field from given value.
|
/// Tries to set the [`isoyear`](#structfield.isoyear) field from given value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_isoyear(&mut self, value: i64) -> ParseResult<()> {
|
pub fn set_isoyear(&mut self, value: i64) -> ParseResult<()> {
|
||||||
set_if_consistent(&mut self.isoyear, value.to_i32().ok_or(OUT_OF_RANGE)?)
|
set_if_consistent(&mut self.isoyear, i32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to set the [`isoyear_div_100`](#structfield.isoyear_div_100) field from given value.
|
/// Tries to set the [`isoyear_div_100`](#structfield.isoyear_div_100) field from given value.
|
||||||
@ -169,7 +169,10 @@ impl Parsed {
|
|||||||
if value < 0 {
|
if value < 0 {
|
||||||
return Err(OUT_OF_RANGE);
|
return Err(OUT_OF_RANGE);
|
||||||
}
|
}
|
||||||
set_if_consistent(&mut self.isoyear_div_100, value.to_i32().ok_or(OUT_OF_RANGE)?)
|
set_if_consistent(
|
||||||
|
&mut self.isoyear_div_100,
|
||||||
|
i32::try_from(value).map_err(|_| OUT_OF_RANGE)?,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to set the [`isoyear_mod_100`](#structfield.isoyear_mod_100) field from given value.
|
/// Tries to set the [`isoyear_mod_100`](#structfield.isoyear_mod_100) field from given value.
|
||||||
@ -178,31 +181,34 @@ impl Parsed {
|
|||||||
if value < 0 {
|
if value < 0 {
|
||||||
return Err(OUT_OF_RANGE);
|
return Err(OUT_OF_RANGE);
|
||||||
}
|
}
|
||||||
set_if_consistent(&mut self.isoyear_mod_100, value.to_i32().ok_or(OUT_OF_RANGE)?)
|
set_if_consistent(
|
||||||
|
&mut self.isoyear_mod_100,
|
||||||
|
i32::try_from(value).map_err(|_| OUT_OF_RANGE)?,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to set the [`month`](#structfield.month) field from given value.
|
/// Tries to set the [`month`](#structfield.month) field from given value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_month(&mut self, value: i64) -> ParseResult<()> {
|
pub fn set_month(&mut self, value: i64) -> ParseResult<()> {
|
||||||
set_if_consistent(&mut self.month, value.to_u32().ok_or(OUT_OF_RANGE)?)
|
set_if_consistent(&mut self.month, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to set the [`week_from_sun`](#structfield.week_from_sun) field from given value.
|
/// Tries to set the [`week_from_sun`](#structfield.week_from_sun) field from given value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_week_from_sun(&mut self, value: i64) -> ParseResult<()> {
|
pub fn set_week_from_sun(&mut self, value: i64) -> ParseResult<()> {
|
||||||
set_if_consistent(&mut self.week_from_sun, value.to_u32().ok_or(OUT_OF_RANGE)?)
|
set_if_consistent(&mut self.week_from_sun, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to set the [`week_from_mon`](#structfield.week_from_mon) field from given value.
|
/// Tries to set the [`week_from_mon`](#structfield.week_from_mon) field from given value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_week_from_mon(&mut self, value: i64) -> ParseResult<()> {
|
pub fn set_week_from_mon(&mut self, value: i64) -> ParseResult<()> {
|
||||||
set_if_consistent(&mut self.week_from_mon, value.to_u32().ok_or(OUT_OF_RANGE)?)
|
set_if_consistent(&mut self.week_from_mon, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to set the [`isoweek`](#structfield.isoweek) field from given value.
|
/// Tries to set the [`isoweek`](#structfield.isoweek) field from given value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_isoweek(&mut self, value: i64) -> ParseResult<()> {
|
pub fn set_isoweek(&mut self, value: i64) -> ParseResult<()> {
|
||||||
set_if_consistent(&mut self.isoweek, value.to_u32().ok_or(OUT_OF_RANGE)?)
|
set_if_consistent(&mut self.isoweek, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to set the [`weekday`](#structfield.weekday) field from given value.
|
/// Tries to set the [`weekday`](#structfield.weekday) field from given value.
|
||||||
@ -214,13 +220,13 @@ impl Parsed {
|
|||||||
/// Tries to set the [`ordinal`](#structfield.ordinal) field from given value.
|
/// Tries to set the [`ordinal`](#structfield.ordinal) field from given value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_ordinal(&mut self, value: i64) -> ParseResult<()> {
|
pub fn set_ordinal(&mut self, value: i64) -> ParseResult<()> {
|
||||||
set_if_consistent(&mut self.ordinal, value.to_u32().ok_or(OUT_OF_RANGE)?)
|
set_if_consistent(&mut self.ordinal, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to set the [`day`](#structfield.day) field from given value.
|
/// Tries to set the [`day`](#structfield.day) field from given value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_day(&mut self, value: i64) -> ParseResult<()> {
|
pub fn set_day(&mut self, value: i64) -> ParseResult<()> {
|
||||||
set_if_consistent(&mut self.day, value.to_u32().ok_or(OUT_OF_RANGE)?)
|
set_if_consistent(&mut self.day, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to set the [`hour_div_12`](#structfield.hour_div_12) field from given value.
|
/// Tries to set the [`hour_div_12`](#structfield.hour_div_12) field from given value.
|
||||||
@ -244,7 +250,7 @@ impl Parsed {
|
|||||||
/// [`hour_mod_12`](#structfield.hour_mod_12) fields from given value.
|
/// [`hour_mod_12`](#structfield.hour_mod_12) fields from given value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_hour(&mut self, value: i64) -> ParseResult<()> {
|
pub fn set_hour(&mut self, value: i64) -> ParseResult<()> {
|
||||||
let v = value.to_u32().ok_or(OUT_OF_RANGE)?;
|
let v = u32::try_from(value).map_err(|_| OUT_OF_RANGE)?;
|
||||||
set_if_consistent(&mut self.hour_div_12, v / 12)?;
|
set_if_consistent(&mut self.hour_div_12, v / 12)?;
|
||||||
set_if_consistent(&mut self.hour_mod_12, v % 12)?;
|
set_if_consistent(&mut self.hour_mod_12, v % 12)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -253,19 +259,19 @@ impl Parsed {
|
|||||||
/// Tries to set the [`minute`](#structfield.minute) field from given value.
|
/// Tries to set the [`minute`](#structfield.minute) field from given value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_minute(&mut self, value: i64) -> ParseResult<()> {
|
pub fn set_minute(&mut self, value: i64) -> ParseResult<()> {
|
||||||
set_if_consistent(&mut self.minute, value.to_u32().ok_or(OUT_OF_RANGE)?)
|
set_if_consistent(&mut self.minute, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to set the [`second`](#structfield.second) field from given value.
|
/// Tries to set the [`second`](#structfield.second) field from given value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_second(&mut self, value: i64) -> ParseResult<()> {
|
pub fn set_second(&mut self, value: i64) -> ParseResult<()> {
|
||||||
set_if_consistent(&mut self.second, value.to_u32().ok_or(OUT_OF_RANGE)?)
|
set_if_consistent(&mut self.second, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to set the [`nanosecond`](#structfield.nanosecond) field from given value.
|
/// Tries to set the [`nanosecond`](#structfield.nanosecond) field from given value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_nanosecond(&mut self, value: i64) -> ParseResult<()> {
|
pub fn set_nanosecond(&mut self, value: i64) -> ParseResult<()> {
|
||||||
set_if_consistent(&mut self.nanosecond, value.to_u32().ok_or(OUT_OF_RANGE)?)
|
set_if_consistent(&mut self.nanosecond, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to set the [`timestamp`](#structfield.timestamp) field from given value.
|
/// Tries to set the [`timestamp`](#structfield.timestamp) field from given value.
|
||||||
@ -277,7 +283,7 @@ impl Parsed {
|
|||||||
/// Tries to set the [`offset`](#structfield.offset) field from given value.
|
/// Tries to set the [`offset`](#structfield.offset) field from given value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_offset(&mut self, value: i64) -> ParseResult<()> {
|
pub fn set_offset(&mut self, value: i64) -> ParseResult<()> {
|
||||||
set_if_consistent(&mut self.offset, value.to_i32().ok_or(OUT_OF_RANGE)?)
|
set_if_consistent(&mut self.offset, i32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a parsed naive date out of given fields.
|
/// Returns a parsed naive date out of given fields.
|
||||||
|
29
src/lib.rs
29
src/lib.rs
@ -422,6 +422,8 @@ mod oldtime;
|
|||||||
// this reexport is to aid the transition and should not be in the prelude!
|
// this reexport is to aid the transition and should not be in the prelude!
|
||||||
pub use oldtime::{Duration, OutOfRangeError};
|
pub use oldtime::{Duration, OutOfRangeError};
|
||||||
|
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
#[cfg(feature = "__doctest")]
|
#[cfg(feature = "__doctest")]
|
||||||
#[cfg_attr(feature = "__doctest", cfg(doctest))]
|
#[cfg_attr(feature = "__doctest", cfg(doctest))]
|
||||||
use doc_comment::doctest;
|
use doc_comment::doctest;
|
||||||
@ -517,3 +519,30 @@ pub use naive::__BenchYearFlags;
|
|||||||
pub mod serde {
|
pub mod serde {
|
||||||
pub use super::datetime::serde::*;
|
pub use super::datetime::serde::*;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Out of range error type used in various converting APIs
|
||||||
|
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
|
pub struct OutOfRange {
|
||||||
|
_private: (),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutOfRange {
|
||||||
|
const fn new() -> OutOfRange {
|
||||||
|
OutOfRange { _private: () }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for OutOfRange {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "out of range")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for OutOfRange {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "out of range")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl std::error::Error for OutOfRange {}
|
||||||
|
49
src/month.rs
49
src/month.rs
@ -1,8 +1,10 @@
|
|||||||
use core::fmt;
|
use core::{convert::TryFrom, fmt};
|
||||||
|
|
||||||
#[cfg(feature = "rkyv")]
|
#[cfg(feature = "rkyv")]
|
||||||
use rkyv::{Archive, Deserialize, Serialize};
|
use rkyv::{Archive, Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::OutOfRange;
|
||||||
|
|
||||||
/// The month of the year.
|
/// The month of the year.
|
||||||
///
|
///
|
||||||
/// This enum is just a convenience implementation.
|
/// This enum is just a convenience implementation.
|
||||||
@ -10,11 +12,11 @@ use rkyv::{Archive, Deserialize, Serialize};
|
|||||||
///
|
///
|
||||||
/// It is possible to convert from a date to a month independently
|
/// It is possible to convert from a date to a month independently
|
||||||
/// ```
|
/// ```
|
||||||
/// use num_traits::FromPrimitive;
|
/// # use std::convert::TryFrom;
|
||||||
/// use chrono::prelude::*;
|
/// use chrono::prelude::*;
|
||||||
/// let date = Utc.with_ymd_and_hms(2019, 10, 28, 9, 10, 11).unwrap();
|
/// let date = Utc.with_ymd_and_hms(2019, 10, 28, 9, 10, 11).unwrap();
|
||||||
/// // `2019-10-28T09:10:11Z`
|
/// // `2019-10-28T09:10:11Z`
|
||||||
/// let month = Month::from_u32(date.month());
|
/// let month = Month::try_from(u8::try_from(date.month()).unwrap()).ok();
|
||||||
/// assert_eq!(month, Some(Month::October))
|
/// assert_eq!(month, Some(Month::October))
|
||||||
/// ```
|
/// ```
|
||||||
/// Or from a Month to an integer usable by dates
|
/// Or from a Month to an integer usable by dates
|
||||||
@ -157,6 +159,28 @@ impl Month {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u8> for Month {
|
||||||
|
type Error = OutOfRange;
|
||||||
|
|
||||||
|
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
1 => Ok(Month::January),
|
||||||
|
2 => Ok(Month::February),
|
||||||
|
3 => Ok(Month::March),
|
||||||
|
4 => Ok(Month::April),
|
||||||
|
5 => Ok(Month::May),
|
||||||
|
6 => Ok(Month::June),
|
||||||
|
7 => Ok(Month::July),
|
||||||
|
8 => Ok(Month::August),
|
||||||
|
9 => Ok(Month::September),
|
||||||
|
10 => Ok(Month::October),
|
||||||
|
11 => Ok(Month::November),
|
||||||
|
12 => Ok(Month::December),
|
||||||
|
_ => Err(OutOfRange::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl num_traits::FromPrimitive for Month {
|
impl num_traits::FromPrimitive for Month {
|
||||||
/// Returns an `Option<Month>` from a i64, assuming a 1-index, January = 1.
|
/// Returns an `Option<Month>` from a i64, assuming a 1-index, January = 1.
|
||||||
///
|
///
|
||||||
@ -325,8 +349,25 @@ mod month_serde {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use core::convert::TryFrom;
|
||||||
|
|
||||||
use super::Month;
|
use super::Month;
|
||||||
use crate::{Datelike, TimeZone, Utc};
|
use crate::{Datelike, OutOfRange, TimeZone, Utc};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_month_enum_try_from() {
|
||||||
|
assert_eq!(Month::try_from(1), Ok(Month::January));
|
||||||
|
assert_eq!(Month::try_from(2), Ok(Month::February));
|
||||||
|
assert_eq!(Month::try_from(12), Ok(Month::December));
|
||||||
|
assert_eq!(Month::try_from(13), Err(OutOfRange::new()));
|
||||||
|
|
||||||
|
let date = Utc.with_ymd_and_hms(2019, 10, 28, 9, 10, 11).unwrap();
|
||||||
|
assert_eq!(Month::try_from(date.month() as u8), Ok(Month::October));
|
||||||
|
|
||||||
|
let month = Month::January;
|
||||||
|
let dt = Utc.with_ymd_and_hms(2019, month.number_from_month(), 28, 9, 10, 11).unwrap();
|
||||||
|
assert_eq!((dt.year(), dt.month(), dt.day()), (2019, 1, 28));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_month_enum_primitive_parse() {
|
fn test_month_enum_primitive_parse() {
|
||||||
|
@ -9,7 +9,6 @@ use core::convert::TryFrom;
|
|||||||
use core::ops::{Add, AddAssign, RangeInclusive, Sub, SubAssign};
|
use core::ops::{Add, AddAssign, RangeInclusive, Sub, SubAssign};
|
||||||
use core::{fmt, str};
|
use core::{fmt, str};
|
||||||
|
|
||||||
use num_traits::ToPrimitive;
|
|
||||||
#[cfg(feature = "rkyv")]
|
#[cfg(feature = "rkyv")]
|
||||||
use rkyv::{Archive, Deserialize, Serialize};
|
use rkyv::{Archive, Deserialize, Serialize};
|
||||||
|
|
||||||
@ -1030,7 +1029,7 @@ impl NaiveDate {
|
|||||||
let year = self.year();
|
let year = self.year();
|
||||||
let (mut year_div_400, year_mod_400) = div_mod_floor(year, 400);
|
let (mut year_div_400, year_mod_400) = div_mod_floor(year, 400);
|
||||||
let cycle = internals::yo_to_cycle(year_mod_400 as u32, self.of().ordinal());
|
let cycle = internals::yo_to_cycle(year_mod_400 as u32, self.of().ordinal());
|
||||||
let cycle = (cycle as i32).checked_add(rhs.num_days().to_i32()?)?;
|
let cycle = (cycle as i32).checked_add(i32::try_from(rhs.num_days()).ok()?)?;
|
||||||
let (cycle_div_400y, cycle) = div_mod_floor(cycle, 146_097);
|
let (cycle_div_400y, cycle) = div_mod_floor(cycle, 146_097);
|
||||||
year_div_400 += cycle_div_400y;
|
year_div_400 += cycle_div_400y;
|
||||||
|
|
||||||
@ -1062,7 +1061,7 @@ impl NaiveDate {
|
|||||||
let year = self.year();
|
let year = self.year();
|
||||||
let (mut year_div_400, year_mod_400) = div_mod_floor(year, 400);
|
let (mut year_div_400, year_mod_400) = div_mod_floor(year, 400);
|
||||||
let cycle = internals::yo_to_cycle(year_mod_400 as u32, self.of().ordinal());
|
let cycle = internals::yo_to_cycle(year_mod_400 as u32, self.of().ordinal());
|
||||||
let cycle = (cycle as i32).checked_sub(rhs.num_days().to_i32()?)?;
|
let cycle = (cycle as i32).checked_sub(i32::try_from(rhs.num_days()).ok()?)?;
|
||||||
let (cycle_div_400y, cycle) = div_mod_floor(cycle, 146_097);
|
let (cycle_div_400y, cycle) = div_mod_floor(cycle, 146_097);
|
||||||
year_div_400 += cycle_div_400y;
|
year_div_400 += cycle_div_400y;
|
||||||
|
|
||||||
|
@ -5,11 +5,11 @@
|
|||||||
|
|
||||||
#[cfg(any(feature = "alloc", feature = "std", test))]
|
#[cfg(any(feature = "alloc", feature = "std", test))]
|
||||||
use core::borrow::Borrow;
|
use core::borrow::Borrow;
|
||||||
|
use core::convert::TryFrom;
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use core::ops::{Add, AddAssign, Sub, SubAssign};
|
use core::ops::{Add, AddAssign, Sub, SubAssign};
|
||||||
use core::{fmt, str};
|
use core::{fmt, str};
|
||||||
|
|
||||||
use num_traits::ToPrimitive;
|
|
||||||
#[cfg(feature = "rkyv")]
|
#[cfg(feature = "rkyv")]
|
||||||
use rkyv::{Archive, Deserialize, Serialize};
|
use rkyv::{Archive, Deserialize, Serialize};
|
||||||
|
|
||||||
@ -211,8 +211,8 @@ impl NaiveDateTime {
|
|||||||
pub fn from_timestamp_opt(secs: i64, nsecs: u32) -> Option<NaiveDateTime> {
|
pub fn from_timestamp_opt(secs: i64, nsecs: u32) -> Option<NaiveDateTime> {
|
||||||
let days = secs.div_euclid(86_400);
|
let days = secs.div_euclid(86_400);
|
||||||
let secs = secs.rem_euclid(86_400);
|
let secs = secs.rem_euclid(86_400);
|
||||||
let date = days
|
let date = i32::try_from(days)
|
||||||
.to_i32()
|
.ok()
|
||||||
.and_then(|days| days.checked_add(719_163))
|
.and_then(|days| days.checked_add(719_163))
|
||||||
.and_then(NaiveDate::from_num_days_from_ce_opt);
|
.and_then(NaiveDate::from_num_days_from_ce_opt);
|
||||||
let time = NaiveTime::from_num_seconds_from_midnight_opt(secs as u32, nsecs);
|
let time = NaiveTime::from_num_seconds_from_midnight_opt(secs as u32, nsecs);
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
#![cfg_attr(feature = "__internal_bench", allow(missing_docs))]
|
#![cfg_attr(feature = "__internal_bench", allow(missing_docs))]
|
||||||
|
|
||||||
use crate::Weekday;
|
use crate::Weekday;
|
||||||
|
use core::convert::TryFrom;
|
||||||
use core::{fmt, i32};
|
use core::{fmt, i32};
|
||||||
use num_traits::FromPrimitive;
|
|
||||||
|
|
||||||
/// The internal date representation. This also includes the packed `Mdf` value.
|
/// The internal date representation. This also includes the packed `Mdf` value.
|
||||||
pub(super) type DateImpl = i32;
|
pub(super) type DateImpl = i32;
|
||||||
@ -319,7 +319,7 @@ impl Of {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub(super) fn weekday(&self) -> Weekday {
|
pub(super) fn weekday(&self) -> Weekday {
|
||||||
let Of(of) = *self;
|
let Of(of) = *self;
|
||||||
Weekday::from_u32(((of >> 4) + (of & 0b111)) % 7).unwrap()
|
Weekday::try_from((((of >> 4) + (of & 0b111)) % 7) as u8).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -327,7 +327,7 @@ impl Of {
|
|||||||
// week ordinal = ordinal + delta
|
// week ordinal = ordinal + delta
|
||||||
let Of(of) = *self;
|
let Of(of) = *self;
|
||||||
let weekord = (of >> 4).wrapping_add(self.flags().isoweek_delta());
|
let weekord = (of >> 4).wrapping_add(self.flags().isoweek_delta());
|
||||||
(weekord / 7, Weekday::from_u32(weekord % 7).unwrap())
|
(weekord / 7, Weekday::try_from((weekord % 7) as u8).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::wrong_self_convention))]
|
#[cfg_attr(feature = "cargo-clippy", allow(clippy::wrong_self_convention))]
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
use core::fmt;
|
use core::{convert::TryFrom, fmt};
|
||||||
|
|
||||||
#[cfg(feature = "rkyv")]
|
#[cfg(feature = "rkyv")]
|
||||||
use rkyv::{Archive, Deserialize, Serialize};
|
use rkyv::{Archive, Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::OutOfRange;
|
||||||
|
|
||||||
/// The day of week.
|
/// The day of week.
|
||||||
///
|
///
|
||||||
/// The order of the days of week depends on the context.
|
/// The order of the days of week depends on the context.
|
||||||
@ -12,12 +14,12 @@ use rkyv::{Archive, Deserialize, Serialize};
|
|||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
/// use chrono::Weekday;
|
/// use chrono::Weekday;
|
||||||
/// use num_traits::cast::FromPrimitive;
|
/// use std::convert::TryFrom;
|
||||||
///
|
///
|
||||||
/// let monday = "Monday".parse::<Weekday>().unwrap();
|
/// let monday = "Monday".parse::<Weekday>().unwrap();
|
||||||
/// assert_eq!(monday, Weekday::Mon);
|
/// assert_eq!(monday, Weekday::Mon);
|
||||||
///
|
///
|
||||||
/// let sunday = Weekday::from_u8(6).unwrap();
|
/// let sunday = Weekday::try_from(6).unwrap();
|
||||||
/// assert_eq!(sunday, Weekday::Sun);
|
/// assert_eq!(sunday, Weekday::Sun);
|
||||||
///
|
///
|
||||||
/// assert_eq!(sunday.num_days_from_monday(), 6); // starts counting with Monday = 0
|
/// assert_eq!(sunday.num_days_from_monday(), 6); // starts counting with Monday = 0
|
||||||
@ -153,6 +155,26 @@ impl fmt::Display for Weekday {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Any weekday can be represented as an integer from 0 to 6, which equals to
|
||||||
|
/// [`Weekday::num_days_from_monday`](#method.num_days_from_monday) in this implementation.
|
||||||
|
/// Do not heavily depend on this though; use explicit methods whenever possible.
|
||||||
|
impl TryFrom<u8> for Weekday {
|
||||||
|
type Error = OutOfRange;
|
||||||
|
|
||||||
|
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
0 => Ok(Weekday::Mon),
|
||||||
|
1 => Ok(Weekday::Tue),
|
||||||
|
2 => Ok(Weekday::Wed),
|
||||||
|
3 => Ok(Weekday::Thu),
|
||||||
|
4 => Ok(Weekday::Fri),
|
||||||
|
5 => Ok(Weekday::Sat),
|
||||||
|
6 => Ok(Weekday::Sun),
|
||||||
|
_ => Err(OutOfRange::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Any weekday can be represented as an integer from 0 to 6, which equals to
|
/// Any weekday can be represented as an integer from 0 to 6, which equals to
|
||||||
/// [`Weekday::num_days_from_monday`](#method.num_days_from_monday) in this implementation.
|
/// [`Weekday::num_days_from_monday`](#method.num_days_from_monday) in this implementation.
|
||||||
/// Do not heavily depend on this though; use explicit methods whenever possible.
|
/// Do not heavily depend on this though; use explicit methods whenever possible.
|
||||||
@ -210,14 +232,13 @@ impl fmt::Debug for ParseWeekdayError {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use num_traits::FromPrimitive;
|
|
||||||
|
|
||||||
use super::Weekday;
|
use super::Weekday;
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_num_days_from() {
|
fn test_num_days_from() {
|
||||||
for i in 0..7 {
|
for i in 0..7 {
|
||||||
let base_day = Weekday::from_u64(i).unwrap();
|
let base_day = Weekday::try_from(i).unwrap();
|
||||||
|
|
||||||
assert_eq!(base_day.num_days_from_monday(), base_day.num_days_from(Weekday::Mon));
|
assert_eq!(base_day.num_days_from_monday(), base_day.num_days_from(Weekday::Mon));
|
||||||
assert_eq!(base_day.num_days_from_sunday(), base_day.num_days_from(Weekday::Sun));
|
assert_eq!(base_day.num_days_from_sunday(), base_day.num_days_from(Weekday::Sun));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user