Skip to content

Commit

Permalink
progress
Browse files Browse the repository at this point in the history
  • Loading branch information
BurntSushi committed Jul 4, 2024
1 parent be84042 commit 9b2f326
Show file tree
Hide file tree
Showing 7 changed files with 1,841 additions and 229 deletions.
63 changes: 51 additions & 12 deletions src/civil/datetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,45 @@ impl DateTime {
self.date().day_of_year_no_leap()
}

/// Returns the beginning of the day that this datetime resides in.
///
/// That is, the datetime returned always keeps the same date, but its
/// time is always `00:00:00` (midnight).
///
/// # Example
///
/// ```
/// use jiff::civil::date;
///
/// let dt = date(2024, 7, 3).at(7, 30, 10, 123_456_789);
/// assert_eq!(dt.start_of_day(), date(2024, 7, 3).at(0, 0, 0, 0));
/// ```
#[inline]
pub fn start_of_day(&self) -> DateTime {
DateTime::from_parts(self.date(), Time::MIN)
}

/// Returns the end of the day that this datetime resides in.
///
/// That is, the datetime returned always keeps the same date, but its
/// time is always `23:59:59.999999999`.
///
/// # Example
///
/// ```
/// use jiff::civil::date;
///
/// let dt = date(2024, 7, 3).at(7, 30, 10, 123_456_789);
/// assert_eq!(
/// dt.end_of_day(),
/// date(2024, 7, 3).at(23, 59, 59, 999_999_999),
/// );
/// ```
#[inline]
pub fn end_of_day(&self) -> DateTime {
DateTime::from_parts(self.date(), Time::MAX)
}

/// Returns the first date of the month that this datetime resides in.
///
/// The time in the datetime returned remains unchanged.
Expand Down Expand Up @@ -1390,15 +1429,15 @@ impl DateTime {
///
/// # Properties
///
/// This routine is _not_ commutative because some additions may
/// This routine is _not_ reversible because some additions may
/// be ambiguous. For example, adding `1 month` to the datetime
/// `2024-03-31T00:00:00` will produce `2024-04-30T00:00:00` since April
/// has only 30 days in a month. Moreover, subtracting `1 month` from
/// `2024-04-30T00:00:00` will produce `2024-03-30T00:00:00`, which is not
/// the date we started with.
///
/// If spans of time are limited to units of days (or less), then this
/// routine _is_ commutative.
/// routine _is_ reversible.
///
/// # Errors
///
Expand Down Expand Up @@ -1478,15 +1517,15 @@ impl DateTime {
///
/// # Properties
///
/// This routine is _not_ commutative because some additions may
/// This routine is _not_ reversible because some additions may
/// be ambiguous. For example, adding `1 month` to the datetime
/// `2024-03-31T00:00:00` will produce `2024-04-30T00:00:00` since April
/// has only 30 days in a month. Moreover, subtracting `1 month` from
/// `2024-04-30T00:00:00` will produce `2024-03-30T00:00:00`, which is not
/// the date we started with.
///
/// If spans of time are limited to units of days (or less), then this
/// routine _is_ commutative.
/// routine _is_ reversible.
///
/// # Errors
///
Expand Down Expand Up @@ -1551,23 +1590,23 @@ impl DateTime {
/// ```
#[inline]
pub fn checked_sub(self, span: Span) -> Result<DateTime, Error> {
self.checked_add(span.negate())
self.checked_add(-span)
}

/// Add the given span of time to this datetime. If the sum would overflow
/// the minimum or maximum datetime values, then the result saturates.
///
/// # Properties
///
/// This routine is _not_ commutative because some additions may
/// This routine is _not_ reversible because some additions may
/// be ambiguous. For example, adding `1 month` to the datetime
/// `2024-03-31T00:00:00` will produce `2024-04-30T00:00:00` since April
/// has only 30 days in a month. Moreover, subtracting `1 month` from
/// `2024-04-30T00:00:00` will produce `2024-03-30T00:00:00`, which is not
/// the date we started with.
///
/// If spans of time are limited to units of days (or less), then this
/// routine _is_ commutative.
/// If spans of time are limited to units of days (or less), and no
/// saturation occurs, then this routine _is_ reversible.
///
/// # Example
///
Expand Down Expand Up @@ -1625,15 +1664,15 @@ impl DateTime {
///
/// # Properties
///
/// This routine is _not_ commutative because some additions may
/// This routine is _not_ reversible because some additions may
/// be ambiguous. For example, adding `1 month` to the datetime
/// `2024-03-31T00:00:00` will produce `2024-04-30T00:00:00` since April
/// has only 30 days in a month. Moreover, subtracting `1 month` from
/// `2024-04-30T00:00:00` will produce `2024-03-30T00:00:00`, which is not
/// the date we started with.
///
/// If spans of time are limited to units of days (or less), then this
/// routine _is_ commutative.
/// If spans of time are limited to units of days (or less), and no
/// saturation occurs, then this routine _is_ reversible.
///
/// # Example
///
Expand Down Expand Up @@ -1676,7 +1715,7 @@ impl DateTime {
/// ```
#[inline]
pub fn saturating_sub(self, span: Span) -> DateTime {
self.saturating_add(span.negate())
self.saturating_add(-span)
}

/// Returns a span representing the elapsed time from this datetime since
Expand Down
4 changes: 2 additions & 2 deletions src/fmt/temporal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ impl DateTimeParser {
/// zone transition "fold" or "gap."
///
/// The most common manifestation of such time zone transitions is daylight
/// savings time. In most cases, the transition into daylight savings time
/// saving time. In most cases, the transition into daylight saving time
/// moves the civil time ("the time you see on the clock") ahead one hour.
/// This is called a "gap" because an hour on the clock is skipped. While
/// the transition out of daylight saving time moves the civil time back
Expand All @@ -274,7 +274,7 @@ impl DateTimeParser {
/// York.) So when a fold occurs, you don't know whether it's the "first"
/// occurrence of that time or the "second."
///
/// Time zone transitions are not just limited to daylight savings time,
/// Time zone transitions are not just limited to daylight saving time,
/// although those are the most common. In other cases, a transition occurs
/// because of a change in the offset of the time zone itself. (See the
/// examples below.)
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub use crate::{
timestamp::{
Timestamp, TimestampDifference, TimestampRound, TimestampSeries,
},
zoned::{Zoned, ZonedRound, ZonedSeries, ZonedWith},
zoned::{Zoned, ZonedDifference, ZonedRound, ZonedSeries, ZonedWith},
};

#[macro_use]
Expand Down
23 changes: 10 additions & 13 deletions src/round.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,15 +613,13 @@ impl RoundRelativeTo {
(
&RelativeToKind::Zoned(ref zdt1),
&RelativeToKind::Zoned(ref zdt2),
) => Ok(zdt1
.until_with_largest_unit(largest, zdt2)
.with_context(|| {
err!(
"failed to get span between {zdt1} and {zdt2} \
) => Ok(zdt1.until((largest, zdt2)).with_context(|| {
err!(
"failed to get span between {zdt1} and {zdt2} \
with largest unit as {unit}",
unit = largest.plural(),
)
})?),
unit = largest.plural(),
)
})?),
_ => todo!(),
}
}
Expand Down Expand Up @@ -715,18 +713,17 @@ impl RelativeRange {
unit = largest.plural(),
)
}),
RelativeRange::Zoned { ref start, ref end } => start
.zoned
.until_with_largest_unit(largest, &end.zoned)
.with_context(|| {
RelativeRange::Zoned { ref start, ref end } => {
start.zoned.until((largest, &end.zoned)).with_context(|| {
err!(
"failed to get span between {start} and {end} \
with largest unit as {unit}",
start = start.zoned,
end = end.zoned,
unit = largest.plural(),
)
}),
})
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1463,7 +1463,7 @@ mod tests {
let rounded = span.round(options);
assert_eq!(rounded, -1.month().days(1).hours(1));
let dt = relative.checked_add(span).unwrap();
let diff = relative.until_with_largest_unit(Unit::Month, &dt).unwrap();
let diff = relative.until((Unit::Month, &dt)).unwrap();
assert_eq!(diff, -1.month().days(1).hours(1));

// Like the above, but don't use a datetime near a DST transition. In
Expand Down
16 changes: 8 additions & 8 deletions src/tz/offset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1146,8 +1146,8 @@ impl OffsetConflict {
let amb = tz.to_ambiguous_timestamp(dt);
match amb.kind() {
Unambiguous { offset } if given != offset => Err(err!(
"parsed datetime {dt} could not resolve to a timestamp since \
'reject' conflict resolution was chosen, and because parsed \
"datetime {dt} could not resolve to a timestamp since \
'reject' conflict resolution was chosen, and because \
datetime has offset {given}, but the time zone {tzname} for \
the given datetime unambiguously has offset {offset}",
tzname = tz.diagnostic_name(),
Expand Down Expand Up @@ -1182,23 +1182,23 @@ impl OffsetConflict {
//
// Ref: https://github.com/tc39/proposal-temporal/issues/2892
Err(err!(
"parsed datetime {dt} could not resolve to timestamp \
"datetime {dt} could not resolve to timestamp \
since 'reject' conflict resolution was chosen, and \
because parsed datetime has offset {given}, but the time \
because datetime has offset {given}, but the time \
zone {tzname} for the given datetime falls in a gap \
between offsets {before} and {after}, neither of which \
match the parsed offset",
match the offset",
tzname = tz.diagnostic_name(),
))
}
Fold { before, after } if given != before && given != after => {
Err(err!(
"parsed datetime {dt} could not resolve to timestamp \
"datetime {dt} could not resolve to timestamp \
since 'reject' conflict resolution was chosen, and \
because parsed datetime has offset {given}, but the time \
because datetime has offset {given}, but the time \
zone {tzname} for the given datetime falls in a fold \
between offsets {before} and {after}, neither of which \
match the parsed offset",
match the offset",
tzname = tz.diagnostic_name(),
))
}
Expand Down
Loading

0 comments on commit 9b2f326

Please sign in to comment.