Repository: chronotope/chrono (language: rust)

Issue:
Reduce the `Datelike` and `Timelike` traits
Chrono would become more correct and convenient if the `Datelike` and `Timelike` traits were removed in 0.5.

I propose to implement their methods directly on the types that currently implement the traits.

- Is anyone even depending on these traits? Writing code that is generic over types implementing `Datelike` or `Timelike` is asking for incorrect results and errors. It kind of defeats the thoughtful API of chrono to write generic code that mixes types like that.
- When implemented on `DateTime` the `with_` method should return `LocalResult`, so library users can choose how to deal with ambiguous or non-existing local datetimes. The current workaround to use them is cumbersome. See https://github.com/chronotope/chrono/issues/1049#issuecomment-1537157454 example 4.
- Trait methods can't be made const for the foreeseable future, which would be a gap in the const API of chrono (once it has one that is).
- The methods are currently less discoverable, but this can be considered a documentation issue.
- Library users would need to do one import less because the methods would just be available on the type.


Discussion / hints:
FWIW I also get hung up on the `Datelike` and `Timelike` traits; e.g. I spend tens of minutes searching for something that I know I've seen work elsewhere to then discover I need to `use ...Datelike` or `Timelike`. It's happened a few times and it's a little bit exasperating. At the same time, this could be fixed with better documentation.

> The methods are currently less discoverable, but this can be considered a documentation issue.
I'm not very convinced by your arguments so far to remove them. Abstracting over a `Date` and the date components of a `Time` seems conceptually reasonable to me, if maybe something that doesn't come up a lot.

However, if you can show that over some large body of Rust code there is negligible code that abstracts over `Datelike` or `Timelike` (with `T: Datelike` or `impl Datelike` bounds), we could consider it.
My 2c: as the author of a library depending on chrono it's useful for me to offer a single function that takes a `T: Datelike`, rather than 3 boilerplate functions that take the various concrete date types
My thoughts have changed a bit on this issue. I now think it is best to *shrink* the `Datelike` and `Timelike` traits.
They currently offer getter and setter methods.

The getter methods are fine as they are:

```rust
pub trait Datelike: Sized {
    // Required methods
    fn year(&self) -> i32;
    fn month(&self) -> u32;
    fn month0(&self) -> u32;
    fn day(&self) -> u32;
    fn day0(&self) -> u32;
    fn ordinal(&self) -> u32;
    fn ordinal0(&self) -> u32;
    fn weekday(&self) -> Weekday;
    fn iso_week(&self) -> IsoWeek;

    // Provided methods
    fn year_ce(&self) -> (bool, u32) { ... }
    fn num_days_from_ce(&self) -> i32 { ... }
}

pub trait Timelike: Sized {
    // Required methods
    fn hour(&self) -> u32;
    fn minute(&self) -> u32;
    fn second(&self) -> u32;
    fn nanosecond(&self) -> u32;

    // Provided methods
    fn hour12(&self) -> (bool, u32) { ... }
    fn num_seconds_from_midnight(&self) -> u32 { ... }
}
```

The setters are where the problem is. They are fallible, and depending on the type they are fallible for different reasons. I am pretty sure any code that is abstracting over `Datelike` or `Timelike` types and modifying them is hiding errors. If a goal of chrono is to help users write correct code involving dates/times it would be better to not have generic setters in my opinion.

This means we would move the following methods to types:
```rust
impl NaiveDate {
    pub fn with_year(&self, year: i32) -> Result<NaiveDate, Error>;
    pub fn with_month(&self, month: u32) -> Result<NaiveDate, Error>;
    pub fn with_month0(&self, month0: u32) -> Result<NaiveDate, Error>;
    pub fn with_day(&self, day: u32) -> Result<NaiveDate, Error>;
    pub fn with_day0(&self, day0: u32) -> Result<NaiveDate, Error>;
    pub fn with_ordinal(&self, ordinal: u32) -> Result<NaiveDate, Error>;
    pub fn with_ordinal0(&self, ordinal0: u32) -> Result<NaiveDate, Error>;
}

impl NaiveTime {
    pub fn with_hour(&self, hour: u32) -> Result<NaiveTime, Error>;
    pub fn with_minute(&self, min: u32) -> Result<NaiveTime, Error>;
    pub fn with_second(&self, sec: u32) -> Result<NaiveTime, Error>;
    pub fn with_nanosecond(&self, nano: u32) -> Result<NaiveTime, Error>;
}

impl NaiveDateTime {
    pub fn with_year(&self, year: i32) -> Result<NaiveDateTime, Error>;
    pub fn with_month(&self, month: u32) -> Result<NaiveDateTime, Error>;
    pub fn with_month0(&self, month0: u32) -> Result<NaiveDateTime, Error>;
    pub fn with_day(&self, day: u32) -> Result<NaiveDateTime, Error>;
    pub fn with_day0(&self, day0: u32) -> Result<NaiveDateTime, Error>;
    pub fn with_ordinal(&self, ordinal: u32) -> Result<NaiveDateTime, Error>;
    pub fn with_ordinal0(&self, ordinal0: u32) -> Result<NaiveDateTime, Error>;

    pub fn with_hour(&self, hour: u32) -> Result<NaiveDateTime, Error>;
    pub fn with_minute(&self, min: u32) -> Result<NaiveDateTime, Error>;
    pub fn with_second(&self, sec: u32) -> Result<NaiveDateTime, Error>;
    pub fn with_nanosecond(&self, nano: u32) -> Result<NaiveDateTime, Error>;
}

impl<Tz: TimeZone> DateTime<Tz> {
    pub fn with_year(&self, year: i32) -> LocalResult<Self>;
    pub fn with_month(&self, month: u32) -> LocalResult<Self>;
    pub fn with_month0(&self, month0: u32) -> LocalResult<Self>;
    pub fn with_day(&self, day: u32) -> LocalResult<Self>;
    pub fn with_day0(&self, day0: u32) -> LocalResult<Self>;
    pub fn with_ordinal(&self, ordinal: u32) -> LocalResult<Self>;
    pub fn with_ordinal0(&self, ordinal0: u32) -> LocalResult<Self>;

    pub fn with_hour(&self, hour: u32) -> LocalResult<Self>;
    pub fn with_minute(&self, min: u32) -> LocalResult<Self>;
    pub fn with_second(&self, sec: u32) -> LocalResult<Self>;
    pub fn with_nanosecond(&self, nano: u32) -> LocalResult<Self>;
}
```
Sidenote about `LocalResult` as return type for `DateTime<Tz>`:

How about returning `Result<LocalDatetime<T>>` instead? This prevents `LocalResult<T>::None` from masking the error cause. `LocalDatetime` would be the same as `LocalResult` sans the `None` variant, ideally as a drop-in replacement.

```
pub enum LocalDatetime<T> {
    /// Given local time representation has a single unique result.
    Single(T),
    /// Given local time representation has multiple results and thus ambiguous.
    /// This can occur when, for example, the negative timezone transition.
    Ambiguous(T /*min*/, T /*max*/),
}
```
> The setters are where the problem is. They are fallible, and depending on the type they are fallible for different reasons. I am pretty sure any code that is abstracting over `Datelike` or `Timelike` types and modifying them is hiding errors. If a goal of chrono is to help users write correct code involving dates/times it would be better to not have generic setters in my opinion.

Okay, so the main issue here is that we different return type for `DateTime<Tz>` because it needs to yield `LocalResult` (or whatever), to cope with possible DST transitions?

I think I can live with moving the setters out of the traits on 0.5.x. I expect their usage is pretty rare anyway.

Fix patch:
diff --git a/src/datetime/mod.rs b/src/datetime/mod.rs
index 7c02565b9a..7197298429 100644
--- a/src/datetime/mod.rs
+++ b/src/datetime/mod.rs
@@ -599,6 +599,187 @@ impl<Tz: TimeZone> DateTime<Tz> {
             .expect("writing rfc3339 datetime to string should never fail");
         result
     }
+
+    /// Makes a new `DateTime` with the year number changed, while keeping the same month and day.
+    ///
+    /// See also the [`NaiveDate::with_year`] method.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if:
+    /// - The resulting date does not exist (February 29 in a non-leap year).
+    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
+    ///   daylight saving time transition.
+    /// - The resulting UTC datetime would be out of range.
+    /// - The resulting local datetime would be out of range (unless the year remains the same).
+    #[inline]
+    pub fn with_year(&self, year: i32) -> Option<DateTime<Tz>> {
+        map_local(self, |dt| match dt.year() == year {
+            true => Some(dt),
+            false => dt.with_year(year),
+        })
+    }
+
+    /// Makes a new `DateTime` with the month number (starting from 1) changed.
+    ///
+    /// Don't combine multiple `Datelike::with_*` methods. The intermediate value may not exist.
+    ///
+    /// See also the [`NaiveDate::with_month`] method.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if:
+    /// - The resulting date does not exist (for example `month(4)` when day of the month is 31).
+    /// - The value for `month` is invalid.
+    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
+    ///   daylight saving time transition.
+    #[inline]
+    pub fn with_month(&self, month: u32) -> Option<DateTime<Tz>> {
+        map_local(self, |datetime| datetime.with_month(month))
+    }
+
+    /// Makes a new `DateTime` with the month number (starting from 0) changed.
+    ///
+    /// See also the [`NaiveDate::with_month0`] method.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if:
+    /// - The resulting date does not exist (for example `month0(3)` when day of the month is 31).
+    /// - The value for `month0` is invalid.
+    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
+    ///   daylight saving time transition.
+    #[inline]
+    pub fn with_month0(&self, month0: u32) -> Option<DateTime<Tz>> {
+        map_local(self, |datetime| datetime.with_month0(month0))
+    }
+
+    /// Makes a new `DateTime` with the day of month (starting from 1) changed.
+    ///
+    /// See also the [`NaiveDate::with_day`] method.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if:
+    /// - The resulting date does not exist (for example `day(31)` in April).
+    /// - The value for `day` is invalid.
+    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
+    ///   daylight saving time transition.
+    #[inline]
+    pub fn with_day(&self, day: u32) -> Option<DateTime<Tz>> {
+        map_local(self, |datetime| datetime.with_day(day))
+    }
+
+    /// Makes a new `DateTime` with the day of month (starting from 0) changed.
+    ///
+    /// See also the [`NaiveDate::with_day0`] method.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if:
+    /// - The resulting date does not exist (for example `day(30)` in April).
+    /// - The value for `day0` is invalid.
+    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
+    ///   daylight saving time transition.
+    #[inline]
+    pub fn with_day0(&self, day0: u32) -> Option<DateTime<Tz>> {
+        map_local(self, |datetime| datetime.with_day0(day0))
+    }
+
+    /// Makes a new `DateTime` with the day of year (starting from 1) changed.
+    ///
+    /// See also the [`NaiveDate::with_ordinal`] method.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if:
+    /// - The resulting date does not exist (`with_ordinal(366)` in a non-leap year).
+    /// - The value for `ordinal` is invalid.
+    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
+    ///   daylight saving time transition.
+    #[inline]
+    pub fn with_ordinal(&self, ordinal: u32) -> Option<DateTime<Tz>> {
+        map_local(self, |datetime| datetime.with_ordinal(ordinal))
+    }
+
+    /// Makes a new `DateTime` with the day of year (starting from 0) changed.
+    ///
+    /// See also the [`NaiveDate::with_ordinal0`] method.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if:
+    /// - The resulting date does not exist (`with_ordinal0(365)` in a non-leap year).
+    /// - The value for `ordinal0` is invalid.
+    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
+    ///   daylight saving time transition.
+    #[inline]
+    pub fn with_ordinal0(&self, ordinal0: u32) -> Option<DateTime<Tz>> {
+        map_local(self, |datetime| datetime.with_ordinal0(ordinal0))
+    }
+
+    /// Makes a new `DateTime` with the hour number changed.
+    ///
+    /// See also the [`NaiveTime::with_hour`] method.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if:
+    /// - The value for `hour` is invalid.
+    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
+    ///   daylight saving time transition.
+    #[inline]
+    pub fn with_hour(&self, hour: u32) -> Option<DateTime<Tz>> {
+        map_local(self, |datetime| datetime.with_hour(hour))
+    }
+
+    /// Makes a new `DateTime` with the minute number changed.
+    ///
+    /// See also the [`NaiveTime::with_minute`] method.
+    ///
+    /// # Errors
+    ///
+    /// - The value for `minute` is invalid.
+    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
+    ///   daylight saving time transition.
+    #[inline]
+    pub fn with_minute(&self, min: u32) -> Option<DateTime<Tz>> {
+        map_local(self, |datetime| datetime.with_minute(min))
+    }
+
+    /// Makes a new `DateTime` with the second number changed.
+    ///
+    /// As with the [`second`](#method.second) method,
+    /// the input range is restricted to 0 through 59.
+    ///
+    /// See also the [`NaiveTime::with_second`] method.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if:
+    /// - The value for `second` is invalid.
+    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
+    ///   daylight saving time transition.
+    #[inline]
+    pub fn with_second(&self, sec: u32) -> Option<DateTime<Tz>> {
+        map_local(self, |datetime| datetime.with_second(sec))
+    }
+
+    /// Makes a new `DateTime` with nanoseconds since the whole non-leap second changed.
+    ///
+    /// Returns `None` when the resulting `NaiveDateTime` would be invalid.
+    /// As with the [`NaiveDateTime::nanosecond`] method,
+    /// the input range can exceed 1,000,000,000 for leap seconds.
+    ///
+    /// See also the [`NaiveTime::with_nanosecond`] method.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if `nanosecond >= 2,000,000,000`.
+    #[inline]
+    pub fn with_nanosecond(&self, nano: u32) -> Option<DateTime<Tz>> {
+        map_local(self, |datetime| datetime.with_nanosecond(nano))
+    }
 }
 
 impl DateTime<Utc> {
@@ -1099,124 +1280,6 @@ impl<Tz: TimeZone> Datelike for DateTime<Tz> {
     fn iso_week(&self) -> IsoWeek {
         self.overflowing_naive_local().iso_week()
     }
-
-    #[inline]
-    /// Makes a new `DateTime` with the year number changed, while keeping the same month and day.
-    ///
-    /// See also the [`NaiveDate::with_year`] method.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if:
-    /// - The resulting date does not exist (February 29 in a non-leap year).
-    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
-    ///   daylight saving time transition.
-    /// - The resulting UTC datetime would be out of range.
-    /// - The resulting local datetime would be out of range (unless the year remains the same).
-    fn with_year(&self, year: i32) -> Option<DateTime<Tz>> {
-        map_local(self, |dt| match dt.year() == year {
-            true => Some(dt),
-            false => dt.with_year(year),
-        })
-    }
-
-    /// Makes a new `DateTime` with the month number (starting from 1) changed.
-    ///
-    /// Don't combine multiple `Datelike::with_*` methods. The intermediate value may not exist.
-    ///
-    /// See also the [`NaiveDate::with_month`] method.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if:
-    /// - The resulting date does not exist (for example `month(4)` when day of the month is 31).
-    /// - The value for `month` is invalid.
-    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
-    ///   daylight saving time transition.
-    #[inline]
-    fn with_month(&self, month: u32) -> Option<DateTime<Tz>> {
-        map_local(self, |datetime| datetime.with_month(month))
-    }
-
-    /// Makes a new `DateTime` with the month number (starting from 0) changed.
-    ///
-    /// See also the [`NaiveDate::with_month0`] method.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if:
-    /// - The resulting date does not exist (for example `month0(3)` when day of the month is 31).
-    /// - The value for `month0` is invalid.
-    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
-    ///   daylight saving time transition.
-    #[inline]
-    fn with_month0(&self, month0: u32) -> Option<DateTime<Tz>> {
-        map_local(self, |datetime| datetime.with_month0(month0))
-    }
-
-    /// Makes a new `DateTime` with the day of month (starting from 1) changed.
-    ///
-    /// See also the [`NaiveDate::with_day`] method.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if:
-    /// - The resulting date does not exist (for example `day(31)` in April).
-    /// - The value for `day` is invalid.
-    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
-    ///   daylight saving time transition.
-    #[inline]
-    fn with_day(&self, day: u32) -> Option<DateTime<Tz>> {
-        map_local(self, |datetime| datetime.with_day(day))
-    }
-
-    /// Makes a new `DateTime` with the day of month (starting from 0) changed.
-    ///
-    /// See also the [`NaiveDate::with_day0`] method.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if:
-    /// - The resulting date does not exist (for example `day(30)` in April).
-    /// - The value for `day0` is invalid.
-    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
-    ///   daylight saving time transition.
-    #[inline]
-    fn with_day0(&self, day0: u32) -> Option<DateTime<Tz>> {
-        map_local(self, |datetime| datetime.with_day0(day0))
-    }
-
-    /// Makes a new `DateTime` with the day of year (starting from 1) changed.
-    ///
-    /// See also the [`NaiveDate::with_ordinal`] method.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if:
-    /// - The resulting date does not exist (`with_ordinal(366)` in a non-leap year).
-    /// - The value for `ordinal` is invalid.
-    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
-    ///   daylight saving time transition.
-    #[inline]
-    fn with_ordinal(&self, ordinal: u32) -> Option<DateTime<Tz>> {
-        map_local(self, |datetime| datetime.with_ordinal(ordinal))
-    }
-
-    /// Makes a new `DateTime` with the day of year (starting from 0) changed.
-    ///
-    /// See also the [`NaiveDate::with_ordinal0`] method.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if:
-    /// - The resulting date does not exist (`with_ordinal0(365)` in a non-leap year).
-    /// - The value for `ordinal0` is invalid.
-    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
-    ///   daylight saving time transition.
-    #[inline]
-    fn with_ordinal0(&self, ordinal0: u32) -> Option<DateTime<Tz>> {
-        map_local(self, |datetime| datetime.with_ordinal0(ordinal0))
-    }
 }
 
 impl<Tz: TimeZone> Timelike for DateTime<Tz> {
@@ -1236,69 +1299,6 @@ impl<Tz: TimeZone> Timelike for DateTime<Tz> {
     fn nanosecond(&self) -> u32 {
         self.overflowing_naive_local().nanosecond()
     }
-
-    /// Makes a new `DateTime` with the hour number changed.
-    ///
-    /// See also the [`NaiveTime::with_hour`] method.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if:
-    /// - The value for `hour` is invalid.
-    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
-    ///   daylight saving time transition.
-    #[inline]
-    fn with_hour(&self, hour: u32) -> Option<DateTime<Tz>> {
-        map_local(self, |datetime| datetime.with_hour(hour))
-    }
-
-    /// Makes a new `DateTime` with the minute number changed.
-    ///
-    /// See also the [`NaiveTime::with_minute`] method.
-    ///
-    /// # Errors
-    ///
-    /// - The value for `minute` is invalid.
-    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
-    ///   daylight saving time transition.
-    #[inline]
-    fn with_minute(&self, min: u32) -> Option<DateTime<Tz>> {
-        map_local(self, |datetime| datetime.with_minute(min))
-    }
-
-    /// Makes a new `DateTime` with the second number changed.
-    ///
-    /// As with the [`second`](#method.second) method,
-    /// the input range is restricted to 0 through 59.
-    ///
-    /// See also the [`NaiveTime::with_second`] method.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if:
-    /// - The value for `second` is invalid.
-    /// - The local time at the resulting date does not exist or is ambiguous, for example during a
-    ///   daylight saving time transition.
-    #[inline]
-    fn with_second(&self, sec: u32) -> Option<DateTime<Tz>> {
-        map_local(self, |datetime| datetime.with_second(sec))
-    }
-
-    /// Makes a new `DateTime` with nanoseconds since the whole non-leap second changed.
-    ///
-    /// Returns `None` when the resulting `NaiveDateTime` would be invalid.
-    /// As with the [`NaiveDateTime::nanosecond`] method,
-    /// the input range can exceed 1,000,000,000 for leap seconds.
-    ///
-    /// See also the [`NaiveTime::with_nanosecond`] method.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if `nanosecond >= 2,000,000,000`.
-    #[inline]
-    fn with_nanosecond(&self, nano: u32) -> Option<DateTime<Tz>> {
-        map_local(self, |datetime| datetime.with_nanosecond(nano))
-    }
 }
 
 // we need them as automatic impls cannot handle associated types
diff --git a/src/format/formatting.rs b/src/format/formatting.rs
index 9af9c605f1..de6e0205ae 100644
--- a/src/format/formatting.rs
+++ b/src/format/formatting.rs
@@ -609,7 +609,7 @@ mod tests {
     use super::{Colons, OffsetFormat, OffsetPrecision, Pad};
     use crate::FixedOffset;
     #[cfg(feature = "alloc")]
-    use crate::{NaiveDate, NaiveTime, TimeZone, Timelike, Utc};
+    use crate::{NaiveDate, NaiveTime, TimeZone, Utc};
 
     #[test]
     #[cfg(feature = "alloc")]
diff --git a/src/format/parse.rs b/src/format/parse.rs
index cedd2d01e4..9c60be1124 100644
--- a/src/format/parse.rs
+++ b/src/format/parse.rs
@@ -589,7 +589,7 @@ fn parse_rfc3339_relaxed<'a>(parsed: &mut Parsed, mut s: &'a str) -> ParseResult
 #[cfg(test)]
 mod tests {
     use crate::format::*;
-    use crate::{DateTime, FixedOffset, NaiveDateTime, TimeZone, Timelike, Utc};
+    use crate::{DateTime, FixedOffset, NaiveDateTime, TimeZone, Utc};
 
     macro_rules! parsed {
         ($($k:ident: $v:expr),*) => (#[allow(unused_mut)] {
diff --git a/src/format/strftime.rs b/src/format/strftime.rs
index 948607c4f7..487b9b0afc 100644
--- a/src/format/strftime.rs
+++ b/src/format/strftime.rs
@@ -687,7 +687,7 @@ mod tests {
     use crate::format::{fixed, internal_fixed, num, num0, nums};
     use crate::format::{Fixed, InternalInternal, Numeric::*};
     #[cfg(feature = "alloc")]
-    use crate::{DateTime, FixedOffset, NaiveDate, TimeZone, Timelike, Utc};
+    use crate::{DateTime, FixedOffset, NaiveDate, TimeZone, Utc};
 
     #[test]
     fn test_strftime_items() {
diff --git a/src/naive/date/mod.rs b/src/naive/date/mod.rs
index 7df9c01f92..52abbe33bf 100644
--- a/src/naive/date/mod.rs
+++ b/src/naive/date/mod.rs
@@ -1202,6 +1202,245 @@ impl NaiveDate {
         self.yof() & (0b1000) == 0
     }
 
+    /// Makes a new `NaiveDate` with the year number changed, while keeping the same month and day.
+    ///
+    /// This method assumes you want to work on the date as a year-month-day value. Don't use it if
+    /// you want the ordinal to stay the same after changing the year, of if you want the week and
+    /// weekday values to stay the same.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if:
+    /// - The resulting date does not exist (February 29 in a non-leap year).
+    /// - The year is out of range for a `NaiveDate`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use chrono::NaiveDate;
+    ///
+    /// assert_eq!(
+    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().with_year(2016),
+    ///     Some(NaiveDate::from_ymd(2016, 9, 8).unwrap())
+    /// );
+    /// assert_eq!(
+    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().with_year(-308),
+    ///     Some(NaiveDate::from_ymd(-308, 9, 8).unwrap())
+    /// );
+    /// ```
+    ///
+    /// A leap day (February 29) is a case where this method can return `None`.
+    ///
+    /// ```
+    /// # use chrono::NaiveDate;
+    /// assert!(NaiveDate::from_ymd(2016, 2, 29).unwrap().with_year(2015).is_none());
+    /// assert!(NaiveDate::from_ymd(2016, 2, 29).unwrap().with_year(2020).is_some());
+    /// ```
+    ///
+    /// Don't use `with_year` if you want the ordinal date to stay the same:
+    ///
+    /// ```
+    /// # use chrono::NaiveDate;
+    /// assert_ne!(
+    ///     NaiveDate::from_yo(2020, 100).unwrap().with_year(2023).unwrap(),
+    ///     NaiveDate::from_yo(2023, 100).unwrap() // result is 2023-101
+    /// );
+    /// ```
+    #[inline]
+    pub const fn with_year(&self, year: i32) -> Option<NaiveDate> {
+        // we need to operate with `mdf` since we should keep the month and day number as is
+        let mdf = self.mdf();
+
+        // adjust the flags as needed
+        let flags = YearFlags::from_year(year);
+        let mdf = mdf.with_flags(flags);
+
+        ok!(NaiveDate::from_mdf(year, mdf))
+    }
+
+    /// Makes a new `NaiveDate` with the month number (starting from 1) changed.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if:
+    /// - The resulting date does not exist (for example `month(4)` when day of the month is 31).
+    /// - The value for `month` is invalid.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use chrono::NaiveDate;
+    ///
+    /// assert_eq!(
+    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().with_month(10),
+    ///     Some(NaiveDate::from_ymd(2015, 10, 8).unwrap())
+    /// );
+    /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).unwrap().with_month(13), None); // No month 13
+    /// assert_eq!(NaiveDate::from_ymd(2015, 9, 30).unwrap().with_month(2), None); // No Feb 30
+    /// ```
+    ///
+    /// Don't combine multiple `Datelike::with_*` methods. The intermediate value may not exist.
+    ///
+    /// ```
+    /// use chrono::{Datelike, Error, NaiveDate};
+    ///
+    /// fn with_year_month(date: NaiveDate, year: i32, month: u32) -> Option<NaiveDate> {
+    ///     date.with_year(year)?.with_month(month)
+    /// }
+    /// let d = NaiveDate::from_ymd(2020, 2, 29).unwrap();
+    /// assert!(with_year_month(d, 2019, 1).is_none()); // fails because of invalid intermediate value
+    ///
+    /// // Correct version:
+    /// fn with_year_month_fixed(date: NaiveDate, year: i32, month: u32) -> Result<NaiveDate, Error> {
+    ///     NaiveDate::from_ymd(year, month, date.day())
+    /// }
+    /// let d = NaiveDate::from_ymd(2020, 2, 29).unwrap();
+    /// assert_eq!(with_year_month_fixed(d, 2019, 1), NaiveDate::from_ymd(2019, 1, 29));
+    /// ```
+    #[inline]
+    pub const fn with_month(&self, month: u32) -> Option<NaiveDate> {
+        self.with_mdf(try_opt!(ok!(self.mdf().with_month(month))))
+    }
+
+    /// Makes a new `NaiveDate` with the month number (starting from 0) changed.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if:
+    /// - The resulting date does not exist (for example `month0(3)` when day of the month is 31).
+    /// - The value for `month0` is invalid.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use chrono::NaiveDate;
+    ///
+    /// assert_eq!(
+    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().with_month0(9),
+    ///     Some(NaiveDate::from_ymd(2015, 10, 8).unwrap())
+    /// );
+    /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).unwrap().with_month0(12), None); // No month 12
+    /// assert_eq!(NaiveDate::from_ymd(2015, 9, 30).unwrap().with_month0(1), None); // No Feb 30
+    /// ```
+    #[inline]
+    pub const fn with_month0(&self, month0: u32) -> Option<NaiveDate> {
+        let month = try_opt!(month0.checked_add(1));
+        self.with_mdf(try_opt!(ok!(self.mdf().with_month(month))))
+    }
+
+    /// Makes a new `NaiveDate` with the day of month (starting from 1) changed.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if:
+    /// - The resulting date does not exist (for example `day(31)` in April).
+    /// - The value for `day` is invalid.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use chrono::NaiveDate;
+    ///
+    /// assert_eq!(
+    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().with_day(30),
+    ///     Some(NaiveDate::from_ymd(2015, 9, 30).unwrap())
+    /// );
+    /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).unwrap().with_day(31), None); // no September 31
+    /// ```
+    #[inline]
+    pub const fn with_day(&self, day: u32) -> Option<NaiveDate> {
+        self.with_mdf(try_opt!(ok!(self.mdf().with_day(day))))
+    }
+
+    /// Makes a new `NaiveDate` with the day of month (starting from 0) changed.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if:
+    /// - The resulting date does not exist (for example `day(30)` in April).
+    /// - The value for `day0` is invalid.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use chrono::NaiveDate;
+    ///
+    /// assert_eq!(
+    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().with_day0(29),
+    ///     Some(NaiveDate::from_ymd(2015, 9, 30).unwrap())
+    /// );
+    /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).unwrap().with_day0(30), None); // no September 31
+    /// ```
+    #[inline]
+    pub const fn with_day0(&self, day0: u32) -> Option<NaiveDate> {
+        let day = try_opt!(day0.checked_add(1));
+        self.with_mdf(try_opt!(ok!(self.mdf().with_day(day))))
+    }
+
+    /// Makes a new `NaiveDate` with the day of year (starting from 1) changed.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if:
+    /// - The resulting date does not exist (`with_ordinal(366)` in a non-leap year).
+    /// - The value for `ordinal` is invalid.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use chrono::NaiveDate;
+    ///
+    /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).unwrap().with_ordinal(60),
+    ///            Some(NaiveDate::from_ymd(2015, 3, 1).unwrap()));
+    /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).unwrap().with_ordinal(366),
+    ///            None); // 2015 had only 365 days
+    ///
+    /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).unwrap().with_ordinal(60),
+    ///            Some(NaiveDate::from_ymd(2016, 2, 29).unwrap()));
+    /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).unwrap().with_ordinal(366),
+    ///            Some(NaiveDate::from_ymd(2016, 12, 31).unwrap()));
+    /// ```
+    #[inline]
+    pub const fn with_ordinal(&self, ordinal: u32) -> Option<NaiveDate> {
+        if ordinal == 0 || ordinal > 366 {
+            return None;
+        }
+        let yof = (self.yof() & !ORDINAL_MASK) | (ordinal << 4) as i32;
+        match yof & OL_MASK <= MAX_OL {
+            true => Some(NaiveDate::from_yof(yof)),
+            false => None, // Does not exist: Ordinal 366 in a common year.
+        }
+    }
+
+    /// Makes a new `NaiveDate` with the day of year (starting from 0) changed.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if:
+    /// - The resulting date does not exist (`with_ordinal0(365)` in a non-leap year).
+    /// - The value for `ordinal0` is invalid.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use chrono::NaiveDate;
+    ///
+    /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).unwrap().with_ordinal0(59),
+    ///            Some(NaiveDate::from_ymd(2015, 3, 1).unwrap()));
+    /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).unwrap().with_ordinal0(365),
+    ///            None); // 2015 had only 365 days
+    ///
+    /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).unwrap().with_ordinal0(59),
+    ///            Some(NaiveDate::from_ymd(2016, 2, 29).unwrap()));
+    /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).unwrap().with_ordinal0(365),
+    ///            Some(NaiveDate::from_ymd(2016, 12, 31).unwrap()));
+    /// ```
+    #[inline]
+    pub const fn with_ordinal0(&self, ordinal0: u32) -> Option<NaiveDate> {
+        let ordinal = try_opt!(ordinal0.checked_add(1));
+        self.with_ordinal(ordinal)
+    }
+
     // This duplicates `Datelike::year()`, because trait methods can't be const yet.
     #[inline]
     const fn year(&self) -> i32 {
@@ -1475,245 +1714,6 @@ impl Datelike for NaiveDate {
     fn iso_week(&self) -> IsoWeek {
         IsoWeek::from_yof(self.year(), self.ordinal(), self.year_flags())
     }
-
-    /// Makes a new `NaiveDate` with the year number changed, while keeping the same month and day.
-    ///
-    /// This method assumes you want to work on the date as a year-month-day value. Don't use it if
-    /// you want the ordinal to stay the same after changing the year, of if you want the week and
-    /// weekday values to stay the same.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if:
-    /// - The resulting date does not exist (February 29 in a non-leap year).
-    /// - The year is out of range for a `NaiveDate`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use chrono::{Datelike, NaiveDate};
-    ///
-    /// assert_eq!(
-    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().with_year(2016),
-    ///     Some(NaiveDate::from_ymd(2016, 9, 8).unwrap())
-    /// );
-    /// assert_eq!(
-    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().with_year(-308),
-    ///     Some(NaiveDate::from_ymd(-308, 9, 8).unwrap())
-    /// );
-    /// ```
-    ///
-    /// A leap day (February 29) is a case where this method can return `None`.
-    ///
-    /// ```
-    /// # use chrono::{NaiveDate, Datelike};
-    /// assert!(NaiveDate::from_ymd(2016, 2, 29).unwrap().with_year(2015).is_none());
-    /// assert!(NaiveDate::from_ymd(2016, 2, 29).unwrap().with_year(2020).is_some());
-    /// ```
-    ///
-    /// Don't use `with_year` if you want the ordinal date to stay the same:
-    ///
-    /// ```
-    /// # use chrono::{Datelike, NaiveDate};
-    /// assert_ne!(
-    ///     NaiveDate::from_yo(2020, 100).unwrap().with_year(2023).unwrap(),
-    ///     NaiveDate::from_yo(2023, 100).unwrap() // result is 2023-101
-    /// );
-    /// ```
-    #[inline]
-    fn with_year(&self, year: i32) -> Option<NaiveDate> {
-        // we need to operate with `mdf` since we should keep the month and day number as is
-        let mdf = self.mdf();
-
-        // adjust the flags as needed
-        let flags = YearFlags::from_year(year);
-        let mdf = mdf.with_flags(flags);
-
-        ok!(NaiveDate::from_mdf(year, mdf))
-    }
-
-    /// Makes a new `NaiveDate` with the month number (starting from 1) changed.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if:
-    /// - The resulting date does not exist (for example `month(4)` when day of the month is 31).
-    /// - The value for `month` is invalid.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use chrono::{Datelike, NaiveDate};
-    ///
-    /// assert_eq!(
-    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().with_month(10),
-    ///     Some(NaiveDate::from_ymd(2015, 10, 8).unwrap())
-    /// );
-    /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).unwrap().with_month(13), None); // No month 13
-    /// assert_eq!(NaiveDate::from_ymd(2015, 9, 30).unwrap().with_month(2), None); // No Feb 30
-    /// ```
-    ///
-    /// Don't combine multiple `Datelike::with_*` methods. The intermediate value may not exist.
-    ///
-    /// ```
-    /// use chrono::{Datelike, Error, NaiveDate};
-    ///
-    /// fn with_year_month(date: NaiveDate, year: i32, month: u32) -> Option<NaiveDate> {
-    ///     date.with_year(year)?.with_month(month)
-    /// }
-    /// let d = NaiveDate::from_ymd(2020, 2, 29).unwrap();
-    /// assert!(with_year_month(d, 2019, 1).is_none()); // fails because of invalid intermediate value
-    ///
-    /// // Correct version:
-    /// fn with_year_month_fixed(date: NaiveDate, year: i32, month: u32) -> Result<NaiveDate, Error> {
-    ///     NaiveDate::from_ymd(year, month, date.day())
-    /// }
-    /// let d = NaiveDate::from_ymd(2020, 2, 29).unwrap();
-    /// assert_eq!(with_year_month_fixed(d, 2019, 1), NaiveDate::from_ymd(2019, 1, 29));
-    /// ```
-    #[inline]
-    fn with_month(&self, month: u32) -> Option<NaiveDate> {
-        self.with_mdf(self.mdf().with_month(month).ok()?)
-    }
-
-    /// Makes a new `NaiveDate` with the month number (starting from 0) changed.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if:
-    /// - The resulting date does not exist (for example `month0(3)` when day of the month is 31).
-    /// - The value for `month0` is invalid.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use chrono::{Datelike, NaiveDate};
-    ///
-    /// assert_eq!(
-    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().with_month0(9),
-    ///     Some(NaiveDate::from_ymd(2015, 10, 8).unwrap())
-    /// );
-    /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).unwrap().with_month0(12), None); // No month 12
-    /// assert_eq!(NaiveDate::from_ymd(2015, 9, 30).unwrap().with_month0(1), None); // No Feb 30
-    /// ```
-    #[inline]
-    fn with_month0(&self, month0: u32) -> Option<NaiveDate> {
-        let month = month0.checked_add(1)?;
-        self.with_mdf(self.mdf().with_month(month).ok()?)
-    }
-
-    /// Makes a new `NaiveDate` with the day of month (starting from 1) changed.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if:
-    /// - The resulting date does not exist (for example `day(31)` in April).
-    /// - The value for `day` is invalid.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use chrono::{Datelike, NaiveDate};
-    ///
-    /// assert_eq!(
-    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().with_day(30),
-    ///     Some(NaiveDate::from_ymd(2015, 9, 30).unwrap())
-    /// );
-    /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).unwrap().with_day(31), None); // no September 31
-    /// ```
-    #[inline]
-    fn with_day(&self, day: u32) -> Option<NaiveDate> {
-        self.with_mdf(self.mdf().with_day(day).ok()?)
-    }
-
-    /// Makes a new `NaiveDate` with the day of month (starting from 0) changed.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if:
-    /// - The resulting date does not exist (for example `day(30)` in April).
-    /// - The value for `day0` is invalid.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use chrono::{Datelike, NaiveDate};
-    ///
-    /// assert_eq!(
-    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().with_day0(29),
-    ///     Some(NaiveDate::from_ymd(2015, 9, 30).unwrap())
-    /// );
-    /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).unwrap().with_day0(30), None); // no September 31
-    /// ```
-    #[inline]
-    fn with_day0(&self, day0: u32) -> Option<NaiveDate> {
-        let day = day0.checked_add(1)?;
-        self.with_mdf(self.mdf().with_day(day).ok()?)
-    }
-
-    /// Makes a new `NaiveDate` with the day of year (starting from 1) changed.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if:
-    /// - The resulting date does not exist (`with_ordinal(366)` in a non-leap year).
-    /// - The value for `ordinal` is invalid.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use chrono::{NaiveDate, Datelike};
-    ///
-    /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).unwrap().with_ordinal(60),
-    ///            Some(NaiveDate::from_ymd(2015, 3, 1).unwrap()));
-    /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).unwrap().with_ordinal(366),
-    ///            None); // 2015 had only 365 days
-    ///
-    /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).unwrap().with_ordinal(60),
-    ///            Some(NaiveDate::from_ymd(2016, 2, 29).unwrap()));
-    /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).unwrap().with_ordinal(366),
-    ///            Some(NaiveDate::from_ymd(2016, 12, 31).unwrap()));
-    /// ```
-    #[inline]
-    fn with_ordinal(&self, ordinal: u32) -> Option<NaiveDate> {
-        if ordinal == 0 || ordinal > 366 {
-            return None;
-        }
-        let yof = (self.yof() & !ORDINAL_MASK) | (ordinal << 4) as i32;
-        match yof & OL_MASK <= MAX_OL {
-            true => Some(NaiveDate::from_yof(yof)),
-            false => None, // Does not exist: Ordinal 366 in a common year.
-        }
-    }
-
-    /// Makes a new `NaiveDate` with the day of year (starting from 0) changed.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if:
-    /// - The resulting date does not exist (`with_ordinal0(365)` in a non-leap year).
-    /// - The value for `ordinal0` is invalid.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use chrono::{NaiveDate, Datelike};
-    ///
-    /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).unwrap().with_ordinal0(59),
-    ///            Some(NaiveDate::from_ymd(2015, 3, 1).unwrap()));
-    /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).unwrap().with_ordinal0(365),
-    ///            None); // 2015 had only 365 days
-    ///
-    /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).unwrap().with_ordinal0(59),
-    ///            Some(NaiveDate::from_ymd(2016, 2, 29).unwrap()));
-    /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).unwrap().with_ordinal0(365),
-    ///            Some(NaiveDate::from_ymd(2016, 12, 31).unwrap()));
-    /// ```
-    #[inline]
-    fn with_ordinal0(&self, ordinal0: u32) -> Option<NaiveDate> {
-        let ordinal = ordinal0.checked_add(1)?;
-        self.with_ordinal(ordinal)
-    }
 }
 
 /// Add `TimeDelta` to `NaiveDate`.
diff --git a/src/naive/datetime/mod.rs b/src/naive/datetime/mod.rs
index 54404e7800..94459cc9ee 100644
--- a/src/naive/datetime/mod.rs
+++ b/src/naive/datetime/mod.rs
@@ -881,187 +881,6 @@ impl NaiveDateTime {
         DateTime::from_naive_utc_and_offset(*self, Utc)
     }
 
-    /// The minimum possible `NaiveDateTime`.
-    pub const MIN: Self = Self { date: NaiveDate::MIN, time: NaiveTime::MIN };
-
-    /// The maximum possible `NaiveDateTime`.
-    pub const MAX: Self = Self { date: NaiveDate::MAX, time: NaiveTime::MAX };
-
-    /// The Unix Epoch, 1970-01-01 00:00:00.
-    pub const UNIX_EPOCH: Self =
-        expect!(ok!(NaiveDate::from_ymd(1970, 1, 1)), "").and_time(NaiveTime::MIN);
-}
-
-impl From<NaiveDate> for NaiveDateTime {
-    /// Converts a `NaiveDate` to a `NaiveDateTime` of the same date but at midnight.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use chrono::{NaiveDate, NaiveDateTime};
-    ///
-    /// let nd = NaiveDate::from_ymd(2016, 5, 28).unwrap();
-    /// let ndt = NaiveDate::from_ymd(2016, 5, 28).unwrap().and_hms(0, 0, 0).unwrap();
-    /// assert_eq!(ndt, NaiveDateTime::from(nd));
-    fn from(date: NaiveDate) -> Self {
-        date.and_hms(0, 0, 0).unwrap()
-    }
-}
-
-impl Datelike for NaiveDateTime {
-    /// Returns the year number in the [calendar date](./struct.NaiveDate.html#calendar-date).
-    ///
-    /// See also the [`NaiveDate::year`](./struct.NaiveDate.html#method.year) method.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
-    ///
-    /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).unwrap().and_hms(12, 34, 56).unwrap();
-    /// assert_eq!(dt.year(), 2015);
-    /// ```
-    #[inline]
-    fn year(&self) -> i32 {
-        self.date.year()
-    }
-
-    /// Returns the month number starting from 1.
-    ///
-    /// The return value ranges from 1 to 12.
-    ///
-    /// See also the [`NaiveDate::month`](./struct.NaiveDate.html#method.month) method.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
-    ///
-    /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).unwrap().and_hms(12, 34, 56).unwrap();
-    /// assert_eq!(dt.month(), 9);
-    /// ```
-    #[inline]
-    fn month(&self) -> u32 {
-        self.date.month()
-    }
-
-    /// Returns the month number starting from 0.
-    ///
-    /// The return value ranges from 0 to 11.
-    ///
-    /// See also the [`NaiveDate::month0`] method.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
-    ///
-    /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).unwrap().and_hms(12, 34, 56).unwrap();
-    /// assert_eq!(dt.month0(), 8);
-    /// ```
-    #[inline]
-    fn month0(&self) -> u32 {
-        self.date.month0()
-    }
-
-    /// Returns the day of month starting from 1.
-    ///
-    /// The return value ranges from 1 to 31. (The last day of month differs by months.)
-    ///
-    /// See also the [`NaiveDate::day`](./struct.NaiveDate.html#method.day) method.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
-    ///
-    /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).unwrap().and_hms(12, 34, 56).unwrap();
-    /// assert_eq!(dt.day(), 25);
-    /// ```
-    #[inline]
-    fn day(&self) -> u32 {
-        self.date.day()
-    }
-
-    /// Returns the day of month starting from 0.
-    ///
-    /// The return value ranges from 0 to 30. (The last day of month differs by months.)
-    ///
-    /// See also the [`NaiveDate::day0`] method.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
-    ///
-    /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).unwrap().and_hms(12, 34, 56).unwrap();
-    /// assert_eq!(dt.day0(), 24);
-    /// ```
-    #[inline]
-    fn day0(&self) -> u32 {
-        self.date.day0()
-    }
-
-    /// Returns the day of year starting from 1.
-    ///
-    /// The return value ranges from 1 to 366. (The last day of year differs by years.)
-    ///
-    /// See also the [`NaiveDate::ordinal`](./struct.NaiveDate.html#method.ordinal) method.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
-    ///
-    /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).unwrap().and_hms(12, 34, 56).unwrap();
-    /// assert_eq!(dt.ordinal(), 268);
-    /// ```
-    #[inline]
-    fn ordinal(&self) -> u32 {
-        self.date.ordinal()
-    }
-
-    /// Returns the day of year starting from 0.
-    ///
-    /// The return value ranges from 0 to 365. (The last day of year differs by years.)
-    ///
-    /// See also the [`NaiveDate::ordinal0`] method.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
-    ///
-    /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).unwrap().and_hms(12, 34, 56).unwrap();
-    /// assert_eq!(dt.ordinal0(), 267);
-    /// ```
-    #[inline]
-    fn ordinal0(&self) -> u32 {
-        self.date.ordinal0()
-    }
-
-    /// Returns the day of week.
-    ///
-    /// See also the [`NaiveDate::weekday`](./struct.NaiveDate.html#method.weekday) method.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use chrono::{Datelike, NaiveDate, NaiveDateTime, Weekday};
-    ///
-    /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).unwrap().and_hms(12, 34, 56).unwrap();
-    /// assert_eq!(dt.weekday(), Weekday::Fri);
-    /// ```
-    #[inline]
-    fn weekday(&self) -> Weekday {
-        self.date.weekday()
-    }
-
-    #[inline]
-    fn iso_week(&self) -> IsoWeek {
-        self.date.iso_week()
-    }
-
     /// Makes a new `NaiveDateTime` with the year number changed, while keeping the same month and
     /// day.
     ///
@@ -1076,7 +895,7 @@ impl Datelike for NaiveDateTime {
     /// # Example
     ///
     /// ```
-    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
+    /// use chrono::{NaiveDate, NaiveDateTime};
     ///
     /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).unwrap().and_hms(12, 34, 56).unwrap();
     /// assert_eq!(
@@ -1089,8 +908,8 @@ impl Datelike for NaiveDateTime {
     /// );
     /// ```
     #[inline]
-    fn with_year(&self, year: i32) -> Option<NaiveDateTime> {
-        self.date.with_year(year).map(|d| NaiveDateTime { date: d, ..*self })
+    pub const fn with_year(&self, year: i32) -> Option<NaiveDateTime> {
+        Some(NaiveDateTime { date: try_opt!(self.date.with_year(year)), ..*self })
     }
 
     /// Makes a new `NaiveDateTime` with the month number (starting from 1) changed.
@@ -1108,7 +927,7 @@ impl Datelike for NaiveDateTime {
     /// # Example
     ///
     /// ```
-    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
+    /// use chrono::{NaiveDate, NaiveDateTime};
     ///
     /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 30).unwrap().and_hms(12, 34, 56).unwrap();
     /// assert_eq!(
@@ -1119,8 +938,8 @@ impl Datelike for NaiveDateTime {
     /// assert_eq!(dt.with_month(2), None); // No February 30
     /// ```
     #[inline]
-    fn with_month(&self, month: u32) -> Option<NaiveDateTime> {
-        self.date.with_month(month).map(|d| NaiveDateTime { date: d, ..*self })
+    pub const fn with_month(&self, month: u32) -> Option<NaiveDateTime> {
+        Some(NaiveDateTime { date: try_opt!(self.date.with_month(month)), ..*self })
     }
 
     /// Makes a new `NaiveDateTime` with the month number (starting from 0) changed.
@@ -1136,7 +955,7 @@ impl Datelike for NaiveDateTime {
     /// # Example
     ///
     /// ```
-    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
+    /// use chrono::{NaiveDate, NaiveDateTime};
     ///
     /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 30).unwrap().and_hms(12, 34, 56).unwrap();
     /// assert_eq!(
@@ -1147,8 +966,8 @@ impl Datelike for NaiveDateTime {
     /// assert_eq!(dt.with_month0(1), None); // No February 30
     /// ```
     #[inline]
-    fn with_month0(&self, month0: u32) -> Option<NaiveDateTime> {
-        self.date.with_month0(month0).map(|d| NaiveDateTime { date: d, ..*self })
+    pub const fn with_month0(&self, month0: u32) -> Option<NaiveDateTime> {
+        Some(NaiveDateTime { date: try_opt!(self.date.with_month0(month0)), ..*self })
     }
 
     /// Makes a new `NaiveDateTime` with the day of month (starting from 1) changed.
@@ -1164,7 +983,7 @@ impl Datelike for NaiveDateTime {
     /// # Example
     ///
     /// ```
-    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
+    /// use chrono::{NaiveDate, NaiveDateTime};
     ///
     /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms(12, 34, 56).unwrap();
     /// assert_eq!(
@@ -1174,8 +993,8 @@ impl Datelike for NaiveDateTime {
     /// assert_eq!(dt.with_day(31), None); // no September 31
     /// ```
     #[inline]
-    fn with_day(&self, day: u32) -> Option<NaiveDateTime> {
-        self.date.with_day(day).map(|d| NaiveDateTime { date: d, ..*self })
+    pub const fn with_day(&self, day: u32) -> Option<NaiveDateTime> {
+        Some(NaiveDateTime { date: try_opt!(self.date.with_day(day)), ..*self })
     }
 
     /// Makes a new `NaiveDateTime` with the day of month (starting from 0) changed.
@@ -1191,7 +1010,7 @@ impl Datelike for NaiveDateTime {
     /// # Example
     ///
     /// ```
-    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
+    /// use chrono::{NaiveDate, NaiveDateTime};
     ///
     /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms(12, 34, 56).unwrap();
     /// assert_eq!(
@@ -1201,8 +1020,8 @@ impl Datelike for NaiveDateTime {
     /// assert_eq!(dt.with_day0(30), None); // no September 31
     /// ```
     #[inline]
-    fn with_day0(&self, day0: u32) -> Option<NaiveDateTime> {
-        self.date.with_day0(day0).map(|d| NaiveDateTime { date: d, ..*self })
+    pub const fn with_day0(&self, day0: u32) -> Option<NaiveDateTime> {
+        Some(NaiveDateTime { date: try_opt!(self.date.with_day0(day0)), ..*self })
     }
 
     /// Makes a new `NaiveDateTime` with the day of year (starting from 1) changed.
@@ -1218,7 +1037,7 @@ impl Datelike for NaiveDateTime {
     /// # Example
     ///
     /// ```
-    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
+    /// use chrono::{NaiveDate, NaiveDateTime};
     ///
     /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms(12, 34, 56).unwrap();
     /// assert_eq!(
@@ -1238,8 +1057,8 @@ impl Datelike for NaiveDateTime {
     /// );
     /// ```
     #[inline]
-    fn with_ordinal(&self, ordinal: u32) -> Option<NaiveDateTime> {
-        self.date.with_ordinal(ordinal).map(|d| NaiveDateTime { date: d, ..*self })
+    pub const fn with_ordinal(&self, ordinal: u32) -> Option<NaiveDateTime> {
+        Some(NaiveDateTime { date: try_opt!(self.date.with_ordinal(ordinal)), ..*self })
     }
 
     /// Makes a new `NaiveDateTime` with the day of year (starting from 0) changed.
@@ -1255,7 +1074,7 @@ impl Datelike for NaiveDateTime {
     /// # Example
     ///
     /// ```
-    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
+    /// use chrono::{NaiveDate, NaiveDateTime};
     ///
     /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms(12, 34, 56).unwrap();
     /// assert_eq!(
@@ -1275,148 +1094,318 @@ impl Datelike for NaiveDateTime {
     /// );
     /// ```
     #[inline]
-    fn with_ordinal0(&self, ordinal0: u32) -> Option<NaiveDateTime> {
-        self.date.with_ordinal0(ordinal0).map(|d| NaiveDateTime { date: d, ..*self })
+    pub const fn with_ordinal0(&self, ordinal0: u32) -> Option<NaiveDateTime> {
+        Some(NaiveDateTime { date: try_opt!(self.date.with_ordinal0(ordinal0)), ..*self })
     }
-}
 
-impl Timelike for NaiveDateTime {
-    /// Returns the hour number from 0 to 23.
+    /// Makes a new `NaiveDateTime` with the hour number changed.
     ///
-    /// See also the [`NaiveTime::hour`] method.
+    /// See also the [`NaiveTime::with_hour`] method.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if the value for `hour` is invalid.
     ///
     /// # Example
     ///
     /// ```
-    /// use chrono::{NaiveDate, NaiveDateTime, Timelike};
+    /// use chrono::{NaiveDate, NaiveDateTime};
     ///
     /// let dt: NaiveDateTime =
     ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_milli(12, 34, 56, 789).unwrap();
-    /// assert_eq!(dt.hour(), 12);
+    /// assert_eq!(
+    ///     dt.with_hour(7),
+    ///     Some(NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_milli(7, 34, 56, 789).unwrap())
+    /// );
+    /// assert_eq!(dt.with_hour(24), None);
     /// ```
     #[inline]
-    fn hour(&self) -> u32 {
-        self.time.hour()
+    pub const fn with_hour(&self, hour: u32) -> Option<NaiveDateTime> {
+        Some(NaiveDateTime { time: try_opt!(self.time.with_hour(hour)), ..*self })
     }
 
-    /// Returns the minute number from 0 to 59.
+    /// Makes a new `NaiveDateTime` with the minute number changed.
     ///
-    /// See also the [`NaiveTime::minute`] method.
+    /// See also the [`NaiveTime::with_minute`] method.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if the value for `minute` is invalid.
     ///
     /// # Example
     ///
     /// ```
-    /// use chrono::{NaiveDate, NaiveDateTime, Timelike};
+    /// use chrono::{NaiveDate, NaiveDateTime};
     ///
     /// let dt: NaiveDateTime =
     ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_milli(12, 34, 56, 789).unwrap();
-    /// assert_eq!(dt.minute(), 34);
+    /// assert_eq!(
+    ///     dt.with_minute(45),
+    ///     Some(NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_milli(12, 45, 56, 789).unwrap())
+    /// );
+    /// assert_eq!(dt.with_minute(60), None);
     /// ```
     #[inline]
-    fn minute(&self) -> u32 {
-        self.time.minute()
+    pub const fn with_minute(&self, min: u32) -> Option<NaiveDateTime> {
+        Some(NaiveDateTime { time: try_opt!(self.time.with_minute(min)), ..*self })
     }
 
-    /// Returns the second number from 0 to 59.
+    /// Makes a new `NaiveDateTime` with the second number changed.
     ///
-    /// See also the [`NaiveTime::second`] method.
+    /// As with the [`second`](#method.second) method,
+    /// the input range is restricted to 0 through 59.
+    ///
+    /// See also the [`NaiveTime::with_second`] method.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if the value for `second` is invalid.
     ///
     /// # Example
     ///
     /// ```
-    /// use chrono::{NaiveDate, NaiveDateTime, Timelike};
+    /// use chrono::{NaiveDate, NaiveDateTime};
     ///
     /// let dt: NaiveDateTime =
     ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_milli(12, 34, 56, 789).unwrap();
-    /// assert_eq!(dt.second(), 56);
+    /// assert_eq!(
+    ///     dt.with_second(17),
+    ///     Some(NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_milli(12, 34, 17, 789).unwrap())
+    /// );
+    /// assert_eq!(dt.with_second(60), None);
     /// ```
     #[inline]
-    fn second(&self) -> u32 {
-        self.time.second()
+    pub const fn with_second(&self, sec: u32) -> Option<NaiveDateTime> {
+        Some(NaiveDateTime { time: try_opt!(self.time.with_second(sec)), ..*self })
     }
 
-    /// Returns the number of nanoseconds since the whole non-leap second.
-    /// The range from 1,000,000,000 to 1,999,999,999 represents
-    /// the [leap second](./struct.NaiveTime.html#leap-second-handling).
+    /// Makes a new `NaiveDateTime` with nanoseconds since the whole non-leap second changed.
     ///
-    /// See also the [`NaiveTime#method.nanosecond`] method.
+    /// Returns `None` when the resulting `NaiveDateTime` would be invalid.
+    /// As with the [`NaiveDateTime::nanosecond`] method,
+    /// the input range can exceed 1,000,000,000 for leap seconds.
+    ///
+    /// See also the [`NaiveTime::with_nanosecond`] method.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if `nanosecond >= 2,000,000,000`.
     ///
     /// # Example
     ///
     /// ```
-    /// use chrono::{NaiveDate, NaiveDateTime, Timelike};
+    /// use chrono::{NaiveDate, NaiveDateTime};
     ///
     /// let dt: NaiveDateTime =
-    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_milli(12, 34, 56, 789).unwrap();
-    /// assert_eq!(dt.nanosecond(), 789_000_000);
+    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_milli(12, 34, 59, 789).unwrap();
+    /// assert_eq!(
+    ///     dt.with_nanosecond(333_333_333),
+    ///     Some(
+    ///         NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_nano(12, 34, 59, 333_333_333).unwrap()
+    ///     )
+    /// );
+    /// assert_eq!(
+    ///     dt.with_nanosecond(1_333_333_333), // leap second
+    ///     Some(
+    ///         NaiveDate::from_ymd(2015, 9, 8)
+    ///             .unwrap()
+    ///             .and_hms_nano(12, 34, 59, 1_333_333_333)
+    ///             .unwrap()
+    ///     )
+    /// );
+    /// assert_eq!(dt.with_nanosecond(2_000_000_000), None);
     /// ```
     #[inline]
-    fn nanosecond(&self) -> u32 {
-        self.time.nanosecond()
+    pub const fn with_nanosecond(&self, nano: u32) -> Option<NaiveDateTime> {
+        Some(NaiveDateTime { time: try_opt!(self.time.with_nanosecond(nano)), ..*self })
     }
 
-    /// Makes a new `NaiveDateTime` with the hour number changed.
+    /// The minimum possible `NaiveDateTime`.
+    pub const MIN: Self = Self { date: NaiveDate::MIN, time: NaiveTime::MIN };
+
+    /// The maximum possible `NaiveDateTime`.
+    pub const MAX: Self = Self { date: NaiveDate::MAX, time: NaiveTime::MAX };
+
+    /// The Unix Epoch, 1970-01-01 00:00:00.
+    pub const UNIX_EPOCH: Self =
+        expect!(ok!(NaiveDate::from_ymd(1970, 1, 1)), "").and_time(NaiveTime::MIN);
+}
+
+impl From<NaiveDate> for NaiveDateTime {
+    /// Converts a `NaiveDate` to a `NaiveDateTime` of the same date but at midnight.
     ///
-    /// See also the [`NaiveTime::with_hour`] method.
+    /// # Example
     ///
-    /// # Errors
+    /// ```
+    /// use chrono::{NaiveDate, NaiveDateTime};
     ///
-    /// Returns `None` if the value for `hour` is invalid.
+    /// let nd = NaiveDate::from_ymd(2016, 5, 28).unwrap();
+    /// let ndt = NaiveDate::from_ymd(2016, 5, 28).unwrap().and_hms(0, 0, 0).unwrap();
+    /// assert_eq!(ndt, NaiveDateTime::from(nd));
+    fn from(date: NaiveDate) -> Self {
+        date.and_hms(0, 0, 0).unwrap()
+    }
+}
+
+impl Datelike for NaiveDateTime {
+    /// Returns the year number in the [calendar date](./struct.NaiveDate.html#calendar-date).
+    ///
+    /// See also the [`NaiveDate::year`](./struct.NaiveDate.html#method.year) method.
     ///
     /// # Example
     ///
     /// ```
-    /// use chrono::{NaiveDate, NaiveDateTime, Timelike};
+    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
     ///
-    /// let dt: NaiveDateTime =
-    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_milli(12, 34, 56, 789).unwrap();
-    /// assert_eq!(
-    ///     dt.with_hour(7),
-    ///     Some(NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_milli(7, 34, 56, 789).unwrap())
-    /// );
-    /// assert_eq!(dt.with_hour(24), None);
+    /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).unwrap().and_hms(12, 34, 56).unwrap();
+    /// assert_eq!(dt.year(), 2015);
     /// ```
     #[inline]
-    fn with_hour(&self, hour: u32) -> Option<NaiveDateTime> {
-        self.time.with_hour(hour).map(|t| NaiveDateTime { time: t, ..*self })
+    fn year(&self) -> i32 {
+        self.date.year()
     }
 
-    /// Makes a new `NaiveDateTime` with the minute number changed.
+    /// Returns the month number starting from 1.
     ///
-    /// See also the [`NaiveTime::with_minute`] method.
+    /// The return value ranges from 1 to 12.
     ///
-    /// # Errors
+    /// See also the [`NaiveDate::month`](./struct.NaiveDate.html#method.month) method.
     ///
-    /// Returns `None` if the value for `minute` is invalid.
+    /// # Example
+    ///
+    /// ```
+    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
+    ///
+    /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).unwrap().and_hms(12, 34, 56).unwrap();
+    /// assert_eq!(dt.month(), 9);
+    /// ```
+    #[inline]
+    fn month(&self) -> u32 {
+        self.date.month()
+    }
+
+    /// Returns the month number starting from 0.
+    ///
+    /// The return value ranges from 0 to 11.
+    ///
+    /// See also the [`NaiveDate::month0`] method.
     ///
     /// # Example
     ///
     /// ```
-    /// use chrono::{NaiveDate, NaiveDateTime, Timelike};
+    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
     ///
-    /// let dt: NaiveDateTime =
-    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_milli(12, 34, 56, 789).unwrap();
-    /// assert_eq!(
-    ///     dt.with_minute(45),
-    ///     Some(NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_milli(12, 45, 56, 789).unwrap())
-    /// );
-    /// assert_eq!(dt.with_minute(60), None);
+    /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).unwrap().and_hms(12, 34, 56).unwrap();
+    /// assert_eq!(dt.month0(), 8);
     /// ```
     #[inline]
-    fn with_minute(&self, min: u32) -> Option<NaiveDateTime> {
-        self.time.with_minute(min).map(|t| NaiveDateTime { time: t, ..*self })
+    fn month0(&self) -> u32 {
+        self.date.month0()
     }
 
-    /// Makes a new `NaiveDateTime` with the second number changed.
+    /// Returns the day of month starting from 1.
     ///
-    /// As with the [`second`](#method.second) method,
-    /// the input range is restricted to 0 through 59.
+    /// The return value ranges from 1 to 31. (The last day of month differs by months.)
     ///
-    /// See also the [`NaiveTime::with_second`] method.
+    /// See also the [`NaiveDate::day`](./struct.NaiveDate.html#method.day) method.
     ///
-    /// # Errors
+    /// # Example
     ///
-    /// Returns `None` if the value for `second` is invalid.
+    /// ```
+    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
+    ///
+    /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).unwrap().and_hms(12, 34, 56).unwrap();
+    /// assert_eq!(dt.day(), 25);
+    /// ```
+    #[inline]
+    fn day(&self) -> u32 {
+        self.date.day()
+    }
+
+    /// Returns the day of month starting from 0.
+    ///
+    /// The return value ranges from 0 to 30. (The last day of month differs by months.)
+    ///
+    /// See also the [`NaiveDate::day0`] method.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
+    ///
+    /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).unwrap().and_hms(12, 34, 56).unwrap();
+    /// assert_eq!(dt.day0(), 24);
+    /// ```
+    #[inline]
+    fn day0(&self) -> u32 {
+        self.date.day0()
+    }
+
+    /// Returns the day of year starting from 1.
+    ///
+    /// The return value ranges from 1 to 366. (The last day of year differs by years.)
+    ///
+    /// See also the [`NaiveDate::ordinal`](./struct.NaiveDate.html#method.ordinal) method.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
+    ///
+    /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).unwrap().and_hms(12, 34, 56).unwrap();
+    /// assert_eq!(dt.ordinal(), 268);
+    /// ```
+    #[inline]
+    fn ordinal(&self) -> u32 {
+        self.date.ordinal()
+    }
+
+    /// Returns the day of year starting from 0.
+    ///
+    /// The return value ranges from 0 to 365. (The last day of year differs by years.)
+    ///
+    /// See also the [`NaiveDate::ordinal0`] method.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use chrono::{Datelike, NaiveDate, NaiveDateTime};
+    ///
+    /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).unwrap().and_hms(12, 34, 56).unwrap();
+    /// assert_eq!(dt.ordinal0(), 267);
+    /// ```
+    #[inline]
+    fn ordinal0(&self) -> u32 {
+        self.date.ordinal0()
+    }
+
+    /// Returns the day of week.
+    ///
+    /// See also the [`NaiveDate::weekday`](./struct.NaiveDate.html#method.weekday) method.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use chrono::{Datelike, NaiveDate, NaiveDateTime, Weekday};
+    ///
+    /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).unwrap().and_hms(12, 34, 56).unwrap();
+    /// assert_eq!(dt.weekday(), Weekday::Fri);
+    /// ```
+    #[inline]
+    fn weekday(&self) -> Weekday {
+        self.date.weekday()
+    }
+
+    #[inline]
+    fn iso_week(&self) -> IsoWeek {
+        self.date.iso_week()
+    }
+}
+
+impl Timelike for NaiveDateTime {
+    /// Returns the hour number from 0 to 23.
+    ///
+    /// See also the [`NaiveTime::hour`] method.
     ///
     /// # Example
     ///
@@ -1425,28 +1414,34 @@ impl Timelike for NaiveDateTime {
     ///
     /// let dt: NaiveDateTime =
     ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_milli(12, 34, 56, 789).unwrap();
-    /// assert_eq!(
-    ///     dt.with_second(17),
-    ///     Some(NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_milli(12, 34, 17, 789).unwrap())
-    /// );
-    /// assert_eq!(dt.with_second(60), None);
+    /// assert_eq!(dt.hour(), 12);
     /// ```
     #[inline]
-    fn with_second(&self, sec: u32) -> Option<NaiveDateTime> {
-        self.time.with_second(sec).map(|t| NaiveDateTime { time: t, ..*self })
+    fn hour(&self) -> u32 {
+        self.time.hour()
     }
 
-    /// Makes a new `NaiveDateTime` with nanoseconds since the whole non-leap second changed.
+    /// Returns the minute number from 0 to 59.
     ///
-    /// Returns `None` when the resulting `NaiveDateTime` would be invalid.
-    /// As with the [`NaiveDateTime::nanosecond`] method,
-    /// the input range can exceed 1,000,000,000 for leap seconds.
+    /// See also the [`NaiveTime::minute`] method.
     ///
-    /// See also the [`NaiveTime::with_nanosecond`] method.
+    /// # Example
     ///
-    /// # Errors
+    /// ```
+    /// use chrono::{NaiveDate, NaiveDateTime, Timelike};
     ///
-    /// Returns `None` if `nanosecond >= 2,000,000,000`.
+    /// let dt: NaiveDateTime =
+    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_milli(12, 34, 56, 789).unwrap();
+    /// assert_eq!(dt.minute(), 34);
+    /// ```
+    #[inline]
+    fn minute(&self) -> u32 {
+        self.time.minute()
+    }
+
+    /// Returns the second number from 0 to 59.
+    ///
+    /// See also the [`NaiveTime::second`] method.
     ///
     /// # Example
     ///
@@ -1454,27 +1449,32 @@ impl Timelike for NaiveDateTime {
     /// use chrono::{NaiveDate, NaiveDateTime, Timelike};
     ///
     /// let dt: NaiveDateTime =
-    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_milli(12, 34, 59, 789).unwrap();
-    /// assert_eq!(
-    ///     dt.with_nanosecond(333_333_333),
-    ///     Some(
-    ///         NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_nano(12, 34, 59, 333_333_333).unwrap()
-    ///     )
-    /// );
-    /// assert_eq!(
-    ///     dt.with_nanosecond(1_333_333_333), // leap second
-    ///     Some(
-    ///         NaiveDate::from_ymd(2015, 9, 8)
-    ///             .unwrap()
-    ///             .and_hms_nano(12, 34, 59, 1_333_333_333)
-    ///             .unwrap()
-    ///     )
-    /// );
-    /// assert_eq!(dt.with_nanosecond(2_000_000_000), None);
+    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_milli(12, 34, 56, 789).unwrap();
+    /// assert_eq!(dt.second(), 56);
     /// ```
     #[inline]
-    fn with_nanosecond(&self, nano: u32) -> Option<NaiveDateTime> {
-        self.time.with_nanosecond(nano).map(|t| NaiveDateTime { time: t, ..*self })
+    fn second(&self) -> u32 {
+        self.time.second()
+    }
+
+    /// Returns the number of nanoseconds since the whole non-leap second.
+    /// The range from 1,000,000,000 to 1,999,999,999 represents
+    /// the [leap second](./struct.NaiveTime.html#leap-second-handling).
+    ///
+    /// See also the [`NaiveTime#method.nanosecond`] method.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use chrono::{NaiveDate, NaiveDateTime, Timelike};
+    ///
+    /// let dt: NaiveDateTime =
+    ///     NaiveDate::from_ymd(2015, 9, 8).unwrap().and_hms_milli(12, 34, 56, 789).unwrap();
+    /// assert_eq!(dt.nanosecond(), 789_000_000);
+    /// ```
+    #[inline]
+    fn nanosecond(&self) -> u32 {
+        self.time.nanosecond()
     }
 }
 
diff --git a/src/naive/time/mod.rs b/src/naive/time/mod.rs
index 5fe426f673..43a8c5cffe 100644
--- a/src/naive/time/mod.rs
+++ b/src/naive/time/mod.rs
@@ -185,7 +185,7 @@ mod tests;
 ///
 /// A `NaiveTime` with a leap second that is not on a minute boundary can only be created from a
 /// [`DateTime`](crate::DateTime) with fractional minutes as offset, or using
-/// [`Timelike::with_nanosecond()`].
+/// [`NaiveTime::with_nanosecond()`].
 ///
 /// ```
 /// use chrono::{FixedOffset, NaiveDate, TimeZone};
@@ -812,6 +812,122 @@ impl NaiveTime {
         self.format_with_items(StrftimeItems::new(fmt))
     }
 
+    /// Makes a new `NaiveTime` with the hour number changed.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if the value for `hour` is invalid.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use chrono::NaiveTime;
+    ///
+    /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).unwrap();
+    /// assert_eq!(dt.with_hour(7), Some(NaiveTime::from_hms_nano(7, 56, 4, 12_345_678).unwrap()));
+    /// assert_eq!(dt.with_hour(24), None);
+    /// ```
+    #[inline]
+    pub const fn with_hour(&self, hour: u32) -> Option<NaiveTime> {
+        if hour >= 24 {
+            return None;
+        }
+        let secs = hour * 3600 + self.secs % 3600;
+        Some(NaiveTime { secs, ..*self })
+    }
+
+    /// Makes a new `NaiveTime` with the minute number changed.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if the value for `minute` is invalid.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use chrono::NaiveTime;
+    ///
+    /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).unwrap();
+    /// assert_eq!(dt.with_minute(45), Some(NaiveTime::from_hms_nano(23, 45, 4, 12_345_678).unwrap()));
+    /// assert_eq!(dt.with_minute(60), None);
+    /// ```
+    #[inline]
+    pub const fn with_minute(&self, min: u32) -> Option<NaiveTime> {
+        if min >= 60 {
+            return None;
+        }
+        let secs = self.secs / 3600 * 3600 + min * 60 + self.secs % 60;
+        Some(NaiveTime { secs, ..*self })
+    }
+
+    /// Makes a new `NaiveTime` with the second number changed.
+    ///
+    /// As with the [`second`](#method.second) method,
+    /// the input range is restricted to 0 through 59.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if the value for `second` is invalid.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use chrono::NaiveTime;
+    ///
+    /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).unwrap();
+    /// assert_eq!(dt.with_second(17), Some(NaiveTime::from_hms_nano(23, 56, 17, 12_345_678).unwrap()));
+    /// assert_eq!(dt.with_second(60), None);
+    /// ```
+    #[inline]
+    pub const fn with_second(&self, sec: u32) -> Option<NaiveTime> {
+        if sec >= 60 {
+            return None;
+        }
+        let secs = self.secs / 60 * 60 + sec;
+        Some(NaiveTime { secs, ..*self })
+    }
+
+    /// Makes a new `NaiveTime` with nanoseconds since the whole non-leap second changed.
+    ///
+    /// As with the [`nanosecond`](#method.nanosecond) method,
+    /// the input range can exceed 1,000,000,000 for leap seconds.
+    ///
+    /// # Errors
+    ///
+    /// Returns `None` if `nanosecond >= 2,000,000,000`.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use chrono::NaiveTime;
+    ///
+    /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).unwrap();
+    /// assert_eq!(
+    ///     dt.with_nanosecond(333_333_333),
+    ///     Some(NaiveTime::from_hms_nano(23, 56, 4, 333_333_333).unwrap())
+    /// );
+    /// assert_eq!(dt.with_nanosecond(2_000_000_000), None);
+    /// ```
+    ///
+    /// Leap seconds can theoretically follow *any* whole second.
+    /// The following would be a proper leap second at the time zone offset of UTC-00:03:57
+    /// (there are several historical examples comparable to this "non-sense" offset),
+    /// and therefore is allowed.
+    ///
+    /// ```
+    /// # use chrono::{NaiveTime, Timelike};
+    /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).unwrap();
+    /// let strange_leap_second = dt.with_nanosecond(1_333_333_333).unwrap();
+    /// assert_eq!(strange_leap_second.nanosecond(), 1_333_333_333);
+    /// ```
+    #[inline]
+    pub const fn with_nanosecond(&self, nano: u32) -> Option<NaiveTime> {
+        if nano >= 2_000_000_000 {
+            return None;
+        }
+        Some(NaiveTime { frac: nano, ..*self })
+    }
+
     /// Returns a triple of the hour, minute and second numbers.
     pub(crate) fn hms(&self) -> (u32, u32, u32) {
         let sec = self.secs % 60;
@@ -928,122 +1044,6 @@ impl Timelike for NaiveTime {
         self.frac
     }
 
-    /// Makes a new `NaiveTime` with the hour number changed.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if the value for `hour` is invalid.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use chrono::{NaiveTime, Timelike};
-    ///
-    /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).unwrap();
-    /// assert_eq!(dt.with_hour(7), Some(NaiveTime::from_hms_nano(7, 56, 4, 12_345_678).unwrap()));
-    /// assert_eq!(dt.with_hour(24), None);
-    /// ```
-    #[inline]
-    fn with_hour(&self, hour: u32) -> Option<NaiveTime> {
-        if hour >= 24 {
-            return None;
-        }
-        let secs = hour * 3600 + self.secs % 3600;
-        Some(NaiveTime { secs, ..*self })
-    }
-
-    /// Makes a new `NaiveTime` with the minute number changed.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if the value for `minute` is invalid.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use chrono::{NaiveTime, Timelike};
-    ///
-    /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).unwrap();
-    /// assert_eq!(dt.with_minute(45), Some(NaiveTime::from_hms_nano(23, 45, 4, 12_345_678).unwrap()));
-    /// assert_eq!(dt.with_minute(60), None);
-    /// ```
-    #[inline]
-    fn with_minute(&self, min: u32) -> Option<NaiveTime> {
-        if min >= 60 {
-            return None;
-        }
-        let secs = self.secs / 3600 * 3600 + min * 60 + self.secs % 60;
-        Some(NaiveTime { secs, ..*self })
-    }
-
-    /// Makes a new `NaiveTime` with the second number changed.
-    ///
-    /// As with the [`second`](#method.second) method,
-    /// the input range is restricted to 0 through 59.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if the value for `second` is invalid.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use chrono::{NaiveTime, Timelike};
-    ///
-    /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).unwrap();
-    /// assert_eq!(dt.with_second(17), Some(NaiveTime::from_hms_nano(23, 56, 17, 12_345_678).unwrap()));
-    /// assert_eq!(dt.with_second(60), None);
-    /// ```
-    #[inline]
-    fn with_second(&self, sec: u32) -> Option<NaiveTime> {
-        if sec >= 60 {
-            return None;
-        }
-        let secs = self.secs / 60 * 60 + sec;
-        Some(NaiveTime { secs, ..*self })
-    }
-
-    /// Makes a new `NaiveTime` with nanoseconds since the whole non-leap second changed.
-    ///
-    /// As with the [`nanosecond`](#method.nanosecond) method,
-    /// the input range can exceed 1,000,000,000 for leap seconds.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` if `nanosecond >= 2,000,000,000`.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use chrono::{NaiveTime, Timelike};
-    ///
-    /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).unwrap();
-    /// assert_eq!(
-    ///     dt.with_nanosecond(333_333_333),
-    ///     Some(NaiveTime::from_hms_nano(23, 56, 4, 333_333_333).unwrap())
-    /// );
-    /// assert_eq!(dt.with_nanosecond(2_000_000_000), None);
-    /// ```
-    ///
-    /// Leap seconds can theoretically follow *any* whole second.
-    /// The following would be a proper leap second at the time zone offset of UTC-00:03:57
-    /// (there are several historical examples comparable to this "non-sense" offset),
-    /// and therefore is allowed.
-    ///
-    /// ```
-    /// # use chrono::{NaiveTime, Timelike};
-    /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).unwrap();
-    /// let strange_leap_second = dt.with_nanosecond(1_333_333_333).unwrap();
-    /// assert_eq!(strange_leap_second.nanosecond(), 1_333_333_333);
-    /// ```
-    #[inline]
-    fn with_nanosecond(&self, nano: u32) -> Option<NaiveTime> {
-        if nano >= 2_000_000_000 {
-            return None;
-        }
-        Some(NaiveTime { frac: nano, ..*self })
-    }
-
     /// Returns the number of non-leap seconds past the last midnight.
     ///
     /// # Example
diff --git a/src/traits.rs b/src/traits.rs
index 3baeb096d1..ea084e8773 100644
--- a/src/traits.rs
+++ b/src/traits.rs
@@ -5,29 +5,10 @@ use crate::{IsoWeek, Weekday};
 /// Methods such as [`year`], [`month`], [`day`] and [`weekday`] can be used to get basic
 /// information about the date.
 ///
-/// The `with_*` methods can change the date.
-///
-/// # Warning
-///
-/// The `with_*` methods can be convenient to change a single component of a date, but they must be
-/// used with some care. Examples to watch out for:
-///
-/// - [`with_year`] changes the year component of a year-month-day value. Don't use this method if
-///   you want the ordinal to stay the same after changing the year, of if you want the week and
-///   weekday values to stay the same.
-/// - Don't combine two `with_*` methods to change two components of the date. For example to
-///   change both the year and month components of a date. This could fail because an intermediate
-///   value does not exist, while the final date would be valid.
-///
-/// For more complex changes to a date, it is best to use the methods on [`NaiveDate`] to create a
-/// new value instead of altering an existing date.
-///
 /// [`year`]: Datelike::year
 /// [`month`]: Datelike::month
 /// [`day`]: Datelike::day
 /// [`weekday`]: Datelike::weekday
-/// [`with_year`]: Datelike::with_year
-/// [`NaiveDate`]: crate::NaiveDate
 pub trait Datelike: Sized {
     /// Returns the year number in the [calendar date](./naive/struct.NaiveDate.html#calendar-date).
     fn year(&self) -> i32;
@@ -80,159 +61,6 @@ pub trait Datelike: Sized {
     /// Returns the ISO week.
     fn iso_week(&self) -> IsoWeek;
 
-    /// Makes a new value with the year number changed, while keeping the same month and day.
-    ///
-    /// This method assumes you want to work on the date as a year-month-day value. Don't use it if
-    /// you want the ordinal to stay the same after changing the year, of if you want the week and
-    /// weekday values to stay the same.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` when:
-    ///
-    /// - The resulting date does not exist (February 29 in a non-leap year).
-    /// - The year is out of range for [`NaiveDate`].
-    /// - In case of [`DateTime<Tz>`] if the resulting date and time fall within a timezone
-    ///   transition such as from DST to standard time.
-    ///
-    /// [`NaiveDate`]: crate::NaiveDate
-    /// [`DateTime<Tz>`]: crate::DateTime
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use chrono::{Datelike, NaiveDate};
-    ///
-    /// assert_eq!(
-    ///     NaiveDate::from_ymd(2020, 5, 13).unwrap().with_year(2023).unwrap(),
-    ///     NaiveDate::from_ymd(2023, 5, 13).unwrap()
-    /// );
-    /// // Resulting date 2023-02-29 does not exist:
-    /// assert!(NaiveDate::from_ymd(2020, 2, 29).unwrap().with_year(2023).is_none());
-    ///
-    /// // Don't use `with_year` if you want the ordinal date to stay the same:
-    /// assert_ne!(
-    ///     NaiveDate::from_yo(2020, 100).unwrap().with_year(2023).unwrap(),
-    ///     NaiveDate::from_yo(2023, 100).unwrap() // result is 2023-101
-    /// );
-    /// ```
-    fn with_year(&self, year: i32) -> Option<Self>;
-
-    /// Makes a new value with the month number (starting from 1) changed.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` when:
-    ///
-    /// - The resulting date does not exist (for example `month(4)` when day of the month is 31).
-    /// - In case of [`DateTime<Tz>`] if the resulting date and time fall within a timezone
-    ///   transition such as from DST to standard time.
-    /// - The value for `month` is out of range.
-    ///
-    /// [`DateTime<Tz>`]: crate::DateTime
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use chrono::{Datelike, NaiveDate};
-    ///
-    /// assert_eq!(
-    ///     NaiveDate::from_ymd(2023, 5, 12).unwrap().with_month(9).unwrap(),
-    ///     NaiveDate::from_ymd(2023, 9, 12).unwrap()
-    /// );
-    /// // Resulting date 2023-09-31 does not exist:
-    /// assert!(NaiveDate::from_ymd(2023, 5, 31).unwrap().with_month(9).is_none());
-    /// ```
-    ///
-    /// Don't combine multiple `Datelike::with_*` methods. The intermediate value may not exist.
-    /// ```
-    /// use chrono::{Datelike, Error, NaiveDate};
-    ///
-    /// fn with_year_month(date: NaiveDate, year: i32, month: u32) -> Option<NaiveDate> {
-    ///     date.with_year(year)?.with_month(month)
-    /// }
-    /// let d = NaiveDate::from_ymd(2020, 2, 29).unwrap();
-    /// assert!(with_year_month(d, 2019, 1).is_none()); // fails because of invalid intermediate value
-    ///
-    /// // Correct version:
-    /// fn with_year_month_fixed(date: NaiveDate, year: i32, month: u32) -> Result<NaiveDate, Error> {
-    ///     NaiveDate::from_ymd(year, month, date.day())
-    /// }
-    /// let d = NaiveDate::from_ymd(2020, 2, 29).unwrap();
-    /// assert_eq!(with_year_month_fixed(d, 2019, 1), NaiveDate::from_ymd(2019, 1, 29));
-    /// ```
-    fn with_month(&self, month: u32) -> Option<Self>;
-
-    /// Makes a new value with the month number (starting from 0) changed.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` when:
-    ///
-    /// - The resulting date does not exist (for example `month0(3)` when day of the month is 31).
-    /// - In case of [`DateTime<Tz>`] if the resulting date and time fall within a timezone
-    ///   transition such as from DST to standard time.
-    /// - The value for `month0` is out of range.
-    ///
-    /// [`DateTime<Tz>`]: crate::DateTime
-    fn with_month0(&self, month0: u32) -> Option<Self>;
-
-    /// Makes a new value with the day of month (starting from 1) changed.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` when:
-    ///
-    /// - The resulting date does not exist (for example `day(31)` in April).
-    /// - In case of [`DateTime<Tz>`] if the resulting date and time fall within a timezone
-    ///   transition such as from DST to standard time.
-    /// - The value for `day` is out of range.
-    ///
-    /// [`DateTime<Tz>`]: crate::DateTime
-    fn with_day(&self, day: u32) -> Option<Self>;
-
-    /// Makes a new value with the day of month (starting from 0) changed.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` when:
-    ///
-    /// - The resulting date does not exist (for example `day0(30)` in April).
-    /// - In case of [`DateTime<Tz>`] if the resulting date and time fall within a timezone
-    ///   transition such as from DST to standard time.
-    /// - The value for `day0` is out of range.
-    ///
-    /// [`DateTime<Tz>`]: crate::DateTime
-    fn with_day0(&self, day0: u32) -> Option<Self>;
-
-    /// Makes a new value with the day of year (starting from 1) changed.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` when:
-    ///
-    /// - The resulting date does not exist (`with_ordinal(366)` in a non-leap year).
-    /// - In case of [`DateTime<Tz>`] if the resulting date and time fall within a timezone
-    ///   transition such as from DST to standard time.
-    /// - The value for `ordinal` is out of range.
-    ///
-    /// [`DateTime<Tz>`]: crate::DateTime
-    fn with_ordinal(&self, ordinal: u32) -> Option<Self>;
-
-    /// Makes a new value with the day of year (starting from 0) changed.
-    ///
-    /// # Errors
-    ///
-    /// Returns `None` when:
-    ///
-    /// - The resulting date does not exist (`with_ordinal0(365)` in a non-leap year).
-    /// - In case of [`DateTime<Tz>`] if the resulting date and time fall within a timezone
-    ///   transition such as from DST to standard time.
-    /// - The value for `ordinal0` is out of range.
-    ///
-    /// [`DateTime<Tz>`]: crate::DateTime
-    fn with_ordinal0(&self, ordinal0: u32) -> Option<Self>;
-
     /// Counts the days in the proleptic Gregorian calendar, with January 1, Year 1 (CE) as day 1.
     ///
     /// # Examples
@@ -291,30 +119,6 @@ pub trait Timelike: Sized {
     /// the [leap second](./naive/struct.NaiveTime.html#leap-second-handling).
     fn nanosecond(&self) -> u32;
 
-    /// Makes a new value with the hour number changed.
-    ///
-    /// Returns `None` when the resulting value would be invalid.
-    fn with_hour(&self, hour: u32) -> Option<Self>;
-
-    /// Makes a new value with the minute number changed.
-    ///
-    /// Returns `None` when the resulting value would be invalid.
-    fn with_minute(&self, min: u32) -> Option<Self>;
-
-    /// Makes a new value with the second number changed.
-    ///
-    /// Returns `None` when the resulting value would be invalid.
-    /// As with the [`second`](#tymethod.second) method,
-    /// the input range is restricted to 0 through 59.
-    fn with_second(&self, sec: u32) -> Option<Self>;
-
-    /// Makes a new value with nanoseconds since the whole non-leap second changed.
-    ///
-    /// Returns `None` when the resulting value would be invalid.
-    /// As with the [`nanosecond`](#tymethod.nanosecond) method,
-    /// the input range can exceed 1,000,000,000 for leap seconds.
-    fn with_nanosecond(&self, nano: u32) -> Option<Self>;
-
     /// Returns the number of non-leap seconds past the last midnight.
     ///
     /// Every value in 00:00:00-23:59:59 maps to an integer in 0-86399.


Test patch: