Ruby 1.9.3p327(2012-11-10revision37606)
|
00001 /* 00002 date_parse.c: Coded by Tadayoshi Funaba 2011,2012 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 /* us -> be */ 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 "[[:alpha:].\\s]+(?:standard|daylight)\\stime\\b" 00705 "|" 00706 "[[: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 set_hash("wday", INT2FIX(day_num(s[1]))); 02151 set_hash("mday", str2num(s[2])); 02152 set_hash("mon", INT2FIX(mon_num(s[3]))); 02153 y = str2num(s[4]); 02154 if (RSTRING_LEN(s[4]) < 4) 02155 y = comp_year50(y); 02156 set_hash("year", y); 02157 set_hash("hour", str2num(s[5])); 02158 set_hash("min", str2num(s[6])); 02159 if (!NIL_P(s[7])) 02160 set_hash("sec", str2num(s[7])); 02161 set_hash("zone", s[8]); 02162 set_hash("offset", date_zone_to_diff(s[8])); 02163 02164 return 1; 02165 } 02166 02167 static int 02168 rfc2822(VALUE str, VALUE hash) 02169 { 02170 static const char pat_source[] = 02171 "\\A\\s*(?:(" ABBR_DAYS ")\\s*,\\s+)?" 02172 "(\\d{1,2})\\s+" 02173 "(" ABBR_MONTHS ")\\s+" 02174 "(-?\\d{2,})\\s+" 02175 "(\\d{2}):(\\d{2})(?::(\\d{2}))?\\s*" 02176 "([-+]\\d{4}|ut|gmt|e[sd]t|c[sd]t|m[sd]t|p[sd]t|[a-ik-z])\\s*\\z"; 02177 static VALUE pat = Qnil; 02178 02179 REGCOMP_I(pat); 02180 MATCH(str, pat, rfc2822_cb); 02181 } 02182 02183 VALUE 02184 date__rfc2822(VALUE str) 02185 { 02186 VALUE backref, hash; 02187 02188 backref = rb_backref_get(); 02189 rb_match_busy(backref); 02190 02191 hash = rb_hash_new(); 02192 rfc2822(str, hash); 02193 rb_backref_set(backref); 02194 return hash; 02195 } 02196 02197 #undef SNUM 02198 #define SNUM 8 02199 02200 static int 02201 httpdate_type1_cb(VALUE m, VALUE hash) 02202 { 02203 VALUE s[SNUM + 1]; 02204 02205 { 02206 int i; 02207 s[0] = Qnil; 02208 for (i = 1; i <= SNUM; i++) 02209 s[i] = rb_reg_nth_match(i, m); 02210 } 02211 02212 set_hash("wday", INT2FIX(day_num(s[1]))); 02213 set_hash("mday", str2num(s[2])); 02214 set_hash("mon", INT2FIX(mon_num(s[3]))); 02215 set_hash("year", str2num(s[4])); 02216 set_hash("hour", str2num(s[5])); 02217 set_hash("min", str2num(s[6])); 02218 set_hash("sec", str2num(s[7])); 02219 set_hash("zone", s[8]); 02220 set_hash("offset", INT2FIX(0)); 02221 02222 return 1; 02223 } 02224 02225 static int 02226 httpdate_type1(VALUE str, VALUE hash) 02227 { 02228 static const char pat_source[] = 02229 "\\A\\s*(" ABBR_DAYS ")\\s*,\\s+" 02230 "(\\d{2})\\s+" 02231 "(" ABBR_MONTHS ")\\s+" 02232 "(-?\\d{4})\\s+" 02233 "(\\d{2}):(\\d{2}):(\\d{2})\\s+" 02234 "(gmt)\\s*\\z"; 02235 static VALUE pat = Qnil; 02236 02237 REGCOMP_I(pat); 02238 MATCH(str, pat, httpdate_type1_cb); 02239 } 02240 02241 #undef SNUM 02242 #define SNUM 8 02243 02244 static int 02245 httpdate_type2_cb(VALUE m, VALUE hash) 02246 { 02247 VALUE s[SNUM + 1], y; 02248 02249 { 02250 int i; 02251 s[0] = Qnil; 02252 for (i = 1; i <= SNUM; i++) 02253 s[i] = rb_reg_nth_match(i, m); 02254 } 02255 02256 set_hash("wday", INT2FIX(day_num(s[1]))); 02257 set_hash("mday", str2num(s[2])); 02258 set_hash("mon", INT2FIX(mon_num(s[3]))); 02259 y = str2num(s[4]); 02260 if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) 02261 y = comp_year69(y); 02262 set_hash("year", y); 02263 set_hash("hour", str2num(s[5])); 02264 set_hash("min", str2num(s[6])); 02265 set_hash("sec", str2num(s[7])); 02266 set_hash("zone", s[8]); 02267 set_hash("offset", INT2FIX(0)); 02268 02269 return 1; 02270 } 02271 02272 static int 02273 httpdate_type2(VALUE str, VALUE hash) 02274 { 02275 static const char pat_source[] = 02276 "\\A\\s*(" DAYS ")\\s*,\\s+" 02277 "(\\d{2})\\s*-\\s*" 02278 "(" ABBR_MONTHS ")\\s*-\\s*" 02279 "(\\d{2})\\s+" 02280 "(\\d{2}):(\\d{2}):(\\d{2})\\s+" 02281 "(gmt)\\s*\\z"; 02282 static VALUE pat = Qnil; 02283 02284 REGCOMP_I(pat); 02285 MATCH(str, pat, httpdate_type2_cb); 02286 } 02287 02288 #undef SNUM 02289 #define SNUM 7 02290 02291 static int 02292 httpdate_type3_cb(VALUE m, VALUE hash) 02293 { 02294 VALUE s[SNUM + 1]; 02295 02296 { 02297 int i; 02298 s[0] = Qnil; 02299 for (i = 1; i <= SNUM; i++) 02300 s[i] = rb_reg_nth_match(i, m); 02301 } 02302 02303 set_hash("wday", INT2FIX(day_num(s[1]))); 02304 set_hash("mon", INT2FIX(mon_num(s[2]))); 02305 set_hash("mday", str2num(s[3])); 02306 set_hash("hour", str2num(s[4])); 02307 set_hash("min", str2num(s[5])); 02308 set_hash("sec", str2num(s[6])); 02309 set_hash("year", str2num(s[7])); 02310 02311 return 1; 02312 } 02313 02314 static int 02315 httpdate_type3(VALUE str, VALUE hash) 02316 { 02317 static const char pat_source[] = 02318 "\\A\\s*(" ABBR_DAYS ")\\s+" 02319 "(" ABBR_MONTHS ")\\s+" 02320 "(\\d{1,2})\\s+" 02321 "(\\d{2}):(\\d{2}):(\\d{2})\\s+" 02322 "(\\d{4})\\s*\\z"; 02323 static VALUE pat = Qnil; 02324 02325 REGCOMP_I(pat); 02326 MATCH(str, pat, httpdate_type3_cb); 02327 } 02328 02329 VALUE 02330 date__httpdate(VALUE str) 02331 { 02332 VALUE backref, hash; 02333 02334 backref = rb_backref_get(); 02335 rb_match_busy(backref); 02336 02337 hash = rb_hash_new(); 02338 02339 if (httpdate_type1(str, hash)) 02340 goto ok; 02341 if (httpdate_type2(str, hash)) 02342 goto ok; 02343 if (httpdate_type3(str, hash)) 02344 goto ok; 02345 02346 ok: 02347 rb_backref_set(backref); 02348 02349 return hash; 02350 } 02351 02352 #undef SNUM 02353 #define SNUM 9 02354 02355 static int 02356 jisx0301_cb(VALUE m, VALUE hash) 02357 { 02358 VALUE s[SNUM + 1]; 02359 int ep; 02360 02361 { 02362 int i; 02363 s[0] = Qnil; 02364 for (i = 1; i <= SNUM; i++) 02365 s[i] = rb_reg_nth_match(i, m); 02366 } 02367 02368 ep = gengo(NIL_P(s[1]) ? 'h' : *RSTRING_PTR(s[1])); 02369 set_hash("year", f_add(str2num(s[2]), INT2FIX(ep))); 02370 set_hash("mon", str2num(s[3])); 02371 set_hash("mday", str2num(s[4])); 02372 if (!NIL_P(s[5])) { 02373 set_hash("hour", str2num(s[5])); 02374 if (!NIL_P(s[6])) 02375 set_hash("min", str2num(s[6])); 02376 if (!NIL_P(s[7])) 02377 set_hash("sec", str2num(s[7])); 02378 } 02379 if (!NIL_P(s[8])) 02380 set_hash("sec_fraction", sec_fraction(s[8])); 02381 if (!NIL_P(s[9])) { 02382 set_hash("zone", s[9]); 02383 set_hash("offset", date_zone_to_diff(s[9])); 02384 } 02385 02386 return 1; 02387 } 02388 02389 static int 02390 jisx0301(VALUE str, VALUE hash) 02391 { 02392 static const char pat_source[] = 02393 "\\A\\s*([mtsh])?(\\d{2})\\.(\\d{2})\\.(\\d{2})" 02394 "(?:t" 02395 "(?:(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d*))?)?" 02396 "(z|[-+]\\d{2}(?::?\\d{2})?)?)?)?\\s*\\z"; 02397 static VALUE pat = Qnil; 02398 02399 REGCOMP_I(pat); 02400 MATCH(str, pat, jisx0301_cb); 02401 } 02402 02403 VALUE 02404 date__jisx0301(VALUE str) 02405 { 02406 VALUE backref, hash; 02407 02408 backref = rb_backref_get(); 02409 rb_match_busy(backref); 02410 02411 hash = rb_hash_new(); 02412 if (jisx0301(str, hash)) 02413 goto ok; 02414 hash = date__iso8601(str); 02415 02416 ok: 02417 rb_backref_set(backref); 02418 return hash; 02419 } 02420 02421 /* 02422 Local variables: 02423 c-file-style: "ruby" 02424 End: 02425 */ 02426