~ubuntu-branches/ubuntu/quantal/ruby1.9.1/quantal

« back to all changes in this revision

Viewing changes to ext/date/date_parse.c

  • Committer: Bazaar Package Importer
  • Author(s): Lucas Nussbaum
  • Date: 2011-09-24 19:16:17 UTC
  • mfrom: (1.1.8 upstream) (13.1.7 experimental)
  • Revision ID: james.westby@ubuntu.com-20110924191617-o1qz4rcmqjot8zuy
Tags: 1.9.3~rc1-1
* New upstream release: 1.9.3 RC1.
  + Includes load.c fixes. Closes: #639959.
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  date_parse.c: Coded by Tadayoshi Funaba 2011
 
3
*/
 
4
 
 
5
#include "ruby.h"
 
6
#include "ruby/encoding.h"
 
7
#include "ruby/re.h"
 
8
#include <ctype.h>
 
9
 
 
10
#define sizeof_array(o) (sizeof o / sizeof o[0])
 
11
 
 
12
#define f_negate(x) rb_funcall(x, rb_intern("-@"), 0)
 
13
#define f_add(x,y) rb_funcall(x, '+', 1, y)
 
14
#define f_sub(x,y) rb_funcall(x, '-', 1, y)
 
15
#define f_mul(x,y) rb_funcall(x, '*', 1, y)
 
16
#define f_div(x,y) rb_funcall(x, '/', 1, y)
 
17
#define f_idiv(x,y) rb_funcall(x, rb_intern("div"), 1, y)
 
18
#define f_mod(x,y) rb_funcall(x, '%', 1, y)
 
19
#define f_expt(x,y) rb_funcall(x, rb_intern("**"), 1, y)
 
20
 
 
21
#define f_lt_p(x,y) rb_funcall(x, '<', 1, y)
 
22
#define f_gt_p(x,y) rb_funcall(x, '>', 1, y)
 
23
#define f_le_p(x,y) rb_funcall(x, rb_intern("<="), 1, y)
 
24
#define f_ge_p(x,y) rb_funcall(x, rb_intern(">="), 1, y)
 
25
 
 
26
#define f_to_s(x) rb_funcall(x, rb_intern("to_s"), 0)
 
27
 
 
28
#define f_match(r,s) rb_funcall(r, rb_intern("match"), 1, s)
 
29
#define f_aref(o,i) rb_funcall(o, rb_intern("[]"), 1, i)
 
30
#define f_aref2(o,i,j) rb_funcall(o, rb_intern("[]"), 2, i, j)
 
31
#define f_begin(o,i) rb_funcall(o, rb_intern("begin"), 1, i)
 
32
#define f_end(o,i) rb_funcall(o, rb_intern("end"), 1, i)
 
33
#define f_aset(o,i,v) rb_funcall(o, rb_intern("[]="), 2, i, v)
 
34
#define f_aset2(o,i,j,v) rb_funcall(o, rb_intern("[]="), 3, i, j, v)
 
35
#define f_sub_bang(s,r,x) rb_funcall(s, rb_intern("sub!"), 2, r, x)
 
36
#define f_gsub_bang(s,r,x) rb_funcall(s, rb_intern("gsub!"), 2, r, x)
 
37
 
 
38
#define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k)), v)
 
39
#define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k)))
 
40
#define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k)))
 
41
 
 
42
#define cstr2num(s) rb_cstr_to_inum(s, 10, 0)
 
43
#define str2num(s) rb_str_to_inum(s, 10, 0)
 
44
 
 
45
static const char *abbr_days[] = {
 
46
    "sun", "mon", "tue", "wed",
 
47
    "thu", "fri", "sat"
 
48
};
 
49
 
 
50
static const char *abbr_months[] = {
 
51
    "jan", "feb", "mar", "apr", "may", "jun",
 
52
    "jul", "aug", "sep", "oct", "nov", "dec"
 
53
};
 
54
 
 
55
#define issign(c) ((c) == '-' || (c) == '+')
 
56
#define asp_string() rb_str_new(" ", 1)
 
57
 
 
58
static void
 
59
s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
 
60
{
 
61
    VALUE c = Qnil;
 
62
 
 
63
    if (TYPE(m) != T_STRING)
 
64
        m = f_to_s(m);
 
65
 
 
66
    if (!NIL_P(y) && !NIL_P(m) && NIL_P(d)) {
 
67
        VALUE oy = y;
 
68
        VALUE om = m;
 
69
        VALUE od = d;
 
70
 
 
71
        y = od;
 
72
        m = oy;
 
73
        d = om;
 
74
    }
 
75
 
 
76
    if (NIL_P(y)) {
 
77
        if (!NIL_P(d) && RSTRING_LEN(d) > 2) {
 
78
            y = d;
 
79
            d = Qnil;
 
80
        }
 
81
        if (!NIL_P(d) && *RSTRING_PTR(d) == '\'') {
 
82
            y = d;
 
83
            d = Qnil;
 
84
        }
 
85
    }
 
86
 
 
87
    if (!NIL_P(y)) {
 
88
        const char *s, *bp, *ep;
 
89
        size_t l;
 
90
 
 
91
        s = RSTRING_PTR(y);
 
92
        while (!issign(*s) && !isdigit(*s))
 
93
            s++;
 
94
        bp = s;
 
95
        if (issign(*s))
 
96
            s++;
 
97
        l = strspn(s, "0123456789");
 
98
        ep = s + l;
 
99
        if (*ep) {
 
100
            y = d;
 
101
            d = rb_str_new(bp, ep - bp);
 
102
        }
 
103
    }
 
104
 
 
105
    if (!NIL_P(m)) {
 
106
        const char *s;
 
107
 
 
108
        s = RSTRING_PTR(m);
 
109
        if (*s == '\'' || RSTRING_LEN(m) > 2) {
 
110
            /* us -> be */
 
111
            VALUE oy = y;
 
112
            VALUE om = m;
 
113
            VALUE od = d;
 
114
 
 
115
            y = om;
 
116
            m = od;
 
117
            d = oy;
 
118
        }
 
119
    }
 
120
 
 
121
    if (!NIL_P(d)) {
 
122
        const char *s;
 
123
 
 
124
        s = RSTRING_PTR(d);
 
125
        if (*s == '\'' || RSTRING_LEN(d) > 2) {
 
126
            VALUE oy = y;
 
127
            VALUE od = d;
 
128
 
 
129
            y = od;
 
130
            d = oy;
 
131
        }
 
132
    }
 
133
 
 
134
    if (!NIL_P(y)) {
 
135
        const char *s, *bp, *ep;
 
136
        int sign = 0;
 
137
        size_t l;
 
138
        VALUE iy;
 
139
 
 
140
        s = RSTRING_PTR(y);
 
141
        while (!issign(*s) && !isdigit(*s))
 
142
            s++;
 
143
        bp = s;
 
144
        if (issign(*s)) {
 
145
            s++;
 
146
            sign = 1;
 
147
        }
 
148
        if (sign)
 
149
            c = Qfalse;
 
150
        l = strspn(s, "0123456789");
 
151
        ep = s + l;
 
152
        if (l > 2)
 
153
            c = Qfalse;
 
154
        {
 
155
            char *buf;
 
156
 
 
157
            buf = ALLOCA_N(char, ep - bp + 1);
 
158
            memcpy(buf, bp, ep - bp);
 
159
            buf[ep - bp] = '\0';
 
160
            iy = cstr2num(buf);
 
161
        }
 
162
        if (bc)
 
163
            iy = f_add(f_negate(iy), INT2FIX(1));
 
164
        set_hash("year", iy);
 
165
    }
 
166
 
 
167
    if (!NIL_P(m)) {
 
168
        const char *s, *bp, *ep;
 
169
        size_t l;
 
170
        VALUE im;
 
171
 
 
172
        s = RSTRING_PTR(m);
 
173
        while (!isdigit(*s))
 
174
            s++;
 
175
        bp = s;
 
176
        l = strspn(s, "0123456789");
 
177
        ep = s + l;
 
178
        {
 
179
            char *buf;
 
180
 
 
181
            buf = ALLOCA_N(char, ep - bp + 1);
 
182
            memcpy(buf, bp, ep - bp);
 
183
            buf[ep - bp] = '\0';
 
184
            im = cstr2num(buf);
 
185
        }
 
186
        set_hash("mon", im);
 
187
    }
 
188
 
 
189
    if (!NIL_P(d)) {
 
190
        const char *s, *bp, *ep;
 
191
        size_t l;
 
192
        VALUE id;
 
193
 
 
194
        s = RSTRING_PTR(d);
 
195
        while (!isdigit(*s))
 
196
            s++;
 
197
        bp = s;
 
198
        l = strspn(s, "0123456789");
 
199
        ep = s + l;
 
200
        {
 
201
            char *buf;
 
202
 
 
203
            buf = ALLOCA_N(char, ep - bp + 1);
 
204
            memcpy(buf, bp, ep - bp);
 
205
            buf[ep - bp] = '\0';
 
206
            id = cstr2num(buf);
 
207
        }
 
208
        set_hash("mday", id);
 
209
    }
 
210
 
 
211
    if (!NIL_P(c))
 
212
        set_hash("_comp", c);
 
213
}
 
214
 
 
215
#define DAYS "sunday|monday|tuesday|wednesday|thursday|friday|saturday"
 
216
#define MONTHS "january|february|march|april|may|june|july|august|september|october|november|december"
 
217
#define ABBR_DAYS "sun|mon|tue|wed|thu|fri|sat"
 
218
#define ABBR_MONTHS "jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec"
 
219
 
 
220
static VALUE
 
221
regcomp(const char *source, long len, int opt)
 
222
{
 
223
    VALUE pat;
 
224
 
 
225
    pat = rb_reg_new(source, len, opt);
 
226
    rb_gc_register_mark_object(pat);
 
227
    return pat;
 
228
}
 
229
 
 
230
#define REGCOMP(pat,opt) \
 
231
{ \
 
232
    if (NIL_P(pat)) \
 
233
        pat = regcomp(pat##_source, sizeof pat##_source - 1, opt); \
 
234
}
 
235
 
 
236
#define REGCOMP_0(pat) REGCOMP(pat, 0)
 
237
#define REGCOMP_I(pat) REGCOMP(pat, ONIG_OPTION_IGNORECASE)
 
238
 
 
239
#define SUBS(s,p,c) \
 
240
{ \
 
241
    return subs(s, p, hash, c); \
 
242
}
 
243
 
 
244
static int
 
245
subs(VALUE str, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE))
 
246
{
 
247
    VALUE m;
 
248
 
 
249
    m = f_match(pat, str);
 
250
 
 
251
    if (NIL_P(m))
 
252
        return 0;
 
253
 
 
254
    {
 
255
        VALUE be, en;
 
256
 
 
257
        be = f_begin(m, INT2FIX(0));
 
258
        en = f_end(m, INT2FIX(0));
 
259
        f_aset2(str, be, LONG2NUM(NUM2LONG(en) - NUM2LONG(be)), asp_string());
 
260
        (*cb)(m, hash);
 
261
    }
 
262
 
 
263
    return 1;
 
264
}
 
265
 
 
266
struct zone {
 
267
    const char *name;
 
268
    int offset;
 
269
};
 
270
 
 
271
static struct zone zones_source[] = {
 
272
    {"ut",   0*3600}, {"gmt",  0*3600}, {"est", -5*3600}, {"edt", -4*3600},
 
273
    {"cst", -6*3600}, {"cdt", -5*3600}, {"mst", -7*3600}, {"mdt", -6*3600},
 
274
    {"pst", -8*3600}, {"pdt", -7*3600},
 
275
    {"a",    1*3600}, {"b",    2*3600}, {"c",    3*3600}, {"d",    4*3600},
 
276
    {"e",    5*3600}, {"f",    6*3600}, {"g",    7*3600}, {"h",    8*3600},
 
277
    {"i",    9*3600}, {"k",   10*3600}, {"l",   11*3600}, {"m",   12*3600},
 
278
    {"n",   -1*3600}, {"o",   -2*3600}, {"p",   -3*3600}, {"q",   -4*3600},
 
279
    {"r",   -5*3600}, {"s",   -6*3600}, {"t",   -7*3600}, {"u",   -8*3600},
 
280
    {"v",   -9*3600}, {"w",  -10*3600}, {"x",  -11*3600}, {"y",  -12*3600},
 
281
    {"z",    0*3600},
 
282
 
 
283
    {"utc",  0*3600}, {"wet",  0*3600},
 
284
    {"at",  -2*3600}, {"brst",-2*3600}, {"ndt", -(2*3600+1800)},
 
285
    {"art", -3*3600}, {"adt", -3*3600}, {"brt", -3*3600}, {"clst",-3*3600},
 
286
    {"nst", -(3*3600+1800)},
 
287
    {"ast", -4*3600}, {"clt", -4*3600},
 
288
    {"akdt",-8*3600}, {"ydt", -8*3600},
 
289
    {"akst",-9*3600}, {"hadt",-9*3600}, {"hdt", -9*3600}, {"yst", -9*3600},
 
290
    {"ahst",-10*3600},{"cat",-10*3600}, {"hast",-10*3600},{"hst",-10*3600},
 
291
    {"nt",  -11*3600},
 
292
    {"idlw",-12*3600},
 
293
    {"bst",  1*3600}, {"cet",  1*3600}, {"fwt",  1*3600}, {"met",  1*3600},
 
294
    {"mewt", 1*3600}, {"mez",  1*3600}, {"swt",  1*3600}, {"wat",  1*3600},
 
295
    {"west", 1*3600},
 
296
    {"cest", 2*3600}, {"eet",  2*3600}, {"fst",  2*3600}, {"mest", 2*3600},
 
297
    {"mesz", 2*3600}, {"sast", 2*3600}, {"sst",  2*3600},
 
298
    {"bt",   3*3600}, {"eat",  3*3600}, {"eest", 3*3600}, {"msk",  3*3600},
 
299
    {"msd",  4*3600}, {"zp4",  4*3600},
 
300
    {"zp5",  5*3600}, {"ist",  (5*3600+1800)},
 
301
    {"zp6",  6*3600},
 
302
    {"wast", 7*3600},
 
303
    {"cct",  8*3600}, {"sgt",  8*3600}, {"wadt", 8*3600},
 
304
    {"jst",  9*3600}, {"kst",  9*3600},
 
305
    {"east",10*3600}, {"gst", 10*3600},
 
306
    {"eadt",11*3600},
 
307
    {"idle",12*3600}, {"nzst",12*3600}, {"nzt", 12*3600},
 
308
    {"nzdt",13*3600},
 
309
 
 
310
    {"afghanistan",             16200}, {"alaskan",                -32400},
 
311
    {"arab",                    10800}, {"arabian",                 14400},
 
312
    {"arabic",                  10800}, {"atlantic",               -14400},
 
313
    {"aus central",             34200}, {"aus eastern",             36000},
 
314
    {"azores",                  -3600}, {"canada central",         -21600},
 
315
    {"cape verde",              -3600}, {"caucasus",                14400},
 
316
    {"cen. australia",          34200}, {"central america",        -21600},
 
317
    {"central asia",            21600}, {"central europe",           3600},
 
318
    {"central european",         3600}, {"central pacific",         39600},
 
319
    {"central",                -21600}, {"china",                   28800},
 
320
    {"dateline",               -43200}, {"e. africa",               10800},
 
321
    {"e. australia",            36000}, {"e. europe",                7200},
 
322
    {"e. south america",       -10800}, {"eastern",                -18000},
 
323
    {"egypt",                    7200}, {"ekaterinburg",            18000},
 
324
    {"fiji",                    43200}, {"fle",                      7200},
 
325
    {"greenland",              -10800}, {"greenwich",                   0},
 
326
    {"gtb",                      7200}, {"hawaiian",               -36000},
 
327
    {"india",                   19800}, {"iran",                    12600},
 
328
    {"jerusalem",                7200}, {"korea",                   32400},
 
329
    {"mexico",                 -21600}, {"mid-atlantic",            -7200},
 
330
    {"mountain",               -25200}, {"myanmar",                 23400},
 
331
    {"n. central asia",         21600}, {"nepal",                   20700},
 
332
    {"new zealand",             43200}, {"newfoundland",           -12600},
 
333
    {"north asia east",         28800}, {"north asia",              25200},
 
334
    {"pacific sa",             -14400}, {"pacific",                -28800},
 
335
    {"romance",                  3600}, {"russian",                 10800},
 
336
    {"sa eastern",             -10800}, {"sa pacific",             -18000},
 
337
    {"sa western",             -14400}, {"samoa",                  -39600},
 
338
    {"se asia",                 25200}, {"malay peninsula",         28800},
 
339
    {"south africa",             7200}, {"sri lanka",               21600},
 
340
    {"taipei",                  28800}, {"tasmania",                36000},
 
341
    {"tokyo",                   32400}, {"tonga",                   46800},
 
342
    {"us eastern",             -18000}, {"us mountain",            -25200},
 
343
    {"vladivostok",             36000}, {"w. australia",            28800},
 
344
    {"w. central africa",        3600}, {"w. europe",                3600},
 
345
    {"west asia",               18000}, {"west pacific",            36000},
 
346
    {"yakutsk",                 32400}
 
347
};
 
348
 
 
349
VALUE
 
350
date_zone_to_diff(VALUE str)
 
351
{
 
352
    VALUE offset = Qnil;
 
353
 
 
354
    long l, i;
 
355
    char *s, *dest, *d;
 
356
    int sp = 1;
 
357
 
 
358
    l = RSTRING_LEN(str);
 
359
    s = RSTRING_PTR(str);
 
360
 
 
361
    dest = d = ALLOCA_N(char, l + 1);
 
362
 
 
363
    for (i = 0; i < l; i++) {
 
364
        if (isspace(s[i]) || s[i] == '\0') {
 
365
            if (!sp)
 
366
                *d++ = ' ';
 
367
            sp = 1;
 
368
        }
 
369
        else {
 
370
            if (isalpha(s[i]))
 
371
                *d++ = tolower(s[i]);
 
372
            else
 
373
                *d++ = s[i];
 
374
            sp = 0;
 
375
        }
 
376
    }
 
377
    if (d > dest) {
 
378
        if (*(d - 1) == ' ')
 
379
            --d;
 
380
        *d = '\0';
 
381
    }
 
382
    str = rb_str_new2(dest);
 
383
    {
 
384
#define STD " standard time"
 
385
#define DST " daylight time"
 
386
        char *ss, *ds;
 
387
        long sl, dl;
 
388
        int dst = 0;
 
389
 
 
390
        sl = RSTRING_LEN(str) - (sizeof STD - 1);
 
391
        ss = RSTRING_PTR(str) + sl;
 
392
        dl = RSTRING_LEN(str) - (sizeof DST - 1);
 
393
        ds = RSTRING_PTR(str) + dl;
 
394
 
 
395
        if (sl >= 0 && strcmp(ss, STD) == 0) {
 
396
            str = rb_str_new(RSTRING_PTR(str), sl);
 
397
        }
 
398
        else if (dl >= 0 && strcmp(ds, DST) == 0) {
 
399
            str = rb_str_new(RSTRING_PTR(str), dl);
 
400
            dst = 1;
 
401
        }
 
402
#undef STD
 
403
#undef DST
 
404
        else {
 
405
#define DST " dst"
 
406
            char *ds;
 
407
            long dl;
 
408
 
 
409
            dl = RSTRING_LEN(str) - (sizeof DST - 1);
 
410
            ds = RSTRING_PTR(str) + dl;
 
411
 
 
412
            if (dl >= 0 && strcmp(ds, DST) == 0) {
 
413
                str = rb_str_new(RSTRING_PTR(str), dl);
 
414
                dst = 1;
 
415
            }
 
416
#undef DST
 
417
        }
 
418
        {
 
419
            static VALUE zones = Qnil;
 
420
 
 
421
            if (NIL_P(zones)) {
 
422
                int i;
 
423
 
 
424
                zones = rb_hash_new();
 
425
                rb_gc_register_mark_object(zones);
 
426
                for (i = 0; i < (int)sizeof_array(zones_source); i++) {
 
427
                    VALUE name = rb_str_new2(zones_source[i].name);
 
428
                    VALUE offset = INT2FIX(zones_source[i].offset);
 
429
                    rb_hash_aset(zones, name, offset);
 
430
                }
 
431
            }
 
432
 
 
433
            offset = f_aref(zones, str);
 
434
            if (!NIL_P(offset)) {
 
435
                if (dst)
 
436
                    offset = f_add(offset, INT2FIX(3600));
 
437
                goto ok;
 
438
            }
 
439
        }
 
440
        {
 
441
            char *s, *p;
 
442
            VALUE sign;
 
443
            VALUE hour = Qnil, min = Qnil, sec = Qnil;
 
444
            VALUE str_orig;
 
445
 
 
446
            s = RSTRING_PTR(str);
 
447
            str_orig = str;
 
448
 
 
449
            if (strncmp(s, "gmt", 3) == 0 ||
 
450
                strncmp(s, "utc", 3) == 0)
 
451
                s += 3;
 
452
            if (issign(*s)) {
 
453
                sign = rb_str_new(s, 1);
 
454
                s++;
 
455
 
 
456
                str = rb_str_new2(s);
 
457
 
 
458
                if (p = strchr(s, ':')) {
 
459
                    hour = rb_str_new(s, p - s);
 
460
                    s = ++p;
 
461
                    if (p = strchr(s, ':')) {
 
462
                        min = rb_str_new(s, p - s);
 
463
                        s = ++p;
 
464
                        if (p = strchr(s, ':')) {
 
465
                            sec = rb_str_new(s, p - s);
 
466
                        }
 
467
                        else
 
468
                            sec = rb_str_new2(s);
 
469
                    }
 
470
                    else
 
471
                        min = rb_str_new2(s);
 
472
                    RB_GC_GUARD(str_orig);
 
473
                    goto num;
 
474
                }
 
475
                if (strpbrk(RSTRING_PTR(str), ",.")) {
 
476
                    char *a, *b;
 
477
 
 
478
                    a = ALLOCA_N(char, RSTRING_LEN(str) + 1);
 
479
                    strcpy(a, RSTRING_PTR(str));
 
480
                    b = strpbrk(a, ",.");
 
481
                    *b = '\0';
 
482
                    b++;
 
483
 
 
484
                    hour = cstr2num(a);
 
485
                    min = f_mul(rb_rational_new2
 
486
                                (cstr2num(b),
 
487
                                 f_expt(INT2FIX(10),
 
488
                                        LONG2NUM((long)strlen(b)))),
 
489
                                INT2FIX(60));
 
490
                    goto num;
 
491
                }
 
492
                {
 
493
                    const char *cs = RSTRING_PTR(str);
 
494
                    long cl = RSTRING_LEN(str);
 
495
 
 
496
                    if (cl % 2) {
 
497
                        if (cl >= 1)
 
498
                            hour = rb_str_new(&cs[0], 1);
 
499
                        if (cl >= 3)
 
500
                            min  = rb_str_new(&cs[1], 2);
 
501
                        if (cl >= 5)
 
502
                            min  = rb_str_new(&cs[3], 2);
 
503
                    }
 
504
                    else {
 
505
                        if (cl >= 2)
 
506
                            hour = rb_str_new(&cs[0], 2);
 
507
                        if (cl >= 4)
 
508
                            min  = rb_str_new(&cs[2], 2);
 
509
                        if (cl >= 6)
 
510
                            sec  = rb_str_new(&cs[4], 2);
 
511
                    }
 
512
                    goto num;
 
513
                }
 
514
              num:
 
515
                if (NIL_P(hour))
 
516
                    offset = INT2FIX(0);
 
517
                else {
 
518
                    if (TYPE(hour) == T_STRING)
 
519
                        hour = str2num(hour);
 
520
                    offset = f_mul(hour, INT2FIX(3600));
 
521
                }
 
522
                if (!NIL_P(min)) {
 
523
                    if (TYPE(min) == T_STRING)
 
524
                        min = str2num(min);
 
525
                    offset = f_add(offset, f_mul(min, INT2FIX(60)));
 
526
                }
 
527
                if (!NIL_P(sec))
 
528
                    offset = f_add(offset, str2num(sec));
 
529
                if (!NIL_P(sign) &&
 
530
                    RSTRING_LEN(sign) == 1 &&
 
531
                    *RSTRING_PTR(sign) == '-')
 
532
                    offset = f_negate(offset);
 
533
            }
 
534
        }
 
535
    }
 
536
    RB_GC_GUARD(str);
 
537
  ok:
 
538
    return offset;
 
539
}
 
540
 
 
541
static int
 
542
day_num(VALUE s)
 
543
{
 
544
    int i;
 
545
 
 
546
    for (i = 0; i < (int)sizeof_array(abbr_days); i++)
 
547
        if (strncasecmp(abbr_days[i], RSTRING_PTR(s), 3) == 0)
 
548
            break;
 
549
    return i;
 
550
}
 
551
 
 
552
static int
 
553
mon_num(VALUE s)
 
554
{
 
555
    int i;
 
556
 
 
557
    for (i = 0; i < (int)sizeof_array(abbr_months); i++)
 
558
        if (strncasecmp(abbr_months[i], RSTRING_PTR(s), 3) == 0)
 
559
            break;
 
560
    return i + 1;
 
561
}
 
562
 
 
563
static int
 
564
parse_day_cb(VALUE m, VALUE hash)
 
565
{
 
566
    VALUE s;
 
567
 
 
568
    s = rb_reg_nth_match(1, m);
 
569
    set_hash("wday", INT2FIX(day_num(s)));
 
570
    return 1;
 
571
}
 
572
 
 
573
static int
 
574
parse_day(VALUE str, VALUE hash)
 
575
{
 
576
    static const char pat_source[] = "\\b(" ABBR_DAYS ")[^-\\d\\s]*";
 
577
    static VALUE pat = Qnil;
 
578
 
 
579
    REGCOMP_I(pat);
 
580
    SUBS(str, pat, parse_day_cb);
 
581
}
 
582
 
 
583
static int
 
584
parse_time2_cb(VALUE m, VALUE hash)
 
585
{
 
586
    VALUE h, min, s, f, p;
 
587
 
 
588
    h = rb_reg_nth_match(1, m);
 
589
    h = str2num(h);
 
590
 
 
591
    min = rb_reg_nth_match(2, m);
 
592
    if (!NIL_P(min))
 
593
        min = str2num(min);
 
594
 
 
595
    s = rb_reg_nth_match(3, m);
 
596
    if (!NIL_P(s))
 
597
        s = str2num(s);
 
598
 
 
599
    f = rb_reg_nth_match(4, m);
 
600
 
 
601
    if (!NIL_P(f))
 
602
        f = rb_rational_new2(str2num(f),
 
603
                             f_expt(INT2FIX(10), LONG2NUM(RSTRING_LEN(f))));
 
604
 
 
605
    p = rb_reg_nth_match(5, m);
 
606
 
 
607
    if (!NIL_P(p)) {
 
608
        int ih = NUM2INT(h);
 
609
        ih %= 12;
 
610
        if (*RSTRING_PTR(p) == 'P' || *RSTRING_PTR(p) == 'p')
 
611
            ih += 12;
 
612
        h = INT2FIX(ih);
 
613
    }
 
614
 
 
615
    set_hash("hour", h);
 
616
    if (!NIL_P(min))
 
617
        set_hash("min", min);
 
618
    if (!NIL_P(s))
 
619
        set_hash("sec", s);
 
620
    if (!NIL_P(f))
 
621
        set_hash("sec_fraction", f);
 
622
 
 
623
    return 1;
 
624
}
 
625
 
 
626
static int
 
627
parse_time_cb(VALUE m, VALUE hash)
 
628
{
 
629
    static const char pat_source[] =
 
630
            "\\A(\\d+)h?"
 
631
              "(?:\\s*:?\\s*(\\d+)m?"
 
632
                "(?:"
 
633
                  "\\s*:?\\s*(\\d+)(?:[,.](\\d+))?s?"
 
634
                ")?"
 
635
              ")?"
 
636
            "(?:\\s*([ap])(?:m\\b|\\.m\\.))?";
 
637
    static VALUE pat = Qnil;
 
638
    VALUE s1, s2;
 
639
 
 
640
    s1 = rb_reg_nth_match(1, m);
 
641
    s2 = rb_reg_nth_match(2, m);
 
642
 
 
643
    if (!NIL_P(s2))
 
644
        set_hash("zone", s2);
 
645
 
 
646
    REGCOMP_I(pat);
 
647
 
 
648
    {
 
649
        VALUE m = f_match(pat, s1);
 
650
 
 
651
        if (NIL_P(m))
 
652
            return 0;
 
653
        parse_time2_cb(m, hash);
 
654
    }
 
655
 
 
656
    return 1;
 
657
}
 
658
 
 
659
static int
 
660
parse_time(VALUE str, VALUE hash)
 
661
{
 
662
    static const char pat_source[] =
 
663
                "("
 
664
                   "(?:"
 
665
                     "\\d+\\s*:\\s*\\d+"
 
666
                     "(?:"
 
667
                       "\\s*:\\s*\\d+(?:[,.]\\d*)?"
 
668
                     ")?"
 
669
                   "|"
 
670
                     "\\d+\\s*h(?:\\s*\\d+m?(?:\\s*\\d+s?)?)?"
 
671
                   ")"
 
672
                   "(?:"
 
673
                     "\\s*"
 
674
                     "[ap](?:m\\b|\\.m\\.)"
 
675
                   ")?"
 
676
                 "|"
 
677
                   "\\d+\\s*[ap](?:m\\b|\\.m\\.)"
 
678
                 ")"
 
679
                 "(?:"
 
680
                   "\\s*"
 
681
                   "("
 
682
                     "(?:gmt|utc?)?[-+]\\d+(?:[,.:]\\d+(?::\\d+)?)?"
 
683
                   "|"
 
684
                     "[[:alpha:].\\s]+(?:standard|daylight)\\stime\\b"
 
685
                   "|"
 
686
                     "[[:alpha:]]+(?:\\sdst)?\\b"
 
687
                   ")"
 
688
                ")?";
 
689
    static VALUE pat = Qnil;
 
690
 
 
691
    REGCOMP_I(pat);
 
692
    SUBS(str, pat, parse_time_cb);
 
693
}
 
694
 
 
695
static int
 
696
parse_eu_cb(VALUE m, VALUE hash)
 
697
{
 
698
    VALUE y, mon, d, b;
 
699
 
 
700
    d = rb_reg_nth_match(1, m);
 
701
    mon = rb_reg_nth_match(2, m);
 
702
    b = rb_reg_nth_match(3, m);
 
703
    y = rb_reg_nth_match(4, m);
 
704
 
 
705
    mon = INT2FIX(mon_num(mon));
 
706
 
 
707
    s3e(hash, y, mon, d, !NIL_P(b) &&
 
708
        (*RSTRING_PTR(b) == 'B' ||
 
709
         *RSTRING_PTR(b) == 'b'));
 
710
    return 1;
 
711
}
 
712
 
 
713
static int
 
714
parse_eu(VALUE str, VALUE hash)
 
715
{
 
716
    static const char pat_source[] =
 
717
                "'?(\\d+)[^-\\d\\s]*"
 
718
                 "\\s*"
 
719
                 "(" ABBR_MONTHS ")[^-\\d\\s']*"
 
720
                 "(?:"
 
721
                   "\\s*"
 
722
                   "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?"
 
723
                   "\\s*"
 
724
                   "('?-?\\d+(?:(?:st|nd|rd|th)\\b)?)"
 
725
                ")?";
 
726
    static VALUE pat = Qnil;
 
727
 
 
728
    REGCOMP_I(pat);
 
729
    SUBS(str, pat, parse_eu_cb);
 
730
}
 
731
 
 
732
static int
 
733
parse_us_cb(VALUE m, VALUE hash)
 
734
{
 
735
    VALUE y, mon, d, b;
 
736
 
 
737
    mon = rb_reg_nth_match(1, m);
 
738
    d = rb_reg_nth_match(2, m);
 
739
    b = rb_reg_nth_match(3, m);
 
740
    y = rb_reg_nth_match(4, m);
 
741
 
 
742
    mon = INT2FIX(mon_num(mon));
 
743
 
 
744
    s3e(hash, y, mon, d, !NIL_P(b) &&
 
745
        (*RSTRING_PTR(b) == 'B' ||
 
746
         *RSTRING_PTR(b) == 'b'));
 
747
    return 1;
 
748
}
 
749
 
 
750
static int
 
751
parse_us(VALUE str, VALUE hash)
 
752
{
 
753
    static const char pat_source[] =
 
754
                "\\b(" ABBR_MONTHS ")[^-\\d\\s']*"
 
755
                 "\\s*"
 
756
                 "('?\\d+)[^-\\d\\s']*"
 
757
                 "(?:"
 
758
                   "\\s*"
 
759
                   "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?"
 
760
                   "\\s*"
 
761
                   "('?-?\\d+)"
 
762
                ")?";
 
763
    static VALUE pat = Qnil;
 
764
 
 
765
    REGCOMP_I(pat);
 
766
    SUBS(str, pat, parse_us_cb);
 
767
}
 
768
 
 
769
static int
 
770
parse_iso_cb(VALUE m, VALUE hash)
 
771
{
 
772
    VALUE y, mon, d;
 
773
 
 
774
    y = rb_reg_nth_match(1, m);
 
775
    mon = rb_reg_nth_match(2, m);
 
776
    d = rb_reg_nth_match(3, m);
 
777
 
 
778
    s3e(hash, y, mon, d, 0);
 
779
    return 1;
 
780
}
 
781
 
 
782
static int
 
783
parse_iso(VALUE str, VALUE hash)
 
784
{
 
785
    static const char pat_source[] = "('?[-+]?\\d+)-(\\d+)-('?-?\\d+)";
 
786
    static VALUE pat = Qnil;
 
787
 
 
788
    REGCOMP_0(pat);
 
789
    SUBS(str, pat, parse_iso_cb);
 
790
}
 
791
 
 
792
static int
 
793
parse_iso21_cb(VALUE m, VALUE hash)
 
794
{
 
795
    VALUE y, w, d;
 
796
 
 
797
    y = rb_reg_nth_match(1, m);
 
798
    w = rb_reg_nth_match(2, m);
 
799
    d = rb_reg_nth_match(3, m);
 
800
 
 
801
    if (!NIL_P(y))
 
802
        set_hash("cwyear", str2num(y));
 
803
    set_hash("cweek", str2num(w));
 
804
    if (!NIL_P(d))
 
805
        set_hash("cwday", str2num(d));
 
806
 
 
807
    return 1;
 
808
}
 
809
 
 
810
static int
 
811
parse_iso21(VALUE str, VALUE hash)
 
812
{
 
813
    static const char pat_source[] =
 
814
        "\\b(\\d{2}|\\d{4})?-?w(\\d{2})(?:-?(\\d))?\\b";
 
815
    static VALUE pat = Qnil;
 
816
 
 
817
    REGCOMP_I(pat);
 
818
    SUBS(str, pat, parse_iso21_cb);
 
819
}
 
820
 
 
821
static int
 
822
parse_iso22_cb(VALUE m, VALUE hash)
 
823
{
 
824
    VALUE d;
 
825
 
 
826
    d = rb_reg_nth_match(1, m);
 
827
    set_hash("cwday", str2num(d));
 
828
    return 1;
 
829
}
 
830
 
 
831
static int
 
832
parse_iso22(VALUE str, VALUE hash)
 
833
{
 
834
    static const char pat_source[] = "-w-(\\d)\\b";
 
835
    static VALUE pat = Qnil;
 
836
 
 
837
    REGCOMP_I(pat);
 
838
    SUBS(str, pat, parse_iso22_cb);
 
839
}
 
840
 
 
841
static int
 
842
parse_iso23_cb(VALUE m, VALUE hash)
 
843
{
 
844
    VALUE mon, d;
 
845
 
 
846
    mon = rb_reg_nth_match(1, m);
 
847
    d = rb_reg_nth_match(2, m);
 
848
 
 
849
    if (!NIL_P(mon))
 
850
        set_hash("mon", str2num(mon));
 
851
    set_hash("mday", str2num(d));
 
852
 
 
853
    return 1;
 
854
}
 
855
 
 
856
static int
 
857
parse_iso23(VALUE str, VALUE hash)
 
858
{
 
859
    static const char pat_source[] = "--(\\d{2})?-(\\d{2})\\b";
 
860
    static VALUE pat = Qnil;
 
861
 
 
862
    REGCOMP_0(pat);
 
863
    SUBS(str, pat, parse_iso23_cb);
 
864
}
 
865
 
 
866
static int
 
867
parse_iso24_cb(VALUE m, VALUE hash)
 
868
{
 
869
    VALUE mon, d;
 
870
 
 
871
    mon = rb_reg_nth_match(1, m);
 
872
    d = rb_reg_nth_match(2, m);
 
873
 
 
874
    set_hash("mon", str2num(mon));
 
875
    if (!NIL_P(d))
 
876
        set_hash("mday", str2num(d));
 
877
 
 
878
    return 1;
 
879
}
 
880
 
 
881
static int
 
882
parse_iso24(VALUE str, VALUE hash)
 
883
{
 
884
    static const char pat_source[] = "--(\\d{2})(\\d{2})?\\b";
 
885
    static VALUE pat = Qnil;
 
886
 
 
887
    REGCOMP_0(pat);
 
888
    SUBS(str, pat, parse_iso24_cb);
 
889
}
 
890
 
 
891
static int
 
892
parse_iso25_cb(VALUE m, VALUE hash)
 
893
{
 
894
    VALUE y, d;
 
895
 
 
896
    y = rb_reg_nth_match(1, m);
 
897
    d = rb_reg_nth_match(2, m);
 
898
 
 
899
    set_hash("year", str2num(y));
 
900
    set_hash("yday", str2num(d));
 
901
 
 
902
    return 1;
 
903
}
 
904
 
 
905
static int
 
906
parse_iso25(VALUE str, VALUE hash)
 
907
{
 
908
    static const char pat0_source[] = "[,.](\\d{2}|\\d{4})-\\d{3}\\b";
 
909
    static VALUE pat0 = Qnil;
 
910
    static const char pat_source[] = "\\b(\\d{2}|\\d{4})-(\\d{3})\\b";
 
911
    static VALUE pat = Qnil;
 
912
 
 
913
    REGCOMP_0(pat0);
 
914
    REGCOMP_0(pat);
 
915
 
 
916
    if (!NIL_P(f_match(pat0, str)))
 
917
        return 0;
 
918
    SUBS(str, pat, parse_iso25_cb);
 
919
}
 
920
 
 
921
static int
 
922
parse_iso26_cb(VALUE m, VALUE hash)
 
923
{
 
924
    VALUE d;
 
925
 
 
926
    d = rb_reg_nth_match(1, m);
 
927
    set_hash("yday", str2num(d));
 
928
 
 
929
    return 1;
 
930
}
 
931
static int
 
932
parse_iso26(VALUE str, VALUE hash)
 
933
{
 
934
    static const char pat0_source[] = "\\d-\\d{3}\\b";
 
935
    static VALUE pat0 = Qnil;
 
936
    static const char pat_source[] = "\\b-(\\d{3})\\b";
 
937
    static VALUE pat = Qnil;
 
938
 
 
939
    REGCOMP_0(pat0);
 
940
    REGCOMP_0(pat);
 
941
 
 
942
    if (!NIL_P(f_match(pat0, str)))
 
943
        return 0;
 
944
    SUBS(str, pat, parse_iso26_cb);
 
945
}
 
946
 
 
947
static int
 
948
parse_iso2(VALUE str, VALUE hash)
 
949
{
 
950
    if (parse_iso21(str, hash))
 
951
        goto ok;
 
952
    if (parse_iso22(str, hash))
 
953
        goto ok;
 
954
    if (parse_iso23(str, hash))
 
955
        goto ok;
 
956
    if (parse_iso24(str, hash))
 
957
        goto ok;
 
958
    if (parse_iso25(str, hash))
 
959
        goto ok;
 
960
    if (parse_iso26(str, hash))
 
961
        goto ok;
 
962
    return 0;
 
963
 
 
964
  ok:
 
965
    return 1;
 
966
}
 
967
 
 
968
static int
 
969
gengo(int c)
 
970
{
 
971
    int e;
 
972
 
 
973
    switch (c) {
 
974
      case 'M': case 'm': e = 1867; break;
 
975
      case 'T': case 't': e = 1911; break;
 
976
      case 'S': case 's': e = 1925; break;
 
977
      case 'H': case 'h': e = 1988; break;
 
978
      default:  e = 0; break;
 
979
    }
 
980
    return e;
 
981
}
 
982
 
 
983
static int
 
984
parse_jis_cb(VALUE m, VALUE hash)
 
985
{
 
986
    VALUE e, y, mon, d;
 
987
    int ep;
 
988
 
 
989
    e = rb_reg_nth_match(1, m);
 
990
    y = rb_reg_nth_match(2, m);
 
991
    mon = rb_reg_nth_match(3, m);
 
992
    d = rb_reg_nth_match(4, m);
 
993
 
 
994
    ep = gengo(*RSTRING_PTR(e));
 
995
 
 
996
    set_hash("year", f_add(str2num(y), INT2FIX(ep)));
 
997
    set_hash("mon", str2num(mon));
 
998
    set_hash("mday", str2num(d));
 
999
 
 
1000
    return 1;
 
1001
}
 
1002
 
 
1003
static int
 
1004
parse_jis(VALUE str, VALUE hash)
 
1005
{
 
1006
    static const char pat_source[] = "\\b([mtsh])(\\d+)\\.(\\d+)\\.(\\d+)";
 
1007
    static VALUE pat = Qnil;
 
1008
 
 
1009
    REGCOMP_I(pat);
 
1010
    SUBS(str, pat, parse_jis_cb);
 
1011
}
 
1012
 
 
1013
static int
 
1014
parse_vms11_cb(VALUE m, VALUE hash)
 
1015
{
 
1016
    VALUE y, mon, d;
 
1017
 
 
1018
    d = rb_reg_nth_match(1, m);
 
1019
    mon = rb_reg_nth_match(2, m);
 
1020
    y = rb_reg_nth_match(3, m);
 
1021
 
 
1022
    mon = INT2FIX(mon_num(mon));
 
1023
 
 
1024
    s3e(hash, y, mon, d, 0);
 
1025
    return 1;
 
1026
}
 
1027
 
 
1028
static int
 
1029
parse_vms11(VALUE str, VALUE hash)
 
1030
{
 
1031
    static const char pat_source[] =
 
1032
        "('?-?\\d+)-(" ABBR_MONTHS ")[^-]*"
 
1033
        "-('?-?\\d+)";
 
1034
    static VALUE pat = Qnil;
 
1035
 
 
1036
    REGCOMP_I(pat);
 
1037
    SUBS(str, pat, parse_vms11_cb);
 
1038
}
 
1039
 
 
1040
static int
 
1041
parse_vms12_cb(VALUE m, VALUE hash)
 
1042
{
 
1043
    VALUE y, mon, d;
 
1044
 
 
1045
    mon = rb_reg_nth_match(1, m);
 
1046
    d = rb_reg_nth_match(2, m);
 
1047
    y = rb_reg_nth_match(3, m);
 
1048
 
 
1049
    mon = INT2FIX(mon_num(mon));
 
1050
 
 
1051
    s3e(hash, y, mon, d, 0);
 
1052
    return 1;
 
1053
}
 
1054
 
 
1055
static int
 
1056
parse_vms12(VALUE str, VALUE hash)
 
1057
{
 
1058
    static const char pat_source[] =
 
1059
        "\\b(" ABBR_MONTHS ")[^-]*"
 
1060
        "-('?-?\\d+)(?:-('?-?\\d+))?";
 
1061
    static VALUE pat = Qnil;
 
1062
 
 
1063
    REGCOMP_I(pat);
 
1064
    SUBS(str, pat, parse_vms12_cb);
 
1065
}
 
1066
 
 
1067
static int
 
1068
parse_vms(VALUE str, VALUE hash)
 
1069
{
 
1070
    if (parse_vms11(str, hash))
 
1071
        goto ok;
 
1072
    if (parse_vms12(str, hash))
 
1073
        goto ok;
 
1074
    return 0;
 
1075
 
 
1076
  ok:
 
1077
    return 1;
 
1078
}
 
1079
 
 
1080
static int
 
1081
parse_sla_cb(VALUE m, VALUE hash)
 
1082
{
 
1083
    VALUE y, mon, d;
 
1084
 
 
1085
    y = rb_reg_nth_match(1, m);
 
1086
    mon = rb_reg_nth_match(2, m);
 
1087
    d = rb_reg_nth_match(3, m);
 
1088
 
 
1089
    s3e(hash, y, mon, d, 0);
 
1090
    return 1;
 
1091
}
 
1092
 
 
1093
static int
 
1094
parse_sla(VALUE str, VALUE hash)
 
1095
{
 
1096
    static const char pat_source[] =
 
1097
        "('?-?\\d+)/\\s*('?\\d+)(?:\\D\\s*('?-?\\d+))?";
 
1098
    static VALUE pat = Qnil;
 
1099
 
 
1100
    REGCOMP_I(pat);
 
1101
    SUBS(str, pat, parse_sla_cb);
 
1102
}
 
1103
 
 
1104
static int
 
1105
parse_dot_cb(VALUE m, VALUE hash)
 
1106
{
 
1107
    VALUE y, mon, d;
 
1108
 
 
1109
    y = rb_reg_nth_match(1, m);
 
1110
    mon = rb_reg_nth_match(2, m);
 
1111
    d = rb_reg_nth_match(3, m);
 
1112
 
 
1113
    s3e(hash, y, mon, d, 0);
 
1114
    return 1;
 
1115
}
 
1116
 
 
1117
static int
 
1118
parse_dot(VALUE str, VALUE hash)
 
1119
{
 
1120
    static const char pat_source[] =
 
1121
        "('?-?\\d+)\\.\\s*('?\\d+)\\.\\s*('?-?\\d+)";
 
1122
    static VALUE pat = Qnil;
 
1123
 
 
1124
    REGCOMP_I(pat);
 
1125
    SUBS(str, pat, parse_dot_cb);
 
1126
}
 
1127
 
 
1128
static int
 
1129
parse_year_cb(VALUE m, VALUE hash)
 
1130
{
 
1131
    VALUE y;
 
1132
 
 
1133
    y = rb_reg_nth_match(1, m);
 
1134
    set_hash("year", str2num(y));
 
1135
    return 1;
 
1136
}
 
1137
 
 
1138
static int
 
1139
parse_year(VALUE str, VALUE hash)
 
1140
{
 
1141
    static const char pat_source[] = "'(\\d+)\\b";
 
1142
    static VALUE pat = Qnil;
 
1143
 
 
1144
    REGCOMP_0(pat);
 
1145
    SUBS(str, pat, parse_year_cb);
 
1146
}
 
1147
 
 
1148
static int
 
1149
parse_mon_cb(VALUE m, VALUE hash)
 
1150
{
 
1151
    VALUE mon;
 
1152
 
 
1153
    mon = rb_reg_nth_match(1, m);
 
1154
    set_hash("mon", INT2FIX(mon_num(mon)));
 
1155
    return 1;
 
1156
}
 
1157
 
 
1158
static int
 
1159
parse_mon(VALUE str, VALUE hash)
 
1160
{
 
1161
    static const char pat_source[] = "\\b(" ABBR_MONTHS ")\\S*";
 
1162
    static VALUE pat = Qnil;
 
1163
 
 
1164
    REGCOMP_I(pat);
 
1165
    SUBS(str, pat, parse_mon_cb);
 
1166
}
 
1167
 
 
1168
static int
 
1169
parse_mday_cb(VALUE m, VALUE hash)
 
1170
{
 
1171
    VALUE d;
 
1172
 
 
1173
    d = rb_reg_nth_match(1, m);
 
1174
    set_hash("mday", str2num(d));
 
1175
    return 1;
 
1176
}
 
1177
 
 
1178
static int
 
1179
parse_mday(VALUE str, VALUE hash)
 
1180
{
 
1181
    static const char pat_source[] = "(\\d+)(st|nd|rd|th)\\b";
 
1182
    static VALUE pat = Qnil;
 
1183
 
 
1184
    REGCOMP_I(pat);
 
1185
    SUBS(str, pat, parse_mday_cb);
 
1186
}
 
1187
 
 
1188
static int
 
1189
n2i(const char *s, long f, long w)
 
1190
{
 
1191
    long e, i;
 
1192
    int v;
 
1193
 
 
1194
    e = f + w;
 
1195
    v = 0;
 
1196
    for (i = f; i < e; i++) {
 
1197
        v *= 10;
 
1198
        v += s[i] - '0';
 
1199
    }
 
1200
    return v;
 
1201
}
 
1202
 
 
1203
static int
 
1204
parse_ddd_cb(VALUE m, VALUE hash)
 
1205
{
 
1206
    VALUE s1, s2, s3, s4, s5;
 
1207
    const char *cs2, *cs3, *cs5;
 
1208
    long l2, l3, l4, l5;
 
1209
 
 
1210
    s1 = rb_reg_nth_match(1, m);
 
1211
    s2 = rb_reg_nth_match(2, m);
 
1212
    s3 = rb_reg_nth_match(3, m);
 
1213
    s4 = rb_reg_nth_match(4, m);
 
1214
    s5 = rb_reg_nth_match(5, m);
 
1215
 
 
1216
    cs2 = RSTRING_PTR(s2);
 
1217
    l2 = RSTRING_LEN(s2);
 
1218
 
 
1219
    switch (l2) {
 
1220
      case 2:
 
1221
        if (NIL_P(s3) && !NIL_P(s4))
 
1222
            set_hash("sec",  INT2FIX(n2i(cs2, l2-2, 2)));
 
1223
        else
 
1224
            set_hash("mday", INT2FIX(n2i(cs2,    0, 2)));
 
1225
        break;
 
1226
      case 4:
 
1227
        if (NIL_P(s3) && !NIL_P(s4)) {
 
1228
            set_hash("sec",  INT2FIX(n2i(cs2, l2-2, 2)));
 
1229
            set_hash("min",  INT2FIX(n2i(cs2, l2-4, 2)));
 
1230
        }
 
1231
        else {
 
1232
            set_hash("mon",  INT2FIX(n2i(cs2,    0, 2)));
 
1233
            set_hash("mday", INT2FIX(n2i(cs2,    2, 2)));
 
1234
        }
 
1235
        break;
 
1236
      case 6:
 
1237
        if (NIL_P(s3) && !NIL_P(s4)) {
 
1238
            set_hash("sec",  INT2FIX(n2i(cs2, l2-2, 2)));
 
1239
            set_hash("min",  INT2FIX(n2i(cs2, l2-4, 2)));
 
1240
            set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
 
1241
        }
 
1242
        else {
 
1243
            int                  y = n2i(cs2,    0, 2);
 
1244
            if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
 
1245
                y = -y;
 
1246
            set_hash("year", INT2FIX(y));
 
1247
            set_hash("mon",  INT2FIX(n2i(cs2,    2, 2)));
 
1248
            set_hash("mday", INT2FIX(n2i(cs2,    4, 2)));
 
1249
        }
 
1250
        break;
 
1251
      case 8:
 
1252
      case 10:
 
1253
      case 12:
 
1254
      case 14:
 
1255
        if (NIL_P(s3) && !NIL_P(s4)) {
 
1256
            set_hash("sec",  INT2FIX(n2i(cs2, l2-2, 2)));
 
1257
            set_hash("min",  INT2FIX(n2i(cs2, l2-4, 2)));
 
1258
            set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
 
1259
            set_hash("mday", INT2FIX(n2i(cs2, l2-8, 2)));
 
1260
            if (l2 >= 10)
 
1261
                set_hash("mon", INT2FIX(n2i(cs2, l2-10, 2)));
 
1262
            if (l2 == 12) {
 
1263
                int y = n2i(cs2, l2-12, 2);
 
1264
                if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
 
1265
                    y = -y;
 
1266
                set_hash("year", INT2FIX(y));
 
1267
            }
 
1268
            if (l2 == 14) {
 
1269
                int y = n2i(cs2, l2-14, 4);
 
1270
                if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
 
1271
                    y = -y;
 
1272
                set_hash("year", INT2FIX(y));
 
1273
                set_hash("_comp", Qfalse);
 
1274
            }
 
1275
        }
 
1276
        else {
 
1277
            int                  y = n2i(cs2,    0, 4);
 
1278
            if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
 
1279
                y = -y;
 
1280
            set_hash("year", INT2FIX(y));
 
1281
            set_hash("mon",  INT2FIX(n2i(cs2,    4, 2)));
 
1282
            set_hash("mday", INT2FIX(n2i(cs2,    6, 2)));
 
1283
            if (l2 >= 10)
 
1284
                set_hash("hour", INT2FIX(n2i(cs2,    8, 2)));
 
1285
            if (l2 >= 12)
 
1286
                set_hash("min",  INT2FIX(n2i(cs2,   10, 2)));
 
1287
            if (l2 >= 14)
 
1288
                set_hash("sec",  INT2FIX(n2i(cs2,   12, 2)));
 
1289
            set_hash("_comp", Qfalse);
 
1290
        }
 
1291
        break;
 
1292
      case 3:
 
1293
        if (NIL_P(s3) && !NIL_P(s4)) {
 
1294
            set_hash("sec",  INT2FIX(n2i(cs2, l2-2, 2)));
 
1295
            set_hash("min",  INT2FIX(n2i(cs2, l2-3, 1)));
 
1296
        }
 
1297
        else
 
1298
            set_hash("yday", INT2FIX(n2i(cs2,    0, 3)));
 
1299
        break;
 
1300
      case 5:
 
1301
        if (NIL_P(s3) && !NIL_P(s4)) {
 
1302
            set_hash("sec",  INT2FIX(n2i(cs2, l2-2, 2)));
 
1303
            set_hash("min",  INT2FIX(n2i(cs2, l2-4, 2)));
 
1304
            set_hash("hour", INT2FIX(n2i(cs2, l2-5, 1)));
 
1305
        }
 
1306
        else {
 
1307
            int                  y = n2i(cs2,    0, 2);
 
1308
            if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
 
1309
                y = -y;
 
1310
            set_hash("year", INT2FIX(y));
 
1311
            set_hash("yday", INT2FIX(n2i(cs2,    2, 3)));
 
1312
        }
 
1313
        break;
 
1314
      case 7:
 
1315
        if (NIL_P(s3) && !NIL_P(s4)) {
 
1316
            set_hash("sec",  INT2FIX(n2i(cs2, l2-2, 2)));
 
1317
            set_hash("min",  INT2FIX(n2i(cs2, l2-4, 2)));
 
1318
            set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
 
1319
            set_hash("mday", INT2FIX(n2i(cs2, l2-7, 1)));
 
1320
        }
 
1321
        else {
 
1322
            int                  y = n2i(cs2,    0, 4);
 
1323
            if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
 
1324
                y = -y;
 
1325
            set_hash("year", INT2FIX(y));
 
1326
            set_hash("yday", INT2FIX(n2i(cs2,    4, 3)));
 
1327
        }
 
1328
        break;
 
1329
    }
 
1330
    RB_GC_GUARD(s2);
 
1331
    if (!NIL_P(s3)) {
 
1332
        cs3 = RSTRING_PTR(s3);
 
1333
        l3 = RSTRING_LEN(s3);
 
1334
 
 
1335
        if (!NIL_P(s4)) {
 
1336
            switch (l3) {
 
1337
              case 2:
 
1338
              case 4:
 
1339
              case 6:
 
1340
                set_hash("sec", INT2FIX(n2i(cs3, l3-2, 2)));
 
1341
                if (l3 >= 4)
 
1342
                    set_hash("min", INT2FIX(n2i(cs3, l3-4, 2)));
 
1343
                if (l3 >= 6)
 
1344
                    set_hash("hour", INT2FIX(n2i(cs3, l3-6, 2)));
 
1345
                break;
 
1346
            }
 
1347
        }
 
1348
        else {
 
1349
            switch (l3) {
 
1350
              case 2:
 
1351
              case 4:
 
1352
              case 6:
 
1353
                set_hash("hour", INT2FIX(n2i(cs3, 0, 2)));
 
1354
                if (l3 >= 4)
 
1355
                    set_hash("min", INT2FIX(n2i(cs3, 2, 2)));
 
1356
                if (l3 >= 6)
 
1357
                    set_hash("sec", INT2FIX(n2i(cs3, 4, 2)));
 
1358
                break;
 
1359
            }
 
1360
        }
 
1361
        RB_GC_GUARD(s3);
 
1362
    }
 
1363
    if (!NIL_P(s4)) {
 
1364
        l4 = RSTRING_LEN(s4);
 
1365
 
 
1366
        set_hash("sec_fraction",
 
1367
                 rb_rational_new2(str2num(s4),
 
1368
                                  f_expt(INT2FIX(10), LONG2NUM(l4))));
 
1369
    }
 
1370
    if (!NIL_P(s5)) {
 
1371
        cs5 = RSTRING_PTR(s5);
 
1372
        l5 = RSTRING_LEN(s5);
 
1373
 
 
1374
        set_hash("zone", s5);
 
1375
 
 
1376
        if (*cs5 == '[') {
 
1377
            char *buf = ALLOCA_N(char, l5 + 1);
 
1378
            char *s1, *s2, *s3;
 
1379
            VALUE zone;
 
1380
 
 
1381
            memcpy(buf, cs5, l5);
 
1382
            buf[l5 - 1] = '\0';
 
1383
 
 
1384
            s1 = buf + 1;
 
1385
            s2 = strchr(buf, ':');
 
1386
            if (s2) {
 
1387
                *s2 = '\0';
 
1388
                s2++;
 
1389
            }
 
1390
            if (s2)
 
1391
                s3 = s2;
 
1392
            else
 
1393
                s3 = s1;
 
1394
            zone = rb_str_new2(s3);
 
1395
            set_hash("zone", zone);
 
1396
            if (isdigit(*s1))
 
1397
                *--s1 = '+';
 
1398
            set_hash("offset", date_zone_to_diff(rb_str_new2(s1)));
 
1399
        }
 
1400
        RB_GC_GUARD(s5);
 
1401
    }
 
1402
 
 
1403
    return 1;
 
1404
}
 
1405
 
 
1406
static int
 
1407
parse_ddd(VALUE str, VALUE hash)
 
1408
{
 
1409
    static const char pat_source[] =
 
1410
                "([-+]?)(\\d{2,14})"
 
1411
                  "(?:"
 
1412
                    "\\s*"
 
1413
                    "t?"
 
1414
                    "\\s*"
 
1415
                    "(\\d{2,6})?(?:[,.](\\d*))?"
 
1416
                  ")?"
 
1417
                  "(?:"
 
1418
                    "\\s*"
 
1419
                    "("
 
1420
                      "z\\b"
 
1421
                    "|"
 
1422
                      "[-+]\\d{1,4}\\b"
 
1423
                    "|"
 
1424
                      "\\[[-+]?\\d[^\\]]*\\]"
 
1425
                    ")"
 
1426
                ")?";
 
1427
    static VALUE pat = Qnil;
 
1428
 
 
1429
    REGCOMP_I(pat);
 
1430
    SUBS(str, pat, parse_ddd_cb);
 
1431
}
 
1432
 
 
1433
static int
 
1434
parse_bc_cb(VALUE m, VALUE hash)
 
1435
{
 
1436
    VALUE y;
 
1437
 
 
1438
    y = ref_hash("year");
 
1439
    if (!NIL_P(y))
 
1440
        set_hash("year", f_add(f_negate(y), INT2FIX(1)));
 
1441
 
 
1442
    return 1;
 
1443
}
 
1444
 
 
1445
static int
 
1446
parse_bc(VALUE str, VALUE hash)
 
1447
{
 
1448
    static const char pat_source[] =
 
1449
        "\\b(bc\\b|bce\\b|b\\.c\\.|b\\.c\\.e\\.)";
 
1450
    static VALUE pat = Qnil;
 
1451
 
 
1452
    REGCOMP_I(pat);
 
1453
    SUBS(str, pat, parse_bc_cb);
 
1454
}
 
1455
 
 
1456
static int
 
1457
parse_frag_cb(VALUE m, VALUE hash)
 
1458
{
 
1459
    VALUE s, n;
 
1460
 
 
1461
    s = rb_reg_nth_match(1, m);
 
1462
 
 
1463
    if (!NIL_P(ref_hash("hour")) && NIL_P(ref_hash("mday"))) {
 
1464
        n = str2num(s);
 
1465
        if (f_ge_p(n, INT2FIX(1)) &&
 
1466
            f_le_p(n, INT2FIX(31)))
 
1467
            set_hash("mday", n);
 
1468
    }
 
1469
    if (!NIL_P(ref_hash("mday")) && NIL_P(ref_hash("hour"))) {
 
1470
        n = str2num(s);
 
1471
        if (f_ge_p(n, INT2FIX(0)) &&
 
1472
            f_le_p(n, INT2FIX(24)))
 
1473
            set_hash("hour", n);
 
1474
    }
 
1475
 
 
1476
    return 1;
 
1477
}
 
1478
 
 
1479
static int
 
1480
parse_frag(VALUE str, VALUE hash)
 
1481
{
 
1482
    static const char pat_source[] = "\\A\\s*(\\d{1,2})\\s*\\z";
 
1483
    static VALUE pat = Qnil;
 
1484
 
 
1485
    REGCOMP_I(pat);
 
1486
    SUBS(str, pat, parse_frag_cb);
 
1487
}
 
1488
 
 
1489
#define HAVE_ALPHA (1<<0)
 
1490
#define HAVE_DIGIT (1<<1)
 
1491
#define HAVE_DASH (1<<2)
 
1492
#define HAVE_DOT (1<<3)
 
1493
#define HAVE_SLASH (1<<4)
 
1494
 
 
1495
static unsigned
 
1496
check_class(VALUE s)
 
1497
{
 
1498
    unsigned flags;
 
1499
    long i;
 
1500
 
 
1501
    flags = 0;
 
1502
    for (i = 0; i < RSTRING_LEN(s); i++) {
 
1503
        if (isalpha(RSTRING_PTR(s)[i]))
 
1504
            flags |= HAVE_ALPHA;
 
1505
        if (isdigit(RSTRING_PTR(s)[i]))
 
1506
            flags |= HAVE_DIGIT;
 
1507
        if (RSTRING_PTR(s)[i] == '-')
 
1508
            flags |= HAVE_DASH;
 
1509
        if (RSTRING_PTR(s)[i] == '.')
 
1510
            flags |= HAVE_DOT;
 
1511
        if (RSTRING_PTR(s)[i] == '/')
 
1512
            flags |= HAVE_SLASH;
 
1513
    }
 
1514
    return flags;
 
1515
}
 
1516
 
 
1517
#define HAVE_ELEM_P(x) ((check_class(str) & (x)) == (x))
 
1518
 
 
1519
VALUE
 
1520
date__parse(VALUE str, VALUE comp)
 
1521
{
 
1522
    VALUE backref, hash;
 
1523
 
 
1524
    backref = rb_backref_get();
 
1525
    rb_match_busy(backref);
 
1526
 
 
1527
    {
 
1528
        static const char pat_source[] = "[^-+',./:@[:alnum:]\\[\\]]+";
 
1529
        static VALUE pat = Qnil;
 
1530
 
 
1531
        REGCOMP_0(pat);
 
1532
        str = rb_str_dup(str);
 
1533
        f_gsub_bang(str, pat, asp_string());
 
1534
    }
 
1535
 
 
1536
    hash = rb_hash_new();
 
1537
    set_hash("_comp", comp);
 
1538
 
 
1539
    if (HAVE_ELEM_P(HAVE_ALPHA))
 
1540
        parse_day(str, hash);
 
1541
    if (HAVE_ELEM_P(HAVE_DIGIT))
 
1542
        parse_time(str, hash);
 
1543
 
 
1544
    if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT))
 
1545
        if (parse_eu(str, hash))
 
1546
            goto ok;
 
1547
    if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT))
 
1548
        if (parse_us(str, hash))
 
1549
            goto ok;
 
1550
    if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DASH))
 
1551
        if (parse_iso(str, hash))
 
1552
            goto ok;
 
1553
    if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DOT))
 
1554
        if (parse_jis(str, hash))
 
1555
            goto ok;
 
1556
    if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT|HAVE_DASH))
 
1557
        if (parse_vms(str, hash))
 
1558
            goto ok;
 
1559
    if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_SLASH))
 
1560
        if (parse_sla(str, hash))
 
1561
            goto ok;
 
1562
    if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DOT))
 
1563
        if (parse_dot(str, hash))
 
1564
            goto ok;
 
1565
    if (HAVE_ELEM_P(HAVE_DIGIT))
 
1566
        if (parse_iso2(str, hash))
 
1567
            goto ok;
 
1568
    if (HAVE_ELEM_P(HAVE_DIGIT))
 
1569
        if (parse_year(str, hash))
 
1570
            goto ok;
 
1571
    if (HAVE_ELEM_P(HAVE_ALPHA))
 
1572
        if (parse_mon(str, hash))
 
1573
            goto ok;
 
1574
    if (HAVE_ELEM_P(HAVE_DIGIT))
 
1575
        if (parse_mday(str, hash))
 
1576
            goto ok;
 
1577
    if (HAVE_ELEM_P(HAVE_DIGIT))
 
1578
        if (parse_ddd(str, hash))
 
1579
            goto ok;
 
1580
 
 
1581
  ok:
 
1582
    if (HAVE_ELEM_P(HAVE_ALPHA))
 
1583
        parse_bc(str, hash);
 
1584
    if (HAVE_ELEM_P(HAVE_DIGIT))
 
1585
        parse_frag(str, hash);
 
1586
 
 
1587
    {
 
1588
        if (RTEST(ref_hash("_comp"))) {
 
1589
            VALUE y;
 
1590
 
 
1591
            y = ref_hash("cwyear");
 
1592
            if (!NIL_P(y))
 
1593
                if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) {
 
1594
                    if (f_ge_p(y, INT2FIX(69)))
 
1595
                        set_hash("cwyear", f_add(y, INT2FIX(1900)));
 
1596
                    else
 
1597
                        set_hash("cwyear", f_add(y, INT2FIX(2000)));
 
1598
                }
 
1599
            y = ref_hash("year");
 
1600
            if (!NIL_P(y))
 
1601
                if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) {
 
1602
                    if (f_ge_p(y, INT2FIX(69)))
 
1603
                        set_hash("year", f_add(y, INT2FIX(1900)));
 
1604
                    else
 
1605
                        set_hash("year", f_add(y, INT2FIX(2000)));
 
1606
                }
 
1607
        }
 
1608
    }
 
1609
 
 
1610
    del_hash("_comp");
 
1611
 
 
1612
    {
 
1613
        VALUE zone = ref_hash("zone");
 
1614
        if (!NIL_P(zone) && NIL_P(ref_hash("offset")))
 
1615
            set_hash("offset", date_zone_to_diff(zone));
 
1616
    }
 
1617
 
 
1618
    rb_backref_set(backref);
 
1619
 
 
1620
    return hash;
 
1621
}
 
1622
 
 
1623
static VALUE
 
1624
comp_year69(VALUE y)
 
1625
{
 
1626
    if (f_ge_p(y, INT2FIX(69)))
 
1627
        return f_add(y, INT2FIX(1900));
 
1628
    return f_add(y, INT2FIX(2000));
 
1629
}
 
1630
 
 
1631
static VALUE
 
1632
comp_year50(VALUE y)
 
1633
{
 
1634
    if (f_ge_p(y, INT2FIX(50)))
 
1635
        return f_add(y, INT2FIX(1900));
 
1636
    return f_add(y, INT2FIX(2000));
 
1637
}
 
1638
 
 
1639
static VALUE
 
1640
sec_fraction(VALUE f)
 
1641
{
 
1642
    return rb_rational_new2(str2num(f),
 
1643
                            f_expt(INT2FIX(10),
 
1644
                                   LONG2NUM(RSTRING_LEN(f))));
 
1645
}
 
1646
 
 
1647
#define SNUM 14
 
1648
 
 
1649
static int
 
1650
iso8601_ext_datetime_cb(VALUE m, VALUE hash)
 
1651
{
 
1652
    VALUE s[SNUM + 1], y;
 
1653
 
 
1654
    {
 
1655
        int i;
 
1656
        s[0] = Qnil;
 
1657
        for (i = 1; i <= SNUM; i++)
 
1658
            s[i] = rb_reg_nth_match(i, m);
 
1659
    }
 
1660
 
 
1661
    if (!NIL_P(s[3])) {
 
1662
        set_hash("mday", str2num(s[3]));
 
1663
        if (strcmp(RSTRING_PTR(s[1]), "-") != 0) {
 
1664
            y = str2num(s[1]);
 
1665
            if (RSTRING_LEN(s[1]) < 4)
 
1666
                y = comp_year69(y);
 
1667
            set_hash("year", y);
 
1668
        }
 
1669
        if (NIL_P(s[2])) {
 
1670
            if (strcmp(RSTRING_PTR(s[1]), "-") != 0)
 
1671
                return 0;
 
1672
        }
 
1673
        else
 
1674
            set_hash("mon", str2num(s[2]));
 
1675
    }
 
1676
    else if (!NIL_P(s[5])) {
 
1677
        set_hash("yday", str2num(s[5]));
 
1678
        if (!NIL_P(s[4])) {
 
1679
            y = str2num(s[4]);
 
1680
            if (RSTRING_LEN(s[4]) < 4)
 
1681
                y = comp_year69(y);
 
1682
            set_hash("year", y);
 
1683
        }
 
1684
    }
 
1685
    else if (!NIL_P(s[8])) {
 
1686
        set_hash("cweek", str2num(s[7]));
 
1687
        set_hash("cwday", str2num(s[8]));
 
1688
        if (!NIL_P(s[6])) {
 
1689
            y = str2num(s[6]);
 
1690
            if (RSTRING_LEN(s[6]) < 4)
 
1691
                y = comp_year69(y);
 
1692
            set_hash("cwyear", y);
 
1693
        }
 
1694
    }
 
1695
    else if (!NIL_P(s[9])) {
 
1696
        set_hash("cwday", str2num(s[9]));
 
1697
    }
 
1698
    if (!NIL_P(s[10])) {
 
1699
        set_hash("hour", str2num(s[10]));
 
1700
        set_hash("min", str2num(s[11]));
 
1701
        if (!NIL_P(s[12]))
 
1702
            set_hash("sec", str2num(s[12]));
 
1703
    }
 
1704
    if (!NIL_P(s[13])) {
 
1705
        set_hash("sec_fraction", sec_fraction(s[13]));
 
1706
    }
 
1707
    if (!NIL_P(s[14])) {
 
1708
        set_hash("zone", s[14]);
 
1709
        set_hash("offset", date_zone_to_diff(s[14]));
 
1710
    }
 
1711
 
 
1712
    return 1;
 
1713
}
 
1714
 
 
1715
static int
 
1716
iso8601_ext_datetime(VALUE str, VALUE hash)
 
1717
{
 
1718
    static const char pat_source[] =
 
1719
        "\\A\\s*(?:([-+]?\\d{2,}|-)-(\\d{2})?-(\\d{2})|"
 
1720
                "([-+]?\\d{2,})?-(\\d{3})|"
 
1721
                "(\\d{4}|\\d{2})?-w(\\d{2})-(\\d)|"
 
1722
                "-w-(\\d))"
 
1723
        "(?:t"
 
1724
        "(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?)?"
 
1725
        "(z|[-+]\\d{2}(?::?\\d{2})?)?)?\\s*\\z";
 
1726
    static VALUE pat = Qnil;
 
1727
 
 
1728
    REGCOMP_I(pat);
 
1729
    SUBS(str, pat, iso8601_ext_datetime_cb);
 
1730
}
 
1731
 
 
1732
#undef SNUM
 
1733
#define SNUM 17
 
1734
 
 
1735
static int
 
1736
iso8601_bas_datetime_cb(VALUE m, VALUE hash)
 
1737
{
 
1738
    VALUE s[SNUM + 1], y;
 
1739
 
 
1740
    {
 
1741
        int i;
 
1742
        s[0] = Qnil;
 
1743
        for (i = 1; i <= SNUM; i++)
 
1744
            s[i] = rb_reg_nth_match(i, m);
 
1745
    }
 
1746
 
 
1747
    if (!NIL_P(s[3])) {
 
1748
        set_hash("mday", str2num(s[3]));
 
1749
        if (strcmp(RSTRING_PTR(s[1]), "--") != 0) {
 
1750
            y = str2num(s[1]);
 
1751
            if (RSTRING_LEN(s[1]) < 4)
 
1752
                y = comp_year69(y);
 
1753
            set_hash("year", y);
 
1754
        }
 
1755
        if (*RSTRING_PTR(s[2]) == '-') {
 
1756
            if (strcmp(RSTRING_PTR(s[1]), "--") != 0)
 
1757
                return 0;
 
1758
        }
 
1759
        else
 
1760
            set_hash("mon", str2num(s[2]));
 
1761
    }
 
1762
    else if (!NIL_P(s[5])) {
 
1763
        set_hash("yday", str2num(s[5]));
 
1764
        y = str2num(s[4]);
 
1765
        if (RSTRING_LEN(s[4]) < 4)
 
1766
            y = comp_year69(y);
 
1767
        set_hash("year", y);
 
1768
    }
 
1769
    else if (!NIL_P(s[6])) {
 
1770
        set_hash("yday", str2num(s[6]));
 
1771
    }
 
1772
    else if (!NIL_P(s[9])) {
 
1773
        set_hash("cweek", str2num(s[8]));
 
1774
        set_hash("cwday", str2num(s[9]));
 
1775
        y = str2num(s[7]);
 
1776
        if (RSTRING_LEN(s[7]) < 4)
 
1777
            y = comp_year69(y);
 
1778
        set_hash("cwyear", y);
 
1779
    }
 
1780
    else if (!NIL_P(s[11])) {
 
1781
        set_hash("cweek", str2num(s[10]));
 
1782
        set_hash("cwday", str2num(s[11]));
 
1783
    }
 
1784
    else if (!NIL_P(s[12])) {
 
1785
        set_hash("cwday", str2num(s[12]));
 
1786
    }
 
1787
    if (!NIL_P(s[13])) {
 
1788
        set_hash("hour", str2num(s[13]));
 
1789
        set_hash("min", str2num(s[14]));
 
1790
        if (!NIL_P(s[15]))
 
1791
            set_hash("sec", str2num(s[15]));
 
1792
    }
 
1793
    if (!NIL_P(s[16])) {
 
1794
        set_hash("sec_fraction", sec_fraction(s[16]));
 
1795
    }
 
1796
    if (!NIL_P(s[17])) {
 
1797
        set_hash("zone", s[17]);
 
1798
        set_hash("offset", date_zone_to_diff(s[17]));
 
1799
    }
 
1800
 
 
1801
    return 1;
 
1802
}
 
1803
 
 
1804
static int
 
1805
iso8601_bas_datetime(VALUE str, VALUE hash)
 
1806
{
 
1807
    static const char pat_source[] =
 
1808
        "\\A\\s*(?:([-+]?(?:\\d{4}|\\d{2})|--)(\\d{2}|-)(\\d{2})|"
 
1809
                   "([-+]?(?:\\d{4}|\\d{2}))(\\d{3})|"
 
1810
                   "-(\\d{3})|"
 
1811
                   "(\\d{4}|\\d{2})w(\\d{2})(\\d)|"
 
1812
                   "-w(\\d{2})(\\d)|"
 
1813
                   "-w-(\\d))"
 
1814
        "(?:t?"
 
1815
        "(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?)?"
 
1816
        "(z|[-+]\\d{2}(?:\\d{2})?)?)?\\s*\\z";
 
1817
    static VALUE pat = Qnil;
 
1818
 
 
1819
    REGCOMP_I(pat);
 
1820
    SUBS(str, pat, iso8601_bas_datetime_cb);
 
1821
}
 
1822
 
 
1823
#undef SNUM
 
1824
#define SNUM 5
 
1825
 
 
1826
static int
 
1827
iso8601_ext_time_cb(VALUE m, VALUE hash)
 
1828
{
 
1829
    VALUE s[SNUM + 1];
 
1830
 
 
1831
    {
 
1832
        int i;
 
1833
        s[0] = Qnil;
 
1834
        for (i = 1; i <= SNUM; i++)
 
1835
            s[i] = rb_reg_nth_match(i, m);
 
1836
    }
 
1837
 
 
1838
    set_hash("hour", str2num(s[1]));
 
1839
    set_hash("min", str2num(s[2]));
 
1840
    if (!NIL_P(s[3]))
 
1841
        set_hash("sec", str2num(s[3]));
 
1842
    if (!NIL_P(s[4]))
 
1843
        set_hash("sec_fraction", sec_fraction(s[4]));
 
1844
    if (!NIL_P(s[5])) {
 
1845
        set_hash("zone", s[5]);
 
1846
        set_hash("offset", date_zone_to_diff(s[5]));
 
1847
    }
 
1848
 
 
1849
    return 1;
 
1850
}
 
1851
 
 
1852
#define iso8601_bas_time_cb iso8601_ext_time_cb
 
1853
 
 
1854
static int
 
1855
iso8601_ext_time(VALUE str, VALUE hash)
 
1856
{
 
1857
    static const char pat_source[] =
 
1858
        "\\A\\s*(?:(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?)?"
 
1859
        "(z|[-+]\\d{2}(:?\\d{2})?)?)?\\s*\\z";
 
1860
    static VALUE pat = Qnil;
 
1861
 
 
1862
    REGCOMP_I(pat);
 
1863
    SUBS(str, pat, iso8601_ext_time_cb);
 
1864
}
 
1865
 
 
1866
static int
 
1867
iso8601_bas_time(VALUE str, VALUE hash)
 
1868
{
 
1869
    static const char pat_source[] =
 
1870
        "\\A\\s*(?:(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?)?"
 
1871
        "(z|[-+]\\d{2}(\\d{2})?)?)?\\s*\\z";
 
1872
    static VALUE pat = Qnil;
 
1873
 
 
1874
    REGCOMP_I(pat);
 
1875
    SUBS(str, pat, iso8601_bas_time_cb);
 
1876
}
 
1877
 
 
1878
VALUE
 
1879
date__iso8601(VALUE str)
 
1880
{
 
1881
    VALUE backref, hash;
 
1882
 
 
1883
    backref = rb_backref_get();
 
1884
    rb_match_busy(backref);
 
1885
 
 
1886
    hash = rb_hash_new();
 
1887
 
 
1888
    if (iso8601_ext_datetime(str, hash))
 
1889
        goto ok;
 
1890
    if (iso8601_bas_datetime(str, hash))
 
1891
        goto ok;
 
1892
    if (iso8601_ext_time(str, hash))
 
1893
        goto ok;
 
1894
    if (iso8601_bas_time(str, hash))
 
1895
        goto ok;
 
1896
 
 
1897
  ok:
 
1898
    rb_backref_set(backref);
 
1899
 
 
1900
    return hash;
 
1901
}
 
1902
 
 
1903
#undef SNUM
 
1904
#define SNUM 8
 
1905
 
 
1906
static int
 
1907
rfc3339_cb(VALUE m, VALUE hash)
 
1908
{
 
1909
    VALUE s[SNUM + 1];
 
1910
 
 
1911
    {
 
1912
        int i;
 
1913
        s[0] = Qnil;
 
1914
        for (i = 1; i <= SNUM; i++)
 
1915
            s[i] = rb_reg_nth_match(i, m);
 
1916
    }
 
1917
 
 
1918
    set_hash("year", str2num(s[1]));
 
1919
    set_hash("mon", str2num(s[2]));
 
1920
    set_hash("mday", str2num(s[3]));
 
1921
    set_hash("hour", str2num(s[4]));
 
1922
    set_hash("min", str2num(s[5]));
 
1923
    set_hash("sec", str2num(s[6]));
 
1924
    set_hash("zone", s[8]);
 
1925
    set_hash("offset", date_zone_to_diff(s[8]));
 
1926
    if (!NIL_P(s[7]))
 
1927
        set_hash("sec_fraction", sec_fraction(s[7]));
 
1928
 
 
1929
    return 1;
 
1930
}
 
1931
 
 
1932
static int
 
1933
rfc3339(VALUE str, VALUE hash)
 
1934
{
 
1935
    static const char pat_source[] =
 
1936
        "\\A\\s*(-?\\d{4})-(\\d{2})-(\\d{2})"
 
1937
        "(?:t|\\s)"
 
1938
        "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?"
 
1939
        "(z|[-+]\\d{2}:\\d{2})\\s*\\z";
 
1940
    static VALUE pat = Qnil;
 
1941
 
 
1942
    REGCOMP_I(pat);
 
1943
    SUBS(str, pat, rfc3339_cb);
 
1944
}
 
1945
 
 
1946
VALUE
 
1947
date__rfc3339(VALUE str)
 
1948
{
 
1949
    VALUE backref, hash;
 
1950
 
 
1951
    backref = rb_backref_get();
 
1952
    rb_match_busy(backref);
 
1953
 
 
1954
    hash = rb_hash_new();
 
1955
    rfc3339(str, hash);
 
1956
    rb_backref_set(backref);
 
1957
    return hash;
 
1958
}
 
1959
 
 
1960
#undef SNUM
 
1961
#define SNUM 8
 
1962
 
 
1963
static int
 
1964
xmlschema_datetime_cb(VALUE m, VALUE hash)
 
1965
{
 
1966
    VALUE s[SNUM + 1];
 
1967
 
 
1968
    {
 
1969
        int i;
 
1970
        s[0] = Qnil;
 
1971
        for (i = 1; i <= SNUM; i++)
 
1972
            s[i] = rb_reg_nth_match(i, m);
 
1973
    }
 
1974
 
 
1975
    set_hash("year", str2num(s[1]));
 
1976
    if (!NIL_P(s[2]))
 
1977
        set_hash("mon", str2num(s[2]));
 
1978
    if (!NIL_P(s[3]))
 
1979
        set_hash("mday", str2num(s[3]));
 
1980
    if (!NIL_P(s[4]))
 
1981
        set_hash("hour", str2num(s[4]));
 
1982
    if (!NIL_P(s[5]))
 
1983
        set_hash("min", str2num(s[5]));
 
1984
    if (!NIL_P(s[6]))
 
1985
        set_hash("sec", str2num(s[6]));
 
1986
    if (!NIL_P(s[7]))
 
1987
        set_hash("sec_fraction", sec_fraction(s[7]));
 
1988
    if (!NIL_P(s[8])) {
 
1989
        set_hash("zone", s[8]);
 
1990
        set_hash("offset", date_zone_to_diff(s[8]));
 
1991
    }
 
1992
 
 
1993
    return 1;
 
1994
}
 
1995
 
 
1996
static int
 
1997
xmlschema_datetime(VALUE str, VALUE hash)
 
1998
{
 
1999
    static const char pat_source[] =
 
2000
        "\\A\\s*(-?\\d{4,})(?:-(\\d{2})(?:-(\\d{2}))?)?"
 
2001
        "(?:t"
 
2002
          "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?)?"
 
2003
        "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
 
2004
    static VALUE pat = Qnil;
 
2005
 
 
2006
    REGCOMP_I(pat);
 
2007
    SUBS(str, pat, xmlschema_datetime_cb);
 
2008
}
 
2009
 
 
2010
#undef SNUM
 
2011
#define SNUM 5
 
2012
 
 
2013
static int
 
2014
xmlschema_time_cb(VALUE m, VALUE hash)
 
2015
{
 
2016
    VALUE s[SNUM + 1];
 
2017
 
 
2018
    {
 
2019
        int i;
 
2020
        s[0] = Qnil;
 
2021
        for (i = 1; i <= SNUM; i++)
 
2022
            s[i] = rb_reg_nth_match(i, m);
 
2023
    }
 
2024
 
 
2025
    set_hash("hour", str2num(s[1]));
 
2026
    set_hash("min", str2num(s[2]));
 
2027
    if (!NIL_P(s[3]))
 
2028
        set_hash("sec", str2num(s[3]));
 
2029
    if (!NIL_P(s[4]))
 
2030
        set_hash("sec_fraction", sec_fraction(s[4]));
 
2031
    if (!NIL_P(s[5])) {
 
2032
        set_hash("zone", s[5]);
 
2033
        set_hash("offset", date_zone_to_diff(s[5]));
 
2034
    }
 
2035
 
 
2036
    return 1;
 
2037
}
 
2038
 
 
2039
static int
 
2040
xmlschema_time(VALUE str, VALUE hash)
 
2041
{
 
2042
    static const char pat_source[] =
 
2043
        "\\A\\s*(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?"
 
2044
        "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
 
2045
    static VALUE pat = Qnil;
 
2046
 
 
2047
    REGCOMP_I(pat);
 
2048
    SUBS(str, pat, xmlschema_time_cb);
 
2049
}
 
2050
 
 
2051
#undef SNUM
 
2052
#define SNUM 4
 
2053
 
 
2054
static int
 
2055
xmlschema_trunc_cb(VALUE m, VALUE hash)
 
2056
{
 
2057
    VALUE s[SNUM + 1];
 
2058
 
 
2059
    {
 
2060
        int i;
 
2061
        s[0] = Qnil;
 
2062
        for (i = 1; i <= SNUM; i++)
 
2063
            s[i] = rb_reg_nth_match(i, m);
 
2064
    }
 
2065
 
 
2066
    if (!NIL_P(s[1]))
 
2067
        set_hash("mon", str2num(s[1]));
 
2068
    if (!NIL_P(s[2]))
 
2069
        set_hash("mday", str2num(s[2]));
 
2070
    if (!NIL_P(s[3]))
 
2071
        set_hash("mday", str2num(s[3]));
 
2072
    if (!NIL_P(s[4])) {
 
2073
        set_hash("zone", s[4]);
 
2074
        set_hash("offset", date_zone_to_diff(s[4]));
 
2075
    }
 
2076
 
 
2077
    return 1;
 
2078
}
 
2079
 
 
2080
static int
 
2081
xmlschema_trunc(VALUE str, VALUE hash)
 
2082
{
 
2083
    static const char pat_source[] =
 
2084
        "\\A\\s*(?:--(\\d{2})(?:-(\\d{2}))?|---(\\d{2}))"
 
2085
        "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
 
2086
    static VALUE pat = Qnil;
 
2087
 
 
2088
    REGCOMP_I(pat);
 
2089
    SUBS(str, pat, xmlschema_trunc_cb);
 
2090
}
 
2091
 
 
2092
VALUE
 
2093
date__xmlschema(VALUE str)
 
2094
{
 
2095
    VALUE backref, hash;
 
2096
 
 
2097
    backref = rb_backref_get();
 
2098
    rb_match_busy(backref);
 
2099
 
 
2100
    hash = rb_hash_new();
 
2101
 
 
2102
    if (xmlschema_datetime(str, hash))
 
2103
        goto ok;
 
2104
    if (xmlschema_time(str, hash))
 
2105
        goto ok;
 
2106
    if (xmlschema_trunc(str, hash))
 
2107
        goto ok;
 
2108
 
 
2109
  ok:
 
2110
    rb_backref_set(backref);
 
2111
 
 
2112
    return hash;
 
2113
}
 
2114
 
 
2115
#undef SNUM
 
2116
#define SNUM 8
 
2117
 
 
2118
static int
 
2119
rfc2822_cb(VALUE m, VALUE hash)
 
2120
{
 
2121
    VALUE s[SNUM + 1], y;
 
2122
 
 
2123
    {
 
2124
        int i;
 
2125
        s[0] = Qnil;
 
2126
        for (i = 1; i <= SNUM; i++)
 
2127
            s[i] = rb_reg_nth_match(i, m);
 
2128
    }
 
2129
 
 
2130
    set_hash("wday", INT2FIX(day_num(s[1])));
 
2131
    set_hash("mday", str2num(s[2]));
 
2132
    set_hash("mon", INT2FIX(mon_num(s[3])));
 
2133
    y = str2num(s[4]);
 
2134
    if (RSTRING_LEN(s[4]) < 4)
 
2135
        y = comp_year50(y);
 
2136
    set_hash("year", y);
 
2137
    set_hash("hour", str2num(s[5]));
 
2138
    set_hash("min", str2num(s[6]));
 
2139
    if (!NIL_P(s[7]))
 
2140
        set_hash("sec", str2num(s[7]));
 
2141
    set_hash("zone", s[8]);
 
2142
    set_hash("offset", date_zone_to_diff(s[8]));
 
2143
 
 
2144
    return 1;
 
2145
}
 
2146
 
 
2147
static int
 
2148
rfc2822(VALUE str, VALUE hash)
 
2149
{
 
2150
    static const char pat_source[] =
 
2151
        "\\A\\s*(?:(" ABBR_DAYS ")\\s*,\\s+)?"
 
2152
        "(\\d{1,2})\\s+"
 
2153
        "(" ABBR_MONTHS ")\\s+"
 
2154
        "(-?\\d{2,})\\s+"
 
2155
        "(\\d{2}):(\\d{2})(?::(\\d{2}))?\\s*"
 
2156
        "([-+]\\d{4}|ut|gmt|e[sd]t|c[sd]t|m[sd]t|p[sd]t|[a-ik-z])\\s*\\z";
 
2157
    static VALUE pat = Qnil;
 
2158
 
 
2159
    REGCOMP_I(pat);
 
2160
    SUBS(str, pat, rfc2822_cb);
 
2161
}
 
2162
 
 
2163
VALUE
 
2164
date__rfc2822(VALUE str)
 
2165
{
 
2166
    VALUE backref, hash;
 
2167
 
 
2168
    backref = rb_backref_get();
 
2169
    rb_match_busy(backref);
 
2170
 
 
2171
    hash = rb_hash_new();
 
2172
    rfc2822(str, hash);
 
2173
    rb_backref_set(backref);
 
2174
    return hash;
 
2175
}
 
2176
 
 
2177
#undef SNUM
 
2178
#define SNUM 8
 
2179
 
 
2180
static int
 
2181
httpdate_type1_cb(VALUE m, VALUE hash)
 
2182
{
 
2183
    VALUE s[SNUM + 1];
 
2184
 
 
2185
    {
 
2186
        int i;
 
2187
        s[0] = Qnil;
 
2188
        for (i = 1; i <= SNUM; i++)
 
2189
            s[i] = rb_reg_nth_match(i, m);
 
2190
    }
 
2191
 
 
2192
    set_hash("wday", INT2FIX(day_num(s[1])));
 
2193
    set_hash("mday", str2num(s[2]));
 
2194
    set_hash("mon", INT2FIX(mon_num(s[3])));
 
2195
    set_hash("year", str2num(s[4]));
 
2196
    set_hash("hour", str2num(s[5]));
 
2197
    set_hash("min", str2num(s[6]));
 
2198
    set_hash("sec", str2num(s[7]));
 
2199
    set_hash("zone", s[8]);
 
2200
    set_hash("offset", INT2FIX(0));
 
2201
 
 
2202
    return 1;
 
2203
}
 
2204
 
 
2205
static int
 
2206
httpdate_type1(VALUE str, VALUE hash)
 
2207
{
 
2208
    static const char pat_source[] =
 
2209
        "\\A\\s*(" ABBR_DAYS ")\\s*,\\s+"
 
2210
        "(\\d{2})\\s+"
 
2211
        "(" ABBR_MONTHS ")\\s+"
 
2212
        "(-?\\d{4})\\s+"
 
2213
        "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
 
2214
        "(gmt)\\s*\\z";
 
2215
    static VALUE pat = Qnil;
 
2216
 
 
2217
    REGCOMP_I(pat);
 
2218
    SUBS(str, pat, httpdate_type1_cb);
 
2219
}
 
2220
 
 
2221
#undef SNUM
 
2222
#define SNUM 8
 
2223
 
 
2224
static int
 
2225
httpdate_type2_cb(VALUE m, VALUE hash)
 
2226
{
 
2227
    VALUE s[SNUM + 1], y;
 
2228
 
 
2229
    {
 
2230
        int i;
 
2231
        s[0] = Qnil;
 
2232
        for (i = 1; i <= SNUM; i++)
 
2233
            s[i] = rb_reg_nth_match(i, m);
 
2234
    }
 
2235
 
 
2236
    set_hash("wday", INT2FIX(day_num(s[1])));
 
2237
    set_hash("mday", str2num(s[2]));
 
2238
    set_hash("mon", INT2FIX(mon_num(s[3])));
 
2239
    y = str2num(s[4]);
 
2240
    if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99)))
 
2241
        y = comp_year69(y);
 
2242
    set_hash("year", y);
 
2243
    set_hash("hour", str2num(s[5]));
 
2244
    set_hash("min", str2num(s[6]));
 
2245
    set_hash("sec", str2num(s[7]));
 
2246
    set_hash("zone", s[8]);
 
2247
    set_hash("offset", INT2FIX(0));
 
2248
 
 
2249
    return 1;
 
2250
}
 
2251
 
 
2252
static int
 
2253
httpdate_type2(VALUE str, VALUE hash)
 
2254
{
 
2255
    static const char pat_source[] =
 
2256
        "\\A\\s*(" DAYS ")\\s*,\\s+"
 
2257
        "(\\d{2})\\s*-\\s*"
 
2258
        "(" ABBR_MONTHS ")\\s*-\\s*"
 
2259
        "(\\d{2})\\s+"
 
2260
        "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
 
2261
        "(gmt)\\s*\\z";
 
2262
    static VALUE pat = Qnil;
 
2263
 
 
2264
    REGCOMP_I(pat);
 
2265
    SUBS(str, pat, httpdate_type2_cb);
 
2266
}
 
2267
 
 
2268
#undef SNUM
 
2269
#define SNUM 7
 
2270
 
 
2271
static int
 
2272
httpdate_type3_cb(VALUE m, VALUE hash)
 
2273
{
 
2274
    VALUE s[SNUM + 1];
 
2275
 
 
2276
    {
 
2277
        int i;
 
2278
        s[0] = Qnil;
 
2279
        for (i = 1; i <= SNUM; i++)
 
2280
            s[i] = rb_reg_nth_match(i, m);
 
2281
    }
 
2282
 
 
2283
    set_hash("wday", INT2FIX(day_num(s[1])));
 
2284
    set_hash("mon", INT2FIX(mon_num(s[2])));
 
2285
    set_hash("mday", str2num(s[3]));
 
2286
    set_hash("hour", str2num(s[4]));
 
2287
    set_hash("min", str2num(s[5]));
 
2288
    set_hash("sec", str2num(s[6]));
 
2289
    set_hash("year", str2num(s[7]));
 
2290
 
 
2291
    return 1;
 
2292
}
 
2293
 
 
2294
static int
 
2295
httpdate_type3(VALUE str, VALUE hash)
 
2296
{
 
2297
    static const char pat_source[] =
 
2298
        "\\A\\s*(" ABBR_DAYS ")\\s+"
 
2299
        "(" ABBR_MONTHS ")\\s+"
 
2300
        "(\\d{1,2})\\s+"
 
2301
        "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
 
2302
        "(\\d{4})\\s*\\z";
 
2303
    static VALUE pat = Qnil;
 
2304
 
 
2305
    REGCOMP_I(pat);
 
2306
    SUBS(str, pat, httpdate_type3_cb);
 
2307
}
 
2308
 
 
2309
VALUE
 
2310
date__httpdate(VALUE str)
 
2311
{
 
2312
    VALUE backref, hash;
 
2313
 
 
2314
    backref = rb_backref_get();
 
2315
    rb_match_busy(backref);
 
2316
 
 
2317
    hash = rb_hash_new();
 
2318
 
 
2319
    if (httpdate_type1(str, hash))
 
2320
        goto ok;
 
2321
    if (httpdate_type2(str, hash))
 
2322
        goto ok;
 
2323
    if (httpdate_type3(str, hash))
 
2324
        goto ok;
 
2325
 
 
2326
  ok:
 
2327
    rb_backref_set(backref);
 
2328
 
 
2329
    return hash;
 
2330
}
 
2331
 
 
2332
#undef SNUM
 
2333
#define SNUM 9
 
2334
 
 
2335
static int
 
2336
jisx0301_cb(VALUE m, VALUE hash)
 
2337
{
 
2338
    VALUE s[SNUM + 1];
 
2339
    int ep;
 
2340
 
 
2341
    {
 
2342
        int i;
 
2343
        s[0] = Qnil;
 
2344
        for (i = 1; i <= SNUM; i++)
 
2345
            s[i] = rb_reg_nth_match(i, m);
 
2346
    }
 
2347
 
 
2348
    ep = gengo(NIL_P(s[1]) ? 'h' : *RSTRING_PTR(s[1]));
 
2349
    set_hash("year", f_add(str2num(s[2]), INT2FIX(ep)));
 
2350
    set_hash("mon", str2num(s[3]));
 
2351
    set_hash("mday", str2num(s[4]));
 
2352
    if (!NIL_P(s[5])) {
 
2353
        set_hash("hour", str2num(s[5]));
 
2354
        if (!NIL_P(s[6]))
 
2355
            set_hash("min", str2num(s[6]));
 
2356
        if (!NIL_P(s[7]))
 
2357
            set_hash("sec", str2num(s[7]));
 
2358
    }
 
2359
    if (!NIL_P(s[8]))
 
2360
        set_hash("sec_fraction", sec_fraction(s[8]));
 
2361
    if (!NIL_P(s[9])) {
 
2362
        set_hash("zone", s[9]);
 
2363
        set_hash("offset", date_zone_to_diff(s[9]));
 
2364
    }
 
2365
 
 
2366
    return 1;
 
2367
}
 
2368
 
 
2369
static int
 
2370
jisx0301(VALUE str, VALUE hash)
 
2371
{
 
2372
    static const char pat_source[] =
 
2373
        "\\A\\s*([mtsh])?(\\d{2})\\.(\\d{2})\\.(\\d{2})"
 
2374
        "(?:t"
 
2375
        "(?:(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d*))?)?"
 
2376
        "(z|[-+]\\d{2}(?::?\\d{2})?)?)?)?\\s*\\z";
 
2377
    static VALUE pat = Qnil;
 
2378
 
 
2379
    REGCOMP_I(pat);
 
2380
    SUBS(str, pat, jisx0301_cb);
 
2381
}
 
2382
 
 
2383
VALUE
 
2384
date__jisx0301(VALUE str)
 
2385
{
 
2386
    VALUE backref, hash;
 
2387
 
 
2388
    backref = rb_backref_get();
 
2389
    rb_match_busy(backref);
 
2390
 
 
2391
    hash = rb_hash_new();
 
2392
    if (jisx0301(str, hash))
 
2393
        goto ok;
 
2394
    hash = date__iso8601(str);
 
2395
 
 
2396
  ok:
 
2397
    rb_backref_set(backref);
 
2398
    return hash;
 
2399
}
 
2400
 
 
2401
/*
 
2402
Local variables:
 
2403
c-file-style: "ruby"
 
2404
End:
 
2405
*/