Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ jobs:
cargo clippy --target=x86_64-pc-windows-msvc --all-targets --color=always \
-- -D warnings
- run: |
cargo clippy --manifest-path fuzz/Cargo.toml --color=always \
cargo clippy --manifest-path fuzz/Cargo.toml --all-targets --color=always \
-- -D warnings
- run: |
cargo clippy --manifest-path bench/Cargo.toml --color=always \
cargo clippy --manifest-path bench/Cargo.toml --all-targets --color=always \
-- -D warnings
env:
RUSTFLAGS: "-Dwarnings"
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ js-sys = { version = "0.3", optional = true } # contains FFI bindings for
windows-targets = { version = "0.52", optional = true }

[target.'cfg(windows)'.dev-dependencies]
windows-bindgen = { version = "0.54" } # The MSRV of its windows-metatada 0.54 dependency is 1.70
windows-bindgen = { version = "0.55" } # The MSRV of its windows-metatada dependency is 1.70

[target.'cfg(unix)'.dependencies]
iana-time-zone = { version = "0.1.45", optional = true, features = ["fallback"] }
Expand Down
8 changes: 2 additions & 6 deletions src/datetime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

//! ISO 8601 date and time with time zone.

#[cfg(all(not(feature = "std"), feature = "alloc"))]
#[cfg(all(feature = "alloc", not(feature = "std"), not(test)))]
use alloc::string::String;
use core::borrow::Borrow;
use core::cmp::Ordering;
Expand Down Expand Up @@ -46,7 +46,7 @@ mod tests;
/// There are some constructors implemented here (the `from_*` methods), but
/// the general-purpose constructors are all via the methods on the
/// [`TimeZone`](./offset/trait.TimeZone.html) implementations.
#[derive(Clone)]
#[derive(Copy, Clone)]
#[cfg_attr(
any(feature = "rkyv", feature = "rkyv-16", feature = "rkyv-32", feature = "rkyv-64"),
derive(Archive, Deserialize, Serialize),
Expand Down Expand Up @@ -1260,10 +1260,6 @@ impl<Tz: TimeZone> Timelike for DateTime<Tz> {
}
}

// we need them as automatic impls cannot handle associated types
impl<Tz: TimeZone> Copy for DateTime<Tz> where <Tz as TimeZone>::Offset: Copy {}
unsafe impl<Tz: TimeZone> Send for DateTime<Tz> where <Tz as TimeZone>::Offset: Send {}

impl<Tz: TimeZone, Tz2: TimeZone> PartialEq<DateTime<Tz2>> for DateTime<Tz> {
fn eq(&self, other: &DateTime<Tz2>) -> bool {
self.datetime == other.datetime
Expand Down
4 changes: 1 addition & 3 deletions src/format/formatting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

//! Date and time formatting routines.

#[cfg(all(not(feature = "std"), feature = "alloc"))]
#[cfg(all(feature = "alloc", not(feature = "std"), not(test)))]
use alloc::string::{String, ToString};
#[cfg(feature = "alloc")]
use core::borrow::Borrow;
Expand All @@ -20,8 +20,6 @@ use crate::{NaiveDate, NaiveTime, Weekday};

#[cfg(feature = "alloc")]
use super::locales;
#[cfg(all(feature = "unstable-locales", feature = "alloc"))]
use super::Locale;
#[cfg(any(feature = "alloc", feature = "serde", feature = "rustc-serialize"))]
use super::{Colons, OffsetFormat, OffsetPrecision, Pad};
#[cfg(feature = "alloc")]
Expand Down
2 changes: 1 addition & 1 deletion src/format/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
//! # Ok::<(), chrono::ParseError>(())
//! ```

#[cfg(all(not(feature = "std"), feature = "alloc"))]
#[cfg(all(feature = "alloc", not(feature = "std"), not(test)))]
use alloc::boxed::Box;
use core::fmt;
use core::str::FromStr;
Expand Down
2 changes: 1 addition & 1 deletion src/format/strftime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ use super::{locales, Locale};
use super::{Fixed, InternalInternal, Item, Numeric, Pad};
#[cfg(any(feature = "alloc", feature = "std"))]
use super::{ParseError, BAD_FORMAT};
#[cfg(feature = "alloc")]
#[cfg(all(feature = "alloc", not(feature = "std"), not(test)))]
use alloc::vec::Vec;

/// Parsing iterator for `strftime`-like format strings.
Expand Down
124 changes: 64 additions & 60 deletions src/naive/date/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,98 +442,102 @@ fn test_date_pred() {
}

#[test]
fn test_date_add() {
fn check((y1, m1, d1): (i32, u32, u32), rhs: TimeDelta, ymd: Option<(i32, u32, u32)>) {
let lhs = NaiveDate::from_ymd(y1, m1, d1).unwrap();
let sum = ymd.map(|(y, m, d)| NaiveDate::from_ymd(y, m, d).unwrap());
assert_eq!(lhs.checked_add_signed(rhs), sum);
assert_eq!(lhs.checked_sub_signed(-rhs), sum);
fn test_date_checked_add_signed() {
fn check(lhs: Option<NaiveDate>, delta: TimeDelta, rhs: Option<NaiveDate>) {
assert_eq!(lhs.unwrap().checked_add_signed(delta), rhs);
assert_eq!(lhs.unwrap().checked_sub_signed(-delta), rhs);
}
let ymd = |y, m, d| NaiveDate::from_ymd(y, m, d).ok();

check((2014, 1, 1), TimeDelta::zero(), Some((2014, 1, 1)));
check((2014, 1, 1), TimeDelta::seconds(86399).unwrap(), Some((2014, 1, 1)));
check(ymd(2014, 1, 1), TimeDelta::zero(), ymd(2014, 1, 1));
check(ymd(2014, 1, 1), TimeDelta::seconds(86399).unwrap(), ymd(2014, 1, 1));
// always round towards zero
check((2014, 1, 1), TimeDelta::seconds(-86399).unwrap(), Some((2014, 1, 1)));
check((2014, 1, 1), TimeDelta::days(1).unwrap(), Some((2014, 1, 2)));
check((2014, 1, 1), TimeDelta::days(-1).unwrap(), Some((2013, 12, 31)));
check((2014, 1, 1), TimeDelta::days(364).unwrap(), Some((2014, 12, 31)));
check((2014, 1, 1), TimeDelta::days(365 * 4 + 1).unwrap(), Some((2018, 1, 1)));
check((2014, 1, 1), TimeDelta::days(365 * 400 + 97).unwrap(), Some((2414, 1, 1)));
check(ymd(2014, 1, 1), TimeDelta::seconds(-86399).unwrap(), ymd(2014, 1, 1));
check(ymd(2014, 1, 1), TimeDelta::days(1).unwrap(), ymd(2014, 1, 2));
check(ymd(2014, 1, 1), TimeDelta::days(-1).unwrap(), ymd(2013, 12, 31));
check(ymd(2014, 1, 1), TimeDelta::days(364).unwrap(), ymd(2014, 12, 31));
check(ymd(2014, 1, 1), TimeDelta::days(365 * 4 + 1).unwrap(), ymd(2018, 1, 1));
check(ymd(2014, 1, 1), TimeDelta::days(365 * 400 + 97).unwrap(), ymd(2414, 1, 1));

check((-7, 1, 1), TimeDelta::days(365 * 12 + 3).unwrap(), Some((5, 1, 1)));
check(ymd(-7, 1, 1), TimeDelta::days(365 * 12 + 3).unwrap(), ymd(5, 1, 1));

// overflow check
check(
(0, 1, 1),
ymd(0, 1, 1),
TimeDelta::days(MAX_DAYS_FROM_YEAR_0 as i64).unwrap(),
Some((MAX_YEAR, 12, 31)),
ymd(MAX_YEAR, 12, 31),
);
check((0, 1, 1), TimeDelta::days(MAX_DAYS_FROM_YEAR_0 as i64 + 1).unwrap(), None);
check((0, 1, 1), TimeDelta::max_value(), None);
check((0, 1, 1), TimeDelta::days(MIN_DAYS_FROM_YEAR_0 as i64).unwrap(), Some((MIN_YEAR, 1, 1)));
check((0, 1, 1), TimeDelta::days(MIN_DAYS_FROM_YEAR_0 as i64 - 1).unwrap(), None);
check((0, 1, 1), TimeDelta::min_value(), None);
check(ymd(0, 1, 1), TimeDelta::days(MAX_DAYS_FROM_YEAR_0 as i64 + 1).unwrap(), None);
check(ymd(0, 1, 1), TimeDelta::max_value(), None);
check(ymd(0, 1, 1), TimeDelta::days(MIN_DAYS_FROM_YEAR_0 as i64).unwrap(), ymd(MIN_YEAR, 1, 1));
check(ymd(0, 1, 1), TimeDelta::days(MIN_DAYS_FROM_YEAR_0 as i64 - 1).unwrap(), None);
check(ymd(0, 1, 1), TimeDelta::min_value(), None);
}

#[test]
fn test_date_sub() {
fn check((y1, m1, d1): (i32, u32, u32), (y2, m2, d2): (i32, u32, u32), diff: TimeDelta) {
let lhs = NaiveDate::from_ymd(y1, m1, d1).unwrap();
let rhs = NaiveDate::from_ymd(y2, m2, d2).unwrap();
assert_eq!(lhs.signed_duration_since(rhs), diff);
assert_eq!(rhs.signed_duration_since(lhs), -diff);
fn test_date_signed_duration_since() {
fn check(lhs: Option<NaiveDate>, rhs: Option<NaiveDate>, delta: TimeDelta) {
assert_eq!(lhs.unwrap().signed_duration_since(rhs.unwrap()), delta);
assert_eq!(rhs.unwrap().signed_duration_since(lhs.unwrap()), -delta);
}
let ymd = |y, m, d| NaiveDate::from_ymd(y, m, d).ok();

check((2014, 1, 1), (2014, 1, 1), TimeDelta::zero());
check((2014, 1, 2), (2014, 1, 1), TimeDelta::days(1).unwrap());
check((2014, 12, 31), (2014, 1, 1), TimeDelta::days(364).unwrap());
check((2015, 1, 3), (2014, 1, 1), TimeDelta::days(365 + 2).unwrap());
check((2018, 1, 1), (2014, 1, 1), TimeDelta::days(365 * 4 + 1).unwrap());
check((2414, 1, 1), (2014, 1, 1), TimeDelta::days(365 * 400 + 97).unwrap());
check(ymd(2014, 1, 1), ymd(2014, 1, 1), TimeDelta::zero());
check(ymd(2014, 1, 2), ymd(2014, 1, 1), TimeDelta::days(1).unwrap());
check(ymd(2014, 12, 31), ymd(2014, 1, 1), TimeDelta::days(364).unwrap());
check(ymd(2015, 1, 3), ymd(2014, 1, 1), TimeDelta::days(365 + 2).unwrap());
check(ymd(2018, 1, 1), ymd(2014, 1, 1), TimeDelta::days(365 * 4 + 1).unwrap());
check(ymd(2414, 1, 1), ymd(2014, 1, 1), TimeDelta::days(365 * 400 + 97).unwrap());

check((MAX_YEAR, 12, 31), (0, 1, 1), TimeDelta::days(MAX_DAYS_FROM_YEAR_0 as i64).unwrap());
check((MIN_YEAR, 1, 1), (0, 1, 1), TimeDelta::days(MIN_DAYS_FROM_YEAR_0 as i64).unwrap());
check(
ymd(MAX_YEAR, 12, 31),
ymd(0, 1, 1),
TimeDelta::days(MAX_DAYS_FROM_YEAR_0 as i64).unwrap(),
);
check(ymd(MIN_YEAR, 1, 1), ymd(0, 1, 1), TimeDelta::days(MIN_DAYS_FROM_YEAR_0 as i64).unwrap());
}

#[test]
fn test_date_add_days() {
fn check((y1, m1, d1): (i32, u32, u32), rhs: Days, ymd: Option<(i32, u32, u32)>) {
let lhs = NaiveDate::from_ymd(y1, m1, d1).unwrap();
let sum = ymd.map(|(y, m, d)| NaiveDate::from_ymd(y, m, d).unwrap());
assert_eq!(lhs.checked_add_days(rhs), sum);
fn check(lhs: Option<NaiveDate>, days: Days, rhs: Option<NaiveDate>) {
assert_eq!(lhs.unwrap().checked_add_days(days), rhs);
}
let ymd = |y, m, d| NaiveDate::from_ymd(y, m, d).ok();

check((2014, 1, 1), Days::new(0), Some((2014, 1, 1)));
check(ymd(2014, 1, 1), Days::new(0), ymd(2014, 1, 1));
// always round towards zero
check((2014, 1, 1), Days::new(1), Some((2014, 1, 2)));
check((2014, 1, 1), Days::new(364), Some((2014, 12, 31)));
check((2014, 1, 1), Days::new(365 * 4 + 1), Some((2018, 1, 1)));
check((2014, 1, 1), Days::new(365 * 400 + 97), Some((2414, 1, 1)));
check(ymd(2014, 1, 1), Days::new(1), ymd(2014, 1, 2));
check(ymd(2014, 1, 1), Days::new(364), ymd(2014, 12, 31));
check(ymd(2014, 1, 1), Days::new(365 * 4 + 1), ymd(2018, 1, 1));
check(ymd(2014, 1, 1), Days::new(365 * 400 + 97), ymd(2414, 1, 1));

check((-7, 1, 1), Days::new(365 * 12 + 3), Some((5, 1, 1)));
check(ymd(-7, 1, 1), Days::new(365 * 12 + 3), ymd(5, 1, 1));

// overflow check
check((0, 1, 1), Days::new(MAX_DAYS_FROM_YEAR_0.try_into().unwrap()), Some((MAX_YEAR, 12, 31)));
check((0, 1, 1), Days::new(u64::try_from(MAX_DAYS_FROM_YEAR_0).unwrap() + 1), None);
check(ymd(0, 1, 1), Days::new(MAX_DAYS_FROM_YEAR_0.try_into().unwrap()), ymd(MAX_YEAR, 12, 31));
check(ymd(0, 1, 1), Days::new(u64::try_from(MAX_DAYS_FROM_YEAR_0).unwrap() + 1), None);
}

#[test]
fn test_date_sub_days() {
fn check((y1, m1, d1): (i32, u32, u32), (y2, m2, d2): (i32, u32, u32), diff: Days) {
let lhs = NaiveDate::from_ymd(y1, m1, d1).unwrap();
let rhs = NaiveDate::from_ymd(y2, m2, d2).unwrap();
assert_eq!(lhs - diff, rhs);
fn check(lhs: Option<NaiveDate>, days: Days, rhs: Option<NaiveDate>) {
assert_eq!(lhs.unwrap().checked_sub_days(days), rhs);
}
let ymd = |y, m, d| NaiveDate::from_ymd(y, m, d).ok();

check((2014, 1, 1), (2014, 1, 1), Days::new(0));
check((2014, 1, 2), (2014, 1, 1), Days::new(1));
check((2014, 12, 31), (2014, 1, 1), Days::new(364));
check((2015, 1, 3), (2014, 1, 1), Days::new(365 + 2));
check((2018, 1, 1), (2014, 1, 1), Days::new(365 * 4 + 1));
check((2414, 1, 1), (2014, 1, 1), Days::new(365 * 400 + 97));
check(ymd(2014, 1, 1), Days::new(0), ymd(2014, 1, 1));
check(ymd(2014, 1, 2), Days::new(1), ymd(2014, 1, 1));
check(ymd(2014, 12, 31), Days::new(364), ymd(2014, 1, 1));
check(ymd(2015, 1, 3), Days::new(365 + 2), ymd(2014, 1, 1));
check(ymd(2018, 1, 1), Days::new(365 * 4 + 1), ymd(2014, 1, 1));
check(ymd(2414, 1, 1), Days::new(365 * 400 + 97), ymd(2014, 1, 1));

check((MAX_YEAR, 12, 31), (0, 1, 1), Days::new(MAX_DAYS_FROM_YEAR_0.try_into().unwrap()));
check((0, 1, 1), (MIN_YEAR, 1, 1), Days::new((-MIN_DAYS_FROM_YEAR_0).try_into().unwrap()));
check(ymd(MAX_YEAR, 12, 31), Days::new(MAX_DAYS_FROM_YEAR_0.try_into().unwrap()), ymd(0, 1, 1));
check(
ymd(0, 1, 1),
Days::new((-MIN_DAYS_FROM_YEAR_0).try_into().unwrap()),
ymd(MIN_YEAR, 1, 1),
);
}

#[test]
Expand Down
26 changes: 12 additions & 14 deletions src/offset/local/win_bindings.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
// Bindings generated by `windows-bindgen` 0.54.0

#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)]
::windows_targets::link!("kernel32.dll" "system" fn GetTimeZoneInformationForYear(wyear : u16, pdtzi : *const DYNAMIC_TIME_ZONE_INFORMATION, ptzi : *mut TIME_ZONE_INFORMATION) -> BOOL);
::windows_targets::link!("kernel32.dll" "system" fn SystemTimeToFileTime(lpsystemtime : *const SYSTEMTIME, lpfiletime : *mut FILETIME) -> BOOL);
::windows_targets::link!("kernel32.dll" "system" fn SystemTimeToTzSpecificLocalTime(lptimezoneinformation : *const TIME_ZONE_INFORMATION, lpuniversaltime : *const SYSTEMTIME, lplocaltime : *mut SYSTEMTIME) -> BOOL);
::windows_targets::link!("kernel32.dll" "system" fn TzSpecificLocalTimeToSystemTime(lptimezoneinformation : *const TIME_ZONE_INFORMATION, lplocaltime : *const SYSTEMTIME, lpuniversaltime : *mut SYSTEMTIME) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn GetTimeZoneInformationForYear(wyear : u16, pdtzi : *const DYNAMIC_TIME_ZONE_INFORMATION, ptzi : *mut TIME_ZONE_INFORMATION) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn SystemTimeToFileTime(lpsystemtime : *const SYSTEMTIME, lpfiletime : *mut FILETIME) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn SystemTimeToTzSpecificLocalTime(lptimezoneinformation : *const TIME_ZONE_INFORMATION, lpuniversaltime : *const SYSTEMTIME, lplocaltime : *mut SYSTEMTIME) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn TzSpecificLocalTimeToSystemTime(lptimezoneinformation : *const TIME_ZONE_INFORMATION, lplocaltime : *const SYSTEMTIME, lpuniversaltime : *mut SYSTEMTIME) -> BOOL);
pub type BOOL = i32;
pub type BOOLEAN = u8;
#[repr(C)]
Expand All @@ -19,8 +17,8 @@ pub struct DYNAMIC_TIME_ZONE_INFORMATION {
pub TimeZoneKeyName: [u16; 128],
pub DynamicDaylightTimeDisabled: BOOLEAN,
}
impl ::core::marker::Copy for DYNAMIC_TIME_ZONE_INFORMATION {}
impl ::core::clone::Clone for DYNAMIC_TIME_ZONE_INFORMATION {
impl Copy for DYNAMIC_TIME_ZONE_INFORMATION {}
impl Clone for DYNAMIC_TIME_ZONE_INFORMATION {
fn clone(&self) -> Self {
*self
}
Expand All @@ -30,8 +28,8 @@ pub struct FILETIME {
pub dwLowDateTime: u32,
pub dwHighDateTime: u32,
}
impl ::core::marker::Copy for FILETIME {}
impl ::core::clone::Clone for FILETIME {
impl Copy for FILETIME {}
impl Clone for FILETIME {
fn clone(&self) -> Self {
*self
}
Expand All @@ -47,8 +45,8 @@ pub struct SYSTEMTIME {
pub wSecond: u16,
pub wMilliseconds: u16,
}
impl ::core::marker::Copy for SYSTEMTIME {}
impl ::core::clone::Clone for SYSTEMTIME {
impl Copy for SYSTEMTIME {}
impl Clone for SYSTEMTIME {
fn clone(&self) -> Self {
*self
}
Expand All @@ -63,8 +61,8 @@ pub struct TIME_ZONE_INFORMATION {
pub DaylightDate: SYSTEMTIME,
pub DaylightBias: i32,
}
impl ::core::marker::Copy for TIME_ZONE_INFORMATION {}
impl ::core::clone::Clone for TIME_ZONE_INFORMATION {
impl Copy for TIME_ZONE_INFORMATION {}
impl Clone for TIME_ZONE_INFORMATION {
fn clone(&self) -> Self {
*self
}
Expand Down
2 changes: 1 addition & 1 deletion src/offset/local/win_bindings.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
--out src/offset/local/win_bindings.rs
--config flatten sys
--config flatten sys no-bindgen-comment
--filter
Windows.Win32.System.Time.GetTimeZoneInformationForYear
Windows.Win32.System.Time.SystemTimeToFileTime
Expand Down
Loading