diff options
Diffstat (limited to 'ruby_1_9_3/ext/date/date_parse.c')
-rw-r--r-- | ruby_1_9_3/ext/date/date_parse.c | 2425 |
1 files changed, 0 insertions, 2425 deletions
diff --git a/ruby_1_9_3/ext/date/date_parse.c b/ruby_1_9_3/ext/date/date_parse.c deleted file mode 100644 index 903163003c..0000000000 --- a/ruby_1_9_3/ext/date/date_parse.c +++ /dev/null @@ -1,2425 +0,0 @@ -/* - date_parse.c: Coded by Tadayoshi Funaba 2011,2012 -*/ - -#include "ruby.h" -#include "ruby/encoding.h" -#include "ruby/re.h" -#include <ctype.h> - -#define sizeof_array(o) (sizeof o / sizeof o[0]) - -#define f_negate(x) rb_funcall(x, rb_intern("-@"), 0) -#define f_add(x,y) rb_funcall(x, '+', 1, y) -#define f_sub(x,y) rb_funcall(x, '-', 1, y) -#define f_mul(x,y) rb_funcall(x, '*', 1, y) -#define f_div(x,y) rb_funcall(x, '/', 1, y) -#define f_idiv(x,y) rb_funcall(x, rb_intern("div"), 1, y) -#define f_mod(x,y) rb_funcall(x, '%', 1, y) -#define f_expt(x,y) rb_funcall(x, rb_intern("**"), 1, y) - -#define f_lt_p(x,y) rb_funcall(x, '<', 1, y) -#define f_gt_p(x,y) rb_funcall(x, '>', 1, y) -#define f_le_p(x,y) rb_funcall(x, rb_intern("<="), 1, y) -#define f_ge_p(x,y) rb_funcall(x, rb_intern(">="), 1, y) - -#define f_to_s(x) rb_funcall(x, rb_intern("to_s"), 0) - -#define f_match(r,s) rb_funcall(r, rb_intern("match"), 1, s) -#define f_aref(o,i) rb_funcall(o, rb_intern("[]"), 1, i) -#define f_aref2(o,i,j) rb_funcall(o, rb_intern("[]"), 2, i, j) -#define f_begin(o,i) rb_funcall(o, rb_intern("begin"), 1, i) -#define f_end(o,i) rb_funcall(o, rb_intern("end"), 1, i) -#define f_aset(o,i,v) rb_funcall(o, rb_intern("[]="), 2, i, v) -#define f_aset2(o,i,j,v) rb_funcall(o, rb_intern("[]="), 3, i, j, v) -#define f_sub_bang(s,r,x) rb_funcall(s, rb_intern("sub!"), 2, r, x) -#define f_gsub_bang(s,r,x) rb_funcall(s, rb_intern("gsub!"), 2, r, x) - -#define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k)), v) -#define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k))) -#define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k))) - -#define cstr2num(s) rb_cstr_to_inum(s, 10, 0) -#define str2num(s) rb_str_to_inum(s, 10, 0) - -static const char *abbr_days[] = { - "sun", "mon", "tue", "wed", - "thu", "fri", "sat" -}; - -static const char *abbr_months[] = { - "jan", "feb", "mar", "apr", "may", "jun", - "jul", "aug", "sep", "oct", "nov", "dec" -}; - -#define issign(c) ((c) == '-' || (c) == '+') -#define asp_string() rb_str_new(" ", 1) - -static void -s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc) -{ - VALUE c = Qnil; - - if (TYPE(m) != T_STRING) - m = f_to_s(m); - - if (!NIL_P(y) && !NIL_P(m) && NIL_P(d)) { - VALUE oy = y; - VALUE om = m; - VALUE od = d; - - y = od; - m = oy; - d = om; - } - - if (NIL_P(y)) { - if (!NIL_P(d) && RSTRING_LEN(d) > 2) { - y = d; - d = Qnil; - } - if (!NIL_P(d) && *RSTRING_PTR(d) == '\'') { - y = d; - d = Qnil; - } - } - - if (!NIL_P(y)) { - const char *s, *bp, *ep; - size_t l; - - s = RSTRING_PTR(y); - while (!issign(*s) && !isdigit(*s)) - s++; - bp = s; - if (issign(*s)) - s++; - l = strspn(s, "0123456789"); - ep = s + l; - if (*ep) { - y = d; - d = rb_str_new(bp, ep - bp); - } - } - - if (!NIL_P(m)) { - const char *s; - - s = RSTRING_PTR(m); - if (*s == '\'' || RSTRING_LEN(m) > 2) { - /* us -> be */ - VALUE oy = y; - VALUE om = m; - VALUE od = d; - - y = om; - m = od; - d = oy; - } - } - - if (!NIL_P(d)) { - const char *s; - - s = RSTRING_PTR(d); - if (*s == '\'' || RSTRING_LEN(d) > 2) { - VALUE oy = y; - VALUE od = d; - - y = od; - d = oy; - } - } - - if (!NIL_P(y)) { - const char *s, *bp, *ep; - int sign = 0; - size_t l; - VALUE iy; - - s = RSTRING_PTR(y); - while (!issign(*s) && !isdigit(*s)) - s++; - bp = s; - if (issign(*s)) { - s++; - sign = 1; - } - if (sign) - c = Qfalse; - l = strspn(s, "0123456789"); - ep = s + l; - if (l > 2) - c = Qfalse; - { - char *buf; - - buf = ALLOCA_N(char, ep - bp + 1); - memcpy(buf, bp, ep - bp); - buf[ep - bp] = '\0'; - iy = cstr2num(buf); - } - if (bc) - iy = f_add(f_negate(iy), INT2FIX(1)); - set_hash("year", iy); - } - - if (!NIL_P(m)) { - const char *s, *bp, *ep; - size_t l; - VALUE im; - - s = RSTRING_PTR(m); - while (!isdigit(*s)) - s++; - bp = s; - l = strspn(s, "0123456789"); - ep = s + l; - { - char *buf; - - buf = ALLOCA_N(char, ep - bp + 1); - memcpy(buf, bp, ep - bp); - buf[ep - bp] = '\0'; - im = cstr2num(buf); - } - set_hash("mon", im); - } - - if (!NIL_P(d)) { - const char *s, *bp, *ep; - size_t l; - VALUE id; - - s = RSTRING_PTR(d); - while (!isdigit(*s)) - s++; - bp = s; - l = strspn(s, "0123456789"); - ep = s + l; - { - char *buf; - - buf = ALLOCA_N(char, ep - bp + 1); - memcpy(buf, bp, ep - bp); - buf[ep - bp] = '\0'; - id = cstr2num(buf); - } - set_hash("mday", id); - } - - if (!NIL_P(c)) - set_hash("_comp", c); -} - -#define DAYS "sunday|monday|tuesday|wednesday|thursday|friday|saturday" -#define MONTHS "january|february|march|april|may|june|july|august|september|october|november|december" -#define ABBR_DAYS "sun|mon|tue|wed|thu|fri|sat" -#define ABBR_MONTHS "jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec" - -static VALUE -regcomp(const char *source, long len, int opt) -{ - VALUE pat; - - pat = rb_reg_new(source, len, opt); - rb_gc_register_mark_object(pat); - return pat; -} - -#define REGCOMP(pat,opt) \ -{ \ - if (NIL_P(pat)) \ - pat = regcomp(pat##_source, sizeof pat##_source - 1, opt); \ -} - -#define REGCOMP_0(pat) REGCOMP(pat, 0) -#define REGCOMP_I(pat) REGCOMP(pat, ONIG_OPTION_IGNORECASE) - -#define MATCH(s,p,c) \ -{ \ - return match(s, p, hash, c); \ -} - -static int -match(VALUE str, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE)) -{ - VALUE m; - - m = f_match(pat, str); - - if (NIL_P(m)) - return 0; - - (*cb)(m, hash); - - return 1; -} - -#define SUBS(s,p,c) \ -{ \ - return subs(s, p, hash, c); \ -} - -static int -subs(VALUE str, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE)) -{ - VALUE m; - - m = f_match(pat, str); - - if (NIL_P(m)) - return 0; - - { - VALUE be, en; - - be = f_begin(m, INT2FIX(0)); - en = f_end(m, INT2FIX(0)); - f_aset2(str, be, LONG2NUM(NUM2LONG(en) - NUM2LONG(be)), asp_string()); - (*cb)(m, hash); - } - - return 1; -} - -struct zone { - const char *name; - int offset; -}; - -static struct zone zones_source[] = { - {"ut", 0*3600}, {"gmt", 0*3600}, {"est", -5*3600}, {"edt", -4*3600}, - {"cst", -6*3600}, {"cdt", -5*3600}, {"mst", -7*3600}, {"mdt", -6*3600}, - {"pst", -8*3600}, {"pdt", -7*3600}, - {"a", 1*3600}, {"b", 2*3600}, {"c", 3*3600}, {"d", 4*3600}, - {"e", 5*3600}, {"f", 6*3600}, {"g", 7*3600}, {"h", 8*3600}, - {"i", 9*3600}, {"k", 10*3600}, {"l", 11*3600}, {"m", 12*3600}, - {"n", -1*3600}, {"o", -2*3600}, {"p", -3*3600}, {"q", -4*3600}, - {"r", -5*3600}, {"s", -6*3600}, {"t", -7*3600}, {"u", -8*3600}, - {"v", -9*3600}, {"w", -10*3600}, {"x", -11*3600}, {"y", -12*3600}, - {"z", 0*3600}, - - {"utc", 0*3600}, {"wet", 0*3600}, - {"at", -2*3600}, {"brst",-2*3600}, {"ndt", -(2*3600+1800)}, - {"art", -3*3600}, {"adt", -3*3600}, {"brt", -3*3600}, {"clst",-3*3600}, - {"nst", -(3*3600+1800)}, - {"ast", -4*3600}, {"clt", -4*3600}, - {"akdt",-8*3600}, {"ydt", -8*3600}, - {"akst",-9*3600}, {"hadt",-9*3600}, {"hdt", -9*3600}, {"yst", -9*3600}, - {"ahst",-10*3600},{"cat",-10*3600}, {"hast",-10*3600},{"hst",-10*3600}, - {"nt", -11*3600}, - {"idlw",-12*3600}, - {"bst", 1*3600}, {"cet", 1*3600}, {"fwt", 1*3600}, {"met", 1*3600}, - {"mewt", 1*3600}, {"mez", 1*3600}, {"swt", 1*3600}, {"wat", 1*3600}, - {"west", 1*3600}, - {"cest", 2*3600}, {"eet", 2*3600}, {"fst", 2*3600}, {"mest", 2*3600}, - {"mesz", 2*3600}, {"sast", 2*3600}, {"sst", 2*3600}, - {"bt", 3*3600}, {"eat", 3*3600}, {"eest", 3*3600}, {"msk", 3*3600}, - {"msd", 4*3600}, {"zp4", 4*3600}, - {"zp5", 5*3600}, {"ist", (5*3600+1800)}, - {"zp6", 6*3600}, - {"wast", 7*3600}, - {"cct", 8*3600}, {"sgt", 8*3600}, {"wadt", 8*3600}, - {"jst", 9*3600}, {"kst", 9*3600}, - {"east",10*3600}, {"gst", 10*3600}, - {"eadt",11*3600}, - {"idle",12*3600}, {"nzst",12*3600}, {"nzt", 12*3600}, - {"nzdt",13*3600}, - - {"afghanistan", 16200}, {"alaskan", -32400}, - {"arab", 10800}, {"arabian", 14400}, - {"arabic", 10800}, {"atlantic", -14400}, - {"aus central", 34200}, {"aus eastern", 36000}, - {"azores", -3600}, {"canada central", -21600}, - {"cape verde", -3600}, {"caucasus", 14400}, - {"cen. australia", 34200}, {"central america", -21600}, - {"central asia", 21600}, {"central europe", 3600}, - {"central european", 3600}, {"central pacific", 39600}, - {"central", -21600}, {"china", 28800}, - {"dateline", -43200}, {"e. africa", 10800}, - {"e. australia", 36000}, {"e. europe", 7200}, - {"e. south america", -10800}, {"eastern", -18000}, - {"egypt", 7200}, {"ekaterinburg", 18000}, - {"fiji", 43200}, {"fle", 7200}, - {"greenland", -10800}, {"greenwich", 0}, - {"gtb", 7200}, {"hawaiian", -36000}, - {"india", 19800}, {"iran", 12600}, - {"jerusalem", 7200}, {"korea", 32400}, - {"mexico", -21600}, {"mid-atlantic", -7200}, - {"mountain", -25200}, {"myanmar", 23400}, - {"n. central asia", 21600}, {"nepal", 20700}, - {"new zealand", 43200}, {"newfoundland", -12600}, - {"north asia east", 28800}, {"north asia", 25200}, - {"pacific sa", -14400}, {"pacific", -28800}, - {"romance", 3600}, {"russian", 10800}, - {"sa eastern", -10800}, {"sa pacific", -18000}, - {"sa western", -14400}, {"samoa", -39600}, - {"se asia", 25200}, {"malay peninsula", 28800}, - {"south africa", 7200}, {"sri lanka", 21600}, - {"taipei", 28800}, {"tasmania", 36000}, - {"tokyo", 32400}, {"tonga", 46800}, - {"us eastern", -18000}, {"us mountain", -25200}, - {"vladivostok", 36000}, {"w. australia", 28800}, - {"w. central africa", 3600}, {"w. europe", 3600}, - {"west asia", 18000}, {"west pacific", 36000}, - {"yakutsk", 32400} -}; - -VALUE -date_zone_to_diff(VALUE str) -{ - VALUE offset = Qnil; - - long l, i; - char *s, *dest, *d; - int sp = 1; - - l = RSTRING_LEN(str); - s = RSTRING_PTR(str); - - dest = d = ALLOCA_N(char, l + 1); - - for (i = 0; i < l; i++) { - if (isspace(s[i]) || s[i] == '\0') { - if (!sp) - *d++ = ' '; - sp = 1; - } - else { - if (isalpha(s[i])) - *d++ = tolower(s[i]); - else - *d++ = s[i]; - sp = 0; - } - } - if (d > dest) { - if (*(d - 1) == ' ') - --d; - *d = '\0'; - } - str = rb_str_new2(dest); - { -#define STD " standard time" -#define DST " daylight time" - char *ss, *ds; - long sl, dl; - int dst = 0; - - sl = RSTRING_LEN(str) - (sizeof STD - 1); - ss = RSTRING_PTR(str) + sl; - dl = RSTRING_LEN(str) - (sizeof DST - 1); - ds = RSTRING_PTR(str) + dl; - - if (sl >= 0 && strcmp(ss, STD) == 0) { - str = rb_str_new(RSTRING_PTR(str), sl); - } - else if (dl >= 0 && strcmp(ds, DST) == 0) { - str = rb_str_new(RSTRING_PTR(str), dl); - dst = 1; - } -#undef STD -#undef DST - else { -#define DST " dst" - char *ds; - long dl; - - dl = RSTRING_LEN(str) - (sizeof DST - 1); - ds = RSTRING_PTR(str) + dl; - - if (dl >= 0 && strcmp(ds, DST) == 0) { - str = rb_str_new(RSTRING_PTR(str), dl); - dst = 1; - } -#undef DST - } - { - static VALUE zones = Qnil; - - if (NIL_P(zones)) { - int i; - - zones = rb_hash_new(); - rb_gc_register_mark_object(zones); - for (i = 0; i < (int)sizeof_array(zones_source); i++) { - VALUE name = rb_str_new2(zones_source[i].name); - VALUE offset = INT2FIX(zones_source[i].offset); - rb_hash_aset(zones, name, offset); - } - } - - offset = f_aref(zones, str); - if (!NIL_P(offset)) { - if (dst) - offset = f_add(offset, INT2FIX(3600)); - goto ok; - } - } - { - char *s, *p; - VALUE sign; - VALUE hour = Qnil, min = Qnil, sec = Qnil; - VALUE str_orig; - - s = RSTRING_PTR(str); - str_orig = str; - - if (strncmp(s, "gmt", 3) == 0 || - strncmp(s, "utc", 3) == 0) - s += 3; - if (issign(*s)) { - sign = rb_str_new(s, 1); - s++; - - str = rb_str_new2(s); - - if (p = strchr(s, ':')) { - hour = rb_str_new(s, p - s); - s = ++p; - if (p = strchr(s, ':')) { - min = rb_str_new(s, p - s); - s = ++p; - if (p = strchr(s, ':')) { - sec = rb_str_new(s, p - s); - } - else - sec = rb_str_new2(s); - } - else - min = rb_str_new2(s); - RB_GC_GUARD(str_orig); - goto num; - } - if (strpbrk(RSTRING_PTR(str), ",.")) { - char *a, *b; - - a = ALLOCA_N(char, RSTRING_LEN(str) + 1); - strcpy(a, RSTRING_PTR(str)); - b = strpbrk(a, ",."); - *b = '\0'; - b++; - - hour = cstr2num(a); - min = f_mul(rb_rational_new2 - (cstr2num(b), - f_expt(INT2FIX(10), - LONG2NUM((long)strlen(b)))), - INT2FIX(60)); - goto num; - } - { - const char *cs = RSTRING_PTR(str); - long cl = RSTRING_LEN(str); - - if (cl % 2) { - if (cl >= 1) - hour = rb_str_new(&cs[0], 1); - if (cl >= 3) - min = rb_str_new(&cs[1], 2); - if (cl >= 5) - min = rb_str_new(&cs[3], 2); - } - else { - if (cl >= 2) - hour = rb_str_new(&cs[0], 2); - if (cl >= 4) - min = rb_str_new(&cs[2], 2); - if (cl >= 6) - sec = rb_str_new(&cs[4], 2); - } - goto num; - } - num: - if (NIL_P(hour)) - offset = INT2FIX(0); - else { - if (TYPE(hour) == T_STRING) - hour = str2num(hour); - offset = f_mul(hour, INT2FIX(3600)); - } - if (!NIL_P(min)) { - if (TYPE(min) == T_STRING) - min = str2num(min); - offset = f_add(offset, f_mul(min, INT2FIX(60))); - } - if (!NIL_P(sec)) - offset = f_add(offset, str2num(sec)); - if (!NIL_P(sign) && - RSTRING_LEN(sign) == 1 && - *RSTRING_PTR(sign) == '-') - offset = f_negate(offset); - } - } - } - RB_GC_GUARD(str); - ok: - return offset; -} - -static int -day_num(VALUE s) -{ - int i; - - for (i = 0; i < (int)sizeof_array(abbr_days); i++) - if (strncasecmp(abbr_days[i], RSTRING_PTR(s), 3) == 0) - break; - return i; -} - -static int -mon_num(VALUE s) -{ - int i; - - for (i = 0; i < (int)sizeof_array(abbr_months); i++) - if (strncasecmp(abbr_months[i], RSTRING_PTR(s), 3) == 0) - break; - return i + 1; -} - -static int -parse_day_cb(VALUE m, VALUE hash) -{ - VALUE s; - - s = rb_reg_nth_match(1, m); - set_hash("wday", INT2FIX(day_num(s))); - return 1; -} - -static int -parse_day(VALUE str, VALUE hash) -{ - static const char pat_source[] = "\\b(" ABBR_DAYS ")[^-\\d\\s]*"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_day_cb); -} - -static int -parse_time2_cb(VALUE m, VALUE hash) -{ - VALUE h, min, s, f, p; - - h = rb_reg_nth_match(1, m); - h = str2num(h); - - min = rb_reg_nth_match(2, m); - if (!NIL_P(min)) - min = str2num(min); - - s = rb_reg_nth_match(3, m); - if (!NIL_P(s)) - s = str2num(s); - - f = rb_reg_nth_match(4, m); - - if (!NIL_P(f)) - f = rb_rational_new2(str2num(f), - f_expt(INT2FIX(10), LONG2NUM(RSTRING_LEN(f)))); - - p = rb_reg_nth_match(5, m); - - if (!NIL_P(p)) { - int ih = NUM2INT(h); - ih %= 12; - if (*RSTRING_PTR(p) == 'P' || *RSTRING_PTR(p) == 'p') - ih += 12; - h = INT2FIX(ih); - } - - set_hash("hour", h); - if (!NIL_P(min)) - set_hash("min", min); - if (!NIL_P(s)) - set_hash("sec", s); - if (!NIL_P(f)) - set_hash("sec_fraction", f); - - return 1; -} - -static int -parse_time_cb(VALUE m, VALUE hash) -{ - static const char pat_source[] = - "\\A(\\d+)h?" - "(?:\\s*:?\\s*(\\d+)m?" - "(?:" - "\\s*:?\\s*(\\d+)(?:[,.](\\d+))?s?" - ")?" - ")?" - "(?:\\s*([ap])(?:m\\b|\\.m\\.))?"; - static VALUE pat = Qnil; - VALUE s1, s2; - - s1 = rb_reg_nth_match(1, m); - s2 = rb_reg_nth_match(2, m); - - if (!NIL_P(s2)) - set_hash("zone", s2); - - REGCOMP_I(pat); - - { - VALUE m = f_match(pat, s1); - - if (NIL_P(m)) - return 0; - parse_time2_cb(m, hash); - } - - return 1; -} - -static int -parse_time(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "(" - "(?:" - "\\d+\\s*:\\s*\\d+" - "(?:" - "\\s*:\\s*\\d+(?:[,.]\\d*)?" - ")?" - "|" - "\\d+\\s*h(?:\\s*\\d+m?(?:\\s*\\d+s?)?)?" - ")" - "(?:" - "\\s*" - "[ap](?:m\\b|\\.m\\.)" - ")?" - "|" - "\\d+\\s*[ap](?:m\\b|\\.m\\.)" - ")" - "(?:" - "\\s*" - "(" - "(?:gmt|utc?)?[-+]\\d+(?:[,.:]\\d+(?::\\d+)?)?" - "|" - "[[:alpha:].\\s]+(?:standard|daylight)\\stime\\b" - "|" - "[[:alpha:]]+(?:\\sdst)?\\b" - ")" - ")?"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_time_cb); -} - -static int -parse_eu_cb(VALUE m, VALUE hash) -{ - VALUE y, mon, d, b; - - d = rb_reg_nth_match(1, m); - mon = rb_reg_nth_match(2, m); - b = rb_reg_nth_match(3, m); - y = rb_reg_nth_match(4, m); - - mon = INT2FIX(mon_num(mon)); - - s3e(hash, y, mon, d, !NIL_P(b) && - (*RSTRING_PTR(b) == 'B' || - *RSTRING_PTR(b) == 'b')); - return 1; -} - -static int -parse_eu(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "'?(\\d+)[^-\\d\\s]*" - "\\s*" - "(" ABBR_MONTHS ")[^-\\d\\s']*" - "(?:" - "\\s*" - "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?" - "\\s*" - "('?-?\\d+(?:(?:st|nd|rd|th)\\b)?)" - ")?"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_eu_cb); -} - -static int -parse_us_cb(VALUE m, VALUE hash) -{ - VALUE y, mon, d, b; - - mon = rb_reg_nth_match(1, m); - d = rb_reg_nth_match(2, m); - b = rb_reg_nth_match(3, m); - y = rb_reg_nth_match(4, m); - - mon = INT2FIX(mon_num(mon)); - - s3e(hash, y, mon, d, !NIL_P(b) && - (*RSTRING_PTR(b) == 'B' || - *RSTRING_PTR(b) == 'b')); - return 1; -} - -static int -parse_us(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\b(" ABBR_MONTHS ")[^-\\d\\s']*" - "\\s*" - "('?\\d+)[^-\\d\\s']*" - "(?:" - "\\s*" - "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?" - "\\s*" - "('?-?\\d+)" - ")?"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_us_cb); -} - -static int -parse_iso_cb(VALUE m, VALUE hash) -{ - VALUE y, mon, d; - - y = rb_reg_nth_match(1, m); - mon = rb_reg_nth_match(2, m); - d = rb_reg_nth_match(3, m); - - s3e(hash, y, mon, d, 0); - return 1; -} - -static int -parse_iso(VALUE str, VALUE hash) -{ - static const char pat_source[] = "('?[-+]?\\d+)-(\\d+)-('?-?\\d+)"; - static VALUE pat = Qnil; - - REGCOMP_0(pat); - SUBS(str, pat, parse_iso_cb); -} - -static int -parse_iso21_cb(VALUE m, VALUE hash) -{ - VALUE y, w, d; - - y = rb_reg_nth_match(1, m); - w = rb_reg_nth_match(2, m); - d = rb_reg_nth_match(3, m); - - if (!NIL_P(y)) - set_hash("cwyear", str2num(y)); - set_hash("cweek", str2num(w)); - if (!NIL_P(d)) - set_hash("cwday", str2num(d)); - - return 1; -} - -static int -parse_iso21(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\b(\\d{2}|\\d{4})?-?w(\\d{2})(?:-?(\\d))?\\b"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_iso21_cb); -} - -static int -parse_iso22_cb(VALUE m, VALUE hash) -{ - VALUE d; - - d = rb_reg_nth_match(1, m); - set_hash("cwday", str2num(d)); - return 1; -} - -static int -parse_iso22(VALUE str, VALUE hash) -{ - static const char pat_source[] = "-w-(\\d)\\b"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_iso22_cb); -} - -static int -parse_iso23_cb(VALUE m, VALUE hash) -{ - VALUE mon, d; - - mon = rb_reg_nth_match(1, m); - d = rb_reg_nth_match(2, m); - - if (!NIL_P(mon)) - set_hash("mon", str2num(mon)); - set_hash("mday", str2num(d)); - - return 1; -} - -static int -parse_iso23(VALUE str, VALUE hash) -{ - static const char pat_source[] = "--(\\d{2})?-(\\d{2})\\b"; - static VALUE pat = Qnil; - - REGCOMP_0(pat); - SUBS(str, pat, parse_iso23_cb); -} - -static int -parse_iso24_cb(VALUE m, VALUE hash) -{ - VALUE mon, d; - - mon = rb_reg_nth_match(1, m); - d = rb_reg_nth_match(2, m); - - set_hash("mon", str2num(mon)); - if (!NIL_P(d)) - set_hash("mday", str2num(d)); - - return 1; -} - -static int -parse_iso24(VALUE str, VALUE hash) -{ - static const char pat_source[] = "--(\\d{2})(\\d{2})?\\b"; - static VALUE pat = Qnil; - - REGCOMP_0(pat); - SUBS(str, pat, parse_iso24_cb); -} - -static int -parse_iso25_cb(VALUE m, VALUE hash) -{ - VALUE y, d; - - y = rb_reg_nth_match(1, m); - d = rb_reg_nth_match(2, m); - - set_hash("year", str2num(y)); - set_hash("yday", str2num(d)); - - return 1; -} - -static int -parse_iso25(VALUE str, VALUE hash) -{ - static const char pat0_source[] = "[,.](\\d{2}|\\d{4})-\\d{3}\\b"; - static VALUE pat0 = Qnil; - static const char pat_source[] = "\\b(\\d{2}|\\d{4})-(\\d{3})\\b"; - static VALUE pat = Qnil; - - REGCOMP_0(pat0); - REGCOMP_0(pat); - - if (!NIL_P(f_match(pat0, str))) - return 0; - SUBS(str, pat, parse_iso25_cb); -} - -static int -parse_iso26_cb(VALUE m, VALUE hash) -{ - VALUE d; - - d = rb_reg_nth_match(1, m); - set_hash("yday", str2num(d)); - - return 1; -} -static int -parse_iso26(VALUE str, VALUE hash) -{ - static const char pat0_source[] = "\\d-\\d{3}\\b"; - static VALUE pat0 = Qnil; - static const char pat_source[] = "\\b-(\\d{3})\\b"; - static VALUE pat = Qnil; - - REGCOMP_0(pat0); - REGCOMP_0(pat); - - if (!NIL_P(f_match(pat0, str))) - return 0; - SUBS(str, pat, parse_iso26_cb); -} - -static int -parse_iso2(VALUE str, VALUE hash) -{ - if (parse_iso21(str, hash)) - goto ok; - if (parse_iso22(str, hash)) - goto ok; - if (parse_iso23(str, hash)) - goto ok; - if (parse_iso24(str, hash)) - goto ok; - if (parse_iso25(str, hash)) - goto ok; - if (parse_iso26(str, hash)) - goto ok; - return 0; - - ok: - return 1; -} - -static int -gengo(int c) -{ - int e; - - switch (c) { - case 'M': case 'm': e = 1867; break; - case 'T': case 't': e = 1911; break; - case 'S': case 's': e = 1925; break; - case 'H': case 'h': e = 1988; break; - default: e = 0; break; - } - return e; -} - -static int -parse_jis_cb(VALUE m, VALUE hash) -{ - VALUE e, y, mon, d; - int ep; - - e = rb_reg_nth_match(1, m); - y = rb_reg_nth_match(2, m); - mon = rb_reg_nth_match(3, m); - d = rb_reg_nth_match(4, m); - - ep = gengo(*RSTRING_PTR(e)); - - set_hash("year", f_add(str2num(y), INT2FIX(ep))); - set_hash("mon", str2num(mon)); - set_hash("mday", str2num(d)); - - return 1; -} - -static int -parse_jis(VALUE str, VALUE hash) -{ - static const char pat_source[] = "\\b([mtsh])(\\d+)\\.(\\d+)\\.(\\d+)"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_jis_cb); -} - -static int -parse_vms11_cb(VALUE m, VALUE hash) -{ - VALUE y, mon, d; - - d = rb_reg_nth_match(1, m); - mon = rb_reg_nth_match(2, m); - y = rb_reg_nth_match(3, m); - - mon = INT2FIX(mon_num(mon)); - - s3e(hash, y, mon, d, 0); - return 1; -} - -static int -parse_vms11(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "('?-?\\d+)-(" ABBR_MONTHS ")[^-]*" - "-('?-?\\d+)"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_vms11_cb); -} - -static int -parse_vms12_cb(VALUE m, VALUE hash) -{ - VALUE y, mon, d; - - mon = rb_reg_nth_match(1, m); - d = rb_reg_nth_match(2, m); - y = rb_reg_nth_match(3, m); - - mon = INT2FIX(mon_num(mon)); - - s3e(hash, y, mon, d, 0); - return 1; -} - -static int -parse_vms12(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\b(" ABBR_MONTHS ")[^-]*" - "-('?-?\\d+)(?:-('?-?\\d+))?"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_vms12_cb); -} - -static int -parse_vms(VALUE str, VALUE hash) -{ - if (parse_vms11(str, hash)) - goto ok; - if (parse_vms12(str, hash)) - goto ok; - return 0; - - ok: - return 1; -} - -static int -parse_sla_cb(VALUE m, VALUE hash) -{ - VALUE y, mon, d; - - y = rb_reg_nth_match(1, m); - mon = rb_reg_nth_match(2, m); - d = rb_reg_nth_match(3, m); - - s3e(hash, y, mon, d, 0); - return 1; -} - -static int -parse_sla(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "('?-?\\d+)/\\s*('?\\d+)(?:\\D\\s*('?-?\\d+))?"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_sla_cb); -} - -static int -parse_dot_cb(VALUE m, VALUE hash) -{ - VALUE y, mon, d; - - y = rb_reg_nth_match(1, m); - mon = rb_reg_nth_match(2, m); - d = rb_reg_nth_match(3, m); - - s3e(hash, y, mon, d, 0); - return 1; -} - -static int -parse_dot(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "('?-?\\d+)\\.\\s*('?\\d+)\\.\\s*('?-?\\d+)"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_dot_cb); -} - -static int -parse_year_cb(VALUE m, VALUE hash) -{ - VALUE y; - - y = rb_reg_nth_match(1, m); - set_hash("year", str2num(y)); - return 1; -} - -static int -parse_year(VALUE str, VALUE hash) -{ - static const char pat_source[] = "'(\\d+)\\b"; - static VALUE pat = Qnil; - - REGCOMP_0(pat); - SUBS(str, pat, parse_year_cb); -} - -static int -parse_mon_cb(VALUE m, VALUE hash) -{ - VALUE mon; - - mon = rb_reg_nth_match(1, m); - set_hash("mon", INT2FIX(mon_num(mon))); - return 1; -} - -static int -parse_mon(VALUE str, VALUE hash) -{ - static const char pat_source[] = "\\b(" ABBR_MONTHS ")\\S*"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_mon_cb); -} - -static int -parse_mday_cb(VALUE m, VALUE hash) -{ - VALUE d; - - d = rb_reg_nth_match(1, m); - set_hash("mday", str2num(d)); - return 1; -} - -static int -parse_mday(VALUE str, VALUE hash) -{ - static const char pat_source[] = "(\\d+)(st|nd|rd|th)\\b"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_mday_cb); -} - -static int -n2i(const char *s, long f, long w) -{ - long e, i; - int v; - - e = f + w; - v = 0; - for (i = f; i < e; i++) { - v *= 10; - v += s[i] - '0'; - } - return v; -} - -static int -parse_ddd_cb(VALUE m, VALUE hash) -{ - VALUE s1, s2, s3, s4, s5; - const char *cs2, *cs3, *cs5; - long l2, l3, l4, l5; - - s1 = rb_reg_nth_match(1, m); - s2 = rb_reg_nth_match(2, m); - s3 = rb_reg_nth_match(3, m); - s4 = rb_reg_nth_match(4, m); - s5 = rb_reg_nth_match(5, m); - - cs2 = RSTRING_PTR(s2); - l2 = RSTRING_LEN(s2); - - switch (l2) { - case 2: - if (NIL_P(s3) && !NIL_P(s4)) - set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2))); - else - set_hash("mday", INT2FIX(n2i(cs2, 0, 2))); - break; - case 4: - if (NIL_P(s3) && !NIL_P(s4)) { - set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2))); - set_hash("min", INT2FIX(n2i(cs2, l2-4, 2))); - } - else { - set_hash("mon", INT2FIX(n2i(cs2, 0, 2))); - set_hash("mday", INT2FIX(n2i(cs2, 2, 2))); - } - break; - case 6: - if (NIL_P(s3) && !NIL_P(s4)) { - set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2))); - set_hash("min", INT2FIX(n2i(cs2, l2-4, 2))); - set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2))); - } - else { - int y = n2i(cs2, 0, 2); - if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-') - y = -y; - set_hash("year", INT2FIX(y)); - set_hash("mon", INT2FIX(n2i(cs2, 2, 2))); - set_hash("mday", INT2FIX(n2i(cs2, 4, 2))); - } - break; - case 8: - case 10: - case 12: - case 14: - if (NIL_P(s3) && !NIL_P(s4)) { - set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2))); - set_hash("min", INT2FIX(n2i(cs2, l2-4, 2))); - set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2))); - set_hash("mday", INT2FIX(n2i(cs2, l2-8, 2))); - if (l2 >= 10) - set_hash("mon", INT2FIX(n2i(cs2, l2-10, 2))); - if (l2 == 12) { - int y = n2i(cs2, l2-12, 2); - if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-') - y = -y; - set_hash("year", INT2FIX(y)); - } - if (l2 == 14) { - int y = n2i(cs2, l2-14, 4); - if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-') - y = -y; - set_hash("year", INT2FIX(y)); - set_hash("_comp", Qfalse); - } - } - else { - int y = n2i(cs2, 0, 4); - if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-') - y = -y; - set_hash("year", INT2FIX(y)); - set_hash("mon", INT2FIX(n2i(cs2, 4, 2))); - set_hash("mday", INT2FIX(n2i(cs2, 6, 2))); - if (l2 >= 10) - set_hash("hour", INT2FIX(n2i(cs2, 8, 2))); - if (l2 >= 12) - set_hash("min", INT2FIX(n2i(cs2, 10, 2))); - if (l2 >= 14) - set_hash("sec", INT2FIX(n2i(cs2, 12, 2))); - set_hash("_comp", Qfalse); - } - break; - case 3: - if (NIL_P(s3) && !NIL_P(s4)) { - set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2))); - set_hash("min", INT2FIX(n2i(cs2, l2-3, 1))); - } - else - set_hash("yday", INT2FIX(n2i(cs2, 0, 3))); - break; - case 5: - if (NIL_P(s3) && !NIL_P(s4)) { - set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2))); - set_hash("min", INT2FIX(n2i(cs2, l2-4, 2))); - set_hash("hour", INT2FIX(n2i(cs2, l2-5, 1))); - } - else { - int y = n2i(cs2, 0, 2); - if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-') - y = -y; - set_hash("year", INT2FIX(y)); - set_hash("yday", INT2FIX(n2i(cs2, 2, 3))); - } - break; - case 7: - if (NIL_P(s3) && !NIL_P(s4)) { - set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2))); - set_hash("min", INT2FIX(n2i(cs2, l2-4, 2))); - set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2))); - set_hash("mday", INT2FIX(n2i(cs2, l2-7, 1))); - } - else { - int y = n2i(cs2, 0, 4); - if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-') - y = -y; - set_hash("year", INT2FIX(y)); - set_hash("yday", INT2FIX(n2i(cs2, 4, 3))); - } - break; - } - RB_GC_GUARD(s2); - if (!NIL_P(s3)) { - cs3 = RSTRING_PTR(s3); - l3 = RSTRING_LEN(s3); - - if (!NIL_P(s4)) { - switch (l3) { - case 2: - case 4: - case 6: - set_hash("sec", INT2FIX(n2i(cs3, l3-2, 2))); - if (l3 >= 4) - set_hash("min", INT2FIX(n2i(cs3, l3-4, 2))); - if (l3 >= 6) - set_hash("hour", INT2FIX(n2i(cs3, l3-6, 2))); - break; - } - } - else { - switch (l3) { - case 2: - case 4: - case 6: - set_hash("hour", INT2FIX(n2i(cs3, 0, 2))); - if (l3 >= 4) - set_hash("min", INT2FIX(n2i(cs3, 2, 2))); - if (l3 >= 6) - set_hash("sec", INT2FIX(n2i(cs3, 4, 2))); - break; - } - } - RB_GC_GUARD(s3); - } - if (!NIL_P(s4)) { - l4 = RSTRING_LEN(s4); - - set_hash("sec_fraction", - rb_rational_new2(str2num(s4), - f_expt(INT2FIX(10), LONG2NUM(l4)))); - } - if (!NIL_P(s5)) { - cs5 = RSTRING_PTR(s5); - l5 = RSTRING_LEN(s5); - - set_hash("zone", s5); - - if (*cs5 == '[') { - char *buf = ALLOCA_N(char, l5 + 1); - char *s1, *s2, *s3; - VALUE zone; - - memcpy(buf, cs5, l5); - buf[l5 - 1] = '\0'; - - s1 = buf + 1; - s2 = strchr(buf, ':'); - if (s2) { - *s2 = '\0'; - s2++; - } - if (s2) - s3 = s2; - else - s3 = s1; - zone = rb_str_new2(s3); - set_hash("zone", zone); - if (isdigit(*s1)) - *--s1 = '+'; - set_hash("offset", date_zone_to_diff(rb_str_new2(s1))); - } - RB_GC_GUARD(s5); - } - - return 1; -} - -static int -parse_ddd(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "([-+]?)(\\d{2,14})" - "(?:" - "\\s*" - "t?" - "\\s*" - "(\\d{2,6})?(?:[,.](\\d*))?" - ")?" - "(?:" - "\\s*" - "(" - "z\\b" - "|" - "[-+]\\d{1,4}\\b" - "|" - "\\[[-+]?\\d[^\\]]*\\]" - ")" - ")?"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_ddd_cb); -} - -static int -parse_bc_cb(VALUE m, VALUE hash) -{ - VALUE y; - - y = ref_hash("year"); - if (!NIL_P(y)) - set_hash("year", f_add(f_negate(y), INT2FIX(1))); - - return 1; -} - -static int -parse_bc(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\b(bc\\b|bce\\b|b\\.c\\.|b\\.c\\.e\\.)"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_bc_cb); -} - -static int -parse_frag_cb(VALUE m, VALUE hash) -{ - VALUE s, n; - - s = rb_reg_nth_match(1, m); - - if (!NIL_P(ref_hash("hour")) && NIL_P(ref_hash("mday"))) { - n = str2num(s); - if (f_ge_p(n, INT2FIX(1)) && - f_le_p(n, INT2FIX(31))) - set_hash("mday", n); - } - if (!NIL_P(ref_hash("mday")) && NIL_P(ref_hash("hour"))) { - n = str2num(s); - if (f_ge_p(n, INT2FIX(0)) && - f_le_p(n, INT2FIX(24))) - set_hash("hour", n); - } - - return 1; -} - -static int -parse_frag(VALUE str, VALUE hash) -{ - static const char pat_source[] = "\\A\\s*(\\d{1,2})\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_frag_cb); -} - -#define HAVE_ALPHA (1<<0) -#define HAVE_DIGIT (1<<1) -#define HAVE_DASH (1<<2) -#define HAVE_DOT (1<<3) -#define HAVE_SLASH (1<<4) - -static unsigned -check_class(VALUE s) -{ - unsigned flags; - long i; - - flags = 0; - for (i = 0; i < RSTRING_LEN(s); i++) { - if (isalpha(RSTRING_PTR(s)[i])) - flags |= HAVE_ALPHA; - if (isdigit(RSTRING_PTR(s)[i])) - flags |= HAVE_DIGIT; - if (RSTRING_PTR(s)[i] == '-') - flags |= HAVE_DASH; - if (RSTRING_PTR(s)[i] == '.') - flags |= HAVE_DOT; - if (RSTRING_PTR(s)[i] == '/') - flags |= HAVE_SLASH; - } - return flags; -} - -#define HAVE_ELEM_P(x) ((check_class(str) & (x)) == (x)) - -VALUE -date__parse(VALUE str, VALUE comp) -{ - VALUE backref, hash; - - backref = rb_backref_get(); - rb_match_busy(backref); - - { - static const char pat_source[] = "[^-+',./:@[:alnum:]\\[\\]]+"; - static VALUE pat = Qnil; - - REGCOMP_0(pat); - str = rb_str_dup(str); - f_gsub_bang(str, pat, asp_string()); - } - - hash = rb_hash_new(); - set_hash("_comp", comp); - - if (HAVE_ELEM_P(HAVE_ALPHA)) - parse_day(str, hash); - if (HAVE_ELEM_P(HAVE_DIGIT)) - parse_time(str, hash); - - if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT)) - if (parse_eu(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT)) - if (parse_us(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DASH)) - if (parse_iso(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DOT)) - if (parse_jis(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT|HAVE_DASH)) - if (parse_vms(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_SLASH)) - if (parse_sla(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DOT)) - if (parse_dot(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_DIGIT)) - if (parse_iso2(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_DIGIT)) - if (parse_year(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_ALPHA)) - if (parse_mon(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_DIGIT)) - if (parse_mday(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_DIGIT)) - if (parse_ddd(str, hash)) - goto ok; - - ok: - if (HAVE_ELEM_P(HAVE_ALPHA)) - parse_bc(str, hash); - if (HAVE_ELEM_P(HAVE_DIGIT)) - parse_frag(str, hash); - - { - if (RTEST(ref_hash("_comp"))) { - VALUE y; - - y = ref_hash("cwyear"); - if (!NIL_P(y)) - if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) { - if (f_ge_p(y, INT2FIX(69))) - set_hash("cwyear", f_add(y, INT2FIX(1900))); - else - set_hash("cwyear", f_add(y, INT2FIX(2000))); - } - y = ref_hash("year"); - if (!NIL_P(y)) - if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) { - if (f_ge_p(y, INT2FIX(69))) - set_hash("year", f_add(y, INT2FIX(1900))); - else - set_hash("year", f_add(y, INT2FIX(2000))); - } - } - } - - del_hash("_comp"); - - { - VALUE zone = ref_hash("zone"); - if (!NIL_P(zone) && NIL_P(ref_hash("offset"))) - set_hash("offset", date_zone_to_diff(zone)); - } - - rb_backref_set(backref); - - return hash; -} - -static VALUE -comp_year69(VALUE y) -{ - if (f_ge_p(y, INT2FIX(69))) - return f_add(y, INT2FIX(1900)); - return f_add(y, INT2FIX(2000)); -} - -static VALUE -comp_year50(VALUE y) -{ - if (f_ge_p(y, INT2FIX(50))) - return f_add(y, INT2FIX(1900)); - return f_add(y, INT2FIX(2000)); -} - -static VALUE -sec_fraction(VALUE f) -{ - return rb_rational_new2(str2num(f), - f_expt(INT2FIX(10), - LONG2NUM(RSTRING_LEN(f)))); -} - -#define SNUM 14 - -static int -iso8601_ext_datetime_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1], y; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - if (!NIL_P(s[3])) { - set_hash("mday", str2num(s[3])); - if (strcmp(RSTRING_PTR(s[1]), "-") != 0) { - y = str2num(s[1]); - if (RSTRING_LEN(s[1]) < 4) - y = comp_year69(y); - set_hash("year", y); - } - if (NIL_P(s[2])) { - if (strcmp(RSTRING_PTR(s[1]), "-") != 0) - return 0; - } - else - set_hash("mon", str2num(s[2])); - } - else if (!NIL_P(s[5])) { - set_hash("yday", str2num(s[5])); - if (!NIL_P(s[4])) { - y = str2num(s[4]); - if (RSTRING_LEN(s[4]) < 4) - y = comp_year69(y); - set_hash("year", y); - } - } - else if (!NIL_P(s[8])) { - set_hash("cweek", str2num(s[7])); - set_hash("cwday", str2num(s[8])); - if (!NIL_P(s[6])) { - y = str2num(s[6]); - if (RSTRING_LEN(s[6]) < 4) - y = comp_year69(y); - set_hash("cwyear", y); - } - } - else if (!NIL_P(s[9])) { - set_hash("cwday", str2num(s[9])); - } - if (!NIL_P(s[10])) { - set_hash("hour", str2num(s[10])); - set_hash("min", str2num(s[11])); - if (!NIL_P(s[12])) - set_hash("sec", str2num(s[12])); - } - if (!NIL_P(s[13])) { - set_hash("sec_fraction", sec_fraction(s[13])); - } - if (!NIL_P(s[14])) { - set_hash("zone", s[14]); - set_hash("offset", date_zone_to_diff(s[14])); - } - - return 1; -} - -static int -iso8601_ext_datetime(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(?:([-+]?\\d{2,}|-)-(\\d{2})?-(\\d{2})|" - "([-+]?\\d{2,})?-(\\d{3})|" - "(\\d{4}|\\d{2})?-w(\\d{2})-(\\d)|" - "-w-(\\d))" - "(?:t" - "(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?)?" - "(z|[-+]\\d{2}(?::?\\d{2})?)?)?\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, iso8601_ext_datetime_cb); -} - -#undef SNUM -#define SNUM 17 - -static int -iso8601_bas_datetime_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1], y; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - if (!NIL_P(s[3])) { - set_hash("mday", str2num(s[3])); - if (strcmp(RSTRING_PTR(s[1]), "--") != 0) { - y = str2num(s[1]); - if (RSTRING_LEN(s[1]) < 4) - y = comp_year69(y); - set_hash("year", y); - } - if (*RSTRING_PTR(s[2]) == '-') { - if (strcmp(RSTRING_PTR(s[1]), "--") != 0) - return 0; - } - else - set_hash("mon", str2num(s[2])); - } - else if (!NIL_P(s[5])) { - set_hash("yday", str2num(s[5])); - y = str2num(s[4]); - if (RSTRING_LEN(s[4]) < 4) - y = comp_year69(y); - set_hash("year", y); - } - else if (!NIL_P(s[6])) { - set_hash("yday", str2num(s[6])); - } - else if (!NIL_P(s[9])) { - set_hash("cweek", str2num(s[8])); - set_hash("cwday", str2num(s[9])); - y = str2num(s[7]); - if (RSTRING_LEN(s[7]) < 4) - y = comp_year69(y); - set_hash("cwyear", y); - } - else if (!NIL_P(s[11])) { - set_hash("cweek", str2num(s[10])); - set_hash("cwday", str2num(s[11])); - } - else if (!NIL_P(s[12])) { - set_hash("cwday", str2num(s[12])); - } - if (!NIL_P(s[13])) { - set_hash("hour", str2num(s[13])); - set_hash("min", str2num(s[14])); - if (!NIL_P(s[15])) - set_hash("sec", str2num(s[15])); - } - if (!NIL_P(s[16])) { - set_hash("sec_fraction", sec_fraction(s[16])); - } - if (!NIL_P(s[17])) { - set_hash("zone", s[17]); - set_hash("offset", date_zone_to_diff(s[17])); - } - - return 1; -} - -static int -iso8601_bas_datetime(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(?:([-+]?(?:\\d{4}|\\d{2})|--)(\\d{2}|-)(\\d{2})|" - "([-+]?(?:\\d{4}|\\d{2}))(\\d{3})|" - "-(\\d{3})|" - "(\\d{4}|\\d{2})w(\\d{2})(\\d)|" - "-w(\\d{2})(\\d)|" - "-w-(\\d))" - "(?:t?" - "(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?)?" - "(z|[-+]\\d{2}(?:\\d{2})?)?)?\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, iso8601_bas_datetime_cb); -} - -#undef SNUM -#define SNUM 5 - -static int -iso8601_ext_time_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1]; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - set_hash("hour", str2num(s[1])); - set_hash("min", str2num(s[2])); - if (!NIL_P(s[3])) - set_hash("sec", str2num(s[3])); - if (!NIL_P(s[4])) - set_hash("sec_fraction", sec_fraction(s[4])); - if (!NIL_P(s[5])) { - set_hash("zone", s[5]); - set_hash("offset", date_zone_to_diff(s[5])); - } - - return 1; -} - -#define iso8601_bas_time_cb iso8601_ext_time_cb - -static int -iso8601_ext_time(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(?:(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?)?" - "(z|[-+]\\d{2}(:?\\d{2})?)?)?\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, iso8601_ext_time_cb); -} - -static int -iso8601_bas_time(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(?:(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?)?" - "(z|[-+]\\d{2}(\\d{2})?)?)?\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, iso8601_bas_time_cb); -} - -VALUE -date__iso8601(VALUE str) -{ - VALUE backref, hash; - - backref = rb_backref_get(); - rb_match_busy(backref); - - hash = rb_hash_new(); - - if (iso8601_ext_datetime(str, hash)) - goto ok; - if (iso8601_bas_datetime(str, hash)) - goto ok; - if (iso8601_ext_time(str, hash)) - goto ok; - if (iso8601_bas_time(str, hash)) - goto ok; - - ok: - rb_backref_set(backref); - - return hash; -} - -#undef SNUM -#define SNUM 8 - -static int -rfc3339_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1]; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - set_hash("year", str2num(s[1])); - set_hash("mon", str2num(s[2])); - set_hash("mday", str2num(s[3])); - set_hash("hour", str2num(s[4])); - set_hash("min", str2num(s[5])); - set_hash("sec", str2num(s[6])); - set_hash("zone", s[8]); - set_hash("offset", date_zone_to_diff(s[8])); - if (!NIL_P(s[7])) - set_hash("sec_fraction", sec_fraction(s[7])); - - return 1; -} - -static int -rfc3339(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(-?\\d{4})-(\\d{2})-(\\d{2})" - "(?:t|\\s)" - "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?" - "(z|[-+]\\d{2}:\\d{2})\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, rfc3339_cb); -} - -VALUE -date__rfc3339(VALUE str) -{ - VALUE backref, hash; - - backref = rb_backref_get(); - rb_match_busy(backref); - - hash = rb_hash_new(); - rfc3339(str, hash); - rb_backref_set(backref); - return hash; -} - -#undef SNUM -#define SNUM 8 - -static int -xmlschema_datetime_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1]; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - set_hash("year", str2num(s[1])); - if (!NIL_P(s[2])) - set_hash("mon", str2num(s[2])); - if (!NIL_P(s[3])) - set_hash("mday", str2num(s[3])); - if (!NIL_P(s[4])) - set_hash("hour", str2num(s[4])); - if (!NIL_P(s[5])) - set_hash("min", str2num(s[5])); - if (!NIL_P(s[6])) - set_hash("sec", str2num(s[6])); - if (!NIL_P(s[7])) - set_hash("sec_fraction", sec_fraction(s[7])); - if (!NIL_P(s[8])) { - set_hash("zone", s[8]); - set_hash("offset", date_zone_to_diff(s[8])); - } - - return 1; -} - -static int -xmlschema_datetime(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(-?\\d{4,})(?:-(\\d{2})(?:-(\\d{2}))?)?" - "(?:t" - "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?)?" - "(z|[-+]\\d{2}:\\d{2})?\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, xmlschema_datetime_cb); -} - -#undef SNUM -#define SNUM 5 - -static int -xmlschema_time_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1]; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - set_hash("hour", str2num(s[1])); - set_hash("min", str2num(s[2])); - if (!NIL_P(s[3])) - set_hash("sec", str2num(s[3])); - if (!NIL_P(s[4])) - set_hash("sec_fraction", sec_fraction(s[4])); - if (!NIL_P(s[5])) { - set_hash("zone", s[5]); - set_hash("offset", date_zone_to_diff(s[5])); - } - - return 1; -} - -static int -xmlschema_time(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?" - "(z|[-+]\\d{2}:\\d{2})?\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, xmlschema_time_cb); -} - -#undef SNUM -#define SNUM 4 - -static int -xmlschema_trunc_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1]; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - if (!NIL_P(s[1])) - set_hash("mon", str2num(s[1])); - if (!NIL_P(s[2])) - set_hash("mday", str2num(s[2])); - if (!NIL_P(s[3])) - set_hash("mday", str2num(s[3])); - if (!NIL_P(s[4])) { - set_hash("zone", s[4]); - set_hash("offset", date_zone_to_diff(s[4])); - } - - return 1; -} - -static int -xmlschema_trunc(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(?:--(\\d{2})(?:-(\\d{2}))?|---(\\d{2}))" - "(z|[-+]\\d{2}:\\d{2})?\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, xmlschema_trunc_cb); -} - -VALUE -date__xmlschema(VALUE str) -{ - VALUE backref, hash; - - backref = rb_backref_get(); - rb_match_busy(backref); - - hash = rb_hash_new(); - - if (xmlschema_datetime(str, hash)) - goto ok; - if (xmlschema_time(str, hash)) - goto ok; - if (xmlschema_trunc(str, hash)) - goto ok; - - ok: - rb_backref_set(backref); - - return hash; -} - -#undef SNUM -#define SNUM 8 - -static int -rfc2822_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1], y; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - set_hash("wday", INT2FIX(day_num(s[1]))); - set_hash("mday", str2num(s[2])); - set_hash("mon", INT2FIX(mon_num(s[3]))); - y = str2num(s[4]); - if (RSTRING_LEN(s[4]) < 4) - y = comp_year50(y); - set_hash("year", y); - set_hash("hour", str2num(s[5])); - set_hash("min", str2num(s[6])); - if (!NIL_P(s[7])) - set_hash("sec", str2num(s[7])); - set_hash("zone", s[8]); - set_hash("offset", date_zone_to_diff(s[8])); - - return 1; -} - -static int -rfc2822(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(?:(" ABBR_DAYS ")\\s*,\\s+)?" - "(\\d{1,2})\\s+" - "(" ABBR_MONTHS ")\\s+" - "(-?\\d{2,})\\s+" - "(\\d{2}):(\\d{2})(?::(\\d{2}))?\\s*" - "([-+]\\d{4}|ut|gmt|e[sd]t|c[sd]t|m[sd]t|p[sd]t|[a-ik-z])\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, rfc2822_cb); -} - -VALUE -date__rfc2822(VALUE str) -{ - VALUE backref, hash; - - backref = rb_backref_get(); - rb_match_busy(backref); - - hash = rb_hash_new(); - rfc2822(str, hash); - rb_backref_set(backref); - return hash; -} - -#undef SNUM -#define SNUM 8 - -static int -httpdate_type1_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1]; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - set_hash("wday", INT2FIX(day_num(s[1]))); - set_hash("mday", str2num(s[2])); - set_hash("mon", INT2FIX(mon_num(s[3]))); - set_hash("year", str2num(s[4])); - set_hash("hour", str2num(s[5])); - set_hash("min", str2num(s[6])); - set_hash("sec", str2num(s[7])); - set_hash("zone", s[8]); - set_hash("offset", INT2FIX(0)); - - return 1; -} - -static int -httpdate_type1(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(" ABBR_DAYS ")\\s*,\\s+" - "(\\d{2})\\s+" - "(" ABBR_MONTHS ")\\s+" - "(-?\\d{4})\\s+" - "(\\d{2}):(\\d{2}):(\\d{2})\\s+" - "(gmt)\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, httpdate_type1_cb); -} - -#undef SNUM -#define SNUM 8 - -static int -httpdate_type2_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1], y; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - set_hash("wday", INT2FIX(day_num(s[1]))); - set_hash("mday", str2num(s[2])); - set_hash("mon", INT2FIX(mon_num(s[3]))); - y = str2num(s[4]); - if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) - y = comp_year69(y); - set_hash("year", y); - set_hash("hour", str2num(s[5])); - set_hash("min", str2num(s[6])); - set_hash("sec", str2num(s[7])); - set_hash("zone", s[8]); - set_hash("offset", INT2FIX(0)); - - return 1; -} - -static int -httpdate_type2(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(" DAYS ")\\s*,\\s+" - "(\\d{2})\\s*-\\s*" - "(" ABBR_MONTHS ")\\s*-\\s*" - "(\\d{2})\\s+" - "(\\d{2}):(\\d{2}):(\\d{2})\\s+" - "(gmt)\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, httpdate_type2_cb); -} - -#undef SNUM -#define SNUM 7 - -static int -httpdate_type3_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1]; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - set_hash("wday", INT2FIX(day_num(s[1]))); - set_hash("mon", INT2FIX(mon_num(s[2]))); - set_hash("mday", str2num(s[3])); - set_hash("hour", str2num(s[4])); - set_hash("min", str2num(s[5])); - set_hash("sec", str2num(s[6])); - set_hash("year", str2num(s[7])); - - return 1; -} - -static int -httpdate_type3(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(" ABBR_DAYS ")\\s+" - "(" ABBR_MONTHS ")\\s+" - "(\\d{1,2})\\s+" - "(\\d{2}):(\\d{2}):(\\d{2})\\s+" - "(\\d{4})\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, httpdate_type3_cb); -} - -VALUE -date__httpdate(VALUE str) -{ - VALUE backref, hash; - - backref = rb_backref_get(); - rb_match_busy(backref); - - hash = rb_hash_new(); - - if (httpdate_type1(str, hash)) - goto ok; - if (httpdate_type2(str, hash)) - goto ok; - if (httpdate_type3(str, hash)) - goto ok; - - ok: - rb_backref_set(backref); - - return hash; -} - -#undef SNUM -#define SNUM 9 - -static int -jisx0301_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1]; - int ep; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - ep = gengo(NIL_P(s[1]) ? 'h' : *RSTRING_PTR(s[1])); - set_hash("year", f_add(str2num(s[2]), INT2FIX(ep))); - set_hash("mon", str2num(s[3])); - set_hash("mday", str2num(s[4])); - if (!NIL_P(s[5])) { - set_hash("hour", str2num(s[5])); - if (!NIL_P(s[6])) - set_hash("min", str2num(s[6])); - if (!NIL_P(s[7])) - set_hash("sec", str2num(s[7])); - } - if (!NIL_P(s[8])) - set_hash("sec_fraction", sec_fraction(s[8])); - if (!NIL_P(s[9])) { - set_hash("zone", s[9]); - set_hash("offset", date_zone_to_diff(s[9])); - } - - return 1; -} - -static int -jisx0301(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*([mtsh])?(\\d{2})\\.(\\d{2})\\.(\\d{2})" - "(?:t" - "(?:(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d*))?)?" - "(z|[-+]\\d{2}(?::?\\d{2})?)?)?)?\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, jisx0301_cb); -} - -VALUE -date__jisx0301(VALUE str) -{ - VALUE backref, hash; - - backref = rb_backref_get(); - rb_match_busy(backref); - - hash = rb_hash_new(); - if (jisx0301(str, hash)) - goto ok; - hash = date__iso8601(str); - - ok: - rb_backref_set(backref); - return hash; -} - -/* -Local variables: -c-file-style: "ruby" -End: -*/ |