Skip to content

Commit a769fdd

Browse files
committed
fix: add support for 'any' unit, when parsing <count> <unit> ago.
Similar to Git, any unit is allowed and will default to seconds, like `60 flurps ago` will mean a minute in the past.
1 parent 3082d40 commit a769fdd

File tree

2 files changed

+31
-18
lines changed

2 files changed

+31
-18
lines changed

gix-date/src/parse.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ mod relative {
156156
"month" => Span::new().try_months(units),
157157
"year" => Span::new().try_years(units),
158158
// Ignore values you don't know, assume seconds then (so does git)
159-
_ => return None,
159+
_anything => Span::new().try_seconds(units),
160160
};
161161
Some(result.map_err(|_| Error::RelativeTimeConversion))
162162
}

gix-date/tests/time/parse.rs

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ mod relative {
184184
// For comparison, a few are the same as in: https://github.com/git/git/blob/master/t/t0006-date.sh
185185
let cases = [
186186
("5 seconds ago", 5.seconds()),
187+
("12345 florx ago", 12_345.seconds()), // Anything parses as seconds
187188
("5 minutes ago", 5.minutes()),
188189
("5 hours ago", 5.hours()),
189190
("5 days ago", 5.days()),
@@ -222,34 +223,46 @@ mod relative {
222223
("630720000 seconds ago", 630_720_000.seconds()), // 20 years
223224
];
224225

225-
let with_times = cases.map(|(input, _)| {
226+
let cases_with_times = cases.map(|(input, _)| {
226227
let time = gix_date::parse(input, Some(now)).expect("relative time string should parse to a Time");
227228
(input, time)
228229
});
229-
assert_eq!(with_times.map(|_| Sign::Plus), with_times.map(|(_, time)| time.sign));
230-
assert_eq!(with_times.map(|_| 0), with_times.map(|(_, time)| time.offset));
230+
assert_eq!(
231+
cases_with_times.map(|(_, time)| time.sign),
232+
cases_with_times.map(|_| Sign::Plus),
233+
"Despite being in the past, the dates produced are positive, as they are still post-epoch"
234+
);
235+
assert_eq!(
236+
cases_with_times.map(|(_, time)| time.offset),
237+
cases_with_times.map(|_| 0),
238+
"They don't pick up local time"
239+
);
231240

232-
let with_expected = cases.map(|(input, span)| {
233-
let expected = Zoned::try_from(now)
234-
.expect("test needs to convert current time to a timestamp")
235-
// account for the loss of precision when creating `Time` with seconds
236-
.round(
237-
jiff::ZonedRound::new()
238-
.smallest(jiff::Unit::Second)
239-
.mode(jiff::RoundMode::Trunc),
240-
)
241-
.expect("test needs to truncate current timestamp to seconds")
242-
.saturating_sub(span)
243-
.timestamp();
241+
let expected = cases.map(|(input, span)| {
242+
let expected = Zoned::new(
243+
now.try_into().expect("system time is representable"),
244+
// As relative dates are always UTC in Git, we do the same, and must
245+
// compare to UTC as well or else time might be off due to daylight savings, etc.
246+
jiff::tz::TimeZone::UTC,
247+
)
248+
// account for the loss of precision when creating `Time` with seconds
249+
.round(
250+
jiff::ZonedRound::new()
251+
.smallest(jiff::Unit::Second)
252+
.mode(jiff::RoundMode::Trunc),
253+
)
254+
.expect("test needs to truncate current timestamp to seconds")
255+
.saturating_sub(span)
256+
.timestamp();
244257

245258
(input, expected)
246259
});
247-
let with_actual = with_times.map(|(input, time)| {
260+
let actual = cases_with_times.map(|(input, time)| {
248261
let actual = jiff::Timestamp::from_second(time.seconds)
249262
.expect("seconds obtained from a Time should convert to Timestamp");
250263
(input, actual)
251264
});
252-
assert_eq!(with_actual, with_expected, "relative times differ");
265+
assert_eq!(actual, expected);
253266
}
254267
}
255268

0 commit comments

Comments
 (0)