Struct NaiveTime
struct NaiveTime { ... }
ISO 8601 time without timezone. Allows for the nanosecond precision and optional leap second representation.
Leap Second Handling
Since 1960s, the manmade atomic clock has been so accurate that it is much more accurate than Earth's own motion. It became desirable to define the civil time in terms of the atomic clock, but that risks the desynchronization of the civil time from Earth. To account for this, the designers of the Coordinated Universal Time (UTC) made that the UTC should be kept within 0.9 seconds of the observed Earth-bound time. When the mean solar day is longer than the ideal (86,400 seconds), the error slowly accumulates and it is necessary to add a leap second to slow the UTC down a bit. (We may also remove a second to speed the UTC up a bit, but it never happened.) The leap second, if any, follows 23:59:59 of June 30 or December 31 in the UTC.
Fast forward to the 21st century, we have seen 26 leap seconds from January 1972 to December 2015. Yes, 26 seconds. Probably you can read this paragraph within 26 seconds. But those 26 seconds, and possibly more in the future, are never predictable, and whether to add a leap second or not is known only before 6 months. Internet-based clocks (via NTP) do account for known leap seconds, but the system API normally doesn't (and often can't, with no network connection) and there is no reliable way to retrieve leap second information.
Chrono does not try to accurately implement leap seconds; it is impossible. Rather, it allows for leap seconds but behaves as if there are no other leap seconds. Various operations will ignore any possible leap second(s) except when any of the operands were actually leap seconds.
If you cannot tolerate this behavior,
you must use a separate TimeZone for the International Atomic Time (TAI).
TAI is like UTC but has no leap seconds, and thus slightly differs from UTC.
Chrono does not yet provide such implementation, but it is planned.
Representing Leap Seconds
The leap second is indicated via fractional seconds more than 1 second. This makes possible to treat a leap second as the prior non-leap second if you don't care about sub-second accuracy. You should use the proper formatting to get the raw leap second.
All methods accepting fractional seconds will accept such values.
use ;
let t = from_hms_milli_opt.unwrap;
let dt1 = from_ymd_opt
.unwrap
.and_hms_micro_opt
.unwrap;
let dt2 = from_ymd_opt
.unwrap
.and_hms_nano_opt
.unwrap
.and_utc;
# let _ = ;
Note that the leap second can happen anytime given an appropriate time zone; 2015-07-01 01:23:60 would be a proper leap second if UTC+01:24 had existed. Practically speaking, though, by the time of the first leap second on 1972-06-30, every time zone offset around the world has standardized to the 5-minute alignment.
Date And Time Arithmetics
As a concrete example, let's assume that 03:00:60 and 04:00:60 are leap seconds.
In reality, of course, leap seconds are separated by at least 6 months.
We will also use some intuitive concise notations for the explanation.
Time + TimeDelta
(short for NaiveTime::overflowing_add_signed):
03:00:00 + 1s = 03:00:01.03:00:59 + 60s = 03:01:59.03:00:59 + 61s = 03:02:00.03:00:59 + 1s = 03:01:00.03:00:60 + 1s = 03:01:00. Note that the sum is identical to the previous.03:00:60 + 60s = 03:01:59.03:00:60 + 61s = 03:02:00.03:00:60.1 + 0.8s = 03:00:60.9.
Time - TimeDelta
(short for NaiveTime::overflowing_sub_signed):
03:00:00 - 1s = 02:59:59.03:01:00 - 1s = 03:00:59.03:01:00 - 60s = 03:00:00.03:00:60 - 60s = 03:00:00. Note that the result is identical to the previous.03:00:60.7 - 0.4s = 03:00:60.3.03:00:60.7 - 0.9s = 03:00:59.8.
Time - Time
(short for NaiveTime::signed_duration_since):
04:00:00 - 03:00:00 = 3600s.03:01:00 - 03:00:00 = 60s.03:00:60 - 03:00:00 = 60s. Note that the difference is identical to the previous.03:00:60.6 - 03:00:59.4 = 1.2s.03:01:00 - 03:00:59.8 = 0.2s.03:01:00 - 03:00:60.5 = 0.5s. Note that the difference is larger than the previous, even though the leap second clearly follows the previous whole second.04:00:60.9 - 03:00:60.1 = (04:00:60.9 - 04:00:00) + (04:00:00 - 03:01:00) + (03:01:00 - 03:00:60.1) = 60.9s + 3540s + 0.9s = 3601.8s.
In general,
-
Time + TimeDeltaunconditionally equals toTimeDelta + Time. -
Time - TimeDeltaunconditionally equals toTime + (-TimeDelta). -
Time1 - Time2unconditionally equals to-(Time2 - Time1). -
Associativity does not generally hold, because
(Time + TimeDelta1) - TimeDelta2no longer equals toTime + (TimeDelta1 - TimeDelta2)for two positive durations.-
As a special case,
(Time + TimeDelta) - TimeDeltaalso does not equal toTime. -
If you can assume that all durations have the same sign, however, then the associativity holds:
(Time + TimeDelta1) + TimeDelta2equals toTime + (TimeDelta1 + TimeDelta2)for two positive durations.
-
Reading And Writing Leap Seconds
The "typical" leap seconds on the minute boundary are correctly handled both in the formatting and parsing. The leap second in the human-readable representation will be represented as the second part being 60, as required by ISO 8601.
use NaiveDate;
let dt = from_ymd_opt
.unwrap
.and_hms_milli_opt
.unwrap
.and_utc;
assert_eq!;
There are hypothetical leap seconds not on the minute boundary nevertheless supported by Chrono. They are allowed for the sake of completeness and consistency; there were several "exotic" time zone offsets with fractional minutes prior to UTC after all. For such cases the human-readable representation is ambiguous and would be read back to the next non-leap second.
A NaiveTime with a leap second that is not on a minute boundary can only be created from a
DateTime with fractional minutes as offset, or using
[Timelike::with_nanosecond()].
use ;
let paramaribo_pre1945 = east_opt.unwrap; // -03:40:36
let leap_sec_2015 =
from_ymd_opt.unwrap.and_hms_milli_opt.unwrap;
let dt1 = paramaribo_pre1945.from_utc_datetime;
assert_eq!;
assert_eq!;
let next_sec = from_ymd_opt.unwrap.and_hms_opt.unwrap;
let dt2 = paramaribo_pre1945.from_utc_datetime;
assert_eq!;
assert_eq!;
assert!;
assert!;
Since Chrono alone cannot determine any existence of leap seconds, there is absolutely no guarantee that the leap second read has actually happened.
Implementations
impl NaiveTime
const fn from_hms(hour: u32, min: u32, sec: u32) -> NaiveTimeMakes a new
NaiveTimefrom hour, minute and second.No leap second is allowed here; use
NaiveTime::from_hms_*methods with a subsecond parameter instead.Panics
Panics on invalid hour, minute and/or second.
const fn from_hms_opt(hour: u32, min: u32, sec: u32) -> Option<NaiveTime>Makes a new
NaiveTimefrom hour, minute and second.The millisecond part is allowed to exceed 1,000,000,000 in order to represent a leap second, but only when
sec == 59.Errors
Returns
Noneon invalid hour, minute and/or second.Example
use NaiveTime; let from_hms_opt = from_hms_opt; assert!; assert!; assert!; assert!; assert!;const fn from_hms_milli(hour: u32, min: u32, sec: u32, milli: u32) -> NaiveTimeMakes a new
NaiveTimefrom hour, minute, second and millisecond.The millisecond part can exceed 1,000 in order to represent the leap second.
Panics
Panics on invalid hour, minute, second and/or millisecond.
const fn from_hms_milli_opt(hour: u32, min: u32, sec: u32, milli: u32) -> Option<NaiveTime>Makes a new
NaiveTimefrom hour, minute, second and millisecond.The millisecond part is allowed to exceed 1,000,000,000 in order to represent a leap second, but only when
sec == 59.Errors
Returns
Noneon invalid hour, minute, second and/or millisecond.Example
use NaiveTime; let from_hmsm_opt = from_hms_milli_opt; assert!; assert!; assert!; // a leap second after 23:59:59 assert!; assert!; assert!; assert!;const fn from_hms_micro(hour: u32, min: u32, sec: u32, micro: u32) -> NaiveTimeMakes a new
NaiveTimefrom hour, minute, second and microsecond.The microsecond part is allowed to exceed 1,000,000,000 in order to represent a leap second, but only when
sec == 59.Panics
Panics on invalid hour, minute, second and/or microsecond.
const fn from_hms_micro_opt(hour: u32, min: u32, sec: u32, micro: u32) -> Option<NaiveTime>Makes a new
NaiveTimefrom hour, minute, second and microsecond.The microsecond part is allowed to exceed 1,000,000,000 in order to represent a leap second, but only when
sec == 59.Errors
Returns
Noneon invalid hour, minute, second and/or microsecond.Example
use NaiveTime; let from_hmsu_opt = from_hms_micro_opt; assert!; assert!; assert!; // a leap second after 23:59:59 assert!; assert!; assert!; assert!;const fn from_hms_nano(hour: u32, min: u32, sec: u32, nano: u32) -> NaiveTimeMakes a new
NaiveTimefrom hour, minute, second and nanosecond.The nanosecond part is allowed to exceed 1,000,000,000 in order to represent a leap second, but only when
sec == 59.Panics
Panics on invalid hour, minute, second and/or nanosecond.
const fn from_hms_nano_opt(hour: u32, min: u32, sec: u32, nano: u32) -> Option<NaiveTime>Makes a new
NaiveTimefrom hour, minute, second and nanosecond.The nanosecond part is allowed to exceed 1,000,000,000 in order to represent a leap second, but only when
sec == 59.Errors
Returns
Noneon invalid hour, minute, second and/or nanosecond.Example
use NaiveTime; let from_hmsn_opt = from_hms_nano_opt; assert!; assert!; assert!; // a leap second after 23:59:59 assert!; assert!; assert!; assert!;const fn from_num_seconds_from_midnight(secs: u32, nano: u32) -> NaiveTimeMakes a new
NaiveTimefrom the number of seconds since midnight and nanosecond.The nanosecond part is allowed to exceed 1,000,000,000 in order to represent a leap second, but only when
secs % 60 == 59.Panics
Panics on invalid number of seconds and/or nanosecond.
const fn from_num_seconds_from_midnight_opt(secs: u32, nano: u32) -> Option<NaiveTime>Makes a new
NaiveTimefrom the number of seconds since midnight and nanosecond.The nanosecond part is allowed to exceed 1,000,000,000 in order to represent a leap second, but only when
secs % 60 == 59.Errors
Returns
Noneon invalid number of seconds and/or nanosecond.Example
use NaiveTime; let from_nsecs_opt = from_num_seconds_from_midnight_opt; assert!; assert!; assert!; // a leap second after 23:59:59 assert!; assert!;fn parse_from_str(s: &str, fmt: &str) -> ParseResult<NaiveTime>Parses a string with the specified format string and returns a new
NaiveTime. See theformat::strftimemodule on the supported escape sequences.Example
use NaiveTime; let parse_from_str = parse_from_str; assert_eq!; assert_eq!;Date and offset is ignored for the purpose of parsing.
# use NaiveTime; # let parse_from_str = parse_from_str; assert_eq!;Leap seconds are correctly handled by treating any time of the form
hh:mm:60as a leap second. (This equally applies to the formatting, so the round trip is possible.)# use NaiveTime; # let parse_from_str = parse_from_str; assert_eq!;Missing seconds are assumed to be zero, but out-of-bound times or insufficient fields are errors otherwise.
# use NaiveTime; # let parse_from_str = parse_from_str; assert_eq!; assert!; assert!; assert!; assert!;All parsed fields should be consistent to each other, otherwise it's an error. Here
%His for 24-hour clocks, unlike%I, and thus can be independently determined without AM/PM.# use NaiveTime; # let parse_from_str = parse_from_str; assert!;fn parse_and_remainder<'a>(s: &'a str, fmt: &str) -> ParseResult<(NaiveTime, &'a str)>Parses a string from a user-specified format into a new
NaiveTimevalue, and a slice with the remaining portion of the string. See theformat::strftimemodule on the supported escape sequences.Similar to
parse_from_str.Example
# use ; let = parse_and_remainder.unwrap; assert_eq!; assert_eq!;const fn overflowing_add_signed(self: &Self, rhs: TimeDelta) -> (NaiveTime, i64)Adds given
TimeDeltato the current time, and also returns the number of seconds in the integral number of days ignored from the addition.Example
use ; let from_hms = ; assert_eq!; assert_eq!; assert_eq!;const fn overflowing_sub_signed(self: &Self, rhs: TimeDelta) -> (NaiveTime, i64)Subtracts given
TimeDeltafrom the current time, and also returns the number of seconds in the integral number of days ignored from the subtraction.Example
use ; let from_hms = ; assert_eq!; assert_eq!; assert_eq!;const fn signed_duration_since(self: Self, rhs: NaiveTime) -> TimeDeltaSubtracts another
NaiveTimefrom the current time. Returns aTimeDeltawithin +/- 1 day. This does not overflow or underflow at all.As a part of Chrono's leap second handling, the subtraction assumes that there is no leap second ever, except when any of the
NaiveTimes themselves represents a leap second in which case the assumption becomes that there are exactly one (or two) leap second(s) ever.Example
use ; let from_hmsm = ; let since = signed_duration_since; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!;Leap seconds are handled, but the subtraction assumes that there were no other leap seconds happened.
# use ; # let from_hmsm = ; # let since = signed_duration_since; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!;fn format_with_items<'a, I, B>(self: &Self, items: I) -> DelayedFormat<I> where I: Iterator<Item = B> + Clone, B: Borrow<Item<'a>>Formats the time with the specified formatting items. Otherwise it is the same as the ordinary
formatmethod.The
Iteratorof items should beCloneable, since the resultingDelayedFormatvalue may be formatted multiple times.Example
use StrftimeItems; use NaiveTime; let fmt = new; let t = from_hms_opt.unwrap; assert_eq!; assert_eq!;The resulting
DelayedFormatcan be formatted directly via theDisplaytrait.# use NaiveTime; # use StrftimeItems; # let fmt = new.clone; # let t = from_hms_opt.unwrap; assert_eq!;fn format<'a>(self: &Self, fmt: &'a str) -> DelayedFormat<StrftimeItems<'a>>Formats the time with the specified format string. See the
format::strftimemodule on the supported escape sequences.This returns a
DelayedFormat, which gets converted to a string only when actual formatting happens. You may use theto_stringmethod to get aString, or just feed it intoprint!and other formatting macros. (In this way it avoids the redundant memory allocation.)A wrong format string does not issue an error immediately. Rather, converting or formatting the
DelayedFormatfails. You are recommended to immediately useDelayedFormatfor this reason.Example
use NaiveTime; let t = from_hms_nano_opt.unwrap; assert_eq!; assert_eq!; assert_eq!;The resulting
DelayedFormatcan be formatted directly via theDisplaytrait.# use NaiveTime; # let t = from_hms_nano_opt.unwrap; assert_eq!; assert_eq!; assert_eq!;
impl Add for NaiveTime
fn add(self: Self, rhs: TimeDelta) -> NaiveTime
impl Add for NaiveTime
fn add(self: Self, rhs: Duration) -> NaiveTime
impl Add for NaiveTime
fn add(self: Self, rhs: FixedOffset) -> NaiveTime
impl AddAssign for NaiveTime
fn add_assign(self: &mut Self, rhs: Duration)
impl AddAssign for NaiveTime
fn add_assign(self: &mut Self, rhs: TimeDelta)
impl Clone for NaiveTime
fn clone(self: &Self) -> NaiveTime
impl Copy for NaiveTime
impl Debug for NaiveTime
fn fmt(self: &Self, f: &mut Formatter<'_>) -> Result
impl Default for NaiveTime
fn default() -> Self
impl Display for NaiveTime
fn fmt(self: &Self, f: &mut Formatter<'_>) -> Result
impl Eq for NaiveTime
impl Freeze for NaiveTime
impl FromStr for NaiveTime
fn from_str(s: &str) -> ParseResult<NaiveTime>
impl Hash for NaiveTime
fn hash<__H: $crate::hash::Hasher>(self: &Self, state: &mut __H)
impl Ord for NaiveTime
fn cmp(self: &Self, other: &NaiveTime) -> Ordering
impl PartialEq for NaiveTime
fn eq(self: &Self, other: &NaiveTime) -> bool
impl PartialOrd for NaiveTime
fn partial_cmp(self: &Self, other: &NaiveTime) -> Option<Ordering>
impl RefUnwindSafe for NaiveTime
impl Send for NaiveTime
impl StructuralPartialEq for NaiveTime
impl Sub for NaiveTime
fn sub(self: Self, rhs: Duration) -> NaiveTime
impl Sub for NaiveTime
fn sub(self: Self, rhs: FixedOffset) -> NaiveTime
impl Sub for NaiveTime
fn sub(self: Self, rhs: TimeDelta) -> NaiveTime
impl Sub for NaiveTime
fn sub(self: Self, rhs: NaiveTime) -> TimeDelta
impl SubAssign for NaiveTime
fn sub_assign(self: &mut Self, rhs: Duration)
impl SubAssign for NaiveTime
fn sub_assign(self: &mut Self, rhs: TimeDelta)
impl Sync for NaiveTime
impl Timelike for NaiveTime
fn hour(self: &Self) -> u32Returns the hour number from 0 to 23.
Example
use ; assert_eq!; assert_eq!;fn minute(self: &Self) -> u32Returns the minute number from 0 to 59.
Example
use ; assert_eq!; assert_eq!;fn second(self: &Self) -> u32Returns the second number from 0 to 59.
Example
use ; assert_eq!; assert_eq!;This method never returns 60 even when it is a leap second. (Why?) Use the proper formatting method to get a human-readable representation.
#fn nanosecond(self: &Self) -> u32Returns 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.
Example
use ; assert_eq!; assert_eq!;Leap seconds may have seemingly out-of-range return values. You can reduce the range with
time.nanosecond() % 1_000_000_000, or use the proper formatting method to get a human-readable representation.#fn with_hour(self: &Self, hour: u32) -> Option<NaiveTime>Makes a new
NaiveTimewith the hour number changed.Errors
Returns
Noneif the value forhouris invalid.Example
use ; let dt = from_hms_nano_opt.unwrap; assert_eq!; assert_eq!;fn with_minute(self: &Self, min: u32) -> Option<NaiveTime>Makes a new
NaiveTimewith the minute number changed.Errors
Returns
Noneif the value forminuteis invalid.Example
use ; let dt = from_hms_nano_opt.unwrap; assert_eq!; assert_eq!;fn with_second(self: &Self, sec: u32) -> Option<NaiveTime>Makes a new
NaiveTimewith the second number changed.As with the
secondmethod, the input range is restricted to 0 through 59.Errors
Returns
Noneif the value forsecondis invalid.Example
use ; let dt = from_hms_nano_opt.unwrap; assert_eq!; assert_eq!;fn with_nanosecond(self: &Self, nano: u32) -> Option<NaiveTime>Makes a new
NaiveTimewith nanoseconds since the whole non-leap second changed.As with the
nanosecondmethod, the input range can exceed 1,000,000,000 for leap seconds.Errors
Returns
Noneifnanosecond >= 2,000,000,000.Example
use ; let dt = from_hms_nano_opt.unwrap; assert_eq!; assert_eq!;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 ; let dt = from_hms_nano_opt.unwrap; let strange_leap_second = dt.with_nanosecond.unwrap; assert_eq!;fn num_seconds_from_midnight(self: &Self) -> u32Returns the number of non-leap seconds past the last midnight.
Example
use ; assert_eq!; assert_eq!; assert_eq!;
impl Unpin for NaiveTime
impl UnsafeUnpin for NaiveTime
impl UnwindSafe for NaiveTime
impl<T> Any for NaiveTime
fn type_id(self: &Self) -> TypeId
impl<T> Borrow for NaiveTime
fn borrow(self: &Self) -> &T
impl<T> BorrowMut for NaiveTime
fn borrow_mut(self: &mut Self) -> &mut T
impl<T> CloneToUninit for NaiveTime
unsafe fn clone_to_uninit(self: &Self, dest: *mut u8)
impl<T> From for NaiveTime
fn from(t: T) -> TReturns the argument unchanged.
impl<T> SubsecRound for NaiveTime
fn round_subsecs(self: Self, digits: u16) -> Tfn trunc_subsecs(self: Self, digits: u16) -> T
impl<T> ToOwned for NaiveTime
fn to_owned(self: &Self) -> Tfn clone_into(self: &Self, target: &mut T)
impl<T> ToString for NaiveTime
fn to_string(self: &Self) -> String
impl<T, U> Into for NaiveTime
fn into(self: Self) -> UCalls
U::from(self).That is, this conversion is whatever the implementation of
[From]<T> for Uchooses to do.
impl<T, U> TryFrom for NaiveTime
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
impl<T, U> TryInto for NaiveTime
fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>