Skip to content

Instantly share code, notes, and snippets.

@nurse
Created March 2, 2012 08:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nurse/1956692 to your computer and use it in GitHub Desktop.
Save nurse/1956692 to your computer and use it in GitHub Desktop.
Time.parse
diff --git a/test/ruby/test_time.rb b/test/ruby/test_time.rb
index cf7aad3..bff1d17 100644
--- a/test/ruby/test_time.rb
+++ b/test/ruby/test_time.rb
@@ -744,4 +744,145 @@ class TestTime < Test::Unit::TestCase
end
assert_equal("Insecure: can't modify #{tc}", error.message, bug5036)
end
+
+ def test_time_html5
+ assert_equal(Time.utc(2000,1,31,12,34), Time.html5("2000-01-31T12:34Z"))
+ assert_equal(Time.utc(2000,1,31,12,34), Time.html5("2000-01-31 12:34Z"))
+ assert_equal(Time.utc(2000,1,31,12,34,56), Time.html5("2000-01-31T12:34:56Z"))
+ assert_raise(ArgumentError){Time.html5("2000-01-32T12:34:56Z")}
+ assert_equal(Time.utc(2000,2,29,12,34,56), Time.html5("2000-02-29T12:34:56Z"))
+ assert_raise(ArgumentError){Time.html5("2000-02-30T12:34:56Z")}
+ assert_raise(ArgumentError){Time.html5("2001-02-29T12:34:56Z")}
+ assert_equal(Time.utc(2004,2,29,12,34,56), Time.html5("2004-02-29T12:34:56Z"))
+ assert_raise(ArgumentError){Time.html5("2100-02-29T12:34:56Z")}
+ assert_equal(Time.utc(2000,3,31,12,34,56), Time.html5("2000-03-31T12:34:56Z"))
+ assert_raise(ArgumentError){Time.html5("2000-03-32T12:34:56Z")}
+ assert_equal(Time.utc(2000,4,30,12,34,56), Time.html5("2000-04-30T12:34:56Z"))
+ assert_raise(ArgumentError){Time.html5("2000-04-31T12:34:56Z")}
+ assert_equal(Time.utc(2000,5,31,12,34,56), Time.html5("2000-05-31T12:34:56Z"))
+ assert_raise(ArgumentError){Time.html5("2000-05-32T12:34:56Z")}
+ assert_equal(Time.utc(2000,6,30,12,34,56), Time.html5("2000-06-30T12:34:56Z"))
+ assert_raise(ArgumentError){Time.html5("2000-06-31T12:34:56Z")}
+ assert_equal(Time.utc(2000,7,31,12,34,56), Time.html5("2000-07-31T12:34:56Z"))
+ assert_raise(ArgumentError){Time.html5("2000-07-32T12:34:56Z")}
+ assert_equal(Time.utc(2000,8,31,12,34,56), Time.html5("2000-08-31T12:34:56Z"))
+ assert_raise(ArgumentError){Time.html5("2000-08-32T12:34:56Z")}
+ assert_equal(Time.utc(2000,9,30,12,34,56), Time.html5("2000-09-30T12:34:56Z"))
+ assert_raise(ArgumentError){Time.html5("2000-09-31T12:34:56Z")}
+ assert_equal(Time.utc(2000,10,31,12,34,56), Time.html5("2000-10-31T12:34:56Z"))
+ assert_raise(ArgumentError){Time.html5("2000-10-32T12:34:56Z")}
+ assert_equal(Time.utc(2000,11,30,12,34,56), Time.html5("2000-11-30T12:34:56Z"))
+ assert_raise(ArgumentError){Time.html5("2000-11-31T12:34:56Z")}
+ assert_equal(Time.utc(2000,12,31,12,34,56), Time.html5("2000-12-31T12:34:56Z"))
+ assert_raise(ArgumentError){Time.html5("2000-12-32T12:34:56Z")}
+ assert_equal(Time.new(2000,1,31,12,34,56,85500), Time.html5("2000-01-31T12:34:56+2345"))
+ assert_equal(Time.new(2000,1,31,12,34,56,85500), Time.html5("2000-01-31T12:34:56+23:45"))
+ assert_equal(Time.new(2000,1,31,12,34,56,-85500), Time.html5("2000-01-31T12:34:56-2345"))
+ assert_equal(Time.new(2000,1,31,12,34,56,-85500), Time.html5("2000-01-31T12:34:56-23:45"))
+ assert_equal(Time.new(2000,1,31,12,34,56,-85500), Time.html5("2000-01-31T12:34:56-23:45"))
+ assert_equal(Time.utc(18446744073709551616,1,31,12,34,56), Time.html5("18446744073709551616-01-31T12:34:56Z"))
+ assert_equal(Time.local(2000,12,31,12,34,56),Time.html5("2000-12-31T12:34:56"))
+ assert_raise(ArgumentError){Time.html5("2000-12-31T12:34:5")}
+ assert_raise(ArgumentError){Time.html5("2000-12-31T12:34:")}
+ assert_equal(Time.local(2000,12,31,12,34),Time.html5("2000-12-31T12:34"))
+ assert_raise(ArgumentError){Time.html5("2000-12-31T12:3")}
+ assert_raise(ArgumentError){Time.html5("2000-12-31T12:")}
+ assert_raise(ArgumentError){Time.html5("2000-12-31T12")}
+ assert_raise(ArgumentError){Time.html5("2000-12-31T1")}
+ assert_raise(ArgumentError){Time.html5("2000-12-31T")}
+ assert_equal(Time.local(2000,12,31), Time.html5("2000-12-31"))
+ assert_raise(ArgumentError){Time.html5("2000-12-")}
+ assert_raise(ArgumentError){Time.html5("2000-12")}
+ assert_raise(ArgumentError){Time.html5("2000-1")}
+ assert_raise(ArgumentError){Time.html5("2000-")}
+ assert_raise(ArgumentError){Time.html5("200")}
+ assert_raise(ArgumentError){Time.html5("20")}
+ assert_raise(ArgumentError){Time.html5("2")}
+ assert_raise(ArgumentError){Time.html5("")}
+ assert_equal(Time.utc(2005,12,31,23,59,59), Time.html5("2005-12-31T23:59:59Z"))
+ assert_raise(ArgumentError){Time.html5("2005-12-31T23:59:59+1")}
+ assert_raise(ArgumentError){Time.html5("2005-12-31T23:59:59+12")}
+ assert_raise(ArgumentError){Time.html5("2005-12-31T23:59:59+123")}
+ assert_raise(ArgumentError){Time.html5("2005-12-31T23:59:59+12345")}
+ assert_raise(ArgumentError){Time.html5("2005-12-31T23:59:599")}
+ assert_raise(ArgumentError){Time.html5("2005-12-31T23:59:59.1111Z")}
+ assert_raise(ArgumentError){Time.html5("-2005-12-31T23:59:59Z")}
+ assert_raise(ArgumentError){Time.html5("2005-13-31T23:59:59Z")}
+ assert_raise(ArgumentError){Time.html5("2005-12-31T24:59:59Z")}
+ assert_raise(ArgumentError){Time.html5("2005-12-31T23:60:59Z")}
+ assert_raise(ArgumentError){Time.html5("2005-12-31T23:59:60Z")} # HTML5 doesn't support leap seconds
+ end
+
+ def test_time_parse_rfc6265_examples
+ # https://raw.github.com/abarth/http-state/master/tests/data/dates/examples.json
+ # https://raw.github.com/abarth/http-state/master/tests/data/dates/bsd-examples.json
+ assert_equal(Time.utc(1970, 1, 1, 0, 0, 0), Time.cookie("Thursday, 01-Jan-1970 00:00:00 GMT"))
+ assert_equal(Time.utc(1977, 4, 18, 22, 50, 13), Time.cookie("Mon, 18-Apr-1977 22:50:13 GMT"))
+ assert_equal(Time.utc(1977, 4, 18, 22, 50, 13), Time.cookie("Mon, 18-Apr-77 22:50:13 GMT"))
+ assert_equal(Time.utc(1995, 1, 1, 0, 0, 0), Time.cookie("Sun, 1-Jan-1995 00:00:00 GMT"))
+ assert_equal(Time.utc(2003, 1, 1, 0, 0, 0), Time.cookie(" 1-Jan-2003 00:00:00 GMT"))
+ assert_equal(Time.utc(2003, 1, 1, 0, 0, 0), Time.cookie(", 1-Jan-2003 00:00:00 GMT"))
+ assert_equal(Time.utc(2003, 1, 1, 0, 0, 0), Time.cookie("1-Jan-2003 00:00:00 GMT"))
+ assert_equal(Time.utc(2003, 1, 1, 0, 0, 0), Time.cookie("Wednes, 1-Januar-2003 00:00:00 GMT"))
+ assert_equal(Time.utc(2003, 1, 1, 0, 0, 0), Time.cookie("Wednesday, 1-Jan-2003 00:00:00 GMT"))
+ assert_equal(Time.utc(2007, 12, 10, 16, 32, 30), Time.cookie("Mon Dec 10 16:32:30 2007 GMT"))
+ assert_equal(Time.utc(2007, 12, 10, 17, 2, 24), Time.cookie("Mon, 10-Dec-2007 17:02:24 GMT"))
+ assert_equal(Time.utc(2007, 12, 10, 20, 35, 3), Time.cookie("Mon, 10-Dec-07 20:35:03 GMT"))
+ assert_equal(Time.utc(2007, 12, 12, 8, 44, 7), Time.cookie("Wed Dec 12 2007 08:44:07 GMT-0500 (EST)"))
+ assert_equal(Time.utc(2007, 4, 18, 22, 50, 12), Time.cookie("22:50:12 Thu Apr 18 2007 GMT"))
+ assert_equal(Time.utc(2007, 4, 18, 22, 50, 12), Time.cookie("Partyday, 18 - Apri-07 22:50:12"))
+ assert_equal(Time.utc(2007, 4, 18, 22, 50, 12), Time.cookie("Partyday, 18- April-07 22:50:12"))
+ assert_equal(Time.utc(2007, 4, 18, 22, 50, 12), Time.cookie("Thu 22:50:12 Apr 18 2007 GMT"))
+ assert_equal(Time.utc(2007, 4, 18, 22, 50, 12), Time.cookie("Thu Apr 18 2007 22:50:12 GMT"))
+ assert_equal(Time.utc(2007, 4, 18, 22, 50, 12), Time.cookie("Thu Apr 18 2007 GMT 22:50:12"))
+ assert_equal(Time.utc(2007, 4, 18, 22, 50, 12), Time.cookie("Thu Apr 18 22:50:12 2007 GMT"))
+ assert_equal(Time.utc(2007, 4, 18, 22, 50, 12), Time.cookie("Thu Apr 22:50:12 18 2007 GMT"))
+ assert_equal(Time.utc(2007, 4, 18, 22, 50, 12), Time.cookie("Wed,18-Apr-07 22:50:12 GMT"))
+ assert_equal(Time.utc(2007, 4, 18, 22, 50, 12), Time.cookie("WillyWonka , 18-apr-07 22:50:12"))
+ assert_equal(Time.utc(2007, 4, 18, 22, 50, 12), Time.cookie("WillyWonka , 18-Apr-07 22:50:12 GMT"))
+ assert_equal(Time.utc(2007, 4, 18, 22, 50, 12), Time.cookie("WillyWonka , 18-Apr-07 22:50:12"))
+ assert_equal(Time.utc(2007, 4, 19, 16, 0, 0), Time.cookie("Thu, 19-Apr-2007 16:00:00 GMT"))
+ assert_equal(Time.utc(2007, 4, 19, 16, 0, 0), Time.cookie("Thu, 19/Apr\\2007 16:00:00 GMT"))
+ assert_equal(Time.utc(2007, 4, 25, 21, 2, 13), Time.cookie("Wed, 25 Apr 2007 21:02:13 GMT"))
+ assert_equal(Time.utc(2009, 12, 10, 13, 57, 2), Time.cookie("Thu, 10 Dec 2009 13:57:2 GMT"))
+ assert_equal(Time.utc(2009, 12, 9, 16, 27, 23), Time.cookie("Wed, 09 Dec 2009 16:27:23 GMT"))
+ assert_equal(Time.utc(2010, 1, 1, 0, 0, 0), Time.cookie("Wednesday, 01-Jan-10 00:00:00 GMT"))
+ assert_equal(Time.utc(2010, 1, 1, 0, 0, 0), Time.cookie("Wednesday, 01-Jan-10 0:0:00 GMT"))
+ assert_equal(Time.utc(2010, 1, 1, 1, 1, 50), Time.cookie("Fri, 1 Jan 2010 01:01:50 GMT"))
+ assert_equal(Time.utc(2012, 12, 8, 21, 24, 9), Time.cookie("Saturday, 8-Dec-2012 21:24:09 GMT"))
+ assert_equal(Time.utc(2012, 12, 9, 13, 42, 5), Time.cookie("Sun, 9 Dec 2012 13:42:05 GMT"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie('"Sat, 15-Apr-17\"21:01:22\"GMT"'))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("15 17 Apr 21:01:22"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("15 Apr 21:01:22 2017"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("15 April 2017 21:01:22"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("15-Sat, Apr 21:01:22 GMT 17"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("15-Sat, Apr 21:01:22 GMT 2017"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("15-Sat, Apr-17 21:01:22 GMT"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("2017 April 15 21:01:22"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("Apr 15 17 21:01:22"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("Apr 15 21:01:22 17"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("Sat, 15-Apr-17 21:01:22 (hello there)"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("Sat, 15-Apr-17 21:01:22 -0400"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("Sat, 15-Apr-17 21:01:22 11:22:33"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("Sat, 15-Apr-17 21:01:22 DST"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("Sat, 15-Apr-17 21:01:22 GMT BLAH"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("Sat, 15-Apr-17 21:01:22 GMT"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("Sat, 15-Apr-17 21:01:22 GMT-0400 (EDT)"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("Sat, 15-Apr-17 21:01:22 GMT-0400"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("Sat, 15-Apr-17 21:01:22 GMT-2"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("Sat, 15-Apr-17 21:01:22"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("Sat, 15-Apr-17 ::00 21:01:22"))
+ assert_equal(Time.utc(2017, 4, 15, 21, 1, 22), Time.cookie("Sat, 15-Apr-17 boink:z 21:01:22"))
+ assert_equal(Time.utc(2020, 1, 1, 0, 0, 0), Time.cookie("Wed, 1 Jan 2020 00:00:00 GMT"))
+ assert_equal(Time.utc(2037, 12, 31, 23, 55, 55), Time.cookie("Thu, 31 Dec 23:55:55 2037 GMT"))
+ assert_raise(ArgumentError){ Time.cookie("98 April 17 21:01:22") }
+ assert_raise(ArgumentError){ Time.cookie("IAintNoDateFool") }
+ assert_raise(ArgumentError){ Time.cookie("Mon, 01-Jan-2011 00: 00:00 GMT") }
+ assert_raise(ArgumentError){ Time.cookie("Sat, 15-Apr-17 91:22:33 21:01:22") }
+ assert_raise(ArgumentError){ Time.cookie("Thu, 012-Aug-2008 20:49:07 GMT") }
+ assert_raise(ArgumentError){ Time.cookie("Thu, 12-Aug-2007 20:61:99999999999 GMT") }
+ assert_raise(ArgumentError){ Time.cookie("Thu, 12-Aug-31841 20:49:07 GMT") }
+ assert_raise(ArgumentError){ Time.cookie("Thu, 12-Aug-9999999999 20:49:07 GMT") }
+ assert_raise(ArgumentError){ Time.cookie("Thu, 999999999999-Aug-2007 20:49:07 GMT") }
+ end
end
diff --git a/time.c b/time.c
index 5748c14..40a1b1a 100644
--- a/time.c
+++ b/time.c
@@ -3152,6 +3152,357 @@ time_s_mktime(int argc, VALUE *argv, VALUE klass)
return time_utc_or_local(argc, argv, FALSE, klass);
}
+#define RFC6265_DELIMITER_P(p) ((p) == 9 || \
+ (0x20 <= (p) && (p) <= 0x2F) || \
+ (0x3B <= (p) && (p) <= 0x40) || \
+ (0x5B <= (p) && (p) <= 0x60) || \
+ (0x7B <= (p) && (p) <= 0x7E))
+
+/*
+ * HTML5 datetime
+ * http://dev.w3.org/html5/spec/the-time-element.html#the-time-element
+ *
+ * * valid date string
+ * * valid local date and time string
+ * * valid global date and time string
+ */
+static VALUE
+parse_html5(VALUE klass, const char *p, const char *e)
+{
+ const char *q;
+ int year = 0, mon = 0, day = 0, hour = 0, min = 0, sec = 0, msec = -1;
+ struct vtm vtm;
+ VALUE offset = FALSE;
+
+ for (q = p; ISDIGIT(*p); p++) {
+ year *= 10;
+ year += *p - '0';
+ if (p - q > 9) {
+ /* too big for 32bit int */
+ vtm.year = rb_cstr_to_inum(q, 10, FALSE);
+ for (; ISDIGIT(*p); p++);
+ goto after_year;
+ }
+ }
+ if (p - q < 4) goto fail;
+ vtm.year = INT2FIX(year);
+
+after_year:
+ if (*p++ != '-' || !ISDIGIT(p[0]) || !ISDIGIT(p[1])) goto fail;
+ mon = p[0] * 10 + p[1] - '0' * 11;
+ if (mon < 1 || 12 < mon) goto fail;
+ p += 2;
+
+ if (*p++ != '-' || !ISDIGIT(p[0]) || !ISDIGIT(p[1])) goto fail;
+ day = p[0] * 10 + p[1] - '0' * 11;
+ if (day <= 28);
+ else if (mon == 2) {
+ if (day == 29 && year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
+ else goto fail;
+ }
+ else if (mon == 4 || mon == 6 || mon == 9 || mon == 11) {
+ if (day > 30) goto fail;
+ }
+ else if (day > 31) goto fail;
+ p += 2;
+
+ if (!*p) goto finish;
+
+ if (*p != 'T' && *p != ' ') goto fail;
+ p++;
+
+ if (!ISDIGIT(p[0]) || !ISDIGIT(p[1])) goto fail;
+ hour = p[0] * 10 + p[1] - '0' * 11;
+ if (23 < hour) goto fail;
+ p += 2;
+
+ if (*p++ != ':' || !ISDIGIT(p[0]) || !ISDIGIT(p[1])) goto fail;
+ min = p[0] * 10 + p[1] - '0' * 11;
+ if (59 < min) goto fail;
+ p += 2;
+
+ if (*p == ':') {
+ if (!ISDIGIT(p[1]) || !ISDIGIT(p[2])) goto fail;
+ sec = p[1] * 10 + p[2] - '0' * 11;
+ if (59 < sec) goto fail;
+ p += 3;
+
+ if (*p == '.') {
+ p++;
+ if (ISDIGIT(*p)) {
+ msec = *p++ * 100 - '0' * 100;
+ if (ISDIGIT(*p)) {
+ msec += *p++ * 10 - '0' * 10;
+ if (ISDIGIT(*p)) {
+ msec += *p++ - '0';
+ }
+ }
+ }
+ else goto fail;
+ }
+ }
+
+ if (!*p) goto finish;
+
+ if (*p == 'Z') {
+ p++;
+ offset = Qnil;
+ }
+ else {
+ int sign, h, m;
+ if ((p[0] != '-' && *p != '+') || !ISDIGIT(p[1]) || !ISDIGIT(p[2])) goto fail;
+ sign = 0x2C - p[0];
+ h = p[1] * 10 + p[2] - '0' * 11;
+ if (h > 23) return Qnil;
+ p += 3;
+ if (*p == ':') p++;
+ if (!ISDIGIT(p[0]) || !ISDIGIT(p[1])) goto fail;
+ m = p[0] * 10 + p[1] - '0' * 11;
+ if (m > 60) return Qnil;
+ p += 2;
+ offset = INT2FIX(sign * (h*60+m) * 60);
+ }
+
+ if (*p) goto fail;
+
+finish:
+ vtm.mon = mon;
+ vtm.mday = day;
+ vtm.hour = hour;
+ vtm.min = min;
+ vtm.sec = sec;
+ vtm.subsecx = (msec == -1) ? INT2FIX(0) : quo(INT2FIX(msec),INT2FIX(1000));
+ vtm.wday = 0;
+ vtm.yday = 0;
+ vtm.isdst = 0;
+ vtm.zone = "";
+
+ if (!offset) {
+ /* local */
+ return time_new_timew(klass, timelocalw(&vtm));
+ }
+ else if (NIL_P(offset)) {
+ /* UTC */
+ return time_new_timew(klass, timegmw(&vtm));
+ }
+ else {
+ /* with offset */
+ vtm.utc_offset = offset;
+ vtm_add_offset(&vtm, neg(offset));
+ vtm.utc_offset = Qnil;
+ return time_set_utc_offset(time_new_timew(klass, timegmw(&vtm)), offset);
+ }
+
+fail:
+ return Qnil;
+}
+
+#define ICCMP(c, i) (((c)&223) == ((i)&223))
+
+/*
+ * Cookie Dates
+ * http://tools.ietf.org/html/rfc6265
+ */
+static VALUE
+parse_rfc6265(VALUE klass, const char *p, const char *e)
+{
+ int found_time_p = FALSE;
+ int found_day_of_month_p = FALSE;
+ int found_month_p = FALSE;
+ int found_year_p = FALSE;
+ int year, mon, day, hour, min, sec;
+
+ while (p < e) {
+ if (ISDIGIT(*p)) {
+ int len;
+ int tmp = *p - '0';
+ const char *q = p;
+ while (ISDIGIT(*++p)) {
+ tmp *= 10;
+ tmp += *p - '0';
+ }
+ len = p - q;
+ switch (len) {
+ case 1:
+ case 2:
+ if (!found_time_p && *p == ':') {
+ p++;
+ hour = tmp;
+ if (ISDIGIT(*p)) {
+ min = *p++ - '0';
+ if (ISDIGIT(*p)) {
+ min *= 10;
+ min += *p++ - '0';
+ }
+ if (*p++ == ':' && ISDIGIT(*p)) {
+ sec = *p++ - '0';
+ if (ISDIGIT(*p)) {
+ sec *= 10;
+ sec += *p++ - '0';
+ }
+ if (!*p || RFC6265_DELIMITER_P(*p)) {
+ found_time_p = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ if (!found_day_of_month_p) {
+ day = tmp;
+ found_day_of_month_p = TRUE;
+ break;
+ }
+ case 3:
+ case 4:
+ if (len >= 2 && !found_year_p) {
+ year = tmp;
+ found_year_p = TRUE;
+ break;
+ }
+ break;
+ }
+ }
+ else if (!found_month_p) {
+ switch (*p&223) {
+ case 'A':
+ if (ICCMP(p[1], 'P') && ICCMP(p[2], 'R')) {
+ mon = 4;
+ goto found_month;
+ }
+ else if (ICCMP(p[1], 'U') && ICCMP(p[2], 'G')) {
+ mon = 8;
+ goto found_month;
+ }
+ break;
+ case 'D':
+ if (ICCMP(p[1], 'E') && ICCMP(p[2], 'C')) {
+ mon = 12;
+ goto found_month;
+ }
+ break;
+ case 'F':
+ if (ICCMP(p[1], 'E') && ICCMP(p[2], 'B')) {
+ mon = 2;
+ goto found_month;
+ }
+ break;
+ case 'J':
+ if (ICCMP(p[1], 'A')) {
+ if (ICCMP(p[2], 'N')) {
+ mon = 1;
+ goto found_month;
+ }
+ }
+ else if ICCMP(p[1], 'U') {
+ if ICCMP(p[2], 'L') {
+ mon = 7;
+ goto found_month;
+ }
+ else if ICCMP(p[2], 'N') {
+ mon = 6;
+ goto found_month;
+ }
+ }
+ break;
+ case 'M':
+ if (ICCMP(p[1], 'A') && ICCMP(p[2], 'Y')) {
+ mon = 5;
+ goto found_month;
+ }
+ break;
+ case 'N':
+ if (ICCMP(p[1], 'O') && ICCMP(p[2], 'V')) {
+ mon = 11;
+ goto found_month;
+ }
+ break;
+ case 'O':
+ if (ICCMP(p[1], 'C') && ICCMP(p[2], 'T')) {
+ mon = 10;
+ goto found_month;
+ }
+ break;
+ case 'S':
+ if (ICCMP(p[1], 'E') && ICCMP(p[2], 'P')) {
+ mon = 9;
+found_month:
+ found_month_p = TRUE;
+ p += 3;
+ }
+ break;
+ }
+ }
+
+ for (; p < e && !RFC6265_DELIMITER_P(*p); p++);
+ for (; RFC6265_DELIMITER_P(*p); p++);
+ }
+
+ if (found_time_p && found_day_of_month_p && found_month_p && found_year_p) {
+ struct vtm vtm;
+ if (year < 70)
+ year += 2000;
+ else if (year < 100)
+ year += 1900;
+ if (day < 1 || 31 < day || year < 1601 || hour > 23 || min > 59 || sec > 59)
+ return Qnil;
+ vtm.year = INT2FIX(year);
+ vtm.mon = mon;
+ vtm.mday = day;
+ vtm.hour = hour;
+ vtm.min = min;
+ vtm.sec = sec;
+ vtm.subsecx = INT2FIX(0);
+ vtm.utc_offset = Qnil;
+ vtm.wday = 0;
+ vtm.yday = 0;
+ vtm.isdst = 0;
+ vtm.zone = "";
+ return time_gmtime(time_new_timew(klass, timegmw(&vtm)));
+ }
+
+ /*
+ fprintf(stderr, "%d %d %d %d %04d-%02d-%02d %02d:%02d:%02d\n",
+ found_time_p, found_day_of_month_p, found_month_p, found_year_p,
+ year, mon, day, hour, min, sec);// */
+ return Qnil;
+}
+
+/* call-seq:
+ * Time.html5(string) -> time
+ *
+ * Parse a string and create a time object.
+ *
+ * HTML5 Dates and Times + negative year
+ */
+
+static VALUE
+time_s_html5(VALUE klass, VALUE str)
+{
+ const char *p = StringValueCStr(str);
+ const char *e = RSTRING_END(str);
+ VALUE v = parse_html5(klass, p, e);
+ if (NIL_P(v)) rb_raise(rb_eArgError, "cannot find valid time information in '%s'", p);
+ return v;
+}
+
+/* call-seq:
+ * Time.cookie(string) -> time
+ *
+ * Parse a string and create a time object.
+ *
+ * RFC6265 HTTP State Management Mechanism, a.k.a. Cookie Dates
+ */
+
+static VALUE
+time_s_cookie(VALUE klass, VALUE str)
+{
+ const char *p = StringValueCStr(str);
+ const char *e = RSTRING_END(str);
+ VALUE v = parse_rfc6265(klass, p, e);
+ if (NIL_P(v)) rb_raise(rb_eArgError, "cannot find valid time information in '%s'", p);
+ return v;
+}
+
/*
* call-seq:
* time.to_i -> int
@@ -4956,6 +5307,8 @@ Init_Time(void)
rb_define_singleton_method(rb_cTime, "gm", time_s_mkutc, -1);
rb_define_singleton_method(rb_cTime, "local", time_s_mktime, -1);
rb_define_singleton_method(rb_cTime, "mktime", time_s_mktime, -1);
+ rb_define_singleton_method(rb_cTime, "html5", time_s_html5, 1);
+ rb_define_singleton_method(rb_cTime, "cookie", time_s_cookie, 1);
rb_define_method(rb_cTime, "to_i", time_to_i, 0);
rb_define_method(rb_cTime, "to_f", time_to_f, 0);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment