diff --git a/src/datetime/mod.rs b/src/datetime/mod.rs index cfa045dcf5..ed6aba6595 100644 --- a/src/datetime/mod.rs +++ b/src/datetime/mod.rs @@ -202,6 +202,18 @@ impl DateTime { /// Returns the number of non-leap seconds since January 1, 1970 0:00:00 UTC /// (aka "UNIX timestamp"). + /// + /// The reverse operation of creating a [`DateTime`] from a timestamp can be performed + /// using [`from_timestamp_opt`](#method.from_timestamp_opt) or [`TimeZone::timestamp_opt`]. + /// + /// ``` + /// use chrono::{DateTime, TimeZone, Utc}; + /// + /// let dt: DateTime = Utc.with_ymd_and_hms(2015, 5, 15, 0, 0, 0).unwrap(); + /// assert_eq!(dt.timestamp(), 1431648000); + /// + /// assert_eq!(DateTime::from_timestamp_opt(dt.timestamp(), dt.subsec_nanos()).unwrap(), dt); + /// ``` #[inline] #[must_use] pub fn timestamp(&self) -> i64 { @@ -552,6 +564,38 @@ impl DateTime { pub const MAX_UTC: DateTime = DateTime { datetime: NaiveDateTime::MAX, offset: Utc }; } +impl DateTime { + /// Makes a new [`DateTime`] from the number of non-leap seconds + /// since January 1, 1970 0:00:00 UTC (aka "UNIX timestamp") + /// and the number of nanoseconds since the last whole non-leap second. + /// + /// This is guaranteed to round-trip with regard to [`timestamp`](#method.timestamp) and + /// [`timestamp_subsec_nanos`](#method.timestamp). + /// + /// Returns `None` on out-of-range number of seconds and/or + /// invalid nanosecond, otherwise returns `Some(DateTime {...})`. + /// + /// If you need to create a `DateTime` with some other [`TimeZone`], use [`TimeZone::timestamp_opt`] + /// or [`DateTime::with_timezone`]. + /// + /// # Example + /// + /// ``` + /// use chrono::{DateTime, Utc}; + /// + /// let dt: DateTime = DateTime::::from_timestamp_opt(1431648000, 0).expect("invalid timestamp"); + /// + /// assert_eq!(dt.to_string(), "2015-05-15 00:00:00 UTC"); + /// assert_eq!(DateTime::from_timestamp_opt(dt.timestamp(), dt.timestamp_subsec_nanos()).unwrap(), dt); + /// ``` + #[inline] + #[must_use] + pub fn from_timestamp_opt(secs: i64, nsecs: u32) -> Option { + NaiveDateTime::from_timestamp_opt(secs, nsecs) + .map(|ndt| DateTime::from_naive_utc_and_offset(ndt, Utc)) + } +} + impl Default for DateTime { fn default() -> Self { Utc.from_utc_datetime(&NaiveDateTime::default()) diff --git a/src/lib.rs b/src/lib.rs index ff6641eb38..c680cd88b5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -301,7 +301,7 @@ //! //! ### Conversion from and to EPOCH timestamps //! -//! Use [`Utc.timestamp(seconds, nanoseconds)`](./offset/trait.TimeZone.html#method.timestamp) +//! Use [`DateTime::from_timestamp_opt(seconds, nanoseconds)`](./struct.DateTime.html#method.from_timestamp_opt) //! to construct a [`DateTime`](./struct.DateTime.html) from a UNIX timestamp //! (seconds, nanoseconds that passed since January 1st 1970). //! @@ -313,10 +313,10 @@ #![cfg_attr(not(feature = "std"), doc = "```ignore")] #![cfg_attr(feature = "std", doc = "```rust")] //! // We need the trait in scope to use Utc::timestamp(). -//! use chrono::{DateTime, FixedOffset, TimeZone, Utc}; +//! use chrono::{DateTime, FixedOffset, Utc}; //! //! // Construct a datetime from epoch: -//! let dt = Utc.timestamp_opt(1_500_000_000, 0).unwrap(); +//! let dt: DateTime = DateTime::from_timestamp_opt(1_500_000_000, 0).unwrap(); //! assert_eq!(dt.to_rfc2822(), "Fri, 14 Jul 2017 02:40:00 +0000"); //! //! // Get epoch value from a datetime: