Skip to content

Commit b34d14e

Browse files
authored
Merge pull request #1702 from EliahKagan/run-ci/duration-units
Parse relative months and years
2 parents e8ce25f + 34d2fce commit b34d14e

File tree

2 files changed

+77
-27
lines changed

2 files changed

+77
-27
lines changed

gix-date/src/parse.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,10 @@ mod relative {
153153
"hour" => Span::new().try_hours(units),
154154
"day" => Span::new().try_days(units),
155155
"week" => Span::new().try_weeks(units),
156-
// TODO months & years? YES
156+
"month" => Span::new().try_months(units),
157+
"year" => Span::new().try_years(units),
157158
// Ignore values you don't know, assume seconds then (so does git)
158-
_ => return None,
159+
_anything => Span::new().try_seconds(units),
159160
};
160161
Some(result.map_err(|_| Error::RelativeTimeConversion))
161162
}

gix-date/tests/time/parse.rs

+74-25
Original file line numberDiff line numberDiff line change
@@ -181,39 +181,88 @@ mod relative {
181181
fn various() {
182182
let now = SystemTime::now();
183183

184+
// For comparison, a few are the same as in: https://github.com/git/git/blob/master/t/t0006-date.sh
184185
let cases = [
185-
("2 weeks ago", 2.weeks()),
186+
("5 seconds ago", 5.seconds()),
187+
("12345 florx ago", 12_345.seconds()), // Anything parses as seconds
188+
("5 minutes ago", 5.minutes()),
189+
("5 hours ago", 5.hours()),
190+
("5 days ago", 5.days()),
191+
("3 weeks ago", 3.weeks()),
192+
("21 days ago", 21.days()), // 3 weeks
193+
("504 hours ago", 504.hours()), // 3 weeks
194+
("30240 minutes ago", 30_240.minutes()), // 3 weeks
195+
("2 months ago", 2.months()),
196+
("1460 hours ago", 1460.hours()), // 2 months
197+
("87600 minutes ago", 87_600.minutes()), // 2 months
186198
("14 weeks ago", 14.weeks()),
187-
("26 weeks ago", 26.weeks()),
188-
("38 weeks ago", 38.weeks()),
189-
("50 weeks ago", 50.weeks()),
190-
("20160 minutes ago", 20_160.minutes()), // 2 weeks
199+
("98 days ago", 98.days()), // 14 weeks
200+
("2352 hours ago", 2352.hours()), // 14 weeks
191201
("141120 minutes ago", 141_120.minutes()), // 14 weeks
202+
("5 months ago", 5.months()),
203+
("3650 hours ago", 3650.hours()), // 5 months
204+
("219000 minutes ago", 219_000.minutes()), // 5 months
205+
("26 weeks ago", 26.weeks()),
206+
("182 days ago", 182.days()), // 26 weeks
207+
("4368 hours ago", 4368.hours()), // 26 weeks
192208
("262080 minutes ago", 262_080.minutes()), // 26 weeks
209+
("8 months ago", 8.months()),
210+
("5840 hours ago", 5840.hours()), // 8 months
211+
("350400 minutes ago", 350_400.minutes()), // 8 months
212+
("38 weeks ago", 38.weeks()),
213+
("266 days ago", 266.days()), // 38 weeks
214+
("6384 hours ago", 6384.hours()), // 38 weeks
193215
("383040 minutes ago", 383_040.minutes()), // 38 weeks
194-
("504000 minutes ago", 504_000.minutes()), // 50 weeks
216+
("11 months ago", 11.months()),
217+
("8030 hours ago", 8030.hours()), // 11 months
218+
("481800 minutes ago", 481_800.minutes()), // 11 months
219+
("14 months ago", 14.months()), // "1 year, 2 months ago" not yet supported.
220+
("21 months ago", 21.months()), // "1 year, 9 months ago" not yet supported.
221+
("2 years ago", 2.years()),
222+
("20 years ago", 20.years()),
223+
("630720000 seconds ago", 630_720_000.seconds()), // 20 years
195224
];
196225

197-
let times = cases.map(|(input, _)| gix_date::parse(input, Some(now)).unwrap());
198-
199-
assert_eq!(times.map(|_| Sign::Plus), times.map(|time| time.sign));
200-
assert_eq!(times.map(|_| 0), times.map(|time| time.offset));
201-
202-
let expected = cases.map(|(_, span)| {
203-
Zoned::try_from(now)
204-
.unwrap()
205-
// account for the loss of precision when creating `Time` with seconds
206-
.round(
207-
jiff::ZonedRound::new()
208-
.smallest(jiff::Unit::Second)
209-
.mode(jiff::RoundMode::Trunc),
210-
)
211-
.unwrap()
212-
.saturating_sub(span)
213-
.timestamp()
226+
let cases_with_times = cases.map(|(input, _)| {
227+
let time = gix_date::parse(input, Some(now)).expect("relative time string should parse to a Time");
228+
(input, time)
229+
});
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+
);
240+
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();
257+
258+
(input, expected)
259+
});
260+
let actual = cases_with_times.map(|(input, time)| {
261+
let actual = jiff::Timestamp::from_second(time.seconds)
262+
.expect("seconds obtained from a Time should convert to Timestamp");
263+
(input, actual)
214264
});
215-
let actual = times.map(|time| jiff::Timestamp::from_second(time.seconds).unwrap());
216-
assert_eq!(actual, expected, "relative times differ");
265+
assert_eq!(actual, expected);
217266
}
218267
}
219268

0 commit comments

Comments
 (0)