Skip to content

Commit

Permalink
Add DateTime::<Utc>::from_timestamp_opt
Browse files Browse the repository at this point in the history
This commit adds the new constructor `from_timestamp_opt` 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 using the `_opt` suffix for fallible functions. As panicking variants on invalid input are deprecated, no panicking variant is provided. See [this issue](chronotope#815) for discussion about error handling and panics.

Closes chronotope#832
  • Loading branch information
demurgos committed Sep 9, 2023
1 parent cef9016 commit 904b40d
Showing 1 changed file with 44 additions and 0 deletions.
44 changes: 44 additions & 0 deletions src/datetime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,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::<Utc>::from_timestamp_opt(dt.timestamp(), dt.subsec_nanos()).unwrap(), dt);
/// ```
#[inline]
#[must_use]
pub fn timestamp(&self) -> i64 {
Expand Down Expand Up @@ -552,6 +564,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::<Utc>::from_timestamp(dt.timestamp(), dt.timestamp_subsec_nanos()), 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

0 comments on commit 904b40d

Please sign in to comment.