Skip to content

Commit f22bced

Browse files
fasterthanlimejhpratt
authored andcommitted
fix: RFC3339 allows spaces (or anything) as separators
1 parent 866c3a0 commit f22bced

File tree

2 files changed

+38
-10
lines changed

2 files changed

+38
-10
lines changed

tests/parsing.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,16 @@ fn rfc_3339() -> time::Result<()> {
323323
offset!(-00:01),
324324
);
325325

326+
// Any separator is allowed by RFC 3339, not just `T`.
327+
assert_eq!(
328+
OffsetDateTime::parse("2021-01-02 03:04:05Z", &Rfc3339)?,
329+
datetime!(2021-01-02 03:04:05 UTC),
330+
);
331+
assert_eq!(
332+
OffsetDateTime::parse("2021-01-02$03:04:05Z", &Rfc3339)?,
333+
datetime!(2021-01-02 03:04:05 UTC),
334+
);
335+
326336
Ok(())
327337
}
328338

@@ -354,8 +364,8 @@ fn rfc_3339_err() {
354364
invalid_component!("day")
355365
));
356366
assert!(matches!(
357-
PrimitiveDateTime::parse("2021-01-01x", &Rfc3339),
358-
invalid_literal!()
367+
PrimitiveDateTime::parse("2021-01-01", &Rfc3339),
368+
invalid_component!("separator")
359369
));
360370
assert!(matches!(
361371
PrimitiveDateTime::parse("2021-01-01T0", &Rfc3339),
@@ -448,8 +458,8 @@ fn rfc_3339_err() {
448458
invalid_component!("day")
449459
));
450460
assert!(matches!(
451-
OffsetDateTime::parse("2021-01-01x", &Rfc3339),
452-
invalid_literal!()
461+
OffsetDateTime::parse("2021-01-01", &Rfc3339),
462+
invalid_component!("separator")
453463
));
454464
assert!(matches!(
455465
OffsetDateTime::parse("2021-01-01T0", &Rfc3339),

time/src/parsing/parsable.rs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -520,9 +520,18 @@ impl sealed::Sealed for Rfc3339 {
520520
let input = exactly_n_digits::<2, _>(input)
521521
.and_then(|item| item.consume_value(|value| parsed.set_day(value)))
522522
.ok_or(InvalidComponent("day"))?;
523-
let input = ascii_char_ignore_case::<b'T'>(input)
524-
.ok_or(InvalidLiteral)?
525-
.into_inner();
523+
524+
// RFC3339 allows any separator, not just `T`, not just `space`.
525+
// cf. Section 5.6: Internet Date/Time Format:
526+
// NOTE: ISO 8601 defines date and time separated by "T".
527+
// Applications using this syntax may choose, for the sake of
528+
// readability, to specify a full-date and full-time separated by
529+
// (say) a space character.
530+
// Specifically, rusqlite uses space separators.
531+
let input = input
532+
.get(1..)
533+
.ok_or_else(|| InvalidComponent("separator"))?;
534+
526535
let input = exactly_n_digits::<2, _>(input)
527536
.and_then(|item| item.consume_value(|value| parsed.set_hour_24(value)))
528537
.ok_or(InvalidComponent("hour"))?;
@@ -618,9 +627,18 @@ impl sealed::Sealed for Rfc3339 {
618627
let input = dash(input).ok_or(InvalidLiteral)?.into_inner();
619628
let ParsedItem(input, day) =
620629
exactly_n_digits::<2, _>(input).ok_or(InvalidComponent("day"))?;
621-
let input = ascii_char_ignore_case::<b'T'>(input)
622-
.ok_or(InvalidLiteral)?
623-
.into_inner();
630+
631+
// RFC3339 allows any separator, not just `T`, not just `space`.
632+
// cf. Section 5.6: Internet Date/Time Format:
633+
// NOTE: ISO 8601 defines date and time separated by "T".
634+
// Applications using this syntax may choose, for the sake of
635+
// readability, to specify a full-date and full-time separated by
636+
// (say) a space character.
637+
// Specifically, rusqlite uses space separators.
638+
let input = input
639+
.get(1..)
640+
.ok_or_else(|| InvalidComponent("separator"))?;
641+
624642
let ParsedItem(input, hour) =
625643
exactly_n_digits::<2, _>(input).ok_or(InvalidComponent("hour"))?;
626644
let input = colon(input).ok_or(InvalidLiteral)?.into_inner();

0 commit comments

Comments
 (0)