Skip to content

Commit

Permalink
Add DateTime::<Utc>::from_timestamp
Browse files Browse the repository at this point in the history
This commit adds the new constructor `from_timestamp` to build a `DateTime<Utc>` from a UNIX timestamp.

Figuring out how to convert a timestamp into a `DateTime<Utc>` was a common issue:
- chronotope#88
- chronotope#200
- chronotope#832

This commit should make `DateTime<Utc>` creation more discoverable and intuitive.

This commit respects the current convention of preferring fallible functions. It avoids however the `_opt` suffix as there is no panicking variant. See [this issue](chronotope#815) for discussion about error handling and panics.

Closes chronotope#832
  • Loading branch information
demurgos committed Sep 10, 2023
1 parent 2960f2c commit c56b52e
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 3 deletions.
44 changes: 44 additions & 0 deletions src/datetime/mod.rs
Expand Up @@ -209,6 +209,18 @@ impl<Tz: TimeZone> DateTime<Tz> {

/// 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> = 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.timestamp_subsec_nanos()).unwrap(), dt);
/// ```
#[inline]
#[must_use]
pub fn timestamp(&self) -> i64 {
Expand Down Expand Up @@ -559,6 +571,38 @@ impl<Tz: TimeZone> DateTime<Tz> {
pub const MAX_UTC: DateTime<Utc> = DateTime { datetime: NaiveDateTime::MAX, offset: Utc };
}

impl DateTime<Utc> {
/// Makes a new [`DateTime<Utc>`] 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<Utc> = DateTime::<Utc>::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<Self> {
NaiveDateTime::from_timestamp_opt(secs, nsecs)
.map(|ndt| DateTime::from_naive_utc_and_offset(ndt, Utc))
}
}

impl Default for DateTime<Utc> {
fn default() -> Self {
Utc.from_utc_datetime(&NaiveDateTime::default())
Expand Down
6 changes: 3 additions & 3 deletions src/lib.rs
Expand Up @@ -309,7 +309,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<Utc>`](./struct.DateTime.html) from a UNIX timestamp
//! (seconds, nanoseconds that passed since January 1st 1970).
//!
Expand All @@ -321,10 +321,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, 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<Utc> = 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:
Expand Down

0 comments on commit c56b52e

Please sign in to comment.