Skip to content

Commit 77db4e8

Browse files
committed
Add from_timestamp_secs method to DateTime
Add a new single-argument function for creating a `DateTime` from a Unix timestamp, to match `from_timestamp_micros`, `from_timestamp_millis`, and `from_timestamp_nanos`. Issue #1716 Suggestion: add DateTime::from_timestamp_secs function
1 parent 59d5f46 commit 77db4e8

2 files changed

Lines changed: 66 additions & 0 deletions

File tree

src/datetime/mod.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,61 @@ impl DateTime<Utc> {
755755
Some(date.and_time(time).and_utc())
756756
}
757757

758+
/// Makes a new `DateTime<Utc>` from the number of non-leap seconds
759+
/// since January 1, 1970 0:00:00 UTC (aka "UNIX timestamp").
760+
///
761+
/// This is a convenience wrapper around [`DateTime::from_timestamp`],
762+
/// which is useful in functions like [`Iterator::map`] to avoid a closure.
763+
///
764+
/// This is guaranteed to round-trip with regard to [`timestamp`](DateTime::timestamp).
765+
///
766+
/// If you need to create a `DateTime` with a [`TimeZone`] different from [`Utc`], use
767+
/// [`TimeZone::timestamp_opt`] or [`DateTime::with_timezone`]; if you need to create a
768+
/// `DateTime` with more precision, use [`DateTime::from_timestamp_micros`],
769+
/// [`DateTime::from_timestamp_millis`], or [`DateTime::from_timestamp_nanos`].
770+
///
771+
/// # Errors
772+
///
773+
/// Returns `None` on out-of-range number of seconds,
774+
/// otherwise returns `Some(DateTime {...})`.
775+
///
776+
/// # Examples
777+
///
778+
/// Using [`Option::and_then`]:
779+
///
780+
/// ```
781+
/// # use chrono::DateTime;
782+
/// let maybe_timestamp: Option<i64> = Some(1431648000);
783+
/// let maybe_dt = maybe_timestamp.and_then(DateTime::from_timestamp_secs);
784+
///
785+
/// assert!(maybe_dt.is_some());
786+
/// assert_eq!(maybe_dt.unwrap().to_string(), "2015-05-15 00:00:00 UTC");
787+
/// ```
788+
///
789+
/// Using [`Iterator::map`]:
790+
///
791+
/// ```
792+
/// # use chrono::{DateTime, Utc};
793+
/// let v = vec![i64::MIN, 1_000_000_000, 1_234_567_890, i64::MAX];
794+
/// let timestamps: Vec<Option<DateTime<Utc>>> = v
795+
/// .into_iter()
796+
/// .map(DateTime::from_timestamp_secs)
797+
/// .collect();
798+
///
799+
/// assert_eq!(vec![
800+
/// None,
801+
/// Some(DateTime::parse_from_rfc3339("2001-09-09 01:46:40Z").unwrap().to_utc()),
802+
/// Some(DateTime::parse_from_rfc3339("2009-02-13 23:31:30Z").unwrap().to_utc()),
803+
/// None,
804+
/// ], timestamps);
805+
/// ```
806+
///
807+
#[inline]
808+
#[must_use]
809+
pub const fn from_timestamp_secs(secs: i64) -> Option<Self> {
810+
Self::from_timestamp(secs, 0)
811+
}
812+
758813
/// Makes a new `DateTime<Utc>` from the number of non-leap milliseconds
759814
/// since January 1, 1970 0:00:00.000 UTC (aka "UNIX timestamp").
760815
///

src/datetime/tests.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,17 @@ fn test_datetime_from_timestamp_nanos() {
247247
}
248248
}
249249

250+
#[test]
251+
fn test_datetime_from_timestamp_secs() {
252+
let valid = [-2208936075, 0, 119731017, 1234567890, 2034061609];
253+
254+
for timestamp_secs in valid.iter().copied() {
255+
let datetime = DateTime::from_timestamp_secs(timestamp_secs).unwrap();
256+
assert_eq!(timestamp_secs, datetime.timestamp());
257+
assert_eq!(DateTime::from_timestamp(timestamp_secs, 0).unwrap(), datetime);
258+
}
259+
}
260+
250261
#[test]
251262
fn test_datetime_from_timestamp() {
252263
let from_timestamp = |secs| DateTime::from_timestamp(secs, 0);

0 commit comments

Comments
 (0)