Skip to content

Commit ffb9d45

Browse files
youdie006jeremyevans
authored andcommitted
Deprecate lenient RFC 3339 date time separators
RFC 3339 allows only "T", and by convention a space, between the date and the time, but Date._rfc3339 also accepts \t, \n, \v, \f and \r. Warn on those under Warning[:deprecated] before they become an error. The separator is now captured so rfc3339_cb can inspect it, which shifts the remaining group indices.
1 parent ac9db54 commit ffb9d45

2 files changed

Lines changed: 39 additions & 9 deletions

File tree

‎ext/date/date_parse.c‎

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2590,7 +2590,11 @@ date__iso8601(VALUE str)
25902590
}
25912591

25922592
#undef SNUM
2593-
#define SNUM 8
2593+
#define SNUM 9
2594+
2595+
#ifndef HAVE_RB_CATEGORY_WARN
2596+
#define rb_category_warn(category, fmt) rb_warn(fmt)
2597+
#endif
25942598

25952599
static int
25962600
rfc3339_cb(VALUE m, VALUE hash)
@@ -2604,16 +2608,24 @@ rfc3339_cb(VALUE m, VALUE hash)
26042608
s[i] = rb_reg_nth_match(i, m);
26052609
}
26062610

2611+
{
2612+
int c = RSTRING_PTR(s[4])[0];
2613+
if (c != 't' && c != 'T' && c != ' ')
2614+
rb_category_warn(RB_WARN_CATEGORY_DEPRECATED,
2615+
"Invalid RFC3339 date time separator provided, "
2616+
"this will raise an error in a future version.");
2617+
}
2618+
26072619
set_hash("year", str2num(s[1]));
26082620
set_hash("mon", str2num(s[2]));
26092621
set_hash("mday", str2num(s[3]));
2610-
set_hash("hour", str2num(s[4]));
2611-
set_hash("min", str2num(s[5]));
2612-
set_hash("sec", str2num(s[6]));
2613-
set_hash("zone", s[8]);
2614-
set_hash("offset", date_zone_to_diff(s[8]));
2615-
if (!NIL_P(s[7]))
2616-
set_hash("sec_fraction", sec_fraction(s[7]));
2622+
set_hash("hour", str2num(s[5]));
2623+
set_hash("min", str2num(s[6]));
2624+
set_hash("sec", str2num(s[7]));
2625+
set_hash("zone", s[9]);
2626+
set_hash("offset", date_zone_to_diff(s[9]));
2627+
if (!NIL_P(s[8]))
2628+
set_hash("sec_fraction", sec_fraction(s[8]));
26172629

26182630
return 1;
26192631
}
@@ -2623,7 +2635,7 @@ rfc3339(VALUE str, VALUE hash)
26232635
{
26242636
static const char pat_source[] =
26252637
"\\A\\s*(-?\\d{4})-(\\d{2})-(\\d{2})"
2626-
"(?:t|\\s)"
2638+
"(t|\\s)"
26272639
"(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?"
26282640
"(z|[-+]\\d{2}:\\d{2})\\s*\\z";
26292641
static VALUE pat = Qnil;

‎test/date/test_date_parse.rb‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,24 @@ def test__rfc3339
889889
assert_raise(TypeError) {Date._rfc3339('2001-02-03T04:05:06Z'.to_sym)}
890890
end
891891

892+
def test__rfc3339__deprecated_separator
893+
pat = /Invalid RFC3339 date time separator/
894+
895+
["\t", "\n", "\v", "\f", "\r"].each do |sep|
896+
h = assert_deprecated_warn(pat) do
897+
Date._rfc3339("2001-02-03#{sep}04:05:06Z")
898+
end
899+
assert_equal([2001, 2, 3, 4, 5, 6, 0],
900+
h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
901+
end
902+
903+
["T", "t", " "].each do |sep|
904+
assert_deprecated_warn("") do
905+
Date._rfc3339("2001-02-03#{sep}04:05:06Z")
906+
end
907+
end
908+
end
909+
892910
def test__xmlschema
893911
h = Date._xmlschema('2001-02-03')
894912
assert_equal([2001, 2, 3, nil, nil, nil, nil],

0 commit comments

Comments
 (0)