00001
00002
00003
00004
00005 #include "ruby.h"
00006 #include "ruby/encoding.h"
00007 #include "ruby/re.h"
00008 #include <ctype.h>
00009
00010 #define sizeof_array(o) (sizeof o / sizeof o[0])
00011
00012 #define f_negate(x) rb_funcall(x, rb_intern("-@"), 0)
00013 #define f_add(x,y) rb_funcall(x, '+', 1, y)
00014 #define f_sub(x,y) rb_funcall(x, '-', 1, y)
00015 #define f_mul(x,y) rb_funcall(x, '*', 1, y)
00016 #define f_div(x,y) rb_funcall(x, '/', 1, y)
00017 #define f_idiv(x,y) rb_funcall(x, rb_intern("div"), 1, y)
00018 #define f_mod(x,y) rb_funcall(x, '%', 1, y)
00019 #define f_expt(x,y) rb_funcall(x, rb_intern("**"), 1, y)
00020
00021 #define f_lt_p(x,y) rb_funcall(x, '<', 1, y)
00022 #define f_gt_p(x,y) rb_funcall(x, '>', 1, y)
00023 #define f_le_p(x,y) rb_funcall(x, rb_intern("<="), 1, y)
00024 #define f_ge_p(x,y) rb_funcall(x, rb_intern(">="), 1, y)
00025
00026 #define f_to_s(x) rb_funcall(x, rb_intern("to_s"), 0)
00027
00028 #define f_match(r,s) rb_funcall(r, rb_intern("match"), 1, s)
00029 #define f_aref(o,i) rb_funcall(o, rb_intern("[]"), 1, i)
00030 #define f_aref2(o,i,j) rb_funcall(o, rb_intern("[]"), 2, i, j)
00031 #define f_begin(o,i) rb_funcall(o, rb_intern("begin"), 1, i)
00032 #define f_end(o,i) rb_funcall(o, rb_intern("end"), 1, i)
00033 #define f_aset(o,i,v) rb_funcall(o, rb_intern("[]="), 2, i, v)
00034 #define f_aset2(o,i,j,v) rb_funcall(o, rb_intern("[]="), 3, i, j, v)
00035 #define f_sub_bang(s,r,x) rb_funcall(s, rb_intern("sub!"), 2, r, x)
00036 #define f_gsub_bang(s,r,x) rb_funcall(s, rb_intern("gsub!"), 2, r, x)
00037
00038 #define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k)), v)
00039 #define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k)))
00040 #define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k)))
00041
00042 #define cstr2num(s) rb_cstr_to_inum(s, 10, 0)
00043 #define str2num(s) rb_str_to_inum(s, 10, 0)
00044
00045 static const char *abbr_days[] = {
00046 "sun", "mon", "tue", "wed",
00047 "thu", "fri", "sat"
00048 };
00049
00050 static const char *abbr_months[] = {
00051 "jan", "feb", "mar", "apr", "may", "jun",
00052 "jul", "aug", "sep", "oct", "nov", "dec"
00053 };
00054
00055 #define issign(c) ((c) == '-' || (c) == '+')
00056 #define asp_string() rb_str_new(" ", 1)
00057
00058 static void
00059 s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
00060 {
00061 VALUE c = Qnil;
00062
00063 if (TYPE(m) != T_STRING)
00064 m = f_to_s(m);
00065
00066 if (!NIL_P(y) && !NIL_P(m) && NIL_P(d)) {
00067 VALUE oy = y;
00068 VALUE om = m;
00069 VALUE od = d;
00070
00071 y = od;
00072 m = oy;
00073 d = om;
00074 }
00075
00076 if (NIL_P(y)) {
00077 if (!NIL_P(d) && RSTRING_LEN(d) > 2) {
00078 y = d;
00079 d = Qnil;
00080 }
00081 if (!NIL_P(d) && *RSTRING_PTR(d) == '\'') {
00082 y = d;
00083 d = Qnil;
00084 }
00085 }
00086
00087 if (!NIL_P(y)) {
00088 const char *s, *bp, *ep;
00089 size_t l;
00090
00091 s = RSTRING_PTR(y);
00092 while (!issign(*s) && !isdigit(*s))
00093 s++;
00094 bp = s;
00095 if (issign(*s))
00096 s++;
00097 l = strspn(s, "0123456789");
00098 ep = s + l;
00099 if (*ep) {
00100 y = d;
00101 d = rb_str_new(bp, ep - bp);
00102 }
00103 }
00104
00105 if (!NIL_P(m)) {
00106 const char *s;
00107
00108 s = RSTRING_PTR(m);
00109 if (*s == '\'' || RSTRING_LEN(m) > 2) {
00110
00111 VALUE oy = y;
00112 VALUE om = m;
00113 VALUE od = d;
00114
00115 y = om;
00116 m = od;
00117 d = oy;
00118 }
00119 }
00120
00121 if (!NIL_P(d)) {
00122 const char *s;
00123
00124 s = RSTRING_PTR(d);
00125 if (*s == '\'' || RSTRING_LEN(d) > 2) {
00126 VALUE oy = y;
00127 VALUE od = d;
00128
00129 y = od;
00130 d = oy;
00131 }
00132 }
00133
00134 if (!NIL_P(y)) {
00135 const char *s, *bp, *ep;
00136 int sign = 0;
00137 size_t l;
00138 VALUE iy;
00139
00140 s = RSTRING_PTR(y);
00141 while (!issign(*s) && !isdigit(*s))
00142 s++;
00143 bp = s;
00144 if (issign(*s)) {
00145 s++;
00146 sign = 1;
00147 }
00148 if (sign)
00149 c = Qfalse;
00150 l = strspn(s, "0123456789");
00151 ep = s + l;
00152 if (l > 2)
00153 c = Qfalse;
00154 {
00155 char *buf;
00156
00157 buf = ALLOCA_N(char, ep - bp + 1);
00158 memcpy(buf, bp, ep - bp);
00159 buf[ep - bp] = '\0';
00160 iy = cstr2num(buf);
00161 }
00162 if (bc)
00163 iy = f_add(f_negate(iy), INT2FIX(1));
00164 set_hash("year", iy);
00165 }
00166
00167 if (!NIL_P(m)) {
00168 const char *s, *bp, *ep;
00169 size_t l;
00170 VALUE im;
00171
00172 s = RSTRING_PTR(m);
00173 while (!isdigit(*s))
00174 s++;
00175 bp = s;
00176 l = strspn(s, "0123456789");
00177 ep = s + l;
00178 {
00179 char *buf;
00180
00181 buf = ALLOCA_N(char, ep - bp + 1);
00182 memcpy(buf, bp, ep - bp);
00183 buf[ep - bp] = '\0';
00184 im = cstr2num(buf);
00185 }
00186 set_hash("mon", im);
00187 }
00188
00189 if (!NIL_P(d)) {
00190 const char *s, *bp, *ep;
00191 size_t l;
00192 VALUE id;
00193
00194 s = RSTRING_PTR(d);
00195 while (!isdigit(*s))
00196 s++;
00197 bp = s;
00198 l = strspn(s, "0123456789");
00199 ep = s + l;
00200 {
00201 char *buf;
00202
00203 buf = ALLOCA_N(char, ep - bp + 1);
00204 memcpy(buf, bp, ep - bp);
00205 buf[ep - bp] = '\0';
00206 id = cstr2num(buf);
00207 }
00208 set_hash("mday", id);
00209 }
00210
00211 if (!NIL_P(c))
00212 set_hash("_comp", c);
00213 }
00214
00215 #define DAYS "sunday|monday|tuesday|wednesday|thursday|friday|saturday"
00216 #define MONTHS "january|february|march|april|may|june|july|august|september|october|november|december"
00217 #define ABBR_DAYS "sun|mon|tue|wed|thu|fri|sat"
00218 #define ABBR_MONTHS "jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec"
00219
00220 static VALUE
00221 regcomp(const char *source, long len, int opt)
00222 {
00223 VALUE pat;
00224
00225 pat = rb_reg_new(source, len, opt);
00226 rb_gc_register_mark_object(pat);
00227 return pat;
00228 }
00229
00230 #define REGCOMP(pat,opt) \
00231 { \
00232 if (NIL_P(pat)) \
00233 pat = regcomp(pat##_source, sizeof pat##_source - 1, opt); \
00234 }
00235
00236 #define REGCOMP_0(pat) REGCOMP(pat, 0)
00237 #define REGCOMP_I(pat) REGCOMP(pat, ONIG_OPTION_IGNORECASE)
00238
00239 #define MATCH(s,p,c) \
00240 { \
00241 return match(s, p, hash, c); \
00242 }
00243
00244 static int
00245 match(VALUE str, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE))
00246 {
00247 VALUE m;
00248
00249 m = f_match(pat, str);
00250
00251 if (NIL_P(m))
00252 return 0;
00253
00254 (*cb)(m, hash);
00255
00256 return 1;
00257 }
00258
00259 #define SUBS(s,p,c) \
00260 { \
00261 return subs(s, p, hash, c); \
00262 }
00263
00264 static int
00265 subs(VALUE str, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE))
00266 {
00267 VALUE m;
00268
00269 m = f_match(pat, str);
00270
00271 if (NIL_P(m))
00272 return 0;
00273
00274 {
00275 VALUE be, en;
00276
00277 be = f_begin(m, INT2FIX(0));
00278 en = f_end(m, INT2FIX(0));
00279 f_aset2(str, be, LONG2NUM(NUM2LONG(en) - NUM2LONG(be)), asp_string());
00280 (*cb)(m, hash);
00281 }
00282
00283 return 1;
00284 }
00285
00286 struct zone {
00287 const char *name;
00288 int offset;
00289 };
00290
00291 static struct zone zones_source[] = {
00292 {"ut", 0*3600}, {"gmt", 0*3600}, {"est", -5*3600}, {"edt", -4*3600},
00293 {"cst", -6*3600}, {"cdt", -5*3600}, {"mst", -7*3600}, {"mdt", -6*3600},
00294 {"pst", -8*3600}, {"pdt", -7*3600},
00295 {"a", 1*3600}, {"b", 2*3600}, {"c", 3*3600}, {"d", 4*3600},
00296 {"e", 5*3600}, {"f", 6*3600}, {"g", 7*3600}, {"h", 8*3600},
00297 {"i", 9*3600}, {"k", 10*3600}, {"l", 11*3600}, {"m", 12*3600},
00298 {"n", -1*3600}, {"o", -2*3600}, {"p", -3*3600}, {"q", -4*3600},
00299 {"r", -5*3600}, {"s", -6*3600}, {"t", -7*3600}, {"u", -8*3600},
00300 {"v", -9*3600}, {"w", -10*3600}, {"x", -11*3600}, {"y", -12*3600},
00301 {"z", 0*3600},
00302
00303 {"utc", 0*3600}, {"wet", 0*3600},
00304 {"at", -2*3600}, {"brst",-2*3600}, {"ndt", -(2*3600+1800)},
00305 {"art", -3*3600}, {"adt", -3*3600}, {"brt", -3*3600}, {"clst",-3*3600},
00306 {"nst", -(3*3600+1800)},
00307 {"ast", -4*3600}, {"clt", -4*3600},
00308 {"akdt",-8*3600}, {"ydt", -8*3600},
00309 {"akst",-9*3600}, {"hadt",-9*3600}, {"hdt", -9*3600}, {"yst", -9*3600},
00310 {"ahst",-10*3600},{"cat",-10*3600}, {"hast",-10*3600},{"hst",-10*3600},
00311 {"nt", -11*3600},
00312 {"idlw",-12*3600},
00313 {"bst", 1*3600}, {"cet", 1*3600}, {"fwt", 1*3600}, {"met", 1*3600},
00314 {"mewt", 1*3600}, {"mez", 1*3600}, {"swt", 1*3600}, {"wat", 1*3600},
00315 {"west", 1*3600},
00316 {"cest", 2*3600}, {"eet", 2*3600}, {"fst", 2*3600}, {"mest", 2*3600},
00317 {"mesz", 2*3600}, {"sast", 2*3600}, {"sst", 2*3600},
00318 {"bt", 3*3600}, {"eat", 3*3600}, {"eest", 3*3600}, {"msk", 3*3600},
00319 {"msd", 4*3600}, {"zp4", 4*3600},
00320 {"zp5", 5*3600}, {"ist", (5*3600+1800)},
00321 {"zp6", 6*3600},
00322 {"wast", 7*3600},
00323 {"cct", 8*3600}, {"sgt", 8*3600}, {"wadt", 8*3600},
00324 {"jst", 9*3600}, {"kst", 9*3600},
00325 {"east",10*3600}, {"gst", 10*3600},
00326 {"eadt",11*3600},
00327 {"idle",12*3600}, {"nzst",12*3600}, {"nzt", 12*3600},
00328 {"nzdt",13*3600},
00329
00330 {"afghanistan", 16200}, {"alaskan", -32400},
00331 {"arab", 10800}, {"arabian", 14400},
00332 {"arabic", 10800}, {"atlantic", -14400},
00333 {"aus central", 34200}, {"aus eastern", 36000},
00334 {"azores", -3600}, {"canada central", -21600},
00335 {"cape verde", -3600}, {"caucasus", 14400},
00336 {"cen. australia", 34200}, {"central america", -21600},
00337 {"central asia", 21600}, {"central europe", 3600},
00338 {"central european", 3600}, {"central pacific", 39600},
00339 {"central", -21600}, {"china", 28800},
00340 {"dateline", -43200}, {"e. africa", 10800},
00341 {"e. australia", 36000}, {"e. europe", 7200},
00342 {"e. south america", -10800}, {"eastern", -18000},
00343 {"egypt", 7200}, {"ekaterinburg", 18000},
00344 {"fiji", 43200}, {"fle", 7200},
00345 {"greenland", -10800}, {"greenwich", 0},
00346 {"gtb", 7200}, {"hawaiian", -36000},
00347 {"india", 19800}, {"iran", 12600},
00348 {"jerusalem", 7200}, {"korea", 32400},
00349 {"mexico", -21600}, {"mid-atlantic", -7200},
00350 {"mountain", -25200}, {"myanmar", 23400},
00351 {"n. central asia", 21600}, {"nepal", 20700},
00352 {"new zealand", 43200}, {"newfoundland", -12600},
00353 {"north asia east", 28800}, {"north asia", 25200},
00354 {"pacific sa", -14400}, {"pacific", -28800},
00355 {"romance", 3600}, {"russian", 10800},
00356 {"sa eastern", -10800}, {"sa pacific", -18000},
00357 {"sa western", -14400}, {"samoa", -39600},
00358 {"se asia", 25200}, {"malay peninsula", 28800},
00359 {"south africa", 7200}, {"sri lanka", 21600},
00360 {"taipei", 28800}, {"tasmania", 36000},
00361 {"tokyo", 32400}, {"tonga", 46800},
00362 {"us eastern", -18000}, {"us mountain", -25200},
00363 {"vladivostok", 36000}, {"w. australia", 28800},
00364 {"w. central africa", 3600}, {"w. europe", 3600},
00365 {"west asia", 18000}, {"west pacific", 36000},
00366 {"yakutsk", 32400}
00367 };
00368
00369 VALUE
00370 date_zone_to_diff(VALUE str)
00371 {
00372 VALUE offset = Qnil;
00373
00374 long l, i;
00375 char *s, *dest, *d;
00376 int sp = 1;
00377
00378 l = RSTRING_LEN(str);
00379 s = RSTRING_PTR(str);
00380
00381 dest = d = ALLOCA_N(char, l + 1);
00382
00383 for (i = 0; i < l; i++) {
00384 if (isspace(s[i]) || s[i] == '\0') {
00385 if (!sp)
00386 *d++ = ' ';
00387 sp = 1;
00388 }
00389 else {
00390 if (isalpha(s[i]))
00391 *d++ = tolower(s[i]);
00392 else
00393 *d++ = s[i];
00394 sp = 0;
00395 }
00396 }
00397 if (d > dest) {
00398 if (*(d - 1) == ' ')
00399 --d;
00400 *d = '\0';
00401 }
00402 str = rb_str_new2(dest);
00403 {
00404 #define STD " standard time"
00405 #define DST " daylight time"
00406 char *ss, *ds;
00407 long sl, dl;
00408 int dst = 0;
00409
00410 sl = RSTRING_LEN(str) - (sizeof STD - 1);
00411 ss = RSTRING_PTR(str) + sl;
00412 dl = RSTRING_LEN(str) - (sizeof DST - 1);
00413 ds = RSTRING_PTR(str) + dl;
00414
00415 if (sl >= 0 && strcmp(ss, STD) == 0) {
00416 str = rb_str_new(RSTRING_PTR(str), sl);
00417 }
00418 else if (dl >= 0 && strcmp(ds, DST) == 0) {
00419 str = rb_str_new(RSTRING_PTR(str), dl);
00420 dst = 1;
00421 }
00422 #undef STD
00423 #undef DST
00424 else {
00425 #define DST " dst"
00426 char *ds;
00427 long dl;
00428
00429 dl = RSTRING_LEN(str) - (sizeof DST - 1);
00430 ds = RSTRING_PTR(str) + dl;
00431
00432 if (dl >= 0 && strcmp(ds, DST) == 0) {
00433 str = rb_str_new(RSTRING_PTR(str), dl);
00434 dst = 1;
00435 }
00436 #undef DST
00437 }
00438 {
00439 static VALUE zones = Qnil;
00440
00441 if (NIL_P(zones)) {
00442 int i;
00443
00444 zones = rb_hash_new();
00445 rb_gc_register_mark_object(zones);
00446 for (i = 0; i < (int)sizeof_array(zones_source); i++) {
00447 VALUE name = rb_str_new2(zones_source[i].name);
00448 VALUE offset = INT2FIX(zones_source[i].offset);
00449 rb_hash_aset(zones, name, offset);
00450 }
00451 }
00452
00453 offset = f_aref(zones, str);
00454 if (!NIL_P(offset)) {
00455 if (dst)
00456 offset = f_add(offset, INT2FIX(3600));
00457 goto ok;
00458 }
00459 }
00460 {
00461 char *s, *p;
00462 VALUE sign;
00463 VALUE hour = Qnil, min = Qnil, sec = Qnil;
00464 VALUE str_orig;
00465
00466 s = RSTRING_PTR(str);
00467 str_orig = str;
00468
00469 if (strncmp(s, "gmt", 3) == 0 ||
00470 strncmp(s, "utc", 3) == 0)
00471 s += 3;
00472 if (issign(*s)) {
00473 sign = rb_str_new(s, 1);
00474 s++;
00475
00476 str = rb_str_new2(s);
00477
00478 if (p = strchr(s, ':')) {
00479 hour = rb_str_new(s, p - s);
00480 s = ++p;
00481 if (p = strchr(s, ':')) {
00482 min = rb_str_new(s, p - s);
00483 s = ++p;
00484 if (p = strchr(s, ':')) {
00485 sec = rb_str_new(s, p - s);
00486 }
00487 else
00488 sec = rb_str_new2(s);
00489 }
00490 else
00491 min = rb_str_new2(s);
00492 RB_GC_GUARD(str_orig);
00493 goto num;
00494 }
00495 if (strpbrk(RSTRING_PTR(str), ",.")) {
00496 char *a, *b;
00497
00498 a = ALLOCA_N(char, RSTRING_LEN(str) + 1);
00499 strcpy(a, RSTRING_PTR(str));
00500 b = strpbrk(a, ",.");
00501 *b = '\0';
00502 b++;
00503
00504 hour = cstr2num(a);
00505 min = f_mul(rb_rational_new2
00506 (cstr2num(b),
00507 f_expt(INT2FIX(10),
00508 LONG2NUM((long)strlen(b)))),
00509 INT2FIX(60));
00510 goto num;
00511 }
00512 {
00513 const char *cs = RSTRING_PTR(str);
00514 long cl = RSTRING_LEN(str);
00515
00516 if (cl % 2) {
00517 if (cl >= 1)
00518 hour = rb_str_new(&cs[0], 1);
00519 if (cl >= 3)
00520 min = rb_str_new(&cs[1], 2);
00521 if (cl >= 5)
00522 min = rb_str_new(&cs[3], 2);
00523 }
00524 else {
00525 if (cl >= 2)
00526 hour = rb_str_new(&cs[0], 2);
00527 if (cl >= 4)
00528 min = rb_str_new(&cs[2], 2);
00529 if (cl >= 6)
00530 sec = rb_str_new(&cs[4], 2);
00531 }
00532 goto num;
00533 }
00534 num:
00535 if (NIL_P(hour))
00536 offset = INT2FIX(0);
00537 else {
00538 if (TYPE(hour) == T_STRING)
00539 hour = str2num(hour);
00540 offset = f_mul(hour, INT2FIX(3600));
00541 }
00542 if (!NIL_P(min)) {
00543 if (TYPE(min) == T_STRING)
00544 min = str2num(min);
00545 offset = f_add(offset, f_mul(min, INT2FIX(60)));
00546 }
00547 if (!NIL_P(sec))
00548 offset = f_add(offset, str2num(sec));
00549 if (!NIL_P(sign) &&
00550 RSTRING_LEN(sign) == 1 &&
00551 *RSTRING_PTR(sign) == '-')
00552 offset = f_negate(offset);
00553 }
00554 }
00555 }
00556 RB_GC_GUARD(str);
00557 ok:
00558 return offset;
00559 }
00560
00561 static int
00562 day_num(VALUE s)
00563 {
00564 int i;
00565
00566 for (i = 0; i < (int)sizeof_array(abbr_days); i++)
00567 if (strncasecmp(abbr_days[i], RSTRING_PTR(s), 3) == 0)
00568 break;
00569 return i;
00570 }
00571
00572 static int
00573 mon_num(VALUE s)
00574 {
00575 int i;
00576
00577 for (i = 0; i < (int)sizeof_array(abbr_months); i++)
00578 if (strncasecmp(abbr_months[i], RSTRING_PTR(s), 3) == 0)
00579 break;
00580 return i + 1;
00581 }
00582
00583 static int
00584 parse_day_cb(VALUE m, VALUE hash)
00585 {
00586 VALUE s;
00587
00588 s = rb_reg_nth_match(1, m);
00589 set_hash("wday", INT2FIX(day_num(s)));
00590 return 1;
00591 }
00592
00593 static int
00594 parse_day(VALUE str, VALUE hash)
00595 {
00596 static const char pat_source[] = "\\b(" ABBR_DAYS ")[^-\\d\\s]*";
00597 static VALUE pat = Qnil;
00598
00599 REGCOMP_I(pat);
00600 SUBS(str, pat, parse_day_cb);
00601 }
00602
00603 static int
00604 parse_time2_cb(VALUE m, VALUE hash)
00605 {
00606 VALUE h, min, s, f, p;
00607
00608 h = rb_reg_nth_match(1, m);
00609 h = str2num(h);
00610
00611 min = rb_reg_nth_match(2, m);
00612 if (!NIL_P(min))
00613 min = str2num(min);
00614
00615 s = rb_reg_nth_match(3, m);
00616 if (!NIL_P(s))
00617 s = str2num(s);
00618
00619 f = rb_reg_nth_match(4, m);
00620
00621 if (!NIL_P(f))
00622 f = rb_rational_new2(str2num(f),
00623 f_expt(INT2FIX(10), LONG2NUM(RSTRING_LEN(f))));
00624
00625 p = rb_reg_nth_match(5, m);
00626
00627 if (!NIL_P(p)) {
00628 int ih = NUM2INT(h);
00629 ih %= 12;
00630 if (*RSTRING_PTR(p) == 'P' || *RSTRING_PTR(p) == 'p')
00631 ih += 12;
00632 h = INT2FIX(ih);
00633 }
00634
00635 set_hash("hour", h);
00636 if (!NIL_P(min))
00637 set_hash("min", min);
00638 if (!NIL_P(s))
00639 set_hash("sec", s);
00640 if (!NIL_P(f))
00641 set_hash("sec_fraction", f);
00642
00643 return 1;
00644 }
00645
00646 static int
00647 parse_time_cb(VALUE m, VALUE hash)
00648 {
00649 static const char pat_source[] =
00650 "\\A(\\d+)h?"
00651 "(?:\\s*:?\\s*(\\d+)m?"
00652 "(?:"
00653 "\\s*:?\\s*(\\d+)(?:[,.](\\d+))?s?"
00654 ")?"
00655 ")?"
00656 "(?:\\s*([ap])(?:m\\b|\\.m\\.))?";
00657 static VALUE pat = Qnil;
00658 VALUE s1, s2;
00659
00660 s1 = rb_reg_nth_match(1, m);
00661 s2 = rb_reg_nth_match(2, m);
00662
00663 if (!NIL_P(s2))
00664 set_hash("zone", s2);
00665
00666 REGCOMP_I(pat);
00667
00668 {
00669 VALUE m = f_match(pat, s1);
00670
00671 if (NIL_P(m))
00672 return 0;
00673 parse_time2_cb(m, hash);
00674 }
00675
00676 return 1;
00677 }
00678
00679 static int
00680 parse_time(VALUE str, VALUE hash)
00681 {
00682 static const char pat_source[] =
00683 "("
00684 "(?:"
00685 "\\d+\\s*:\\s*\\d+"
00686 "(?:"
00687 "\\s*:\\s*\\d+(?:[,.]\\d*)?"
00688 ")?"
00689 "|"
00690 "\\d+\\s*h(?:\\s*\\d+m?(?:\\s*\\d+s?)?)?"
00691 ")"
00692 "(?:"
00693 "\\s*"
00694 "[ap](?:m\\b|\\.m\\.)"
00695 ")?"
00696 "|"
00697 "\\d+\\s*[ap](?:m\\b|\\.m\\.)"
00698 ")"
00699 "(?:"
00700 "\\s*"
00701 "("
00702 "(?:gmt|utc?)?[-+]\\d+(?:[,.:]\\d+(?::\\d+)?)?"
00703 "|"
00704 "(?-i:[[:alpha:].\\s]+)(?:standard|daylight)\\stime\\b"
00705 "|"
00706 "(?-i:[[:alpha:]]+)(?:\\sdst)?\\b"
00707 ")"
00708 ")?";
00709 static VALUE pat = Qnil;
00710
00711 REGCOMP_I(pat);
00712 SUBS(str, pat, parse_time_cb);
00713 }
00714
00715 static int
00716 parse_eu_cb(VALUE m, VALUE hash)
00717 {
00718 VALUE y, mon, d, b;
00719
00720 d = rb_reg_nth_match(1, m);
00721 mon = rb_reg_nth_match(2, m);
00722 b = rb_reg_nth_match(3, m);
00723 y = rb_reg_nth_match(4, m);
00724
00725 mon = INT2FIX(mon_num(mon));
00726
00727 s3e(hash, y, mon, d, !NIL_P(b) &&
00728 (*RSTRING_PTR(b) == 'B' ||
00729 *RSTRING_PTR(b) == 'b'));
00730 return 1;
00731 }
00732
00733 static int
00734 parse_eu(VALUE str, VALUE hash)
00735 {
00736 static const char pat_source[] =
00737 "'?(\\d+)[^-\\d\\s]*"
00738 "\\s*"
00739 "(" ABBR_MONTHS ")[^-\\d\\s']*"
00740 "(?:"
00741 "\\s*"
00742 "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?"
00743 "\\s*"
00744 "('?-?\\d+(?:(?:st|nd|rd|th)\\b)?)"
00745 ")?";
00746 static VALUE pat = Qnil;
00747
00748 REGCOMP_I(pat);
00749 SUBS(str, pat, parse_eu_cb);
00750 }
00751
00752 static int
00753 parse_us_cb(VALUE m, VALUE hash)
00754 {
00755 VALUE y, mon, d, b;
00756
00757 mon = rb_reg_nth_match(1, m);
00758 d = rb_reg_nth_match(2, m);
00759 b = rb_reg_nth_match(3, m);
00760 y = rb_reg_nth_match(4, m);
00761
00762 mon = INT2FIX(mon_num(mon));
00763
00764 s3e(hash, y, mon, d, !NIL_P(b) &&
00765 (*RSTRING_PTR(b) == 'B' ||
00766 *RSTRING_PTR(b) == 'b'));
00767 return 1;
00768 }
00769
00770 static int
00771 parse_us(VALUE str, VALUE hash)
00772 {
00773 static const char pat_source[] =
00774 "\\b(" ABBR_MONTHS ")[^-\\d\\s']*"
00775 "\\s*"
00776 "('?\\d+)[^-\\d\\s']*"
00777 "(?:"
00778 "\\s*"
00779 "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?"
00780 "\\s*"
00781 "('?-?\\d+)"
00782 ")?";
00783 static VALUE pat = Qnil;
00784
00785 REGCOMP_I(pat);
00786 SUBS(str, pat, parse_us_cb);
00787 }
00788
00789 static int
00790 parse_iso_cb(VALUE m, VALUE hash)
00791 {
00792 VALUE y, mon, d;
00793
00794 y = rb_reg_nth_match(1, m);
00795 mon = rb_reg_nth_match(2, m);
00796 d = rb_reg_nth_match(3, m);
00797
00798 s3e(hash, y, mon, d, 0);
00799 return 1;
00800 }
00801
00802 static int
00803 parse_iso(VALUE str, VALUE hash)
00804 {
00805 static const char pat_source[] = "('?[-+]?\\d+)-(\\d+)-('?-?\\d+)";
00806 static VALUE pat = Qnil;
00807
00808 REGCOMP_0(pat);
00809 SUBS(str, pat, parse_iso_cb);
00810 }
00811
00812 static int
00813 parse_iso21_cb(VALUE m, VALUE hash)
00814 {
00815 VALUE y, w, d;
00816
00817 y = rb_reg_nth_match(1, m);
00818 w = rb_reg_nth_match(2, m);
00819 d = rb_reg_nth_match(3, m);
00820
00821 if (!NIL_P(y))
00822 set_hash("cwyear", str2num(y));
00823 set_hash("cweek", str2num(w));
00824 if (!NIL_P(d))
00825 set_hash("cwday", str2num(d));
00826
00827 return 1;
00828 }
00829
00830 static int
00831 parse_iso21(VALUE str, VALUE hash)
00832 {
00833 static const char pat_source[] =
00834 "\\b(\\d{2}|\\d{4})?-?w(\\d{2})(?:-?(\\d))?\\b";
00835 static VALUE pat = Qnil;
00836
00837 REGCOMP_I(pat);
00838 SUBS(str, pat, parse_iso21_cb);
00839 }
00840
00841 static int
00842 parse_iso22_cb(VALUE m, VALUE hash)
00843 {
00844 VALUE d;
00845
00846 d = rb_reg_nth_match(1, m);
00847 set_hash("cwday", str2num(d));
00848 return 1;
00849 }
00850
00851 static int
00852 parse_iso22(VALUE str, VALUE hash)
00853 {
00854 static const char pat_source[] = "-w-(\\d)\\b";
00855 static VALUE pat = Qnil;
00856
00857 REGCOMP_I(pat);
00858 SUBS(str, pat, parse_iso22_cb);
00859 }
00860
00861 static int
00862 parse_iso23_cb(VALUE m, VALUE hash)
00863 {
00864 VALUE mon, d;
00865
00866 mon = rb_reg_nth_match(1, m);
00867 d = rb_reg_nth_match(2, m);
00868
00869 if (!NIL_P(mon))
00870 set_hash("mon", str2num(mon));
00871 set_hash("mday", str2num(d));
00872
00873 return 1;
00874 }
00875
00876 static int
00877 parse_iso23(VALUE str, VALUE hash)
00878 {
00879 static const char pat_source[] = "--(\\d{2})?-(\\d{2})\\b";
00880 static VALUE pat = Qnil;
00881
00882 REGCOMP_0(pat);
00883 SUBS(str, pat, parse_iso23_cb);
00884 }
00885
00886 static int
00887 parse_iso24_cb(VALUE m, VALUE hash)
00888 {
00889 VALUE mon, d;
00890
00891 mon = rb_reg_nth_match(1, m);
00892 d = rb_reg_nth_match(2, m);
00893
00894 set_hash("mon", str2num(mon));
00895 if (!NIL_P(d))
00896 set_hash("mday", str2num(d));
00897
00898 return 1;
00899 }
00900
00901 static int
00902 parse_iso24(VALUE str, VALUE hash)
00903 {
00904 static const char pat_source[] = "--(\\d{2})(\\d{2})?\\b";
00905 static VALUE pat = Qnil;
00906
00907 REGCOMP_0(pat);
00908 SUBS(str, pat, parse_iso24_cb);
00909 }
00910
00911 static int
00912 parse_iso25_cb(VALUE m, VALUE hash)
00913 {
00914 VALUE y, d;
00915
00916 y = rb_reg_nth_match(1, m);
00917 d = rb_reg_nth_match(2, m);
00918
00919 set_hash("year", str2num(y));
00920 set_hash("yday", str2num(d));
00921
00922 return 1;
00923 }
00924
00925 static int
00926 parse_iso25(VALUE str, VALUE hash)
00927 {
00928 static const char pat0_source[] = "[,.](\\d{2}|\\d{4})-\\d{3}\\b";
00929 static VALUE pat0 = Qnil;
00930 static const char pat_source[] = "\\b(\\d{2}|\\d{4})-(\\d{3})\\b";
00931 static VALUE pat = Qnil;
00932
00933 REGCOMP_0(pat0);
00934 REGCOMP_0(pat);
00935
00936 if (!NIL_P(f_match(pat0, str)))
00937 return 0;
00938 SUBS(str, pat, parse_iso25_cb);
00939 }
00940
00941 static int
00942 parse_iso26_cb(VALUE m, VALUE hash)
00943 {
00944 VALUE d;
00945
00946 d = rb_reg_nth_match(1, m);
00947 set_hash("yday", str2num(d));
00948
00949 return 1;
00950 }
00951 static int
00952 parse_iso26(VALUE str, VALUE hash)
00953 {
00954 static const char pat0_source[] = "\\d-\\d{3}\\b";
00955 static VALUE pat0 = Qnil;
00956 static const char pat_source[] = "\\b-(\\d{3})\\b";
00957 static VALUE pat = Qnil;
00958
00959 REGCOMP_0(pat0);
00960 REGCOMP_0(pat);
00961
00962 if (!NIL_P(f_match(pat0, str)))
00963 return 0;
00964 SUBS(str, pat, parse_iso26_cb);
00965 }
00966
00967 static int
00968 parse_iso2(VALUE str, VALUE hash)
00969 {
00970 if (parse_iso21(str, hash))
00971 goto ok;
00972 if (parse_iso22(str, hash))
00973 goto ok;
00974 if (parse_iso23(str, hash))
00975 goto ok;
00976 if (parse_iso24(str, hash))
00977 goto ok;
00978 if (parse_iso25(str, hash))
00979 goto ok;
00980 if (parse_iso26(str, hash))
00981 goto ok;
00982 return 0;
00983
00984 ok:
00985 return 1;
00986 }
00987
00988 static int
00989 gengo(int c)
00990 {
00991 int e;
00992
00993 switch (c) {
00994 case 'M': case 'm': e = 1867; break;
00995 case 'T': case 't': e = 1911; break;
00996 case 'S': case 's': e = 1925; break;
00997 case 'H': case 'h': e = 1988; break;
00998 default: e = 0; break;
00999 }
01000 return e;
01001 }
01002
01003 static int
01004 parse_jis_cb(VALUE m, VALUE hash)
01005 {
01006 VALUE e, y, mon, d;
01007 int ep;
01008
01009 e = rb_reg_nth_match(1, m);
01010 y = rb_reg_nth_match(2, m);
01011 mon = rb_reg_nth_match(3, m);
01012 d = rb_reg_nth_match(4, m);
01013
01014 ep = gengo(*RSTRING_PTR(e));
01015
01016 set_hash("year", f_add(str2num(y), INT2FIX(ep)));
01017 set_hash("mon", str2num(mon));
01018 set_hash("mday", str2num(d));
01019
01020 return 1;
01021 }
01022
01023 static int
01024 parse_jis(VALUE str, VALUE hash)
01025 {
01026 static const char pat_source[] = "\\b([mtsh])(\\d+)\\.(\\d+)\\.(\\d+)";
01027 static VALUE pat = Qnil;
01028
01029 REGCOMP_I(pat);
01030 SUBS(str, pat, parse_jis_cb);
01031 }
01032
01033 static int
01034 parse_vms11_cb(VALUE m, VALUE hash)
01035 {
01036 VALUE y, mon, d;
01037
01038 d = rb_reg_nth_match(1, m);
01039 mon = rb_reg_nth_match(2, m);
01040 y = rb_reg_nth_match(3, m);
01041
01042 mon = INT2FIX(mon_num(mon));
01043
01044 s3e(hash, y, mon, d, 0);
01045 return 1;
01046 }
01047
01048 static int
01049 parse_vms11(VALUE str, VALUE hash)
01050 {
01051 static const char pat_source[] =
01052 "('?-?\\d+)-(" ABBR_MONTHS ")[^-]*"
01053 "-('?-?\\d+)";
01054 static VALUE pat = Qnil;
01055
01056 REGCOMP_I(pat);
01057 SUBS(str, pat, parse_vms11_cb);
01058 }
01059
01060 static int
01061 parse_vms12_cb(VALUE m, VALUE hash)
01062 {
01063 VALUE y, mon, d;
01064
01065 mon = rb_reg_nth_match(1, m);
01066 d = rb_reg_nth_match(2, m);
01067 y = rb_reg_nth_match(3, m);
01068
01069 mon = INT2FIX(mon_num(mon));
01070
01071 s3e(hash, y, mon, d, 0);
01072 return 1;
01073 }
01074
01075 static int
01076 parse_vms12(VALUE str, VALUE hash)
01077 {
01078 static const char pat_source[] =
01079 "\\b(" ABBR_MONTHS ")[^-]*"
01080 "-('?-?\\d+)(?:-('?-?\\d+))?";
01081 static VALUE pat = Qnil;
01082
01083 REGCOMP_I(pat);
01084 SUBS(str, pat, parse_vms12_cb);
01085 }
01086
01087 static int
01088 parse_vms(VALUE str, VALUE hash)
01089 {
01090 if (parse_vms11(str, hash))
01091 goto ok;
01092 if (parse_vms12(str, hash))
01093 goto ok;
01094 return 0;
01095
01096 ok:
01097 return 1;
01098 }
01099
01100 static int
01101 parse_sla_cb(VALUE m, VALUE hash)
01102 {
01103 VALUE y, mon, d;
01104
01105 y = rb_reg_nth_match(1, m);
01106 mon = rb_reg_nth_match(2, m);
01107 d = rb_reg_nth_match(3, m);
01108
01109 s3e(hash, y, mon, d, 0);
01110 return 1;
01111 }
01112
01113 static int
01114 parse_sla(VALUE str, VALUE hash)
01115 {
01116 static const char pat_source[] =
01117 "('?-?\\d+)/\\s*('?\\d+)(?:\\D\\s*('?-?\\d+))?";
01118 static VALUE pat = Qnil;
01119
01120 REGCOMP_I(pat);
01121 SUBS(str, pat, parse_sla_cb);
01122 }
01123
01124 static int
01125 parse_dot_cb(VALUE m, VALUE hash)
01126 {
01127 VALUE y, mon, d;
01128
01129 y = rb_reg_nth_match(1, m);
01130 mon = rb_reg_nth_match(2, m);
01131 d = rb_reg_nth_match(3, m);
01132
01133 s3e(hash, y, mon, d, 0);
01134 return 1;
01135 }
01136
01137 static int
01138 parse_dot(VALUE str, VALUE hash)
01139 {
01140 static const char pat_source[] =
01141 "('?-?\\d+)\\.\\s*('?\\d+)\\.\\s*('?-?\\d+)";
01142 static VALUE pat = Qnil;
01143
01144 REGCOMP_I(pat);
01145 SUBS(str, pat, parse_dot_cb);
01146 }
01147
01148 static int
01149 parse_year_cb(VALUE m, VALUE hash)
01150 {
01151 VALUE y;
01152
01153 y = rb_reg_nth_match(1, m);
01154 set_hash("year", str2num(y));
01155 return 1;
01156 }
01157
01158 static int
01159 parse_year(VALUE str, VALUE hash)
01160 {
01161 static const char pat_source[] = "'(\\d+)\\b";
01162 static VALUE pat = Qnil;
01163
01164 REGCOMP_0(pat);
01165 SUBS(str, pat, parse_year_cb);
01166 }
01167
01168 static int
01169 parse_mon_cb(VALUE m, VALUE hash)
01170 {
01171 VALUE mon;
01172
01173 mon = rb_reg_nth_match(1, m);
01174 set_hash("mon", INT2FIX(mon_num(mon)));
01175 return 1;
01176 }
01177
01178 static int
01179 parse_mon(VALUE str, VALUE hash)
01180 {
01181 static const char pat_source[] = "\\b(" ABBR_MONTHS ")\\S*";
01182 static VALUE pat = Qnil;
01183
01184 REGCOMP_I(pat);
01185 SUBS(str, pat, parse_mon_cb);
01186 }
01187
01188 static int
01189 parse_mday_cb(VALUE m, VALUE hash)
01190 {
01191 VALUE d;
01192
01193 d = rb_reg_nth_match(1, m);
01194 set_hash("mday", str2num(d));
01195 return 1;
01196 }
01197
01198 static int
01199 parse_mday(VALUE str, VALUE hash)
01200 {
01201 static const char pat_source[] = "(\\d+)(st|nd|rd|th)\\b";
01202 static VALUE pat = Qnil;
01203
01204 REGCOMP_I(pat);
01205 SUBS(str, pat, parse_mday_cb);
01206 }
01207
01208 static int
01209 n2i(const char *s, long f, long w)
01210 {
01211 long e, i;
01212 int v;
01213
01214 e = f + w;
01215 v = 0;
01216 for (i = f; i < e; i++) {
01217 v *= 10;
01218 v += s[i] - '0';
01219 }
01220 return v;
01221 }
01222
01223 static int
01224 parse_ddd_cb(VALUE m, VALUE hash)
01225 {
01226 VALUE s1, s2, s3, s4, s5;
01227 const char *cs2, *cs3, *cs5;
01228 long l2, l3, l4, l5;
01229
01230 s1 = rb_reg_nth_match(1, m);
01231 s2 = rb_reg_nth_match(2, m);
01232 s3 = rb_reg_nth_match(3, m);
01233 s4 = rb_reg_nth_match(4, m);
01234 s5 = rb_reg_nth_match(5, m);
01235
01236 cs2 = RSTRING_PTR(s2);
01237 l2 = RSTRING_LEN(s2);
01238
01239 switch (l2) {
01240 case 2:
01241 if (NIL_P(s3) && !NIL_P(s4))
01242 set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
01243 else
01244 set_hash("mday", INT2FIX(n2i(cs2, 0, 2)));
01245 break;
01246 case 4:
01247 if (NIL_P(s3) && !NIL_P(s4)) {
01248 set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
01249 set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
01250 }
01251 else {
01252 set_hash("mon", INT2FIX(n2i(cs2, 0, 2)));
01253 set_hash("mday", INT2FIX(n2i(cs2, 2, 2)));
01254 }
01255 break;
01256 case 6:
01257 if (NIL_P(s3) && !NIL_P(s4)) {
01258 set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
01259 set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
01260 set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
01261 }
01262 else {
01263 int y = n2i(cs2, 0, 2);
01264 if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
01265 y = -y;
01266 set_hash("year", INT2FIX(y));
01267 set_hash("mon", INT2FIX(n2i(cs2, 2, 2)));
01268 set_hash("mday", INT2FIX(n2i(cs2, 4, 2)));
01269 }
01270 break;
01271 case 8:
01272 case 10:
01273 case 12:
01274 case 14:
01275 if (NIL_P(s3) && !NIL_P(s4)) {
01276 set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
01277 set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
01278 set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
01279 set_hash("mday", INT2FIX(n2i(cs2, l2-8, 2)));
01280 if (l2 >= 10)
01281 set_hash("mon", INT2FIX(n2i(cs2, l2-10, 2)));
01282 if (l2 == 12) {
01283 int y = n2i(cs2, l2-12, 2);
01284 if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
01285 y = -y;
01286 set_hash("year", INT2FIX(y));
01287 }
01288 if (l2 == 14) {
01289 int y = n2i(cs2, l2-14, 4);
01290 if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
01291 y = -y;
01292 set_hash("year", INT2FIX(y));
01293 set_hash("_comp", Qfalse);
01294 }
01295 }
01296 else {
01297 int y = n2i(cs2, 0, 4);
01298 if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
01299 y = -y;
01300 set_hash("year", INT2FIX(y));
01301 set_hash("mon", INT2FIX(n2i(cs2, 4, 2)));
01302 set_hash("mday", INT2FIX(n2i(cs2, 6, 2)));
01303 if (l2 >= 10)
01304 set_hash("hour", INT2FIX(n2i(cs2, 8, 2)));
01305 if (l2 >= 12)
01306 set_hash("min", INT2FIX(n2i(cs2, 10, 2)));
01307 if (l2 >= 14)
01308 set_hash("sec", INT2FIX(n2i(cs2, 12, 2)));
01309 set_hash("_comp", Qfalse);
01310 }
01311 break;
01312 case 3:
01313 if (NIL_P(s3) && !NIL_P(s4)) {
01314 set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
01315 set_hash("min", INT2FIX(n2i(cs2, l2-3, 1)));
01316 }
01317 else
01318 set_hash("yday", INT2FIX(n2i(cs2, 0, 3)));
01319 break;
01320 case 5:
01321 if (NIL_P(s3) && !NIL_P(s4)) {
01322 set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
01323 set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
01324 set_hash("hour", INT2FIX(n2i(cs2, l2-5, 1)));
01325 }
01326 else {
01327 int y = n2i(cs2, 0, 2);
01328 if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
01329 y = -y;
01330 set_hash("year", INT2FIX(y));
01331 set_hash("yday", INT2FIX(n2i(cs2, 2, 3)));
01332 }
01333 break;
01334 case 7:
01335 if (NIL_P(s3) && !NIL_P(s4)) {
01336 set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
01337 set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
01338 set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
01339 set_hash("mday", INT2FIX(n2i(cs2, l2-7, 1)));
01340 }
01341 else {
01342 int y = n2i(cs2, 0, 4);
01343 if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
01344 y = -y;
01345 set_hash("year", INT2FIX(y));
01346 set_hash("yday", INT2FIX(n2i(cs2, 4, 3)));
01347 }
01348 break;
01349 }
01350 RB_GC_GUARD(s2);
01351 if (!NIL_P(s3)) {
01352 cs3 = RSTRING_PTR(s3);
01353 l3 = RSTRING_LEN(s3);
01354
01355 if (!NIL_P(s4)) {
01356 switch (l3) {
01357 case 2:
01358 case 4:
01359 case 6:
01360 set_hash("sec", INT2FIX(n2i(cs3, l3-2, 2)));
01361 if (l3 >= 4)
01362 set_hash("min", INT2FIX(n2i(cs3, l3-4, 2)));
01363 if (l3 >= 6)
01364 set_hash("hour", INT2FIX(n2i(cs3, l3-6, 2)));
01365 break;
01366 }
01367 }
01368 else {
01369 switch (l3) {
01370 case 2:
01371 case 4:
01372 case 6:
01373 set_hash("hour", INT2FIX(n2i(cs3, 0, 2)));
01374 if (l3 >= 4)
01375 set_hash("min", INT2FIX(n2i(cs3, 2, 2)));
01376 if (l3 >= 6)
01377 set_hash("sec", INT2FIX(n2i(cs3, 4, 2)));
01378 break;
01379 }
01380 }
01381 RB_GC_GUARD(s3);
01382 }
01383 if (!NIL_P(s4)) {
01384 l4 = RSTRING_LEN(s4);
01385
01386 set_hash("sec_fraction",
01387 rb_rational_new2(str2num(s4),
01388 f_expt(INT2FIX(10), LONG2NUM(l4))));
01389 }
01390 if (!NIL_P(s5)) {
01391 cs5 = RSTRING_PTR(s5);
01392 l5 = RSTRING_LEN(s5);
01393
01394 set_hash("zone", s5);
01395
01396 if (*cs5 == '[') {
01397 char *buf = ALLOCA_N(char, l5 + 1);
01398 char *s1, *s2, *s3;
01399 VALUE zone;
01400
01401 memcpy(buf, cs5, l5);
01402 buf[l5 - 1] = '\0';
01403
01404 s1 = buf + 1;
01405 s2 = strchr(buf, ':');
01406 if (s2) {
01407 *s2 = '\0';
01408 s2++;
01409 }
01410 if (s2)
01411 s3 = s2;
01412 else
01413 s3 = s1;
01414 zone = rb_str_new2(s3);
01415 set_hash("zone", zone);
01416 if (isdigit(*s1))
01417 *--s1 = '+';
01418 set_hash("offset", date_zone_to_diff(rb_str_new2(s1)));
01419 }
01420 RB_GC_GUARD(s5);
01421 }
01422
01423 return 1;
01424 }
01425
01426 static int
01427 parse_ddd(VALUE str, VALUE hash)
01428 {
01429 static const char pat_source[] =
01430 "([-+]?)(\\d{2,14})"
01431 "(?:"
01432 "\\s*"
01433 "t?"
01434 "\\s*"
01435 "(\\d{2,6})?(?:[,.](\\d*))?"
01436 ")?"
01437 "(?:"
01438 "\\s*"
01439 "("
01440 "z\\b"
01441 "|"
01442 "[-+]\\d{1,4}\\b"
01443 "|"
01444 "\\[[-+]?\\d[^\\]]*\\]"
01445 ")"
01446 ")?";
01447 static VALUE pat = Qnil;
01448
01449 REGCOMP_I(pat);
01450 SUBS(str, pat, parse_ddd_cb);
01451 }
01452
01453 static int
01454 parse_bc_cb(VALUE m, VALUE hash)
01455 {
01456 VALUE y;
01457
01458 y = ref_hash("year");
01459 if (!NIL_P(y))
01460 set_hash("year", f_add(f_negate(y), INT2FIX(1)));
01461
01462 return 1;
01463 }
01464
01465 static int
01466 parse_bc(VALUE str, VALUE hash)
01467 {
01468 static const char pat_source[] =
01469 "\\b(bc\\b|bce\\b|b\\.c\\.|b\\.c\\.e\\.)";
01470 static VALUE pat = Qnil;
01471
01472 REGCOMP_I(pat);
01473 SUBS(str, pat, parse_bc_cb);
01474 }
01475
01476 static int
01477 parse_frag_cb(VALUE m, VALUE hash)
01478 {
01479 VALUE s, n;
01480
01481 s = rb_reg_nth_match(1, m);
01482
01483 if (!NIL_P(ref_hash("hour")) && NIL_P(ref_hash("mday"))) {
01484 n = str2num(s);
01485 if (f_ge_p(n, INT2FIX(1)) &&
01486 f_le_p(n, INT2FIX(31)))
01487 set_hash("mday", n);
01488 }
01489 if (!NIL_P(ref_hash("mday")) && NIL_P(ref_hash("hour"))) {
01490 n = str2num(s);
01491 if (f_ge_p(n, INT2FIX(0)) &&
01492 f_le_p(n, INT2FIX(24)))
01493 set_hash("hour", n);
01494 }
01495
01496 return 1;
01497 }
01498
01499 static int
01500 parse_frag(VALUE str, VALUE hash)
01501 {
01502 static const char pat_source[] = "\\A\\s*(\\d{1,2})\\s*\\z";
01503 static VALUE pat = Qnil;
01504
01505 REGCOMP_I(pat);
01506 SUBS(str, pat, parse_frag_cb);
01507 }
01508
01509 #define HAVE_ALPHA (1<<0)
01510 #define HAVE_DIGIT (1<<1)
01511 #define HAVE_DASH (1<<2)
01512 #define HAVE_DOT (1<<3)
01513 #define HAVE_SLASH (1<<4)
01514
01515 static unsigned
01516 check_class(VALUE s)
01517 {
01518 unsigned flags;
01519 long i;
01520
01521 flags = 0;
01522 for (i = 0; i < RSTRING_LEN(s); i++) {
01523 if (isalpha(RSTRING_PTR(s)[i]))
01524 flags |= HAVE_ALPHA;
01525 if (isdigit(RSTRING_PTR(s)[i]))
01526 flags |= HAVE_DIGIT;
01527 if (RSTRING_PTR(s)[i] == '-')
01528 flags |= HAVE_DASH;
01529 if (RSTRING_PTR(s)[i] == '.')
01530 flags |= HAVE_DOT;
01531 if (RSTRING_PTR(s)[i] == '/')
01532 flags |= HAVE_SLASH;
01533 }
01534 return flags;
01535 }
01536
01537 #define HAVE_ELEM_P(x) ((check_class(str) & (x)) == (x))
01538
01539 VALUE
01540 date__parse(VALUE str, VALUE comp)
01541 {
01542 VALUE backref, hash;
01543
01544 backref = rb_backref_get();
01545 rb_match_busy(backref);
01546
01547 {
01548 static const char pat_source[] = "[^-+',./:@[:alnum:]\\[\\]]+";
01549 static VALUE pat = Qnil;
01550
01551 REGCOMP_0(pat);
01552 str = rb_str_dup(str);
01553 f_gsub_bang(str, pat, asp_string());
01554 }
01555
01556 hash = rb_hash_new();
01557 set_hash("_comp", comp);
01558
01559 if (HAVE_ELEM_P(HAVE_ALPHA))
01560 parse_day(str, hash);
01561 if (HAVE_ELEM_P(HAVE_DIGIT))
01562 parse_time(str, hash);
01563
01564 if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT))
01565 if (parse_eu(str, hash))
01566 goto ok;
01567 if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT))
01568 if (parse_us(str, hash))
01569 goto ok;
01570 if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DASH))
01571 if (parse_iso(str, hash))
01572 goto ok;
01573 if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DOT))
01574 if (parse_jis(str, hash))
01575 goto ok;
01576 if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT|HAVE_DASH))
01577 if (parse_vms(str, hash))
01578 goto ok;
01579 if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_SLASH))
01580 if (parse_sla(str, hash))
01581 goto ok;
01582 if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DOT))
01583 if (parse_dot(str, hash))
01584 goto ok;
01585 if (HAVE_ELEM_P(HAVE_DIGIT))
01586 if (parse_iso2(str, hash))
01587 goto ok;
01588 if (HAVE_ELEM_P(HAVE_DIGIT))
01589 if (parse_year(str, hash))
01590 goto ok;
01591 if (HAVE_ELEM_P(HAVE_ALPHA))
01592 if (parse_mon(str, hash))
01593 goto ok;
01594 if (HAVE_ELEM_P(HAVE_DIGIT))
01595 if (parse_mday(str, hash))
01596 goto ok;
01597 if (HAVE_ELEM_P(HAVE_DIGIT))
01598 if (parse_ddd(str, hash))
01599 goto ok;
01600
01601 ok:
01602 if (HAVE_ELEM_P(HAVE_ALPHA))
01603 parse_bc(str, hash);
01604 if (HAVE_ELEM_P(HAVE_DIGIT))
01605 parse_frag(str, hash);
01606
01607 {
01608 if (RTEST(ref_hash("_comp"))) {
01609 VALUE y;
01610
01611 y = ref_hash("cwyear");
01612 if (!NIL_P(y))
01613 if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) {
01614 if (f_ge_p(y, INT2FIX(69)))
01615 set_hash("cwyear", f_add(y, INT2FIX(1900)));
01616 else
01617 set_hash("cwyear", f_add(y, INT2FIX(2000)));
01618 }
01619 y = ref_hash("year");
01620 if (!NIL_P(y))
01621 if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) {
01622 if (f_ge_p(y, INT2FIX(69)))
01623 set_hash("year", f_add(y, INT2FIX(1900)));
01624 else
01625 set_hash("year", f_add(y, INT2FIX(2000)));
01626 }
01627 }
01628 }
01629
01630 del_hash("_comp");
01631
01632 {
01633 VALUE zone = ref_hash("zone");
01634 if (!NIL_P(zone) && NIL_P(ref_hash("offset")))
01635 set_hash("offset", date_zone_to_diff(zone));
01636 }
01637
01638 rb_backref_set(backref);
01639
01640 return hash;
01641 }
01642
01643 static VALUE
01644 comp_year69(VALUE y)
01645 {
01646 if (f_ge_p(y, INT2FIX(69)))
01647 return f_add(y, INT2FIX(1900));
01648 return f_add(y, INT2FIX(2000));
01649 }
01650
01651 static VALUE
01652 comp_year50(VALUE y)
01653 {
01654 if (f_ge_p(y, INT2FIX(50)))
01655 return f_add(y, INT2FIX(1900));
01656 return f_add(y, INT2FIX(2000));
01657 }
01658
01659 static VALUE
01660 sec_fraction(VALUE f)
01661 {
01662 return rb_rational_new2(str2num(f),
01663 f_expt(INT2FIX(10),
01664 LONG2NUM(RSTRING_LEN(f))));
01665 }
01666
01667 #define SNUM 14
01668
01669 static int
01670 iso8601_ext_datetime_cb(VALUE m, VALUE hash)
01671 {
01672 VALUE s[SNUM + 1], y;
01673
01674 {
01675 int i;
01676 s[0] = Qnil;
01677 for (i = 1; i <= SNUM; i++)
01678 s[i] = rb_reg_nth_match(i, m);
01679 }
01680
01681 if (!NIL_P(s[3])) {
01682 set_hash("mday", str2num(s[3]));
01683 if (strcmp(RSTRING_PTR(s[1]), "-") != 0) {
01684 y = str2num(s[1]);
01685 if (RSTRING_LEN(s[1]) < 4)
01686 y = comp_year69(y);
01687 set_hash("year", y);
01688 }
01689 if (NIL_P(s[2])) {
01690 if (strcmp(RSTRING_PTR(s[1]), "-") != 0)
01691 return 0;
01692 }
01693 else
01694 set_hash("mon", str2num(s[2]));
01695 }
01696 else if (!NIL_P(s[5])) {
01697 set_hash("yday", str2num(s[5]));
01698 if (!NIL_P(s[4])) {
01699 y = str2num(s[4]);
01700 if (RSTRING_LEN(s[4]) < 4)
01701 y = comp_year69(y);
01702 set_hash("year", y);
01703 }
01704 }
01705 else if (!NIL_P(s[8])) {
01706 set_hash("cweek", str2num(s[7]));
01707 set_hash("cwday", str2num(s[8]));
01708 if (!NIL_P(s[6])) {
01709 y = str2num(s[6]);
01710 if (RSTRING_LEN(s[6]) < 4)
01711 y = comp_year69(y);
01712 set_hash("cwyear", y);
01713 }
01714 }
01715 else if (!NIL_P(s[9])) {
01716 set_hash("cwday", str2num(s[9]));
01717 }
01718 if (!NIL_P(s[10])) {
01719 set_hash("hour", str2num(s[10]));
01720 set_hash("min", str2num(s[11]));
01721 if (!NIL_P(s[12]))
01722 set_hash("sec", str2num(s[12]));
01723 }
01724 if (!NIL_P(s[13])) {
01725 set_hash("sec_fraction", sec_fraction(s[13]));
01726 }
01727 if (!NIL_P(s[14])) {
01728 set_hash("zone", s[14]);
01729 set_hash("offset", date_zone_to_diff(s[14]));
01730 }
01731
01732 return 1;
01733 }
01734
01735 static int
01736 iso8601_ext_datetime(VALUE str, VALUE hash)
01737 {
01738 static const char pat_source[] =
01739 "\\A\\s*(?:([-+]?\\d{2,}|-)-(\\d{2})?-(\\d{2})|"
01740 "([-+]?\\d{2,})?-(\\d{3})|"
01741 "(\\d{4}|\\d{2})?-w(\\d{2})-(\\d)|"
01742 "-w-(\\d))"
01743 "(?:t"
01744 "(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?)?"
01745 "(z|[-+]\\d{2}(?::?\\d{2})?)?)?\\s*\\z";
01746 static VALUE pat = Qnil;
01747
01748 REGCOMP_I(pat);
01749 MATCH(str, pat, iso8601_ext_datetime_cb);
01750 }
01751
01752 #undef SNUM
01753 #define SNUM 17
01754
01755 static int
01756 iso8601_bas_datetime_cb(VALUE m, VALUE hash)
01757 {
01758 VALUE s[SNUM + 1], y;
01759
01760 {
01761 int i;
01762 s[0] = Qnil;
01763 for (i = 1; i <= SNUM; i++)
01764 s[i] = rb_reg_nth_match(i, m);
01765 }
01766
01767 if (!NIL_P(s[3])) {
01768 set_hash("mday", str2num(s[3]));
01769 if (strcmp(RSTRING_PTR(s[1]), "--") != 0) {
01770 y = str2num(s[1]);
01771 if (RSTRING_LEN(s[1]) < 4)
01772 y = comp_year69(y);
01773 set_hash("year", y);
01774 }
01775 if (*RSTRING_PTR(s[2]) == '-') {
01776 if (strcmp(RSTRING_PTR(s[1]), "--") != 0)
01777 return 0;
01778 }
01779 else
01780 set_hash("mon", str2num(s[2]));
01781 }
01782 else if (!NIL_P(s[5])) {
01783 set_hash("yday", str2num(s[5]));
01784 y = str2num(s[4]);
01785 if (RSTRING_LEN(s[4]) < 4)
01786 y = comp_year69(y);
01787 set_hash("year", y);
01788 }
01789 else if (!NIL_P(s[6])) {
01790 set_hash("yday", str2num(s[6]));
01791 }
01792 else if (!NIL_P(s[9])) {
01793 set_hash("cweek", str2num(s[8]));
01794 set_hash("cwday", str2num(s[9]));
01795 y = str2num(s[7]);
01796 if (RSTRING_LEN(s[7]) < 4)
01797 y = comp_year69(y);
01798 set_hash("cwyear", y);
01799 }
01800 else if (!NIL_P(s[11])) {
01801 set_hash("cweek", str2num(s[10]));
01802 set_hash("cwday", str2num(s[11]));
01803 }
01804 else if (!NIL_P(s[12])) {
01805 set_hash("cwday", str2num(s[12]));
01806 }
01807 if (!NIL_P(s[13])) {
01808 set_hash("hour", str2num(s[13]));
01809 set_hash("min", str2num(s[14]));
01810 if (!NIL_P(s[15]))
01811 set_hash("sec", str2num(s[15]));
01812 }
01813 if (!NIL_P(s[16])) {
01814 set_hash("sec_fraction", sec_fraction(s[16]));
01815 }
01816 if (!NIL_P(s[17])) {
01817 set_hash("zone", s[17]);
01818 set_hash("offset", date_zone_to_diff(s[17]));
01819 }
01820
01821 return 1;
01822 }
01823
01824 static int
01825 iso8601_bas_datetime(VALUE str, VALUE hash)
01826 {
01827 static const char pat_source[] =
01828 "\\A\\s*(?:([-+]?(?:\\d{4}|\\d{2})|--)(\\d{2}|-)(\\d{2})|"
01829 "([-+]?(?:\\d{4}|\\d{2}))(\\d{3})|"
01830 "-(\\d{3})|"
01831 "(\\d{4}|\\d{2})w(\\d{2})(\\d)|"
01832 "-w(\\d{2})(\\d)|"
01833 "-w-(\\d))"
01834 "(?:t?"
01835 "(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?)?"
01836 "(z|[-+]\\d{2}(?:\\d{2})?)?)?\\s*\\z";
01837 static VALUE pat = Qnil;
01838
01839 REGCOMP_I(pat);
01840 MATCH(str, pat, iso8601_bas_datetime_cb);
01841 }
01842
01843 #undef SNUM
01844 #define SNUM 5
01845
01846 static int
01847 iso8601_ext_time_cb(VALUE m, VALUE hash)
01848 {
01849 VALUE s[SNUM + 1];
01850
01851 {
01852 int i;
01853 s[0] = Qnil;
01854 for (i = 1; i <= SNUM; i++)
01855 s[i] = rb_reg_nth_match(i, m);
01856 }
01857
01858 set_hash("hour", str2num(s[1]));
01859 set_hash("min", str2num(s[2]));
01860 if (!NIL_P(s[3]))
01861 set_hash("sec", str2num(s[3]));
01862 if (!NIL_P(s[4]))
01863 set_hash("sec_fraction", sec_fraction(s[4]));
01864 if (!NIL_P(s[5])) {
01865 set_hash("zone", s[5]);
01866 set_hash("offset", date_zone_to_diff(s[5]));
01867 }
01868
01869 return 1;
01870 }
01871
01872 #define iso8601_bas_time_cb iso8601_ext_time_cb
01873
01874 static int
01875 iso8601_ext_time(VALUE str, VALUE hash)
01876 {
01877 static const char pat_source[] =
01878 "\\A\\s*(?:(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?)?"
01879 "(z|[-+]\\d{2}(:?\\d{2})?)?)?\\s*\\z";
01880 static VALUE pat = Qnil;
01881
01882 REGCOMP_I(pat);
01883 MATCH(str, pat, iso8601_ext_time_cb);
01884 }
01885
01886 static int
01887 iso8601_bas_time(VALUE str, VALUE hash)
01888 {
01889 static const char pat_source[] =
01890 "\\A\\s*(?:(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?)?"
01891 "(z|[-+]\\d{2}(\\d{2})?)?)?\\s*\\z";
01892 static VALUE pat = Qnil;
01893
01894 REGCOMP_I(pat);
01895 MATCH(str, pat, iso8601_bas_time_cb);
01896 }
01897
01898 VALUE
01899 date__iso8601(VALUE str)
01900 {
01901 VALUE backref, hash;
01902
01903 backref = rb_backref_get();
01904 rb_match_busy(backref);
01905
01906 hash = rb_hash_new();
01907
01908 if (iso8601_ext_datetime(str, hash))
01909 goto ok;
01910 if (iso8601_bas_datetime(str, hash))
01911 goto ok;
01912 if (iso8601_ext_time(str, hash))
01913 goto ok;
01914 if (iso8601_bas_time(str, hash))
01915 goto ok;
01916
01917 ok:
01918 rb_backref_set(backref);
01919
01920 return hash;
01921 }
01922
01923 #undef SNUM
01924 #define SNUM 8
01925
01926 static int
01927 rfc3339_cb(VALUE m, VALUE hash)
01928 {
01929 VALUE s[SNUM + 1];
01930
01931 {
01932 int i;
01933 s[0] = Qnil;
01934 for (i = 1; i <= SNUM; i++)
01935 s[i] = rb_reg_nth_match(i, m);
01936 }
01937
01938 set_hash("year", str2num(s[1]));
01939 set_hash("mon", str2num(s[2]));
01940 set_hash("mday", str2num(s[3]));
01941 set_hash("hour", str2num(s[4]));
01942 set_hash("min", str2num(s[5]));
01943 set_hash("sec", str2num(s[6]));
01944 set_hash("zone", s[8]);
01945 set_hash("offset", date_zone_to_diff(s[8]));
01946 if (!NIL_P(s[7]))
01947 set_hash("sec_fraction", sec_fraction(s[7]));
01948
01949 return 1;
01950 }
01951
01952 static int
01953 rfc3339(VALUE str, VALUE hash)
01954 {
01955 static const char pat_source[] =
01956 "\\A\\s*(-?\\d{4})-(\\d{2})-(\\d{2})"
01957 "(?:t|\\s)"
01958 "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?"
01959 "(z|[-+]\\d{2}:\\d{2})\\s*\\z";
01960 static VALUE pat = Qnil;
01961
01962 REGCOMP_I(pat);
01963 MATCH(str, pat, rfc3339_cb);
01964 }
01965
01966 VALUE
01967 date__rfc3339(VALUE str)
01968 {
01969 VALUE backref, hash;
01970
01971 backref = rb_backref_get();
01972 rb_match_busy(backref);
01973
01974 hash = rb_hash_new();
01975 rfc3339(str, hash);
01976 rb_backref_set(backref);
01977 return hash;
01978 }
01979
01980 #undef SNUM
01981 #define SNUM 8
01982
01983 static int
01984 xmlschema_datetime_cb(VALUE m, VALUE hash)
01985 {
01986 VALUE s[SNUM + 1];
01987
01988 {
01989 int i;
01990 s[0] = Qnil;
01991 for (i = 1; i <= SNUM; i++)
01992 s[i] = rb_reg_nth_match(i, m);
01993 }
01994
01995 set_hash("year", str2num(s[1]));
01996 if (!NIL_P(s[2]))
01997 set_hash("mon", str2num(s[2]));
01998 if (!NIL_P(s[3]))
01999 set_hash("mday", str2num(s[3]));
02000 if (!NIL_P(s[4]))
02001 set_hash("hour", str2num(s[4]));
02002 if (!NIL_P(s[5]))
02003 set_hash("min", str2num(s[5]));
02004 if (!NIL_P(s[6]))
02005 set_hash("sec", str2num(s[6]));
02006 if (!NIL_P(s[7]))
02007 set_hash("sec_fraction", sec_fraction(s[7]));
02008 if (!NIL_P(s[8])) {
02009 set_hash("zone", s[8]);
02010 set_hash("offset", date_zone_to_diff(s[8]));
02011 }
02012
02013 return 1;
02014 }
02015
02016 static int
02017 xmlschema_datetime(VALUE str, VALUE hash)
02018 {
02019 static const char pat_source[] =
02020 "\\A\\s*(-?\\d{4,})(?:-(\\d{2})(?:-(\\d{2}))?)?"
02021 "(?:t"
02022 "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?)?"
02023 "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
02024 static VALUE pat = Qnil;
02025
02026 REGCOMP_I(pat);
02027 MATCH(str, pat, xmlschema_datetime_cb);
02028 }
02029
02030 #undef SNUM
02031 #define SNUM 5
02032
02033 static int
02034 xmlschema_time_cb(VALUE m, VALUE hash)
02035 {
02036 VALUE s[SNUM + 1];
02037
02038 {
02039 int i;
02040 s[0] = Qnil;
02041 for (i = 1; i <= SNUM; i++)
02042 s[i] = rb_reg_nth_match(i, m);
02043 }
02044
02045 set_hash("hour", str2num(s[1]));
02046 set_hash("min", str2num(s[2]));
02047 if (!NIL_P(s[3]))
02048 set_hash("sec", str2num(s[3]));
02049 if (!NIL_P(s[4]))
02050 set_hash("sec_fraction", sec_fraction(s[4]));
02051 if (!NIL_P(s[5])) {
02052 set_hash("zone", s[5]);
02053 set_hash("offset", date_zone_to_diff(s[5]));
02054 }
02055
02056 return 1;
02057 }
02058
02059 static int
02060 xmlschema_time(VALUE str, VALUE hash)
02061 {
02062 static const char pat_source[] =
02063 "\\A\\s*(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?"
02064 "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
02065 static VALUE pat = Qnil;
02066
02067 REGCOMP_I(pat);
02068 MATCH(str, pat, xmlschema_time_cb);
02069 }
02070
02071 #undef SNUM
02072 #define SNUM 4
02073
02074 static int
02075 xmlschema_trunc_cb(VALUE m, VALUE hash)
02076 {
02077 VALUE s[SNUM + 1];
02078
02079 {
02080 int i;
02081 s[0] = Qnil;
02082 for (i = 1; i <= SNUM; i++)
02083 s[i] = rb_reg_nth_match(i, m);
02084 }
02085
02086 if (!NIL_P(s[1]))
02087 set_hash("mon", str2num(s[1]));
02088 if (!NIL_P(s[2]))
02089 set_hash("mday", str2num(s[2]));
02090 if (!NIL_P(s[3]))
02091 set_hash("mday", str2num(s[3]));
02092 if (!NIL_P(s[4])) {
02093 set_hash("zone", s[4]);
02094 set_hash("offset", date_zone_to_diff(s[4]));
02095 }
02096
02097 return 1;
02098 }
02099
02100 static int
02101 xmlschema_trunc(VALUE str, VALUE hash)
02102 {
02103 static const char pat_source[] =
02104 "\\A\\s*(?:--(\\d{2})(?:-(\\d{2}))?|---(\\d{2}))"
02105 "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
02106 static VALUE pat = Qnil;
02107
02108 REGCOMP_I(pat);
02109 MATCH(str, pat, xmlschema_trunc_cb);
02110 }
02111
02112 VALUE
02113 date__xmlschema(VALUE str)
02114 {
02115 VALUE backref, hash;
02116
02117 backref = rb_backref_get();
02118 rb_match_busy(backref);
02119
02120 hash = rb_hash_new();
02121
02122 if (xmlschema_datetime(str, hash))
02123 goto ok;
02124 if (xmlschema_time(str, hash))
02125 goto ok;
02126 if (xmlschema_trunc(str, hash))
02127 goto ok;
02128
02129 ok:
02130 rb_backref_set(backref);
02131
02132 return hash;
02133 }
02134
02135 #undef SNUM
02136 #define SNUM 8
02137
02138 static int
02139 rfc2822_cb(VALUE m, VALUE hash)
02140 {
02141 VALUE s[SNUM + 1], y;
02142
02143 {
02144 int i;
02145 s[0] = Qnil;
02146 for (i = 1; i <= SNUM; i++)
02147 s[i] = rb_reg_nth_match(i, m);
02148 }
02149
02150 if (!NIL_P(s[1])) {
02151 set_hash("wday", INT2FIX(day_num(s[1])));
02152 }
02153 set_hash("mday", str2num(s[2]));
02154 set_hash("mon", INT2FIX(mon_num(s[3])));
02155 y = str2num(s[4]);
02156 if (RSTRING_LEN(s[4]) < 4)
02157 y = comp_year50(y);
02158 set_hash("year", y);
02159 set_hash("hour", str2num(s[5]));
02160 set_hash("min", str2num(s[6]));
02161 if (!NIL_P(s[7]))
02162 set_hash("sec", str2num(s[7]));
02163 set_hash("zone", s[8]);
02164 set_hash("offset", date_zone_to_diff(s[8]));
02165
02166 return 1;
02167 }
02168
02169 static int
02170 rfc2822(VALUE str, VALUE hash)
02171 {
02172 static const char pat_source[] =
02173 "\\A\\s*(?:(" ABBR_DAYS ")\\s*,\\s+)?"
02174 "(\\d{1,2})\\s+"
02175 "(" ABBR_MONTHS ")\\s+"
02176 "(-?\\d{2,})\\s+"
02177 "(\\d{2}):(\\d{2})(?::(\\d{2}))?\\s*"
02178 "([-+]\\d{4}|ut|gmt|e[sd]t|c[sd]t|m[sd]t|p[sd]t|[a-ik-z])\\s*\\z";
02179 static VALUE pat = Qnil;
02180
02181 REGCOMP_I(pat);
02182 MATCH(str, pat, rfc2822_cb);
02183 }
02184
02185 VALUE
02186 date__rfc2822(VALUE str)
02187 {
02188 VALUE backref, hash;
02189
02190 backref = rb_backref_get();
02191 rb_match_busy(backref);
02192
02193 hash = rb_hash_new();
02194 rfc2822(str, hash);
02195 rb_backref_set(backref);
02196 return hash;
02197 }
02198
02199 #undef SNUM
02200 #define SNUM 8
02201
02202 static int
02203 httpdate_type1_cb(VALUE m, VALUE hash)
02204 {
02205 VALUE s[SNUM + 1];
02206
02207 {
02208 int i;
02209 s[0] = Qnil;
02210 for (i = 1; i <= SNUM; i++)
02211 s[i] = rb_reg_nth_match(i, m);
02212 }
02213
02214 set_hash("wday", INT2FIX(day_num(s[1])));
02215 set_hash("mday", str2num(s[2]));
02216 set_hash("mon", INT2FIX(mon_num(s[3])));
02217 set_hash("year", str2num(s[4]));
02218 set_hash("hour", str2num(s[5]));
02219 set_hash("min", str2num(s[6]));
02220 set_hash("sec", str2num(s[7]));
02221 set_hash("zone", s[8]);
02222 set_hash("offset", INT2FIX(0));
02223
02224 return 1;
02225 }
02226
02227 static int
02228 httpdate_type1(VALUE str, VALUE hash)
02229 {
02230 static const char pat_source[] =
02231 "\\A\\s*(" ABBR_DAYS ")\\s*,\\s+"
02232 "(\\d{2})\\s+"
02233 "(" ABBR_MONTHS ")\\s+"
02234 "(-?\\d{4})\\s+"
02235 "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
02236 "(gmt)\\s*\\z";
02237 static VALUE pat = Qnil;
02238
02239 REGCOMP_I(pat);
02240 MATCH(str, pat, httpdate_type1_cb);
02241 }
02242
02243 #undef SNUM
02244 #define SNUM 8
02245
02246 static int
02247 httpdate_type2_cb(VALUE m, VALUE hash)
02248 {
02249 VALUE s[SNUM + 1], y;
02250
02251 {
02252 int i;
02253 s[0] = Qnil;
02254 for (i = 1; i <= SNUM; i++)
02255 s[i] = rb_reg_nth_match(i, m);
02256 }
02257
02258 set_hash("wday", INT2FIX(day_num(s[1])));
02259 set_hash("mday", str2num(s[2]));
02260 set_hash("mon", INT2FIX(mon_num(s[3])));
02261 y = str2num(s[4]);
02262 if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99)))
02263 y = comp_year69(y);
02264 set_hash("year", y);
02265 set_hash("hour", str2num(s[5]));
02266 set_hash("min", str2num(s[6]));
02267 set_hash("sec", str2num(s[7]));
02268 set_hash("zone", s[8]);
02269 set_hash("offset", INT2FIX(0));
02270
02271 return 1;
02272 }
02273
02274 static int
02275 httpdate_type2(VALUE str, VALUE hash)
02276 {
02277 static const char pat_source[] =
02278 "\\A\\s*(" DAYS ")\\s*,\\s+"
02279 "(\\d{2})\\s*-\\s*"
02280 "(" ABBR_MONTHS ")\\s*-\\s*"
02281 "(\\d{2})\\s+"
02282 "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
02283 "(gmt)\\s*\\z";
02284 static VALUE pat = Qnil;
02285
02286 REGCOMP_I(pat);
02287 MATCH(str, pat, httpdate_type2_cb);
02288 }
02289
02290 #undef SNUM
02291 #define SNUM 7
02292
02293 static int
02294 httpdate_type3_cb(VALUE m, VALUE hash)
02295 {
02296 VALUE s[SNUM + 1];
02297
02298 {
02299 int i;
02300 s[0] = Qnil;
02301 for (i = 1; i <= SNUM; i++)
02302 s[i] = rb_reg_nth_match(i, m);
02303 }
02304
02305 set_hash("wday", INT2FIX(day_num(s[1])));
02306 set_hash("mon", INT2FIX(mon_num(s[2])));
02307 set_hash("mday", str2num(s[3]));
02308 set_hash("hour", str2num(s[4]));
02309 set_hash("min", str2num(s[5]));
02310 set_hash("sec", str2num(s[6]));
02311 set_hash("year", str2num(s[7]));
02312
02313 return 1;
02314 }
02315
02316 static int
02317 httpdate_type3(VALUE str, VALUE hash)
02318 {
02319 static const char pat_source[] =
02320 "\\A\\s*(" ABBR_DAYS ")\\s+"
02321 "(" ABBR_MONTHS ")\\s+"
02322 "(\\d{1,2})\\s+"
02323 "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
02324 "(\\d{4})\\s*\\z";
02325 static VALUE pat = Qnil;
02326
02327 REGCOMP_I(pat);
02328 MATCH(str, pat, httpdate_type3_cb);
02329 }
02330
02331 VALUE
02332 date__httpdate(VALUE str)
02333 {
02334 VALUE backref, hash;
02335
02336 backref = rb_backref_get();
02337 rb_match_busy(backref);
02338
02339 hash = rb_hash_new();
02340
02341 if (httpdate_type1(str, hash))
02342 goto ok;
02343 if (httpdate_type2(str, hash))
02344 goto ok;
02345 if (httpdate_type3(str, hash))
02346 goto ok;
02347
02348 ok:
02349 rb_backref_set(backref);
02350
02351 return hash;
02352 }
02353
02354 #undef SNUM
02355 #define SNUM 9
02356
02357 static int
02358 jisx0301_cb(VALUE m, VALUE hash)
02359 {
02360 VALUE s[SNUM + 1];
02361 int ep;
02362
02363 {
02364 int i;
02365 s[0] = Qnil;
02366 for (i = 1; i <= SNUM; i++)
02367 s[i] = rb_reg_nth_match(i, m);
02368 }
02369
02370 ep = gengo(NIL_P(s[1]) ? 'h' : *RSTRING_PTR(s[1]));
02371 set_hash("year", f_add(str2num(s[2]), INT2FIX(ep)));
02372 set_hash("mon", str2num(s[3]));
02373 set_hash("mday", str2num(s[4]));
02374 if (!NIL_P(s[5])) {
02375 set_hash("hour", str2num(s[5]));
02376 if (!NIL_P(s[6]))
02377 set_hash("min", str2num(s[6]));
02378 if (!NIL_P(s[7]))
02379 set_hash("sec", str2num(s[7]));
02380 }
02381 if (!NIL_P(s[8]))
02382 set_hash("sec_fraction", sec_fraction(s[8]));
02383 if (!NIL_P(s[9])) {
02384 set_hash("zone", s[9]);
02385 set_hash("offset", date_zone_to_diff(s[9]));
02386 }
02387
02388 return 1;
02389 }
02390
02391 static int
02392 jisx0301(VALUE str, VALUE hash)
02393 {
02394 static const char pat_source[] =
02395 "\\A\\s*([mtsh])?(\\d{2})\\.(\\d{2})\\.(\\d{2})"
02396 "(?:t"
02397 "(?:(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d*))?)?"
02398 "(z|[-+]\\d{2}(?::?\\d{2})?)?)?)?\\s*\\z";
02399 static VALUE pat = Qnil;
02400
02401 REGCOMP_I(pat);
02402 MATCH(str, pat, jisx0301_cb);
02403 }
02404
02405 VALUE
02406 date__jisx0301(VALUE str)
02407 {
02408 VALUE backref, hash;
02409
02410 backref = rb_backref_get();
02411 rb_match_busy(backref);
02412
02413 hash = rb_hash_new();
02414 if (jisx0301(str, hash))
02415 goto ok;
02416 hash = date__iso8601(str);
02417
02418 ok:
02419 rb_backref_set(backref);
02420 return hash;
02421 }
02422
02423
02424
02425
02426
02427
02428