Skip to content

Commit 6a5767e

Browse files
committed
core/functions: Improve error handling in datetime.rs
Eliminates few unwrap() calls.
1 parent 51aa25d commit 6a5767e

File tree

1 file changed

+39
-19
lines changed

1 file changed

+39
-19
lines changed

core/functions/datetime.rs

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ where
4949
return Value::Null;
5050
}
5151

52-
let value = values.next().unwrap();
52+
let Some(value) = values.next() else {
53+
return Value::Null;
54+
};
5355
let value = value.as_value_ref();
5456
let format_str = if matches!(
5557
value,
@@ -80,11 +82,15 @@ where
8082
{
8183
let values = values.into_iter();
8284
if values.len() == 0 {
83-
let now = parse_naive_date_time(Value::build_text("now")).unwrap();
85+
let Some(now) = parse_naive_date_time(Value::build_text("now")) else {
86+
return Value::Null;
87+
};
8488
return format_dt(now, output_type, false);
8589
}
8690
let mut values = values.peekable();
87-
let first = values.peek().unwrap();
91+
let Some(first) = values.peek() else {
92+
return Value::Null;
93+
};
8894
if let Some(mut dt) = parse_naive_date_time(first) {
8995
// if successful, treat subsequent entries as modifiers
9096
modify_dt(&mut dt, values.skip(1), output_type)
@@ -231,18 +237,19 @@ fn apply_modifier(dt: &mut NaiveDateTime, modifier: &str, n_floor: &mut i64) ->
231237
}
232238
Modifier::StartOfMonth => {
233239
*dt = NaiveDate::from_ymd_opt(dt.year(), dt.month(), 1)
234-
.unwrap()
235-
.and_hms_opt(0, 0, 0)
236-
.unwrap();
240+
.and_then(|d| d.and_hms_opt(0, 0, 0))
241+
.ok_or_else(|| InvalidModifier("failed to construct start of month".to_string()))?;
237242
}
238243
Modifier::StartOfYear => {
239244
*dt = NaiveDate::from_ymd_opt(dt.year(), 1, 1)
240-
.unwrap()
241-
.and_hms_opt(0, 0, 0)
242-
.unwrap();
245+
.and_then(|d| d.and_hms_opt(0, 0, 0))
246+
.ok_or_else(|| InvalidModifier("failed to construct start of year".to_string()))?;
243247
}
244248
Modifier::StartOfDay => {
245-
*dt = dt.date().and_hms_opt(0, 0, 0).unwrap();
249+
*dt = dt
250+
.date()
251+
.and_hms_opt(0, 0, 0)
252+
.ok_or_else(|| InvalidModifier("failed to construct start of day".to_string()))?;
246253
}
247254
Modifier::Weekday(day) => {
248255
let current_day = dt.weekday().num_days_from_sunday();
@@ -259,11 +266,18 @@ fn apply_modifier(dt: &mut NaiveDateTime, modifier: &str, n_floor: &mut i64) ->
259266
}
260267
Modifier::Utc => {
261268
// TODO: handle datetime('now', 'utc') no-op
262-
let local_dt = chrono::Local.from_local_datetime(dt).unwrap();
269+
let local_dt = chrono::Local
270+
.from_local_datetime(dt)
271+
.single()
272+
.ok_or_else(|| {
273+
InvalidModifier("ambiguous local datetime during DST transition".to_string())
274+
})?;
263275
*dt = local_dt.with_timezone(&Utc).naive_utc();
264276
}
265277
Modifier::Subsec => {
266-
*dt = dt.with_nanosecond(dt.nanosecond()).unwrap();
278+
*dt = dt
279+
.with_nanosecond(dt.nanosecond())
280+
.ok_or_else(|| InvalidModifier("failed to set nanoseconds".to_string()))?;
267281
return Ok(true);
268282
}
269283
}
@@ -482,7 +496,7 @@ fn get_date_time_from_time_value_string(value: &str) -> Option<NaiveDateTime> {
482496

483497
// First, try to parse as date-only format
484498
if let Ok(date) = NaiveDate::parse_from_str(value, date_only_format) {
485-
return Some(date.and_time(NaiveTime::from_hms_opt(0, 0, 0).unwrap()));
499+
return NaiveTime::from_hms_opt(0, 0, 0).map(|time| date.and_time(time));
486500
}
487501

488502
for format in &datetime_formats {
@@ -598,10 +612,9 @@ fn is_leap_second(dt: &NaiveDateTime) -> bool {
598612

599613
fn get_max_datetime_exclusive() -> NaiveDateTime {
600614
// The maximum date in SQLite is 9999-12-31
601-
NaiveDateTime::new(
602-
NaiveDate::from_ymd_opt(10000, 1, 1).unwrap(),
603-
NaiveTime::from_hms_milli_opt(00, 00, 00, 000).unwrap(),
604-
)
615+
let date = NaiveDate::from_ymd_opt(10000, 1, 1).expect("10000-01-01 is valid");
616+
let time = NaiveTime::from_hms_milli_opt(00, 00, 00, 000).expect("00:00:00.000 is valid");
617+
NaiveDateTime::new(date, time)
605618
}
606619

607620
/// Modifier doc https://www.sqlite.org/lang_datefunc.html#modifiers
@@ -824,8 +837,15 @@ where
824837
return Value::Null;
825838
}
826839

827-
let start = parse_naive_date_time(values.next().unwrap());
828-
let end = parse_naive_date_time(values.next().unwrap());
840+
let Some(start_val) = values.next() else {
841+
return Value::Null;
842+
};
843+
let Some(end_val) = values.next() else {
844+
return Value::Null;
845+
};
846+
847+
let start = parse_naive_date_time(start_val);
848+
let end = parse_naive_date_time(end_val);
829849

830850
match (start, end) {
831851
(Some(start), Some(end)) => {

0 commit comments

Comments
 (0)