Ruby 2.0.0p353(2013-11-22revision43784)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

date_core.c
Go to the documentation of this file.
1 /*
2 date_core.c: Coded by Tadayoshi Funaba 2010-2013
3 */
4
5 #include "ruby.h"
6 #include "ruby/encoding.h"
7 #include <math.h>
8 #include <time.h>
9
10 #define NDEBUG
11 #include <assert.h>
12
13 #ifdef RUBY_EXTCONF_H
14 #include RUBY_EXTCONF_H
15 #endif
16
17 #define USE_PACK
18
19 static ID id_cmp, id_le_p, id_ge_p, id_eqeq_p;
20 static VALUE cDate, cDateTime;
21 static VALUE half_days_in_day, day_in_nanoseconds;
22 static double positive_inf, negative_inf;
23
24 #define f_boolcast(x) ((x) ? Qtrue : Qfalse)
25
26 #define f_abs(x) rb_funcall(x, rb_intern("abs"), 0)
27 #define f_negate(x) rb_funcall(x, rb_intern("-@"), 0)
28 #define f_add(x,y) rb_funcall(x, '+', 1, y)
29 #define f_sub(x,y) rb_funcall(x, '-', 1, y)
30 #define f_mul(x,y) rb_funcall(x, '*', 1, y)
31 #define f_div(x,y) rb_funcall(x, '/', 1, y)
32 #define f_quo(x,y) rb_funcall(x, rb_intern("quo"), 1, y)
33 #define f_idiv(x,y) rb_funcall(x, rb_intern("div"), 1, y)
34 #define f_mod(x,y) rb_funcall(x, '%', 1, y)
35 #define f_remainder(x,y) rb_funcall(x, rb_intern("remainder"), 1, y)
36 #define f_expt(x,y) rb_funcall(x, rb_intern("**"), 1, y)
37 #define f_floor(x) rb_funcall(x, rb_intern("floor"), 0)
38 #define f_ceil(x) rb_funcall(x, rb_intern("ceil"), 0)
39 #define f_truncate(x) rb_funcall(x, rb_intern("truncate"), 0)
40 #define f_round(x) rb_funcall(x, rb_intern("round"), 0)
41
42 #define f_to_i(x) rb_funcall(x, rb_intern("to_i"), 0)
43 #define f_to_r(x) rb_funcall(x, rb_intern("to_r"), 0)
44 #define f_to_s(x) rb_funcall(x, rb_intern("to_s"), 0)
45 #define f_inspect(x) rb_funcall(x, rb_intern("inspect"), 0)
46
47 #define f_add3(x,y,z) f_add(f_add(x, y), z)
48 #define f_sub3(x,y,z) f_sub(f_sub(x, y), z)
49
50 inline static VALUE
51 f_cmp(VALUE x, VALUE y)
52 {
53 if (FIXNUM_P(x) && FIXNUM_P(y)) {
54 long c = FIX2LONG(x) - FIX2LONG(y);
55 if (c > 0)
56 c = 1;
57 else if (c < 0)
58 c = -1;
59 return INT2FIX(c);
60 }
61 return rb_funcall(x, id_cmp, 1, y);
62 }
63
64 inline static VALUE
65 f_lt_p(VALUE x, VALUE y)
66 {
67 if (FIXNUM_P(x) && FIXNUM_P(y))
68 return f_boolcast(FIX2LONG(x) < FIX2LONG(y));
69 return rb_funcall(x, '<', 1, y);
70 }
71
72 inline static VALUE
73 f_gt_p(VALUE x, VALUE y)
74 {
75 if (FIXNUM_P(x) && FIXNUM_P(y))
76 return f_boolcast(FIX2LONG(x) > FIX2LONG(y));
77 return rb_funcall(x, '>', 1, y);
78 }
79
80 inline static VALUE
81 f_le_p(VALUE x, VALUE y)
82 {
83 if (FIXNUM_P(x) && FIXNUM_P(y))
84 return f_boolcast(FIX2LONG(x) <= FIX2LONG(y));
85 return rb_funcall(x, id_le_p, 1, y);
86 }
87
88 inline static VALUE
89 f_ge_p(VALUE x, VALUE y)
90 {
91 if (FIXNUM_P(x) && FIXNUM_P(y))
92 return f_boolcast(FIX2LONG(x) >= FIX2LONG(y));
93 return rb_funcall(x, rb_intern(">="), 1, y);
94 }
95
96 inline static VALUE
97 f_eqeq_p(VALUE x, VALUE y)
98 {
99 if (FIXNUM_P(x) && FIXNUM_P(y))
100 return f_boolcast(FIX2LONG(x) == FIX2LONG(y));
101 return rb_funcall(x, rb_intern("=="), 1, y);
102 }
103
104 inline static VALUE
105 f_zero_p(VALUE x)
106 {
107 switch (TYPE(x)) {
108 case T_FIXNUM:
109 return f_boolcast(FIX2LONG(x) == 0);
110 case T_BIGNUM:
111 return Qfalse;
112 case T_RATIONAL:
113 {
114 VALUE num = RRATIONAL(x)->num;
115 return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 0);
116 }
117 }
118 return rb_funcall(x, id_eqeq_p, 1, INT2FIX(0));
119 }
120
121 #define f_nonzero_p(x) (!f_zero_p(x))
122
123 inline static VALUE
124 f_negative_p(VALUE x)
125 {
126 if (FIXNUM_P(x))
127 return f_boolcast(FIX2LONG(x) < 0);
128 return rb_funcall(x, '<', 1, INT2FIX(0));
129 }
130
131 #define f_positive_p(x) (!f_negative_p(x))
132
133 #define f_ajd(x) rb_funcall(x, rb_intern("ajd"), 0)
134 #define f_jd(x) rb_funcall(x, rb_intern("jd"), 0)
135 #define f_year(x) rb_funcall(x, rb_intern("year"), 0)
136 #define f_mon(x) rb_funcall(x, rb_intern("mon"), 0)
137 #define f_mday(x) rb_funcall(x, rb_intern("mday"), 0)
138 #define f_wday(x) rb_funcall(x, rb_intern("wday"), 0)
139 #define f_hour(x) rb_funcall(x, rb_intern("hour"), 0)
140 #define f_min(x) rb_funcall(x, rb_intern("min"), 0)
141 #define f_sec(x) rb_funcall(x, rb_intern("sec"), 0)
142
143 /* copied from time.c */
144 #define NDIV(x,y) (-(-((x)+1)/(y))-1)
145 #define NMOD(x,y) ((y)-(-((x)+1)%(y))-1)
146 #define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d))
147 #define MOD(n,d) ((n)<0 ? NMOD((n),(d)) : (n)%(d))
148
149 #define HAVE_JD (1 << 0)
150 #define HAVE_DF (1 << 1)
151 #define HAVE_CIVIL (1 << 2)
152 #define HAVE_TIME (1 << 3)
153 #define COMPLEX_DAT (1 << 7)
154
155 #define have_jd_p(x) ((x)->flags & HAVE_JD)
156 #define have_df_p(x) ((x)->flags & HAVE_DF)
157 #define have_civil_p(x) ((x)->flags & HAVE_CIVIL)
158 #define have_time_p(x) ((x)->flags & HAVE_TIME)
159 #define complex_dat_p(x) ((x)->flags & COMPLEX_DAT)
160 #define simple_dat_p(x) (!complex_dat_p(x))
161
162 #define ITALY 2299161 /* 1582-10-15 */
163 #define ENGLAND 2361222 /* 1752-09-14 */
164 #define JULIAN positive_inf
165 #define GREGORIAN negative_inf
166 #define DEFAULT_SG ITALY
167
168 #define UNIX_EPOCH_IN_CJD INT2FIX(2440588) /* 1970-01-01 */
169
170 #define MINUTE_IN_SECONDS 60
171 #define HOUR_IN_SECONDS 3600
172 #define DAY_IN_SECONDS 86400
173 #define SECOND_IN_MILLISECONDS 1000
174 #define SECOND_IN_NANOSECONDS 1000000000
175
176 #define JC_PERIOD0 1461 /* 365.25 * 4 */
177 #define GC_PERIOD0 146097 /* 365.2425 * 400 */
178 #define CM_PERIOD0 71149239 /* (lcm 7 1461 146097) */
179 #define CM_PERIOD (0xfffffff / CM_PERIOD0 * CM_PERIOD0)
180 #define CM_PERIOD_JCY (CM_PERIOD / JC_PERIOD0 * 4)
181 #define CM_PERIOD_GCY (CM_PERIOD / GC_PERIOD0 * 400)
182
183 #define REFORM_BEGIN_YEAR 1582
184 #define REFORM_END_YEAR 1930
185 #define REFORM_BEGIN_JD 2298874 /* ns 1582-01-01 */
186 #define REFORM_END_JD 2426355 /* os 1930-12-31 */
187
188 #ifdef USE_PACK
189 #define SEC_WIDTH 6
190 #define MIN_WIDTH 6
191 #define HOUR_WIDTH 5
192 #define MDAY_WIDTH 5
193 #define MON_WIDTH 4
194
195 #define SEC_SHIFT 0
196 #define MIN_SHIFT SEC_WIDTH
197 #define HOUR_SHIFT (MIN_WIDTH + SEC_WIDTH)
198 #define MDAY_SHIFT (HOUR_WIDTH + MIN_WIDTH + SEC_WIDTH)
199 #define MON_SHIFT (MDAY_WIDTH + HOUR_WIDTH + MIN_WIDTH + SEC_WIDTH)
200
201 #define PK_MASK(x) ((1 << (x)) - 1)
202
203 #define EX_SEC(x) (((x) >> SEC_SHIFT) & PK_MASK(SEC_WIDTH))
204 #define EX_MIN(x) (((x) >> MIN_SHIFT) & PK_MASK(MIN_WIDTH))
205 #define EX_HOUR(x) (((x) >> HOUR_SHIFT) & PK_MASK(HOUR_WIDTH))
206 #define EX_MDAY(x) (((x) >> MDAY_SHIFT) & PK_MASK(MDAY_WIDTH))
207 #define EX_MON(x) (((x) >> MON_SHIFT) & PK_MASK(MON_WIDTH))
208
209 #define PACK5(m,d,h,min,s) \
210 (((m) << MON_SHIFT) | ((d) << MDAY_SHIFT) |\
211 ((h) << HOUR_SHIFT) | ((min) << MIN_SHIFT) | ((s) << SEC_SHIFT))
212
213 #define PACK2(m,d) \
214 (((m) << MON_SHIFT) | ((d) << MDAY_SHIFT))
215 #endif
216
217 #ifdef HAVE_FLOAT_H
218 #include <float.h>
219 #endif
220
221 #if defined(FLT_RADIX) && defined(FLT_MANT_DIG) && FLT_RADIX == 2 && FLT_MANT_DIG > 22
222 #define date_sg_t float
223 #else
224 #define date_sg_t double
225 #endif
226
227 /* A set of nth, jd, df and sf denote ajd + 1/2. Each ajd begin at
228 * noon of GMT (assume equal to UTC). However, this begins at
229 * midnight.
230 */
231
232 struct SimpleDateData
233 {
234 unsigned flags;
235 VALUE nth; /* not always canonicalized */
236 int jd; /* as utc */
237 /* df is zero */
238 /* sf is zero */
239 /* of is zero */
240 date_sg_t sg; /* 2298874..2426355 or -/+oo -- at most 22 bits */
241 /* decoded as utc=local */
242 int year; /* truncated */
243 #ifndef USE_PACK
244 int mon;
245 int mday;
246 /* hour is zero */
247 /* min is zero */
248 /* sec is zero */
249 #else
250 /* packed civil */
251 unsigned pc;
252 #endif
253 };
254
255 struct ComplexDateData
256 {
257 unsigned flags;
258 VALUE nth; /* not always canonicalized */
259 int jd; /* as utc */
260 int df; /* as utc, in secs */
261 VALUE sf; /* in nano secs */
262 int of; /* in secs */
263 date_sg_t sg; /* 2298874..2426355 or -/+oo -- at most 22 bits */
264 /* decoded as local */
265 int year; /* truncated */
266 #ifndef USE_PACK
267 int mon;
268 int mday;
269 int hour;
270 int min;
271 int sec;
272 #else
273 /* packed civil */
274 unsigned pc;
275 #endif
276 };
277
278 union DateData {
279 unsigned flags;
280 struct SimpleDateData s;
281 struct ComplexDateData c;
282 };
283
284 #define get_d1(x)\
285 union DateData *dat;\
286 Data_Get_Struct(x, union DateData, dat);
287
288 #define get_d1a(x)\
289 union DateData *adat;\
290 Data_Get_Struct(x, union DateData, adat);
291
292 #define get_d1b(x)\
293 union DateData *bdat;\
294 Data_Get_Struct(x, union DateData, bdat);
295
296 #define get_d2(x,y)\
297 union DateData *adat, *bdat;\
298 Data_Get_Struct(x, union DateData, adat);\
299 Data_Get_Struct(y, union DateData, bdat);
300
301 inline static VALUE
302 canon(VALUE x)
303 {
304 if (TYPE(x) == T_RATIONAL) {
305 VALUE den = RRATIONAL(x)->den;
306 if (FIXNUM_P(den) && FIX2LONG(den) == 1)
307 return RRATIONAL(x)->num;
308 }
309 return x;
310 }
311
312 #ifndef USE_PACK
313 #define set_to_simple(x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \
314 {\
315 (x)->nth = canon(_nth);\
316 (x)->jd = _jd;\
317 (x)->sg = (date_sg_t)(_sg);\
318 (x)->year = _year;\
319 (x)->mon = _mon;\
320 (x)->mday = _mday;\
321 (x)->flags = _flags;\
322 }
323 #else
324 #define set_to_simple(x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \
325 {\
326 (x)->nth = canon(_nth);\
327 (x)->jd = _jd;\
328 (x)->sg = (date_sg_t)(_sg);\
329 (x)->year = _year;\
330 (x)->pc = PACK2(_mon, _mday);\
331 (x)->flags = _flags;\
332 }
333 #endif
334
335 #ifndef USE_PACK
336 #define set_to_complex(x, _nth, _jd ,_df, _sf, _of, _sg,\
337 _year, _mon, _mday, _hour, _min, _sec, _flags) \
338 {\
339 (x)->nth = canon(_nth);\
340 (x)->jd = _jd;\
341 (x)->df = _df;\
342 (x)->sf = canon(_sf);\
343 (x)->of = _of;\
344 (x)->sg = (date_sg_t)(_sg);\
345 (x)->year = _year;\
346 (x)->mon = _mon;\
347 (x)->mday = _mday;\
348 (x)->hour = _hour;\
349 (x)->min = _min;\
350 (x)->sec = _sec;\
351 (x)->flags = _flags;\
352 }
353 #else
354 #define set_to_complex(x, _nth, _jd ,_df, _sf, _of, _sg,\
355 _year, _mon, _mday, _hour, _min, _sec, _flags) \
356 {\
357 (x)->nth = canon(_nth);\
358 (x)->jd = _jd;\
359 (x)->df = _df;\
360 (x)->sf = canon(_sf);\
361 (x)->of = _of;\
362 (x)->sg = (date_sg_t)(_sg);\
363 (x)->year = _year;\
364 (x)->pc = PACK5(_mon, _mday, _hour, _min, _sec);\
365 (x)->flags = _flags;\
366 }
367 #endif
368
369 #ifndef USE_PACK
370 #define copy_simple_to_complex(x, y) \
371 {\
372 (x)->nth = (y)->nth;\
373 (x)->jd = (y)->jd;\
374 (x)->df = 0;\
375 (x)->sf = INT2FIX(0);\
376 (x)->of = 0;\
377 (x)->sg = (date_sg_t)((y)->sg);\
378 (x)->year = (y)->year;\
379 (x)->mon = (y)->mon;\
380 (x)->mday = (y)->mday;\
381 (x)->hour = 0;\
382 (x)->min = 0;\
383 (x)->sec = 0;\
384 (x)->flags = (y)->flags;\
385 }
386 #else
387 #define copy_simple_to_complex(x, y) \
388 {\
389 (x)->nth = (y)->nth;\
390 (x)->jd = (y)->jd;\
391 (x)->df = 0;\
392 (x)->sf = INT2FIX(0);\
393 (x)->of = 0;\
394 (x)->sg = (date_sg_t)((y)->sg);\
395 (x)->year = (y)->year;\
396 (x)->pc = PACK5(EX_MON((y)->pc), EX_MDAY((y)->pc), 0, 0, 0);\
397 (x)->flags = (y)->flags;\
398 }
399 #endif
400
401 #ifndef USE_PACK
402 #define copy_complex_to_simple(x, y) \
403 {\
404 (x)->nth = (y)->nth;\
405 (x)->jd = (y)->jd;\
406 (x)->sg = (date_sg_t)((y)->sg);\
407 (x)->year = (y)->year;\
408 (x)->mon = (y)->mon;\
409 (x)->mday = (y)->mday;\
410 (x)->flags = (y)->flags;\
411 }
412 #else
413 #define copy_complex_to_simple(x, y) \
414 {\
415 (x)->nth = (y)->nth;\
416 (x)->jd = (y)->jd;\
417 (x)->sg = (date_sg_t)((y)->sg);\
418 (x)->year = (y)->year;\
419 (x)->pc = PACK2(EX_MON((y)->pc), EX_MDAY((y)->pc));\
420 (x)->flags = (y)->flags;\
421 }
422 #endif
423
424 /* base */
425
426 static int c_valid_civil_p(int, int, int, double,
427 int *, int *, int *, int *);
428
429 static int
430 c_find_fdoy(int y, double sg, int *rjd, int *ns)
431 {
432 int d, rm, rd;
433
434 for (d = 1; d < 31; d++)
435 if (c_valid_civil_p(y, 1, d, sg, &rm, &rd, rjd, ns))
436 return 1;
437 return 0;
438 }
439
440 static int
441 c_find_ldoy(int y, double sg, int *rjd, int *ns)
442 {
443 int i, rm, rd;
444
445 for (i = 0; i < 30; i++)
446 if (c_valid_civil_p(y, 12, 31 - i, sg, &rm, &rd, rjd, ns))
447 return 1;
448 return 0;
449 }
450
451 #ifndef NDEBUG
452 static int
453 c_find_fdom(int y, int m, double sg, int *rjd, int *ns)
454 {
455 int d, rm, rd;
456
457 for (d = 1; d < 31; d++)
458 if (c_valid_civil_p(y, m, d, sg, &rm, &rd, rjd, ns))
459 return 1;
460 return 0;
461 }
462 #endif
463
464 static int
465 c_find_ldom(int y, int m, double sg, int *rjd, int *ns)
466 {
467 int i, rm, rd;
468
469 for (i = 0; i < 30; i++)
470 if (c_valid_civil_p(y, m, 31 - i, sg, &rm, &rd, rjd, ns))
471 return 1;
472 return 0;
473 }
474
475 static void
476 c_civil_to_jd(int y, int m, int d, double sg, int *rjd, int *ns)
477 {
478 double a, b, jd;
479
480 if (m <= 2) {
481 y -= 1;
482 m += 12;
483 }
484 a = floor(y / 100.0);
485 b = 2 - a + floor(a / 4.0);
486 jd = floor(365.25 * (y + 4716)) +
487 floor(30.6001 * (m + 1)) +
488 d + b - 1524;
489 if (jd < sg) {
490 jd -= b;
491 *ns = 0;
492 }
493 else
494 *ns = 1;
495
496 *rjd = (int)jd;
497 }
498
499 static void
500 c_jd_to_civil(int jd, double sg, int *ry, int *rm, int *rdom)
501 {
502 double x, a, b, c, d, e, y, m, dom;
503
504 if (jd < sg)
505 a = jd;
506 else {
507 x = floor((jd - 1867216.25) / 36524.25);
508 a = jd + 1 + x - floor(x / 4.0);
509 }
510 b = a + 1524;
511 c = floor((b - 122.1) / 365.25);
512 d = floor(365.25 * c);
513 e = floor((b - d) / 30.6001);
514 dom = b - d - floor(30.6001 * e);
515 if (e <= 13) {
516 m = e - 1;
517 y = c - 4716;
518 }
519 else {
520 m = e - 13;
521 y = c - 4715;
522 }
523
524 *ry = (int)y;
525 *rm = (int)m;
526 *rdom = (int)dom;
527 }
528
529 static void
530 c_ordinal_to_jd(int y, int d, double sg, int *rjd, int *ns)
531 {
532 int ns2;
533
534 c_find_fdoy(y, sg, rjd, &ns2);
535 *rjd += d - 1;
536 *ns = (*rjd < sg) ? 0 : 1;
537 }
538
539 static void
540 c_jd_to_ordinal(int jd, double sg, int *ry, int *rd)
541 {
542 int rm2, rd2, rjd, ns;
543
544 c_jd_to_civil(jd, sg, ry, &rm2, &rd2);
545 c_find_fdoy(*ry, sg, &rjd, &ns);
546 *rd = (jd - rjd) + 1;
547 }
548
549 static void
550 c_commercial_to_jd(int y, int w, int d, double sg, int *rjd, int *ns)
551 {
552 int rjd2, ns2;
553
554 c_find_fdoy(y, sg, &rjd2, &ns2);
555 rjd2 += 3;
556 *rjd =
557 (rjd2 - MOD((rjd2 - 1) + 1, 7)) +
558 7 * (w - 1) +
559 (d - 1);
560 *ns = (*rjd < sg) ? 0 : 1;
561 }
562
563 static void
564 c_jd_to_commercial(int jd, double sg, int *ry, int *rw, int *rd)
565 {
566 int ry2, rm2, rd2, a, rjd2, ns2;
567
568 c_jd_to_civil(jd - 3, sg, &ry2, &rm2, &rd2);
569 a = ry2;
570 c_commercial_to_jd(a + 1, 1, 1, sg, &rjd2, &ns2);
571 if (jd >= rjd2)
572 *ry = a + 1;
573 else {
574 c_commercial_to_jd(a, 1, 1, sg, &rjd2, &ns2);
575 *ry = a;
576 }
577 *rw = 1 + DIV(jd - rjd2, 7);
578 *rd = MOD(jd + 1, 7);
579 if (*rd == 0)
580 *rd = 7;
581 }
582
583 static void
584 c_weeknum_to_jd(int y, int w, int d, int f, double sg, int *rjd, int *ns)
585 {
586 int rjd2, ns2;
587
588 c_find_fdoy(y, sg, &rjd2, &ns2);
589 rjd2 += 6;
590 *rjd = (rjd2 - MOD(((rjd2 - f) + 1), 7) - 7) + 7 * w + d;
591 *ns = (*rjd < sg) ? 0 : 1;
592 }
593
594 static void
595 c_jd_to_weeknum(int jd, int f, double sg, int *ry, int *rw, int *rd)
596 {
597 int rm, rd2, rjd, ns, j;
598
599 c_jd_to_civil(jd, sg, ry, &rm, &rd2);
600 c_find_fdoy(*ry, sg, &rjd, &ns);
601 rjd += 6;
602 j = jd - (rjd - MOD((rjd - f) + 1, 7)) + 7;
603 *rw = (int)DIV(j, 7);
604 *rd = (int)MOD(j, 7);
605 }
606
607 #ifndef NDEBUG
608 static void
609 c_nth_kday_to_jd(int y, int m, int n, int k, double sg, int *rjd, int *ns)
610 {
611 int rjd2, ns2;
612
613 if (n > 0) {
614 c_find_fdom(y, m, sg, &rjd2, &ns2);
615 rjd2 -= 1;
616 }
617 else {
618 c_find_ldom(y, m, sg, &rjd2, &ns2);
619 rjd2 += 7;
620 }
621 *rjd = (rjd2 - MOD((rjd2 - k) + 1, 7)) + 7 * n;
622 *ns = (*rjd < sg) ? 0 : 1;
623 }
624 #endif
625
626 inline static int
627 c_jd_to_wday(int jd)
628 {
629 return MOD(jd + 1, 7);
630 }
631
632 #ifndef NDEBUG
633 static void
634 c_jd_to_nth_kday(int jd, double sg, int *ry, int *rm, int *rn, int *rk)
635 {
636 int rd, rjd, ns2;
637
638 c_jd_to_civil(jd, sg, ry, rm, &rd);
639 c_find_fdom(*ry, *rm, sg, &rjd, &ns2);
640 *rn = DIV(jd - rjd, 7) + 1;
641 *rk = c_jd_to_wday(jd);
642 }
643 #endif
644
645 static int
646 c_valid_ordinal_p(int y, int d, double sg,
647 int *rd, int *rjd, int *ns)
648 {
649 int ry2, rd2;
650
651 if (d < 0) {
652 int rjd2, ns2;
653
654 if (!c_find_ldoy(y, sg, &rjd2, &ns2))
655 return 0;
656 c_jd_to_ordinal(rjd2 + d + 1, sg, &ry2, &rd2);
657 if (ry2 != y)
658 return 0;
659 d = rd2;
660 }
661 c_ordinal_to_jd(y, d, sg, rjd, ns);
662 c_jd_to_ordinal(*rjd, sg, &ry2, &rd2);
663 if (ry2 != y || rd2 != d)
664 return 0;
665 return 1;
666 }
667
668 static const int monthtab[2][13] = {
669 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
670 { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
671 };
672
673 inline static int
674 c_julian_leap_p(int y)
675 {
676 return MOD(y, 4) == 0;
677 }
678
679 inline static int
680 c_gregorian_leap_p(int y)
681 {
682 return MOD(y, 4) == 0 && y % 100 != 0 || MOD(y, 400) == 0;
683 }
684
685 static int
686 c_julian_last_day_of_month(int y, int m)
687 {
688 assert(m >= 1 && m <= 12);
689 return monthtab[c_julian_leap_p(y) ? 1 : 0][m];
690 }
691
692 static int
693 c_gregorian_last_day_of_month(int y, int m)
694 {
695 assert(m >= 1 && m <= 12);
696 return monthtab[c_gregorian_leap_p(y) ? 1 : 0][m];
697 }
698
699 static int
700 c_valid_julian_p(int y, int m, int d, int *rm, int *rd)
701 {
702 int last;
703
704 if (m < 0)
705 m += 13;
706 if (m < 1 || m > 12)
707 return 0;
708 last = c_julian_last_day_of_month(y, m);
709 if (d < 0)
710 d = last + d + 1;
711 if (d < 1 || d > last)
712 return 0;
713 *rm = m;
714 *rd = d;
715 return 1;
716 }
717
718 static int
719 c_valid_gregorian_p(int y, int m, int d, int *rm, int *rd)
720 {
721 int last;
722
723 if (m < 0)
724 m += 13;
725 if (m < 1 || m > 12)
726 return 0;
727 last = c_gregorian_last_day_of_month(y, m);
728 if (d < 0)
729 d = last + d + 1;
730 if (d < 1 || d > last)
731 return 0;
732 *rm = m;
733 *rd = d;
734 return 1;
735 }
736
737 static int
738 c_valid_civil_p(int y, int m, int d, double sg,
739 int *rm, int *rd, int *rjd, int *ns)
740 {
741 int ry;
742
743 if (m < 0)
744 m += 13;
745 if (d < 0) {
746 if (!c_find_ldom(y, m, sg, rjd, ns))
747 return 0;
748 c_jd_to_civil(*rjd + d + 1, sg, &ry, rm, rd);
749 if (ry != y || *rm != m)
750 return 0;
751 d = *rd;
752 }
753 c_civil_to_jd(y, m, d, sg, rjd, ns);
754 c_jd_to_civil(*rjd, sg, &ry, rm, rd);
755 if (ry != y || *rm != m || *rd != d)
756 return 0;
757 return 1;
758 }
759
760 static int
761 c_valid_commercial_p(int y, int w, int d, double sg,
762 int *rw, int *rd, int *rjd, int *ns)
763 {
764 int ns2, ry2, rw2, rd2;
765
766 if (d < 0)
767 d += 8;
768 if (w < 0) {
769 int rjd2;
770
771 c_commercial_to_jd(y + 1, 1, 1, sg, &rjd2, &ns2);
772 c_jd_to_commercial(rjd2 + w * 7, sg, &ry2, &rw2, &rd2);
773 if (ry2 != y)
774 return 0;
775 w = rw2;
776 }
777 c_commercial_to_jd(y, w, d, sg, rjd, ns);
778 c_jd_to_commercial(*rjd, sg, &ry2, rw, rd);
779 if (y != ry2 || w != *rw || d != *rd)
780 return 0;
781 return 1;
782 }
783
784 static int
785 c_valid_weeknum_p(int y, int w, int d, int f, double sg,
786 int *rw, int *rd, int *rjd, int *ns)
787 {
788 int ns2, ry2, rw2, rd2;
789
790 if (d < 0)
791 d += 7;
792 if (w < 0) {
793 int rjd2;
794
795 c_weeknum_to_jd(y + 1, 1, f, f, sg, &rjd2, &ns2);
796 c_jd_to_weeknum(rjd2 + w * 7, f, sg, &ry2, &rw2, &rd2);
797 if (ry2 != y)
798 return 0;
799 w = rw2;
800 }
801 c_weeknum_to_jd(y, w, d, f, sg, rjd, ns);
802 c_jd_to_weeknum(*rjd, f, sg, &ry2, rw, rd);
803 if (y != ry2 || w != *rw || d != *rd)
804 return 0;
805 return 1;
806 }
807
808 #ifndef NDEBUG
809 static int
810 c_valid_nth_kday_p(int y, int m, int n, int k, double sg,
811 int *rm, int *rn, int *rk, int *rjd, int *ns)
812 {
813 int ns2, ry2, rm2, rn2, rk2;
814
815 if (k < 0)
816 k += 7;
817 if (n < 0) {
818 int t, ny, nm, rjd2;
819
820 t = y * 12 + m;
821 ny = DIV(t, 12);
822 nm = MOD(t, 12) + 1;
823
824 c_nth_kday_to_jd(ny, nm, 1, k, sg, &rjd2, &ns2);
825 c_jd_to_nth_kday(rjd2 + n * 7, sg, &ry2, &rm2, &rn2, &rk2);
826 if (ry2 != y || rm2 != m)
827 return 0;
828 n = rn2;
829 }
830 c_nth_kday_to_jd(y, m, n, k, sg, rjd, ns);
831 c_jd_to_nth_kday(*rjd, sg, &ry2, rm, rn, rk);
832 if (y != ry2 || m != *rm || n != *rn || k != *rk)
833 return 0;
834 return 1;
835 }
836 #endif
837
838 static int
839 c_valid_time_p(int h, int min, int s, int *rh, int *rmin, int *rs)
840 {
841 if (h < 0)
842 h += 24;
843 if (min < 0)
844 min += 60;
845 if (s < 0)
846 s += 60;
847 *rh = h;
848 *rmin = min;
849 *rs = s;
850 return !(h < 0 || h > 24 ||
851 min < 0 || min > 59 ||
852 s < 0 || s > 59 ||
853 (h == 24 && (min > 0 || s > 0)));
854 }
855
856 inline static int
857 c_valid_start_p(double sg)
858 {
859 if (isnan(sg))
860 return 0;
861 if (isinf(sg))
862 return 1;
863 if (sg < REFORM_BEGIN_JD || sg > REFORM_END_JD)
864 return 0;
865 return 1;
866 }
867
868 inline static int
869 df_local_to_utc(int df, int of)
870 {
871 df -= of;
872 if (df < 0)
873 df += DAY_IN_SECONDS;
874 else if (df >= DAY_IN_SECONDS)
875 df -= DAY_IN_SECONDS;
876 return df;
877 }
878
879 inline static int
880 df_utc_to_local(int df, int of)
881 {
882 df += of;
883 if (df < 0)
884 df += DAY_IN_SECONDS;
885 else if (df >= DAY_IN_SECONDS)
886 df -= DAY_IN_SECONDS;
887 return df;
888 }
889
890 inline static int
891 jd_local_to_utc(int jd, int df, int of)
892 {
893 df -= of;
894 if (df < 0)
895 jd -= 1;
896 else if (df >= DAY_IN_SECONDS)
897 jd += 1;
898 return jd;
899 }
900
901 inline static int
902 jd_utc_to_local(int jd, int df, int of)
903 {
904 df += of;
905 if (df < 0)
906 jd -= 1;
907 else if (df >= DAY_IN_SECONDS)
908 jd += 1;
909 return jd;
910 }
911
912 inline static int
913 time_to_df(int h, int min, int s)
914 {
915 return h * HOUR_IN_SECONDS + min * MINUTE_IN_SECONDS + s;
916 }
917
918 inline static void
919 df_to_time(int df, int *h, int *min, int *s)
920 {
921 *h = df / HOUR_IN_SECONDS;
922 df %= HOUR_IN_SECONDS;
923 *min = df / MINUTE_IN_SECONDS;
924 *s = df % MINUTE_IN_SECONDS;
925 }
926
927 static VALUE
928 sec_to_day(VALUE s)
929 {
930 if (FIXNUM_P(s))
931 return rb_rational_new2(s, INT2FIX(DAY_IN_SECONDS));
932 return f_quo(s, INT2FIX(DAY_IN_SECONDS));
933 }
934
935 inline static VALUE
936 isec_to_day(int s)
937 {
938 return sec_to_day(INT2FIX(s));
939 }
940
941 static VALUE
942 ns_to_day(VALUE n)
943 {
944 if (FIXNUM_P(n))
945 return rb_rational_new2(n, day_in_nanoseconds);
946 return f_quo(n, day_in_nanoseconds);
947 }
948
949 #ifndef NDEBUG
950 static VALUE
951 ms_to_sec(VALUE m)
952 {
953 if (FIXNUM_P(m))
954 return rb_rational_new2(m, INT2FIX(SECOND_IN_MILLISECONDS));
955 return f_quo(m, INT2FIX(SECOND_IN_MILLISECONDS));
956 }
957 #endif
958
959 static VALUE
960 ns_to_sec(VALUE n)
961 {
962 if (FIXNUM_P(n))
963 return rb_rational_new2(n, INT2FIX(SECOND_IN_NANOSECONDS));
964 return f_quo(n, INT2FIX(SECOND_IN_NANOSECONDS));
965 }
966
967 #ifndef NDEBUG
968 inline static VALUE
969 ins_to_day(int n)
970 {
971 return ns_to_day(INT2FIX(n));
972 }
973 #endif
974
975 static int
976 safe_mul_p(VALUE x, long m)
977 {
978 long ix;
979
980 if (!FIXNUM_P(x))
981 return 0;
982 ix = FIX2LONG(x);
983 if (ix < 0) {
984 if (ix <= (FIXNUM_MIN / m))
985 return 0;
986 }
987 else {
988 if (ix >= (FIXNUM_MAX / m))
989 return 0;
990 }
991 return 1;
992 }
993
994 static VALUE
995 day_to_sec(VALUE d)
996 {
997 if (safe_mul_p(d, DAY_IN_SECONDS))
998 return LONG2FIX(FIX2LONG(d) * DAY_IN_SECONDS);
999 return f_mul(d, INT2FIX(DAY_IN_SECONDS));
1000 }
1001
1002 #ifndef NDEBUG
1003 static VALUE
1004 day_to_ns(VALUE d)
1005 {
1006 return f_mul(d, day_in_nanoseconds);
1007 }
1008 #endif
1009
1010 static VALUE
1011 sec_to_ms(VALUE s)
1012 {
1013 if (safe_mul_p(s, SECOND_IN_MILLISECONDS))
1014 return LONG2FIX(FIX2LONG(s) * SECOND_IN_MILLISECONDS);
1015 return f_mul(s, INT2FIX(SECOND_IN_MILLISECONDS));
1016 }
1017
1018 static VALUE
1019 sec_to_ns(VALUE s)
1020 {
1021 if (safe_mul_p(s, SECOND_IN_NANOSECONDS))
1022 return LONG2FIX(FIX2LONG(s) * SECOND_IN_NANOSECONDS);
1023 return f_mul(s, INT2FIX(SECOND_IN_NANOSECONDS));
1024 }
1025
1026 #ifndef NDEBUG
1027 static VALUE
1028 isec_to_ns(int s)
1029 {
1030 return sec_to_ns(INT2FIX(s));
1031 }
1032 #endif
1033
1034 static VALUE
1035 div_day(VALUE d, VALUE *f)
1036 {
1037 if (f)
1038 *f = f_mod(d, INT2FIX(1));
1039 return f_floor(d);
1040 }
1041
1042 static VALUE
1043 div_df(VALUE d, VALUE *f)
1044 {
1045 VALUE s = day_to_sec(d);
1046
1047 if (f)
1048 *f = f_mod(s, INT2FIX(1));
1049 return f_floor(s);
1050 }
1051
1052 #ifndef NDEBUG
1053 static VALUE
1054 div_sf(VALUE s, VALUE *f)
1055 {
1056 VALUE n = sec_to_ns(s);
1057
1058 if (f)
1059 *f = f_mod(n, INT2FIX(1));
1060 return f_floor(n);
1061 }
1062 #endif
1063
1064 static void
1065 decode_day(VALUE d, VALUE *jd, VALUE *df, VALUE *sf)
1066 {
1067 VALUE f;
1068
1069 *jd = div_day(d, &f);
1070 *df = div_df(f, &f);
1071 *sf = sec_to_ns(f);
1072 }
1073
1074 inline static double
1075 s_virtual_sg(union DateData *x)
1076 {
1077 if (isinf(x->s.sg))
1078 return x->s.sg;
1079 if (f_zero_p(x->s.nth))
1080 return x->s.sg;
1081 else if (f_negative_p(x->s.nth))
1082 return positive_inf;
1083 return negative_inf;
1084 }
1085
1086 inline static double
1087 c_virtual_sg(union DateData *x)
1088 {
1089 if (isinf(x->c.sg))
1090 return x->c.sg;
1091 if (f_zero_p(x->c.nth))
1092 return x->c.sg;
1093 else if (f_negative_p(x->c.nth))
1094 return positive_inf;
1095 return negative_inf;
1096 }
1097
1098 inline static double
1099 m_virtual_sg(union DateData *x)
1100 {
1101 if (simple_dat_p(x))
1102 return s_virtual_sg(x);
1103 else
1104 return c_virtual_sg(x);
1105 }
1106
1107 #define canonicalize_jd(_nth, _jd) \
1108 {\
1109 if (_jd < 0) {\
1110 _nth = f_sub(_nth, INT2FIX(1));\
1111 _jd += CM_PERIOD;\
1112 }\
1113 if (_jd >= CM_PERIOD) {\
1114 _nth = f_add(_nth, INT2FIX(1));\
1115 _jd -= CM_PERIOD;\
1116 }\
1117 }
1118
1119 inline static void
1120 canonicalize_s_jd(union DateData *x)
1121 {
1122 int j = x->s.jd;
1123 assert(have_jd_p(x));
1124 canonicalize_jd(x->s.nth, x->s.jd);
1125 if (x->s.jd != j)
1126 x->flags &= ~HAVE_CIVIL;
1127 }
1128
1129 inline static void
1130 get_s_jd(union DateData *x)
1131 {
1132 assert(simple_dat_p(x));
1133 if (!have_jd_p(x)) {
1134 int jd, ns;
1135
1136 assert(have_civil_p(x));
1137 #ifndef USE_PACK
1138 c_civil_to_jd(x->s.year, x->s.mon, x->s.mday,
1139 s_virtual_sg(x), &jd, &ns);
1140 #else
1141 c_civil_to_jd(x->s.year, EX_MON(x->s.pc), EX_MDAY(x->s.pc),
1142 s_virtual_sg(x), &jd, &ns);
1143 #endif
1144 x->s.jd = jd;
1145 x->s.flags |= HAVE_JD;
1146 }
1147 }
1148
1149 inline static void
1150 get_s_civil(union DateData *x)
1151 {
1152 assert(simple_dat_p(x));
1153 if (!have_civil_p(x)) {
1154 int y, m, d;
1155
1156 assert(have_jd_p(x));
1157 c_jd_to_civil(x->s.jd, s_virtual_sg(x), &y, &m, &d);
1158 x->s.year = y;
1159 #ifndef USE_PACK
1160 x->s.mon = m;
1161 x->s.mday = d;
1162 #else
1163 x->s.pc = PACK2(m, d);
1164 #endif
1165 x->s.flags |= HAVE_CIVIL;
1166 }
1167 }
1168
1169 inline static void
1170 get_c_df(union DateData *x)
1171 {
1172 assert(complex_dat_p(x));
1173 if (!have_df_p(x)) {
1174 assert(have_time_p(x));
1175 #ifndef USE_PACK
1176 x->c.df = df_local_to_utc(time_to_df(x->c.hour, x->c.min, x->c.sec),
1177 x->c.of);
1178 #else
1179 x->c.df = df_local_to_utc(time_to_df(EX_HOUR(x->c.pc),
1180 EX_MIN(x->c.pc),
1181 EX_SEC(x->c.pc)),
1182 x->c.of);
1183 #endif
1184 x->c.flags |= HAVE_DF;
1185 }
1186 }
1187
1188 inline static void
1189 get_c_time(union DateData *x)
1190 {
1191 assert(complex_dat_p(x));
1192 if (!have_time_p(x)) {
1193 #ifndef USE_PACK
1194 int r;
1195 assert(have_df_p(x));
1196 r = df_utc_to_local(x->c.df, x->c.of);
1197 df_to_time(r, &x->c.hour, &x->c.min, &x->c.sec);
1198 x->c.flags |= HAVE_TIME;
1199 #else
1200 int r, m, d, h, min, s;
1201
1202 assert(have_df_p(x));
1203 m = EX_MON(x->c.pc);
1204 d = EX_MDAY(x->c.pc);
1205 r = df_utc_to_local(x->c.df, x->c.of);
1206 df_to_time(r, &h, &min, &s);
1207 x->c.pc = PACK5(m, d, h, min, s);
1208 x->c.flags |= HAVE_TIME;
1209 #endif
1210 }
1211 }
1212
1213 inline static void
1214 canonicalize_c_jd(union DateData *x)
1215 {
1216 int j = x->c.jd;
1217 assert(have_jd_p(x));
1218 canonicalize_jd(x->c.nth, x->c.jd);
1219 if (x->c.jd != j)
1220 x->flags &= ~HAVE_CIVIL;
1221 }
1222
1223 inline static void
1224 get_c_jd(union DateData *x)
1225 {
1226 assert(complex_dat_p(x));
1227 if (!have_jd_p(x)) {
1228 int jd, ns;
1229
1230 assert(have_civil_p(x));
1231 #ifndef USE_PACK
1232 c_civil_to_jd(x->c.year, x->c.mon, x->c.mday,
1233 c_virtual_sg(x), &jd, &ns);
1234 #else
1235 c_civil_to_jd(x->c.year, EX_MON(x->c.pc), EX_MDAY(x->c.pc),
1236 c_virtual_sg(x), &jd, &ns);
1237 #endif
1238
1239 get_c_time(x);
1240 #ifndef USE_PACK
1241 x->c.jd = jd_local_to_utc(jd,
1242 time_to_df(x->c.hour, x->c.min, x->c.sec),
1243 x->c.of);
1244 #else
1245 x->c.jd = jd_local_to_utc(jd,
1246 time_to_df(EX_HOUR(x->c.pc),
1247 EX_MIN(x->c.pc),
1248 EX_SEC(x->c.pc)),
1249 x->c.of);
1250 #endif
1251 x->c.flags |= HAVE_JD;
1252 }
1253 }
1254
1255 inline static void
1256 get_c_civil(union DateData *x)
1257 {
1258 assert(complex_dat_p(x));
1259 if (!have_civil_p(x)) {
1260 #ifndef USE_PACK
1261 int jd, y, m, d;
1262 #else
1263 int jd, y, m, d, h, min, s;
1264 #endif
1265
1266 assert(have_jd_p(x));
1267 get_c_df(x);
1268 jd = jd_utc_to_local(x->c.jd, x->c.df, x->c.of);
1269 c_jd_to_civil(jd, c_virtual_sg(x), &y, &m, &d);
1270 x->c.year = y;
1271 #ifndef USE_PACK
1272 x->c.mon = m;
1273 x->c.mday = d;
1274 #else
1275 h = EX_HOUR(x->c.pc);
1276 min = EX_MIN(x->c.pc);
1277 s = EX_SEC(x->c.pc);
1278 x->c.pc = PACK5(m, d, h, min, s);
1279 #endif
1280 x->c.flags |= HAVE_CIVIL;
1281 }
1282 }
1283
1284 inline static int
1285 local_jd(union DateData *x)
1286 {
1287 assert(complex_dat_p(x));
1288 assert(have_jd_p(x));
1289 assert(have_df_p(x));
1290 return jd_utc_to_local(x->c.jd, x->c.df, x->c.of);
1291 }
1292
1293 inline static int
1294 local_df(union DateData *x)
1295 {
1296 assert(complex_dat_p(x));
1297 assert(have_df_p(x));
1298 return df_utc_to_local(x->c.df, x->c.of);
1299 }
1300
1301 static void
1302 decode_year(VALUE y, double style,
1303 VALUE *nth, int *ry)
1304 {
1305 int period;
1306 VALUE t;
1307
1308 period = (style < 0) ?
1309 CM_PERIOD_GCY :
1310 CM_PERIOD_JCY;
1311 if (FIXNUM_P(y)) {
1312 long iy, it, inth;
1313
1314 iy = FIX2LONG(y);
1315 if (iy >= (FIXNUM_MAX - 4712))
1316 goto big;
1317 it = iy + 4712; /* shift */
1318 inth = DIV(it, ((long)period));
1319 *nth = LONG2FIX(inth);
1320 if (inth)
1321 it = MOD(it, ((long)period));
1322 *ry = (int)it - 4712; /* unshift */
1323 return;
1324 }
1325 big:
1326 t = f_add(y, INT2FIX(4712)); /* shift */
1327 *nth = f_idiv(t, INT2FIX(period));
1328 if (f_nonzero_p(*nth))
1329 t = f_mod(t, INT2FIX(period));
1330 *ry = FIX2INT(t) - 4712; /* unshift */
1331 }
1332
1333 static void
1334 encode_year(VALUE nth, int y, double style,
1335 VALUE *ry)
1336 {
1337 int period;
1338 VALUE t;
1339
1340 period = (style < 0) ?
1341 CM_PERIOD_GCY :
1342 CM_PERIOD_JCY;
1343 if (f_zero_p(nth))
1344 *ry = INT2FIX(y);
1345 else {
1346 t = f_mul(INT2FIX(period), nth);
1347 t = f_add(t, INT2FIX(y));
1348 *ry = t;
1349 }
1350 }
1351
1352 static void
1353 decode_jd(VALUE jd, VALUE *nth, int *rjd)
1354 {
1355 assert(FIXNUM_P(jd) || RB_TYPE_P(jd, T_BIGNUM));
1356 *nth = f_idiv(jd, INT2FIX(CM_PERIOD));
1357 if (f_zero_p(*nth)) {
1358 assert(FIXNUM_P(jd));
1359 *rjd = FIX2INT(jd);
1360 return;
1361 }
1362 *rjd = FIX2INT(f_mod(jd, INT2FIX(CM_PERIOD)));
1363 }
1364
1365 static void
1366 encode_jd(VALUE nth, int jd, VALUE *rjd)
1367 {
1368 if (f_zero_p(nth)) {
1369 *rjd = INT2FIX(jd);
1370 return;
1371 }
1372 *rjd = f_add(f_mul(INT2FIX(CM_PERIOD), nth), INT2FIX(jd));
1373 }
1374
1375 inline static double
1376 guess_style(VALUE y, double sg) /* -/+oo or zero */
1377 {
1378 double style = 0;
1379
1380 if (isinf(sg))
1381 style = sg;
1382 else if (!FIXNUM_P(y))
1383 style = f_positive_p(y) ? negative_inf : positive_inf;
1384 else {
1385 long iy = FIX2LONG(y);
1386
1387 assert(FIXNUM_P(y));
1388 if (iy < REFORM_BEGIN_YEAR)
1389 style = positive_inf;
1390 else if (iy > REFORM_END_YEAR)
1391 style = negative_inf;
1392 }
1393 return style;
1394 }
1395
1396 inline static void
1397 m_canonicalize_jd(union DateData *x)
1398 {
1399 if (simple_dat_p(x)) {
1400 get_s_jd(x);
1401 canonicalize_s_jd(x);
1402 }
1403 else {
1404 get_c_jd(x);
1405 canonicalize_c_jd(x);
1406 }
1407 }
1408
1409 inline static VALUE
1410 m_nth(union DateData *x)
1411 {
1412 if (simple_dat_p(x))
1413 return x->s.nth;
1414 else {
1415 get_c_civil(x);
1416 return x->c.nth;
1417 }
1418 }
1419
1420 inline static int
1421 m_jd(union DateData *x)
1422 {
1423 if (simple_dat_p(x)) {
1424 get_s_jd(x);
1425 return x->s.jd;
1426 }
1427 else {
1428 get_c_jd(x);
1429 return x->c.jd;
1430 }
1431 }
1432
1433 static VALUE
1434 m_real_jd(union DateData *x)
1435 {
1436 VALUE nth, rjd;
1437 int jd;
1438
1439 nth = m_nth(x);
1440 jd = m_jd(x);
1441
1442 encode_jd(nth, jd, &rjd);
1443 return rjd;
1444 }
1445
1446 static int
1447 m_local_jd(union DateData *x)
1448 {
1449 if (simple_dat_p(x)) {
1450 get_s_jd(x);
1451 return x->s.jd;
1452 }
1453 else {
1454 get_c_jd(x);
1455 get_c_df(x);
1456 return local_jd(x);
1457 }
1458 }
1459
1460 static VALUE
1461 m_real_local_jd(union DateData *x)
1462 {
1463 VALUE nth, rjd;
1464 int jd;
1465
1466 nth = m_nth(x);
1467 jd = m_local_jd(x);
1468
1469 encode_jd(nth, jd, &rjd);
1470 return rjd;
1471 }
1472
1473 inline static int
1474 m_df(union DateData *x)
1475 {
1476 if (simple_dat_p(x))
1477 return 0;
1478 else {
1479 get_c_df(x);
1480 return x->c.df;
1481 }
1482 }
1483
1484 #ifndef NDEBUG
1485 static VALUE
1486 m_df_in_day(union DateData *x)
1487 {
1488 return isec_to_day(m_df(x));
1489 }
1490 #endif
1491
1492 static int
1493 m_local_df(union DateData *x)
1494 {
1495 if (simple_dat_p(x))
1496 return 0;
1497 else {
1498 get_c_df(x);
1499 return local_df(x);
1500 }
1501 }
1502
1503 #ifndef NDEBUG
1504 static VALUE
1505 m_local_df_in_day(union DateData *x)
1506 {
1507 return isec_to_day(m_local_df(x));
1508 }
1509 #endif
1510
1511 inline static VALUE
1512 m_sf(union DateData *x)
1513 {
1514 if (simple_dat_p(x))
1515 return INT2FIX(0);
1516 else
1517 return x->c.sf;
1518 }
1519
1520 #ifndef NDEBUG
1521 static VALUE
1522 m_sf_in_day(union DateData *x)
1523 {
1524 return ns_to_day(m_sf(x));
1525 }
1526 #endif
1527
1528 static VALUE
1529 m_sf_in_sec(union DateData *x)
1530 {
1531 return ns_to_sec(m_sf(x));
1532 }
1533
1534 static VALUE
1535 m_fr(union DateData *x)
1536 {
1537 if (simple_dat_p(x))
1538 return INT2FIX(0);
1539 else {
1540 int df;
1541 VALUE sf, fr;
1542
1543 df = m_local_df(x);
1544 sf = m_sf(x);
1545 fr = isec_to_day(df);
1546 if (f_nonzero_p(sf))
1547 fr = f_add(fr, ns_to_day(sf));
1548 return fr;
1549 }
1550 }
1551
1552 #define HALF_DAYS_IN_SECONDS (DAY_IN_SECONDS / 2)
1553
1554 static VALUE
1555 m_ajd(union DateData *x)
1556 {
1557 VALUE r, sf;
1558 int df;
1559
1560 if (simple_dat_p(x)) {
1561 r = m_real_jd(x);
1562 if (FIXNUM_P(r) && FIX2LONG(r) <= (FIXNUM_MAX / 2)) {
1563 long ir = FIX2LONG(r);
1564 ir = ir * 2 - 1;
1565 return rb_rational_new2(LONG2FIX(ir), INT2FIX(2));
1566 }
1567 else
1568 return rb_rational_new2(f_sub(f_mul(r,
1569 INT2FIX(2)),
1570 INT2FIX(1)),
1571 INT2FIX(2));
1572 }
1573
1574 r = m_real_jd(x);
1575 df = m_df(x);
1576 df -= HALF_DAYS_IN_SECONDS;
1577 if (df)
1578 r = f_add(r, isec_to_day(df));
1579 sf = m_sf(x);
1580 if (f_nonzero_p(sf))
1581 r = f_add(r, ns_to_day(sf));
1582
1583 return r;
1584 }
1585
1586 static VALUE
1587 m_amjd(union DateData *x)
1588 {
1589 VALUE r, sf;
1590 int df;
1591
1592 r = m_real_jd(x);
1593 if (FIXNUM_P(r) && FIX2LONG(r) >= (FIXNUM_MIN + 2400001)) {
1594 long ir = FIX2LONG(r);
1595 ir -= 2400001;
1596 r = rb_rational_new1(LONG2FIX(ir));
1597 }
1598 else
1599 r = rb_rational_new1(f_sub(m_real_jd(x),
1600 INT2FIX(2400001)));
1601
1602 if (simple_dat_p(x))
1603 return r;
1604
1605 df = m_df(x);
1606 if (df)
1607 r = f_add(r, isec_to_day(df));
1608 sf = m_sf(x);
1609 if (f_nonzero_p(sf))
1610 r = f_add(r, ns_to_day(sf));
1611
1612 return r;
1613 }
1614
1615 inline static int
1616 m_of(union DateData *x)
1617 {
1618 if (simple_dat_p(x))
1619 return 0;
1620 else {
1621 get_c_jd(x);
1622 return x->c.of;
1623 }
1624 }
1625
1626 static VALUE
1627 m_of_in_day(union DateData *x)
1628 {
1629 return isec_to_day(m_of(x));
1630 }
1631
1632 inline static double
1633 m_sg(union DateData *x)
1634 {
1635 if (simple_dat_p(x))
1636 return x->s.sg;
1637 else {
1638 get_c_jd(x);
1639 return x->c.sg;
1640 }
1641 }
1642
1643 static int
1644 m_julian_p(union DateData *x)
1645 {
1646 int jd;
1647 double sg;
1648
1649 if (simple_dat_p(x)) {
1650 get_s_jd(x);
1651 jd = x->s.jd;
1652 sg = s_virtual_sg(x);
1653 }
1654 else {
1655 get_c_jd(x);
1656 jd = x->c.jd;
1657 sg = c_virtual_sg(x);
1658 }
1659 if (isinf(sg))
1660 return sg == positive_inf;
1661 return jd < sg;
1662 }
1663
1664 inline static int
1665 m_gregorian_p(union DateData *x)
1666 {
1667 return !m_julian_p(x);
1668 }
1669
1670 inline static int
1671 m_proleptic_julian_p(union DateData *x)
1672 {
1673 double sg;
1674
1675 sg = m_sg(x);
1676 if (isinf(sg) && sg > 0)
1677 return 1;
1678 return 0;
1679 }
1680
1681 inline static int
1682 m_proleptic_gregorian_p(union DateData *x)
1683 {
1684 double sg;
1685
1686 sg = m_sg(x);
1687 if (isinf(sg) && sg < 0)
1688 return 1;
1689 return 0;
1690 }
1691
1692 inline static int
1693 m_year(union DateData *x)
1694 {
1695 if (simple_dat_p(x)) {
1696 get_s_civil(x);
1697 return x->s.year;
1698 }
1699 else {
1700 get_c_civil(x);
1701 return x->c.year;
1702 }
1703 }
1704
1705 static VALUE
1706 m_real_year(union DateData *x)
1707 {
1708 VALUE nth, ry;
1709 int year;
1710
1711 nth = m_nth(x);
1712 year = m_year(x);
1713
1714 if (f_zero_p(nth))
1715 return INT2FIX(year);
1716
1717 encode_year(nth, year,
1718 m_gregorian_p(x) ? -1 : +1,
1719 &ry);
1720 return ry;
1721 }
1722
1723
1724 #ifdef USE_PACK
1725 inline static int
1726 m_pc(union DateData *x)
1727 {
1728 if (simple_dat_p(x)) {
1729 get_s_civil(x);
1730 return x->s.pc;
1731 }
1732 else {
1733 get_c_civil(x);
1734 get_c_time(x);
1735 return x->c.pc;
1736 }
1737 }
1738 #endif
1739
1740 inline static int
1741 m_mon(union DateData *x)
1742 {
1743 if (simple_dat_p(x)) {
1744 get_s_civil(x);
1745 #ifndef USE_PACK
1746 return x->s.mon;
1747 #else
1748 return EX_MON(x->s.pc);
1749 #endif
1750 }
1751 else {
1752 get_c_civil(x);
1753 #ifndef USE_PACK
1754 return x->c.mon;
1755 #else
1756 return EX_MON(x->c.pc);
1757 #endif
1758 }
1759 }
1760
1761 inline static int
1762 m_mday(union DateData *x)
1763 {
1764 if (simple_dat_p(x)) {
1765 get_s_civil(x);
1766 #ifndef USE_PACK
1767 return x->s.mday;
1768 #else
1769 return EX_MDAY(x->s.pc);
1770 #endif
1771 }
1772 else {
1773 get_c_civil(x);
1774 #ifndef USE_PACK
1775 return x->c.mday;
1776 #else
1777 return EX_MDAY(x->c.pc);
1778 #endif
1779 }
1780 }
1781
1782 static const int yeartab[2][13] = {
1783 { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
1784 { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
1785 };
1786
1787 static int
1788 c_julian_to_yday(int y, int m, int d)
1789 {
1790 assert(m >= 1 && m <= 12);
1791 return yeartab[c_julian_leap_p(y) ? 1 : 0][m] + d;
1792 }
1793
1794 static int
1795 c_gregorian_to_yday(int y, int m, int d)
1796 {
1797 assert(m >= 1 && m <= 12);
1798 return yeartab[c_gregorian_leap_p(y) ? 1 : 0][m] + d;
1799 }
1800
1801 static int
1802 m_yday(union DateData *x)
1803 {
1804 int jd, ry, rd;
1805 double sg;
1806
1807 jd = m_local_jd(x);
1808 sg = m_virtual_sg(x); /* !=m_sg() */
1809
1810 if (m_proleptic_gregorian_p(x) ||
1811 (jd - sg) > 366)
1812 return c_gregorian_to_yday(m_year(x), m_mon(x), m_mday(x));
1813 if (m_proleptic_julian_p(x))
1814 return c_julian_to_yday(m_year(x), m_mon(x), m_mday(x));
1815 c_jd_to_ordinal(jd, sg, &ry, &rd);
1816 return rd;
1817 }
1818
1819 static int
1820 m_wday(union DateData *x)
1821 {
1822 return c_jd_to_wday(m_local_jd(x));
1823 }
1824
1825 static int
1826 m_cwyear(union DateData *x)
1827 {
1828 int ry, rw, rd;
1829
1830 c_jd_to_commercial(m_local_jd(x), m_virtual_sg(x), /* !=m_sg() */
1831 &ry, &rw, &rd);
1832 return ry;
1833 }
1834
1835 static VALUE
1836 m_real_cwyear(union DateData *x)
1837 {
1838 VALUE nth, ry;
1839 int year;
1840
1841 nth = m_nth(x);
1842 year = m_cwyear(x);
1843
1844 if (f_zero_p(nth))
1845 return INT2FIX(year);
1846
1847 encode_year(nth, year,
1848 m_gregorian_p(x) ? -1 : +1,
1849 &ry);
1850 return ry;
1851 }
1852
1853 static int
1854 m_cweek(union DateData *x)
1855 {
1856 int ry, rw, rd;
1857
1858 c_jd_to_commercial(m_local_jd(x), m_virtual_sg(x), /* !=m_sg() */
1859 &ry, &rw, &rd);
1860 return rw;
1861 }
1862
1863 static int
1864 m_cwday(union DateData *x)
1865 {
1866 int w;
1867
1868 w = m_wday(x);
1869 if (w == 0)
1870 w = 7;
1871 return w;
1872 }
1873
1874 static int
1875 m_wnumx(union DateData *x, int f)
1876 {
1877 int ry, rw, rd;
1878
1879 c_jd_to_weeknum(m_local_jd(x), f, m_virtual_sg(x), /* !=m_sg() */
1880 &ry, &rw, &rd);
1881 return rw;
1882 }
1883
1884 static int
1885 m_wnum0(union DateData *x)
1886 {
1887 return m_wnumx(x, 0);
1888 }
1889
1890 static int
1891 m_wnum1(union DateData *x)
1892 {
1893 return m_wnumx(x, 1);
1894 }
1895
1896 inline static int
1897 m_hour(union DateData *x)
1898 {
1899 if (simple_dat_p(x))
1900 return 0;
1901 else {
1902 get_c_time(x);
1903 #ifndef USE_PACK
1904 return x->c.hour;
1905 #else
1906 return EX_HOUR(x->c.pc);
1907 #endif
1908 }
1909 }
1910
1911 inline static int
1912 m_min(union DateData *x)
1913 {
1914 if (simple_dat_p(x))
1915 return 0;
1916 else {
1917 get_c_time(x);
1918 #ifndef USE_PACK
1919 return x->c.min;
1920 #else
1921 return EX_MIN(x->c.pc);
1922 #endif
1923 }
1924 }
1925
1926 inline static int
1927 m_sec(union DateData *x)
1928 {
1929 if (simple_dat_p(x))
1930 return 0;
1931 else {
1932 get_c_time(x);
1933 #ifndef USE_PACK
1934 return x->c.sec;
1935 #else
1936 return EX_SEC(x->c.pc);
1937 #endif
1938 }
1939 }
1940
1941 #define decode_offset(of,s,h,m)\
1942 {\
1943 int a;\
1944 s = (of < 0) ? '-' : '+';\
1945 a = (of < 0) ? -of : of;\
1946 h = a / HOUR_IN_SECONDS;\
1947 m = a % HOUR_IN_SECONDS / MINUTE_IN_SECONDS;\
1948 }
1949
1950 static VALUE
1951 of2str(int of)
1952 {
1953 int s, h, m;
1954
1955 decode_offset(of, s, h, m);
1956 return rb_enc_sprintf(rb_usascii_encoding(), "%c%02d:%02d", s, h, m);
1957 }
1958
1959 static VALUE
1960 m_zone(union DateData *x)
1961 {
1962 if (simple_dat_p(x))
1963 return rb_usascii_str_new2("+00:00");
1964 return of2str(m_of(x));
1965 }
1966
1967 inline static VALUE
1968 f_kind_of_p(VALUE x, VALUE c)
1969 {
1970 return rb_obj_is_kind_of(x, c);
1971 }
1972
1973 inline static VALUE
1974 k_date_p(VALUE x)
1975 {
1976 return f_kind_of_p(x, cDate);
1977 }
1978
1979 inline static VALUE
1980 k_datetime_p(VALUE x)
1981 {
1982 return f_kind_of_p(x, cDateTime);
1983 }
1984
1985 inline static VALUE
1986 k_numeric_p(VALUE x)
1987 {
1988 return f_kind_of_p(x, rb_cNumeric);
1989 }
1990
1991 inline static VALUE
1992 k_rational_p(VALUE x)
1993 {
1994 return f_kind_of_p(x, rb_cRational);
1995 }
1996
1997 #ifndef NDEBUG
1998 static void
1999 civil_to_jd(VALUE y, int m, int d, double sg,
2000 VALUE *nth, int *ry,
2001 int *rjd,
2002 int *ns)
2003 {
2004 double style = guess_style(y, sg);
2005
2006 if (style == 0) {
2007 int jd;
2008
2009 c_civil_to_jd(FIX2INT(y), m, d, sg, &jd, ns);
2010 decode_jd(INT2FIX(jd), nth, rjd);
2011 if (f_zero_p(*nth))
2012 *ry = FIX2INT(y);
2013 else {
2014 VALUE nth2;
2015 decode_year(y, *ns ? -1 : +1, &nth2, ry);
2016 }
2017 }
2018 else {
2019 decode_year(y, style, nth, ry);
2020 c_civil_to_jd(*ry, m, d, style, rjd, ns);
2021 }
2022 }
2023
2024 static void
2025 jd_to_civil(VALUE jd, double sg,
2026 VALUE *nth, int *rjd,
2027 int *ry, int *rm, int *rd)
2028 {
2029 decode_jd(jd, nth, rjd);
2030 c_jd_to_civil(*rjd, sg, ry, rm, rd);
2031 }
2032
2033 static void
2034 ordinal_to_jd(VALUE y, int d, double sg,
2035 VALUE *nth, int *ry,
2036 int *rjd,
2037 int *ns)
2038 {
2039 double style = guess_style(y, sg);
2040
2041 if (style == 0) {
2042 int jd;
2043
2044 c_ordinal_to_jd(FIX2INT(y), d, sg, &jd, ns);
2045 decode_jd(INT2FIX(jd), nth, rjd);
2046 if (f_zero_p(*nth))
2047 *ry = FIX2INT(y);
2048 else {
2049 VALUE nth2;
2050 decode_year(y, *ns ? -1 : +1, &nth2, ry);
2051 }
2052 }
2053 else {
2054 decode_year(y, style, nth, ry);
2055 c_ordinal_to_jd(*ry, d, style, rjd, ns);
2056 }
2057 }
2058
2059 static void
2060 jd_to_ordinal(VALUE jd, double sg,
2061 VALUE *nth, int *rjd,
2062 int *ry, int *rd)
2063 {
2064 decode_jd(jd, nth, rjd);
2065 c_jd_to_ordinal(*rjd, sg, ry, rd);
2066 }
2067
2068 static void
2069 commercial_to_jd(VALUE y, int w, int d, double sg,
2070 VALUE *nth, int *ry,
2071 int *rjd,
2072 int *ns)
2073 {
2074 double style = guess_style(y, sg);
2075
2076 if (style == 0) {
2077 int jd;
2078
2079 c_commercial_to_jd(FIX2INT(y), w, d, sg, &jd, ns);
2080 decode_jd(INT2FIX(jd), nth, rjd);
2081 if (f_zero_p(*nth))
2082 *ry = FIX2INT(y);
2083 else {
2084 VALUE nth2;
2085 decode_year(y, *ns ? -1 : +1, &nth2, ry);
2086 }
2087 }
2088 else {
2089 decode_year(y, style, nth, ry);
2090 c_commercial_to_jd(*ry, w, d, style, rjd, ns);
2091 }
2092 }
2093
2094 static void
2095 jd_to_commercial(VALUE jd, double sg,
2096 VALUE *nth, int *rjd,
2097 int *ry, int *rw, int *rd)
2098 {
2099 decode_jd(jd, nth, rjd);
2100 c_jd_to_commercial(*rjd, sg, ry, rw, rd);
2101 }
2102
2103 static void
2104 weeknum_to_jd(VALUE y, int w, int d, int f, double sg,
2105 VALUE *nth, int *ry,
2106 int *rjd,
2107 int *ns)
2108 {
2109 double style = guess_style(y, sg);
2110
2111 if (style == 0) {
2112 int jd;
2113
2114 c_weeknum_to_jd(FIX2INT(y), w, d, f, sg, &jd, ns);
2115 decode_jd(INT2FIX(jd), nth, rjd);
2116 if (f_zero_p(*nth))
2117 *ry = FIX2INT(y);
2118 else {
2119 VALUE nth2;
2120 decode_year(y, *ns ? -1 : +1, &nth2, ry);
2121 }
2122 }
2123 else {
2124 decode_year(y, style, nth, ry);
2125 c_weeknum_to_jd(*ry, w, d, f, style, rjd, ns);
2126 }
2127 }
2128
2129 static void
2130 jd_to_weeknum(VALUE jd, int f, double sg,
2131 VALUE *nth, int *rjd,
2132 int *ry, int *rw, int *rd)
2133 {
2134 decode_jd(jd, nth, rjd);
2135 c_jd_to_weeknum(*rjd, f, sg, ry, rw, rd);
2136 }
2137
2138 static void
2139 nth_kday_to_jd(VALUE y, int m, int n, int k, double sg,
2140 VALUE *nth, int *ry,
2141 int *rjd,
2142 int *ns)
2143 {
2144 double style = guess_style(y, sg);
2145
2146 if (style == 0) {
2147 int jd;
2148
2149 c_nth_kday_to_jd(FIX2INT(y), m, n, k, sg, &jd, ns);
2150 decode_jd(INT2FIX(jd), nth, rjd);
2151 if (f_zero_p(*nth))
2152 *ry = FIX2INT(y);
2153 else {
2154 VALUE nth2;
2155 decode_year(y, *ns ? -1 : +1, &nth2, ry);
2156 }
2157 }
2158 else {
2159 decode_year(y, style, nth, ry);
2160 c_nth_kday_to_jd(*ry, m, n, k, style, rjd, ns);
2161 }
2162 }
2163
2164 static void
2165 jd_to_nth_kday(VALUE jd, double sg,
2166 VALUE *nth, int *rjd,
2167 int *ry, int *rm, int *rn, int *rk)
2168 {
2169 decode_jd(jd, nth, rjd);
2170 c_jd_to_nth_kday(*rjd, sg, ry, rm, rn, rk);
2171 }
2172 #endif
2173
2174 static int
2175 valid_ordinal_p(VALUE y, int d, double sg,
2176 VALUE *nth, int *ry,
2177 int *rd, int *rjd,
2178 int *ns)
2179 {
2180 double style = guess_style(y, sg);
2181 int r;
2182
2183 if (style == 0) {
2184 int jd;
2185
2186 r = c_valid_ordinal_p(FIX2INT(y), d, sg, rd, &jd, ns);
2187 if (!r)
2188 return 0;
2189 decode_jd(INT2FIX(jd), nth, rjd);
2190 if (f_zero_p(*nth))
2191 *ry = FIX2INT(y);
2192 else {
2193 VALUE nth2;
2194 decode_year(y, *ns ? -1 : +1, &nth2, ry);
2195 }
2196 }
2197 else {
2198 decode_year(y, style, nth, ry);
2199 r = c_valid_ordinal_p(*ry, d, style, rd, rjd, ns);
2200 }
2201 return r;
2202 }
2203
2204 static int
2205 valid_gregorian_p(VALUE y, int m, int d,
2206 VALUE *nth, int *ry,
2207 int *rm, int *rd)
2208 {
2209 decode_year(y, -1, nth, ry);
2210 return c_valid_gregorian_p(*ry, m, d, rm, rd);
2211 }
2212
2213 static int
2214 valid_civil_p(VALUE y, int m, int d, double sg,
2215 VALUE *nth, int *ry,
2216 int *rm, int *rd, int *rjd,
2217 int *ns)
2218 {
2219 double style = guess_style(y, sg);
2220 int r;
2221
2222 if (style == 0) {
2223 int jd;
2224
2225 r = c_valid_civil_p(FIX2INT(y), m, d, sg, rm, rd, &jd, ns);
2226 if (!r)
2227 return 0;
2228 decode_jd(INT2FIX(jd), nth, rjd);
2229 if (f_zero_p(*nth))
2230 *ry = FIX2INT(y);
2231 else {
2232 VALUE nth2;
2233 decode_year(y, *ns ? -1 : +1, &nth2, ry);
2234 }
2235 }
2236 else {
2237 decode_year(y, style, nth, ry);
2238 if (style < 0)
2239 r = c_valid_gregorian_p(*ry, m, d, rm, rd);
2240 else
2241 r = c_valid_julian_p(*ry, m, d, rm, rd);
2242 if (!r)
2243 return 0;
2244 c_civil_to_jd(*ry, *rm, *rd, style, rjd, ns);
2245 }
2246 return r;
2247 }
2248
2249 static int
2250 valid_commercial_p(VALUE y, int w, int d, double sg,
2251 VALUE *nth, int *ry,
2252 int *rw, int *rd, int *rjd,
2253 int *ns)
2254 {
2255 double style = guess_style(y, sg);
2256 int r;
2257
2258 if (style == 0) {
2259 int jd;
2260
2261 r = c_valid_commercial_p(FIX2INT(y), w, d, sg, rw, rd, &jd, ns);
2262 if (!r)
2263 return 0;
2264 decode_jd(INT2FIX(jd), nth, rjd);
2265 if (f_zero_p(*nth))
2266 *ry = FIX2INT(y);
2267 else {
2268 VALUE nth2;
2269 decode_year(y, *ns ? -1 : +1, &nth2, ry);
2270 }
2271 }
2272 else {
2273 decode_year(y, style, nth, ry);
2274 r = c_valid_commercial_p(*ry, w, d, style, rw, rd, rjd, ns);
2275 }
2276 return r;
2277 }
2278
2279 static int
2280 valid_weeknum_p(VALUE y, int w, int d, int f, double sg,
2281 VALUE *nth, int *ry,
2282 int *rw, int *rd, int *rjd,
2283 int *ns)
2284 {
2285 double style = guess_style(y, sg);
2286 int r;
2287
2288 if (style == 0) {
2289 int jd;
2290
2291 r = c_valid_weeknum_p(FIX2INT(y), w, d, f, sg, rw, rd, &jd, ns);
2292 if (!r)
2293 return 0;
2294 decode_jd(INT2FIX(jd), nth, rjd);
2295 if (f_zero_p(*nth))
2296 *ry = FIX2INT(y);
2297 else {
2298 VALUE nth2;
2299 decode_year(y, *ns ? -1 : +1, &nth2, ry);
2300 }
2301 }
2302 else {
2303 decode_year(y, style, nth, ry);
2304 r = c_valid_weeknum_p(*ry, w, d, f, style, rw, rd, rjd, ns);
2305 }
2306 return r;
2307 }
2308
2309 #ifndef NDEBUG
2310 static int
2311 valid_nth_kday_p(VALUE y, int m, int n, int k, double sg,
2312 VALUE *nth, int *ry,
2313 int *rm, int *rn, int *rk, int *rjd,
2314 int *ns)
2315 {
2316 double style = guess_style(y, sg);
2317 int r;
2318
2319 if (style == 0) {
2320 int jd;
2321
2322 r = c_valid_nth_kday_p(FIX2INT(y), m, n, k, sg, rm, rn, rk, &jd, ns);
2323 if (!r)
2324 return 0;
2325 decode_jd(INT2FIX(jd), nth, rjd);
2326 if (f_zero_p(*nth))
2327 *ry = FIX2INT(y);
2328 else {
2329 VALUE nth2;
2330 decode_year(y, *ns ? -1 : +1, &nth2, ry);
2331 }
2332 }
2333 else {
2334 decode_year(y, style, nth, ry);
2335 r = c_valid_nth_kday_p(*ry, m, n, k, style, rm, rn, rk, rjd, ns);
2336 }
2337 return r;
2338 }
2339 #endif
2340
2341 VALUE date_zone_to_diff(VALUE);
2342
2343 static int
2344 offset_to_sec(VALUE vof, int *rof)
2345 {
2346 switch (TYPE(vof)) {
2347 case T_FIXNUM:
2348 {
2349 long n;
2350
2351 n = FIX2LONG(vof);
2352 if (n != -1 && n != 0 && n != 1)
2353 return 0;
2354 *rof = (int)n * DAY_IN_SECONDS;
2355 return 1;
2356 }
2357 case T_FLOAT:
2358 {
2359 double n;
2360
2361 n = RFLOAT_VALUE(vof) * DAY_IN_SECONDS;
2362 if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
2363 return 0;
2364 *rof = (int)round(n);
2365 if (*rof != n)
2366 rb_warning("fraction of offset is ignored");
2367 return 1;
2368 }
2369 default:
2370 if (!k_numeric_p(vof))
2371 rb_raise(rb_eTypeError, "expected numeric");
2372 vof = f_to_r(vof);
2373 #ifdef CANONICALIZATION_FOR_MATHN
2374 if (!k_rational_p(vof))
2375 return offset_to_sec(vof, rof);
2376 #endif
2377 /* fall through */
2378 case T_RATIONAL:
2379 {
2380 VALUE vs, vn, vd;
2381 long n;
2382
2383 vs = day_to_sec(vof);
2384
2385 #ifdef CANONICALIZATION_FOR_MATHN
2386 if (!k_rational_p(vs)) {
2387 if (!FIXNUM_P(vs))
2388 return 0;
2389 n = FIX2LONG(vs);
2390 if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
2391 return 0;
2392 *rof = (int)n;
2393 return 1;
2394 }
2395 #endif
2396 vn = RRATIONAL(vs)->num;
2397 vd = RRATIONAL(vs)->den;
2398
2399 if (FIXNUM_P(vn) && FIXNUM_P(vd) && (FIX2LONG(vd) == 1))
2400 n = FIX2LONG(vn);
2401 else {
2402 vn = f_round(vs);
2403 if (!f_eqeq_p(vn, vs))
2404 rb_warning("fraction of offset is ignored");
2405 if (!FIXNUM_P(vn))
2406 return 0;
2407 n = FIX2LONG(vn);
2408 if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
2409 return 0;
2410 }
2411 *rof = (int)n;
2412 return 1;
2413 }
2414 case T_STRING:
2415 {
2416 VALUE vs = date_zone_to_diff(vof);
2417 long n;
2418
2419 if (!FIXNUM_P(vs))
2420 return 0;
2421 n = FIX2LONG(vs);
2422 if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
2423 return 0;
2424 *rof = (int)n;
2425 return 1;
2426 }
2427 }
2428 return 0;
2429 }
2430
2431 /* date */
2432
2433 #define valid_sg(sg) \
2434 {\
2435 if (!c_valid_start_p(sg)) {\
2436 sg = 0;\
2437 rb_warning("invalid start is ignored");\
2438 }\
2439 }
2440
2441 static VALUE
2442 valid_jd_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
2443 {
2444 double sg = NUM2DBL(argv[1]);
2445 valid_sg(sg);
2446 return argv[0];
2447 }
2448
2449 #ifndef NDEBUG
2450 static VALUE
2451 date_s__valid_jd_p(int argc, VALUE *argv, VALUE klass)
2452 {
2453 VALUE vjd, vsg;
2454 VALUE argv2[2];
2455
2456 rb_scan_args(argc, argv, "11", &vjd, &vsg);
2457
2458 argv2[0] = vjd;
2459 if (argc < 2)
2460 argv2[1] = DBL2NUM(GREGORIAN);
2461 else
2462 argv2[1] = vsg;
2463
2464 return valid_jd_sub(2, argv2, klass, 1);
2465 }
2466 #endif
2467
2468 /*
2469 * call-seq:
2470 * Date.valid_jd?(jd[, start=Date::ITALY]) -> bool
2471 *
2472 * Just returns true. It's nonsense, but is for symmetry.
2473 *
2474 * Date.valid_jd?(2451944) #=> true
2475 *
2476 * See also jd.
2477 */
2478 static VALUE
2479 date_s_valid_jd_p(int argc, VALUE *argv, VALUE klass)
2480 {
2481 VALUE vjd, vsg;
2482 VALUE argv2[2];
2483
2484 rb_scan_args(argc, argv, "11", &vjd, &vsg);
2485
2486 argv2[0] = vjd;
2487 if (argc < 2)
2488 argv2[1] = INT2FIX(DEFAULT_SG);
2489 else
2490 argv2[1] = vsg;
2491
2492 if (NIL_P(valid_jd_sub(2, argv2, klass, 0)))
2493 return Qfalse;
2494 return Qtrue;
2495 }
2496
2497 static VALUE
2498 valid_civil_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
2499 {
2500 VALUE nth, y;
2501 int m, d, ry, rm, rd;
2502 double sg;
2503
2504 y = argv[0];
2505 m = NUM2INT(argv[1]);
2506 d = NUM2INT(argv[2]);
2507 sg = NUM2DBL(argv[3]);
2508
2509 valid_sg(sg);
2510
2511 if (!need_jd && (guess_style(y, sg) < 0)) {
2512 if (!valid_gregorian_p(y, m, d,
2513 &nth, &ry,
2514 &rm, &rd))
2515 return Qnil;
2516 return INT2FIX(0); /* dummy */
2517 }
2518 else {
2519 int rjd, ns;
2520 VALUE rjd2;
2521
2522 if (!valid_civil_p(y, m, d, sg,
2523 &nth, &ry,
2524 &rm, &rd, &rjd,
2525 &ns))
2526 return Qnil;
2527 if (!need_jd)
2528 return INT2FIX(0); /* dummy */
2529 encode_jd(nth, rjd, &rjd2);
2530 return rjd2;
2531 }
2532 }
2533
2534 #ifndef NDEBUG
2535 static VALUE
2536 date_s__valid_civil_p(int argc, VALUE *argv, VALUE klass)
2537 {
2538 VALUE vy, vm, vd, vsg;
2539 VALUE argv2[4];
2540
2541 rb_scan_args(argc, argv, "31", &vy, &vm, &vd, &vsg);
2542
2543 argv2[0] = vy;
2544 argv2[1] = vm;
2545 argv2[2] = vd;
2546 if (argc < 4)
2547 argv2[3] = DBL2NUM(GREGORIAN);
2548 else
2549 argv2[3] = vsg;
2550
2551 return valid_civil_sub(4, argv2, klass, 1);
2552 }
2553 #endif
2554
2555 /*
2556 * call-seq:
2557 * Date.valid_civil?(year, month, mday[, start=Date::ITALY]) -> bool
2558 * Date.valid_date?(year, month, mday[, start=Date::ITALY]) -> bool
2559 *
2560 * Returns true if the given calendar date is valid, and false if not.
2561 *
2562 * Date.valid_date?(2001,2,3) #=> true
2563 * Date.valid_date?(2001,2,29) #=> false
2564 *
2565 * See also jd and civil.
2566 */
2567 static VALUE
2568 date_s_valid_civil_p(int argc, VALUE *argv, VALUE klass)
2569 {
2570 VALUE vy, vm, vd, vsg;
2571 VALUE argv2[4];
2572
2573 rb_scan_args(argc, argv, "31", &vy, &vm, &vd, &vsg);
2574
2575 argv2[0] = vy;
2576 argv2[1] = vm;
2577 argv2[2] = vd;
2578 if (argc < 4)
2579 argv2[3] = INT2FIX(DEFAULT_SG);
2580 else
2581 argv2[3] = vsg;
2582
2583 if (NIL_P(valid_civil_sub(4, argv2, klass, 0)))
2584 return Qfalse;
2585 return Qtrue;
2586 }
2587
2588 static VALUE
2589 valid_ordinal_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
2590 {
2591 VALUE nth, y;
2592 int d, ry, rd;
2593 double sg;
2594
2595 y = argv[0];
2596 d = NUM2INT(argv[1]);
2597 sg = NUM2DBL(argv[2]);
2598
2599 valid_sg(sg);
2600
2601 {
2602 int rjd, ns;
2603 VALUE rjd2;
2604
2605 if (!valid_ordinal_p(y, d, sg,
2606 &nth, &ry,
2607 &rd, &rjd,
2608 &ns))
2609 return Qnil;
2610 if (!need_jd)
2611 return INT2FIX(0); /* dummy */
2612 encode_jd(nth, rjd, &rjd2);
2613 return rjd2;
2614 }
2615 }
2616
2617 #ifndef NDEBUG
2618 static VALUE
2619 date_s__valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
2620 {
2621 VALUE vy, vd, vsg;
2622 VALUE argv2[3];
2623
2624 rb_scan_args(argc, argv, "21", &vy, &vd, &vsg);
2625
2626 argv2[0] = vy;
2627 argv2[1] = vd;
2628 if (argc < 3)
2629 argv2[2] = DBL2NUM(GREGORIAN);
2630 else
2631 argv2[2] = vsg;
2632
2633 return valid_ordinal_sub(3, argv2, klass, 1);
2634 }
2635 #endif
2636
2637 /*
2638 * call-seq:
2639 * Date.valid_ordinal?(year, yday[, start=Date::ITALY]) -> bool
2640 *
2641 * Returns true if the given ordinal date is valid, and false if not.
2642 *
2643 * Date.valid_ordinal?(2001,34) #=> true
2644 * Date.valid_ordinal?(2001,366) #=> false
2645 *
2646 * See also jd and ordinal.
2647 */
2648 static VALUE
2649 date_s_valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
2650 {
2651 VALUE vy, vd, vsg;
2652 VALUE argv2[3];
2653
2654 rb_scan_args(argc, argv, "21", &vy, &vd, &vsg);
2655
2656 argv2[0] = vy;
2657 argv2[1] = vd;
2658 if (argc < 3)
2659 argv2[2] = INT2FIX(DEFAULT_SG);
2660 else
2661 argv2[2] = vsg;
2662
2663 if (NIL_P(valid_ordinal_sub(3, argv2, klass, 0)))
2664 return Qfalse;
2665 return Qtrue;
2666 }
2667
2668 static VALUE
2669 valid_commercial_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
2670 {
2671 VALUE nth, y;
2672 int w, d, ry, rw, rd;
2673 double sg;
2674
2675 y = argv[0];
2676 w = NUM2INT(argv[1]);
2677 d = NUM2INT(argv[2]);
2678 sg = NUM2DBL(argv[3]);
2679
2680 valid_sg(sg);
2681
2682 {
2683 int rjd, ns;
2684 VALUE rjd2;
2685
2686 if (!valid_commercial_p(y, w, d, sg,
2687 &nth, &ry,
2688 &rw, &rd, &rjd,
2689 &ns))
2690 return Qnil;
2691 if (!need_jd)
2692 return INT2FIX(0); /* dummy */
2693 encode_jd(nth, rjd, &rjd2);
2694 return rjd2;
2695 }
2696 }
2697
2698 #ifndef NDEBUG
2699 static VALUE
2700 date_s__valid_commercial_p(int argc, VALUE *argv, VALUE klass)
2701 {
2702 VALUE vy, vw, vd, vsg;
2703 VALUE argv2[4];
2704
2705 rb_scan_args(argc, argv, "31", &vy, &vw, &vd, &vsg);
2706
2707 argv2[0] = vy;
2708 argv2[1] = vw;
2709 argv2[2] = vd;
2710 if (argc < 4)
2711 argv2[3] = DBL2NUM(GREGORIAN);
2712 else
2713 argv2[3] = vsg;
2714
2715 return valid_commercial_sub(4, argv2, klass, 1);
2716 }
2717 #endif
2718
2719 /*
2720 * call-seq:
2721 * Date.valid_commercial?(cwyear, cweek, cwday[, start=Date::ITALY]) -> bool
2722 *
2723 * Returns true if the given week date is valid, and false if not.
2724 *
2725 * Date.valid_commercial?(2001,5,6) #=> true
2726 * Date.valid_commercial?(2001,5,8) #=> false
2727 *
2728 * See also jd and commercial.
2729 */
2730 static VALUE
2731 date_s_valid_commercial_p(int argc, VALUE *argv, VALUE klass)
2732 {
2733 VALUE vy, vw, vd, vsg;
2734 VALUE argv2[4];
2735
2736 rb_scan_args(argc, argv, "31", &vy, &vw, &vd, &vsg);
2737
2738 argv2[0] = vy;
2739 argv2[1] = vw;
2740 argv2[2] = vd;
2741 if (argc < 4)
2742 argv2[3] = INT2FIX(DEFAULT_SG);
2743 else
2744 argv2[3] = vsg;
2745
2746 if (NIL_P(valid_commercial_sub(4, argv2, klass, 0)))
2747 return Qfalse;
2748 return Qtrue;
2749 }
2750
2751 #ifndef NDEBUG
2752 static VALUE
2753 valid_weeknum_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
2754 {
2755 VALUE nth, y;
2756 int w, d, f, ry, rw, rd;
2757 double sg;
2758
2759 y = argv[0];
2760 w = NUM2INT(argv[1]);
2761 d = NUM2INT(argv[2]);
2762 f = NUM2INT(argv[3]);
2763 sg = NUM2DBL(argv[4]);
2764
2765 valid_sg(sg);
2766
2767 {
2768 int rjd, ns;
2769 VALUE rjd2;
2770
2771 if (!valid_weeknum_p(y, w, d, f, sg,
2772 &nth, &ry,
2773 &rw, &rd, &rjd,
2774 &ns))
2775 return Qnil;
2776 if (!need_jd)
2777 return INT2FIX(0); /* dummy */
2778 encode_jd(nth, rjd, &rjd2);
2779 return rjd2;
2780 }
2781 }
2782
2783 static VALUE
2784 date_s__valid_weeknum_p(int argc, VALUE *argv, VALUE klass)
2785 {
2786 VALUE vy, vw, vd, vf, vsg;
2787 VALUE argv2[5];
2788
2789 rb_scan_args(argc, argv, "41", &vy, &vw, &vd, &vf, &vsg);
2790
2791 argv2[0] = vy;
2792 argv2[1] = vw;
2793 argv2[2] = vd;
2794 argv2[3] = vf;
2795 if (argc < 5)
2796 argv2[4] = DBL2NUM(GREGORIAN);
2797 else
2798 argv2[4] = vsg;
2799
2800 return valid_weeknum_sub(5, argv2, klass, 1);
2801 }
2802
2803 static VALUE
2804 date_s_valid_weeknum_p(int argc, VALUE *argv, VALUE klass)
2805 {
2806 VALUE vy, vw, vd, vf, vsg;
2807 VALUE argv2[5];
2808
2809 rb_scan_args(argc, argv, "41", &vy, &vw, &vd, &vf, &vsg);
2810
2811 argv2[0] = vy;
2812 argv2[1] = vw;
2813 argv2[2] = vd;
2814 argv2[3] = vf;
2815 if (argc < 5)
2816 argv2[4] = INT2FIX(DEFAULT_SG);
2817 else
2818 argv2[4] = vsg;
2819
2820 if (NIL_P(valid_weeknum_sub(5, argv2, klass, 0)))
2821 return Qfalse;
2822 return Qtrue;
2823 }
2824
2825 static VALUE
2826 valid_nth_kday_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
2827 {
2828 VALUE nth, y;
2829 int m, n, k, ry, rm, rn, rk;
2830 double sg;
2831
2832 y = argv[0];
2833 m = NUM2INT(argv[1]);
2834 n = NUM2INT(argv[2]);
2835 k = NUM2INT(argv[3]);
2836 sg = NUM2DBL(argv[4]);
2837
2838 {
2839 int rjd, ns;
2840 VALUE rjd2;
2841
2842 if (!valid_nth_kday_p(y, m, n, k, sg,
2843 &nth, &ry,
2844 &rm, &rn, &rk, &rjd,
2845 &ns))
2846 return Qnil;
2847 if (!need_jd)
2848 return INT2FIX(0); /* dummy */
2849 encode_jd(nth, rjd, &rjd2);
2850 return rjd2;
2851 }
2852 }
2853
2854 static VALUE
2855 date_s__valid_nth_kday_p(int argc, VALUE *argv, VALUE klass)
2856 {
2857 VALUE vy, vm, vn, vk, vsg;
2858 VALUE argv2[5];
2859
2860 rb_scan_args(argc, argv, "41", &vy, &vm, &vn, &vk, &vsg);
2861
2862 argv2[0] = vy;
2863 argv2[1] = vm;
2864 argv2[2] = vn;
2865 argv2[3] = vk;
2866 if (argc < 5)
2867 argv2[4] = DBL2NUM(GREGORIAN);
2868 else
2869 argv2[4] = vsg;
2870
2871 return valid_nth_kday_sub(5, argv2, klass, 1);
2872 }
2873
2874 static VALUE
2875 date_s_valid_nth_kday_p(int argc, VALUE *argv, VALUE klass)
2876 {
2877 VALUE vy, vm, vn, vk, vsg;
2878 VALUE argv2[5];
2879
2880 rb_scan_args(argc, argv, "41", &vy, &vm, &vn, &vk, &vsg);
2881
2882 argv2[0] = vy;
2883 argv2[1] = vm;
2884 argv2[2] = vn;
2885 argv2[3] = vk;
2886 if (argc < 5)
2887 argv2[4] = INT2FIX(DEFAULT_SG);
2888 else
2889 argv2[4] = vsg;
2890
2891 if (NIL_P(valid_nth_kday_sub(5, argv2, klass, 0)))
2892 return Qfalse;
2893 return Qtrue;
2894 }
2895
2896 static VALUE
2897 date_s_zone_to_diff(VALUE klass, VALUE str)
2898 {
2899 return date_zone_to_diff(str);
2900 }
2901 #endif
2902
2903 /*
2904 * call-seq:
2905 * Date.julian_leap?(year) -> bool
2906 *
2907 * Returns true if the given year is a leap year of the proleptic
2908 * Julian calendar.
2909 *
2910 * Date.julian_leap?(1900) #=> true
2911 * Date.julian_leap?(1901) #=> false
2912 */
2913 static VALUE
2914 date_s_julian_leap_p(VALUE klass, VALUE y)
2915 {
2916 VALUE nth;
2917 int ry;
2918
2919 decode_year(y, +1, &nth, &ry);
2920 return f_boolcast(c_julian_leap_p(ry));
2921 }
2922
2923 /*
2924 * call-seq:
2925 * Date.gregorian_leap?(year) -> bool
2926 * Date.leap?(year) -> bool
2927 *
2928 * Returns true if the given year is a leap year of the proleptic
2929 * Gregorian calendar.
2930 *
2931 * Date.gregorian_leap?(1900) #=> false
2932 * Date.gregorian_leap?(2000) #=> true
2933 */
2934 static VALUE
2935 date_s_gregorian_leap_p(VALUE klass, VALUE y)
2936 {
2937 VALUE nth;
2938 int ry;
2939
2940 decode_year(y, -1, &nth, &ry);
2941 return f_boolcast(c_gregorian_leap_p(ry));
2942 }
2943
2944 static void
2945 d_lite_gc_mark(union DateData *dat)
2946 {
2947 if (simple_dat_p(dat))
2948 rb_gc_mark(dat->s.nth);
2949 else {
2950 rb_gc_mark(dat->c.nth);
2951 rb_gc_mark(dat->c.sf);
2952
2953 }
2954 }
2955
2956 inline static VALUE
2957 d_simple_new_internal(VALUE klass,
2958 VALUE nth, int jd,
2959 double sg,
2960 int y, int m, int d,
2961 unsigned flags)
2962 {
2963 struct SimpleDateData *dat;
2964 VALUE obj;
2965
2966 obj = Data_Make_Struct(klass, struct SimpleDateData,
2967 d_lite_gc_mark, -1, dat);
2968 set_to_simple(dat, nth, jd, sg, y, m, d, flags & ~COMPLEX_DAT);
2969
2970 assert(have_jd_p(dat) || have_civil_p(dat));
2971
2972 return obj;
2973 }
2974
2975 inline static VALUE
2976 d_complex_new_internal(VALUE klass,
2977 VALUE nth, int jd,
2978 int df, VALUE sf,
2979 int of, double sg,
2980 int y, int m, int d,
2981 int h, int min, int s,
2982 unsigned flags)
2983 {
2984 struct ComplexDateData *dat;
2985 VALUE obj;
2986
2987 obj = Data_Make_Struct(klass, struct ComplexDateData,
2988 d_lite_gc_mark, -1, dat);
2989 set_to_complex(dat, nth, jd, df, sf, of, sg,
2990 y, m, d, h, min, s, flags | COMPLEX_DAT);
2991
2992 assert(have_jd_p(dat) || have_civil_p(dat));
2993 assert(have_df_p(dat) || have_time_p(dat));
2994
2995 return obj;
2996 }
2997
2998 static VALUE
2999 d_lite_s_alloc_simple(VALUE klass)
3000 {
3001 return d_simple_new_internal(klass,
3002 INT2FIX(0), 0,
3003 DEFAULT_SG,
3004 0, 0, 0,
3005 HAVE_JD);
3006 }
3007
3008 static VALUE
3009 d_lite_s_alloc_complex(VALUE klass)
3010 {
3011 return d_complex_new_internal(klass,
3012 INT2FIX(0), 0,
3013 0, INT2FIX(0),
3014 0, DEFAULT_SG,
3015 0, 0, 0,
3016 0, 0, 0,
3017 HAVE_JD | HAVE_DF);
3018 }
3019
3020 static VALUE
3021 d_lite_s_alloc(VALUE klass)
3022 {
3023 return d_lite_s_alloc_complex(klass);
3024 }
3025
3026 static void
3027 old_to_new(VALUE ajd, VALUE of, VALUE sg,
3028 VALUE *rnth, int *rjd, int *rdf, VALUE *rsf,
3029 int *rof, double *rsg)
3030 {
3031 VALUE jd, df, sf, of2, t;
3032
3033 decode_day(f_add(ajd, half_days_in_day),
3034 &jd, &df, &sf);
3035 t = day_to_sec(of);
3036 of2 = f_round(t);
3037
3038 if (!f_eqeq_p(of2, t))
3039 rb_warning("fraction of offset is ignored");
3040
3041 decode_jd(jd, rnth, rjd);
3042
3043 *rdf = NUM2INT(df);
3044 *rsf = sf;
3045 *rof = NUM2INT(of2);
3046 *rsg = NUM2DBL(sg);
3047
3048 if (*rdf < 0 || *rdf >= DAY_IN_SECONDS)
3049 rb_raise(rb_eArgError, "invalid day fraction");
3050
3051 if (f_lt_p(*rsf, INT2FIX(0)) ||
3052 f_ge_p(*rsf, INT2FIX(SECOND_IN_NANOSECONDS)))
3053
3054 if (*rof < -DAY_IN_SECONDS || *rof > DAY_IN_SECONDS) {
3055 *rof = 0;
3056 rb_warning("invalid offset is ignored");
3057 }
3058
3059 if (!c_valid_start_p(*rsg)) {
3060 *rsg = DEFAULT_SG;
3061 rb_warning("invalid start is ignored");
3062 }
3063 }
3064
3065 #ifndef NDEBUG
3066 static VALUE
3067 date_s_new_bang(int argc, VALUE *argv, VALUE klass)
3068 {
3069 VALUE ajd, of, sg, nth, sf;
3070 int jd, df, rof;
3071 double rsg;
3072
3073 rb_scan_args(argc, argv, "03", &ajd, &of, &sg);
3074
3075 switch (argc) {
3076 case 0:
3077 ajd = INT2FIX(0);
3078 case 1:
3079 of = INT2FIX(0);
3080 case 2:
3081 sg = INT2FIX(DEFAULT_SG);
3082 }
3083
3084 old_to_new(ajd, of, sg,
3085 &nth, &jd, &df, &sf, &rof, &rsg);
3086
3087 if (!df && f_zero_p(sf) && !rof)
3088 return d_simple_new_internal(klass,
3089 nth, jd,
3090 rsg,
3091 0, 0, 0,
3092 HAVE_JD);
3093 else
3094 return d_complex_new_internal(klass,
3095 nth, jd,
3096 df, sf,
3097 rof, rsg,
3098 0, 0, 0,
3099 0, 0, 0,
3100 HAVE_JD | HAVE_DF);
3101 }
3102 #endif
3103
3104 inline static int
3105 wholenum_p(VALUE x)
3106 {
3107 if (FIXNUM_P(x))
3108 return 1;
3109 switch (TYPE(x)) {
3110 case T_BIGNUM:
3111 return 1;
3112 case T_FLOAT:
3113 {
3114 double d = RFLOAT_VALUE(x);
3115 return round(d) == d;
3116 }
3117 break;
3118 case T_RATIONAL:
3119 {
3120 VALUE den = RRATIONAL(x)->den;
3121 return FIXNUM_P(den) && FIX2LONG(den) == 1;
3122 }
3123 break;
3124 }
3125 return 0;
3126 }
3127
3128 inline static VALUE
3129 to_integer(VALUE x)
3130 {
3131 if (FIXNUM_P(x) || RB_TYPE_P(x, T_BIGNUM))
3132 return x;
3133 return f_to_i(x);
3134 }
3135
3136 inline static VALUE
3137 d_trunc(VALUE d, VALUE *fr)
3138 {
3139 VALUE rd;
3140
3141 if (wholenum_p(d)) {
3142 rd = to_integer(d);
3143 *fr = INT2FIX(0);
3144 }
3145 else {
3146 rd = f_idiv(d, INT2FIX(1));
3147 *fr = f_mod(d, INT2FIX(1));
3148 }
3149 return rd;
3150 }
3151
3152 #define jd_trunc d_trunc
3153 #define k_trunc d_trunc
3154
3155 inline static VALUE
3156 h_trunc(VALUE h, VALUE *fr)
3157 {
3158 VALUE rh;
3159
3160 if (wholenum_p(h)) {
3161 rh = to_integer(h);
3162 *fr = INT2FIX(0);
3163 }
3164 else {
3165 rh = f_idiv(h, INT2FIX(1));
3166 *fr = f_mod(h, INT2FIX(1));
3167 *fr = f_quo(*fr, INT2FIX(24));
3168 }
3169 return rh;
3170 }
3171
3172 inline static VALUE
3173 min_trunc(VALUE min, VALUE *fr)
3174 {
3175 VALUE rmin;
3176
3177 if (wholenum_p(min)) {
3178 rmin = to_integer(min);
3179 *fr = INT2FIX(0);
3180 }
3181 else {
3182 rmin = f_idiv(min, INT2FIX(1));
3183 *fr = f_mod(min, INT2FIX(1));
3184 *fr = f_quo(*fr, INT2FIX(1440));
3185 }
3186 return rmin;
3187 }
3188
3189 inline static VALUE
3190 s_trunc(VALUE s, VALUE *fr)
3191 {
3192 VALUE rs;
3193
3194 if (wholenum_p(s)) {
3195 rs = to_integer(s);
3196 *fr = INT2FIX(0);
3197 }
3198 else {
3199 rs = f_idiv(s, INT2FIX(1));
3200 *fr = f_mod(s, INT2FIX(1));
3201 *fr = f_quo(*fr, INT2FIX(86400));
3202 }
3203 return rs;
3204 }
3205
3206 #define num2num_with_frac(s,n) \
3207 {\
3208 s = s##_trunc(v##s, &fr);\
3209 if (f_nonzero_p(fr)) {\
3210 if (argc > n)\
3211 rb_raise(rb_eArgError, "invalid fraction");\
3212 fr2 = fr;\
3213 }\
3214 }
3215
3216 #define num2int_with_frac(s,n) \
3217 {\
3218 s = NUM2INT(s##_trunc(v##s, &fr));\
3219 if (f_nonzero_p(fr)) {\
3220 if (argc > n)\
3221 rb_raise(rb_eArgError, "invalid fraction");\
3222 fr2 = fr;\
3223 }\
3224 }
3225
3226 #define canon24oc() \
3227 {\
3228 if (rh == 24) {\
3229 rh = 0;\
3230 fr2 = f_add(fr2, INT2FIX(1));\
3231 }\
3232 }
3233
3234 #define add_frac() \
3235 {\
3236 if (f_nonzero_p(fr2))\
3237 ret = d_lite_plus(ret, fr2);\
3238 }
3239
3240 #define val2sg(vsg,dsg) \
3241 {\
3242 dsg = NUM2DBL(vsg);\
3243 if (!c_valid_start_p(dsg)) {\
3244 dsg = DEFAULT_SG;\
3245 rb_warning("invalid start is ignored");\
3246 }\
3247 }
3248
3249 static VALUE d_lite_plus(VALUE, VALUE);
3250
3251 /*
3252 * call-seq:
3253 * Date.jd([jd=0[, start=Date::ITALY]]) -> date
3254 *
3255 * Creates a date object denoting the given chronological Julian day
3256 * number.
3257 *
3258 * Date.jd(2451944) #=> #<Date: 2001-02-03 ...>
3259 * Date.jd(2451945) #=> #<Date: 2001-02-04 ...>
3260 * Date.jd(0) #=> #<Date: -4712-01-01 ...>
3261 *
3262 * See also new.
3263 */
3264 static VALUE
3265 date_s_jd(int argc, VALUE *argv, VALUE klass)
3266 {
3267 VALUE vjd, vsg, jd, fr, fr2, ret;
3268 double sg;
3269
3270 rb_scan_args(argc, argv, "02", &vjd, &vsg);
3271
3272 jd = INT2FIX(0);
3273 fr2 = INT2FIX(0);
3274 sg = DEFAULT_SG;
3275
3276 switch (argc) {
3277 case 2:
3278 val2sg(vsg, sg);
3279 case 1:
3280 num2num_with_frac(jd, positive_inf);
3281 }
3282
3283 {
3284 VALUE nth;
3285 int rjd;
3286
3287 decode_jd(jd, &nth, &rjd);
3288 ret = d_simple_new_internal(klass,
3289 nth, rjd,
3290 sg,
3291 0, 0, 0,
3292 HAVE_JD);
3293 }
3294 add_frac();
3295 return ret;
3296 }
3297
3298 /*
3299 * call-seq:
3300 * Date.ordinal([year=-4712[, yday=1[, start=Date::ITALY]]]) -> date
3301 *
3302 * Creates a date object denoting the given ordinal date.
3303 *
3304 * The day of year should be a negative or a positive number (as a
3305 * relative day from the end of year when negative). It should not be
3306 * zero.
3307 *
3308 * Date.ordinal(2001) #=> #<Date: 2001-01-01 ...>
3309 * Date.ordinal(2001,34) #=> #<Date: 2001-02-03 ...>
3310 * Date.ordinal(2001,-1) #=> #<Date: 2001-12-31 ...>
3311 *
3312 * See also jd and new.
3313 */
3314 static VALUE
3315 date_s_ordinal(int argc, VALUE *argv, VALUE klass)
3316 {
3317 VALUE vy, vd, vsg, y, fr, fr2, ret;
3318 int d;
3319 double sg;
3320
3321 rb_scan_args(argc, argv, "03", &vy, &vd, &vsg);
3322
3323 y = INT2FIX(-4712);
3324 d = 1;
3325 fr2 = INT2FIX(0);
3326 sg = DEFAULT_SG;
3327
3328 switch (argc) {
3329 case 3:
3330 val2sg(vsg, sg);
3331 case 2:
3332 num2int_with_frac(d, positive_inf);
3333 case 1:
3334 y = vy;
3335 }
3336
3337 {
3338 VALUE nth;
3339 int ry, rd, rjd, ns;
3340
3341 if (!valid_ordinal_p(y, d, sg,
3342 &nth, &ry,
3343 &rd, &rjd,
3344 &ns))
3345 rb_raise(rb_eArgError, "invalid date");
3346
3347 ret = d_simple_new_internal(klass,
3348 nth, rjd,
3349 sg,
3350 0, 0, 0,
3351 HAVE_JD);
3352 }
3353 add_frac();
3354 return ret;
3355 }
3356
3357 /*
3358 * call-seq:
3359 * Date.civil([year=-4712[, month=1[, mday=1[, start=Date::ITALY]]]]) -> date
3360 * Date.new([year=-4712[, month=1[, mday=1[, start=Date::ITALY]]]]) -> date
3361 *
3362 * Creates a date object denoting the given calendar date.
3363 *
3364 * In this class, BCE years are counted astronomically. Thus, the
3365 * year before the year 1 is the year zero, and the year preceding the
3366 * year zero is the year -1. The month and the day of month should be
3367 * a negative or a positive number (as a relative month/day from the
3368 * end of year/month when negative). They should not be zero.
3369 *
3370 * The last argument should be a Julian day number which denotes the
3371 * day of calendar reform. Date::ITALY (2299161=1582-10-15),
3372 * Date::ENGLAND (2361222=1752-09-14), Date::GREGORIAN (the proleptic
3373 * Gregorian calendar) and Date::JULIAN (the proleptic Julian
3374 * calendar) can be specified as a day of calendar reform.
3375 *
3376 * Date.new(2001) #=> #<Date: 2001-01-01 ...>
3377 * Date.new(2001,2,3) #=> #<Date: 2001-02-03 ...>
3378 * Date.new(2001,2,-1) #=> #<Date: 2001-02-28 ...>
3379 *
3380 * See also jd.
3381 */
3382 static VALUE
3383 date_s_civil(int argc, VALUE *argv, VALUE klass)
3384 {
3385 VALUE vy, vm, vd, vsg, y, fr, fr2, ret;
3386 int m, d;
3387 double sg;
3388
3389 rb_scan_args(argc, argv, "04", &vy, &vm, &vd, &vsg);
3390
3391 y = INT2FIX(-4712);
3392 m = 1;
3393 d = 1;
3394 fr2 = INT2FIX(0);
3395 sg = DEFAULT_SG;
3396
3397 switch (argc) {
3398 case 4:
3399 val2sg(vsg, sg);
3400 case 3:
3401 num2int_with_frac(d, positive_inf);
3402 case 2:
3403 m = NUM2INT(vm);
3404 case 1:
3405 y = vy;
3406 }
3407
3408 if (guess_style(y, sg) < 0) {
3409 VALUE nth;
3410 int ry, rm, rd;
3411
3412 if (!valid_gregorian_p(y, m, d,
3413 &nth, &ry,
3414 &rm, &rd))
3415 rb_raise(rb_eArgError, "invalid date");
3416
3417 ret = d_simple_new_internal(klass,
3418 nth, 0,
3419 sg,
3420 ry, rm, rd,
3421 HAVE_CIVIL);
3422 }
3423 else {
3424 VALUE nth;
3425 int ry, rm, rd, rjd, ns;
3426
3427 if (!valid_civil_p(y, m, d, sg,
3428 &nth, &ry,
3429 &rm, &rd, &rjd,
3430 &ns))
3431 rb_raise(rb_eArgError, "invalid date");
3432
3433 ret = d_simple_new_internal(klass,
3434 nth, rjd,
3435 sg,
3436 ry, rm, rd,
3437 HAVE_JD | HAVE_CIVIL);
3438 }
3439 add_frac();
3440 return ret;
3441 }
3442
3443 /*
3444 * call-seq:
3445 * Date.commercial([cwyear=-4712[, cweek=1[, cwday=1[, start=Date::ITALY]]]]) -> date
3446 *
3447 * Creates a date object denoting the given week date.
3448 *
3449 * The week and the day of week should be a negative or a positive
3450 * number (as a relative week/day from the end of year/week when
3451 * negative). They should not be zero.
3452 *
3453 * Date.commercial(2001) #=> #<Date: 2001-01-01 ...>
3454 * Date.commercial(2002) #=> #<Date: 2001-12-31 ...>
3455 * Date.commercial(2001,5,6) #=> #<Date: 2001-02-03 ...>
3456 *
3457 * See also jd and new.
3458 */
3459 static VALUE
3460 date_s_commercial(int argc, VALUE *argv, VALUE klass)
3461 {
3462 VALUE vy, vw, vd, vsg, y, fr, fr2, ret;
3463 int w, d;
3464 double sg;
3465
3466 rb_scan_args(argc, argv, "04", &vy, &vw, &vd, &vsg);
3467
3468 y = INT2FIX(-4712);
3469 w = 1;
3470 d = 1;
3471 fr2 = INT2FIX(0);
3472 sg = DEFAULT_SG;
3473
3474 switch (argc) {
3475 case 4:
3476 val2sg(vsg, sg);
3477 case 3:
3478 num2int_with_frac(d, positive_inf);
3479 case 2:
3480 w = NUM2INT(vw);
3481 case 1:
3482 y = vy;
3483 }
3484
3485 {
3486 VALUE nth;
3487 int ry, rw, rd, rjd, ns;
3488
3489 if (!valid_commercial_p(y, w, d, sg,
3490 &nth, &ry,
3491 &rw, &rd, &rjd,
3492 &ns))
3493 rb_raise(rb_eArgError, "invalid date");
3494
3495 ret = d_simple_new_internal(klass,
3496 nth, rjd,
3497 sg,
3498 0, 0, 0,
3499 HAVE_JD);
3500 }
3501 add_frac();
3502 return ret;
3503 }
3504
3505 #ifndef NDEBUG
3506 static VALUE
3507 date_s_weeknum(int argc, VALUE *argv, VALUE klass)
3508 {
3509 VALUE vy, vw, vd, vf, vsg, y, fr, fr2, ret;
3510 int w, d, f;
3511 double sg;
3512
3513 rb_scan_args(argc, argv, "05", &vy, &vw, &vd, &vf, &vsg);
3514
3515 y = INT2FIX(-4712);
3516 w = 0;
3517 d = 1;
3518 f = 0;
3519 fr2 = INT2FIX(0);
3520 sg = DEFAULT_SG;
3521
3522 switch (argc) {
3523 case 5:
3524 val2sg(vsg, sg);
3525 case 4:
3526 f = NUM2INT(vf);
3527 case 3:
3528 num2int_with_frac(d, positive_inf);
3529 case 2:
3530 w = NUM2INT(vw);
3531 case 1:
3532 y = vy;
3533 }
3534
3535 {
3536 VALUE nth;
3537 int ry, rw, rd, rjd, ns;
3538
3539 if (!valid_weeknum_p(y, w, d, f, sg,
3540 &nth, &ry,
3541 &rw, &rd, &rjd,
3542 &ns))
3543 rb_raise(rb_eArgError, "invalid date");
3544
3545 ret = d_simple_new_internal(klass,
3546 nth, rjd,
3547 sg,
3548 0, 0, 0,
3549 HAVE_JD);
3550 }
3551 add_frac();
3552 return ret;
3553 }
3554
3555 static VALUE
3556 date_s_nth_kday(int argc, VALUE *argv, VALUE klass)
3557 {
3558 VALUE vy, vm, vn, vk, vsg, y, fr, fr2, ret;
3559 int m, n, k;
3560 double sg;
3561
3562 rb_scan_args(argc, argv, "05", &vy, &vm, &vn, &vk, &vsg);
3563
3564 y = INT2FIX(-4712);
3565 m = 1;
3566 n = 1;
3567 k = 1;
3568 fr2 = INT2FIX(0);
3569 sg = DEFAULT_SG;
3570
3571 switch (argc) {
3572 case 5:
3573 val2sg(vsg, sg);
3574 case 4:
3575 num2int_with_frac(k, positive_inf);
3576 case 3:
3577 n = NUM2INT(vn);
3578 case 2:
3579 m = NUM2INT(vm);
3580 case 1:
3581 y = vy;
3582 }
3583
3584 {
3585 VALUE nth;
3586 int ry, rm, rn, rk, rjd, ns;
3587
3588 if (!valid_nth_kday_p(y, m, n, k, sg,
3589 &nth, &ry,
3590 &rm, &rn, &rk, &rjd,
3591 &ns))
3592 rb_raise(rb_eArgError, "invalid date");
3593
3594 ret = d_simple_new_internal(klass,
3595 nth, rjd,
3596 sg,
3597 0, 0, 0,
3598 HAVE_JD);
3599 }
3600 add_frac();
3601 return ret;
3602 }
3603 #endif
3604
3605 #if !defined(HAVE_GMTIME_R)
3606 static struct tm*
3607 gmtime_r(const time_t *t, struct tm *tm)
3608 {
3609 auto struct tm *tmp = gmtime(t);
3610 if (tmp)
3611 *tm = *tmp;
3612 return tmp;
3613 }
3614
3615 static struct tm*
3616 localtime_r(const time_t *t, struct tm *tm)
3617 {
3618 auto struct tm *tmp = localtime(t);
3619 if (tmp)
3620 *tm = *tmp;
3621 return tmp;
3622 }
3623 #endif
3624
3625 static void set_sg(union DateData *, double);
3626
3627 /*
3628 * call-seq:
3629 * Date.today([start=Date::ITALY]) -> date
3630 *
3631 * Date.today #=> #<Date: 2011-06-11 ..>
3632 *
3633 * Creates a date object denoting the present day.
3634 */
3635 static VALUE
3636 date_s_today(int argc, VALUE *argv, VALUE klass)
3637 {
3638 VALUE vsg, nth, ret;
3639 double sg;
3640 time_t t;
3641 struct tm tm;
3642 int y, ry, m, d;
3643
3644 rb_scan_args(argc, argv, "01", &vsg);
3645
3646 if (argc < 1)
3647 sg = DEFAULT_SG;
3648 else
3649 val2sg(vsg, sg);
3650
3651 if (time(&t) == -1)
3652 rb_sys_fail("time");
3653 tzset();
3654 if (!localtime_r(&t, &tm))
3655 rb_sys_fail("localtime");
3656
3657 y = tm.tm_year + 1900;
3658 m = tm.tm_mon + 1;
3659 d = tm.tm_mday;
3660
3661 decode_year(INT2FIX(y), -1, &nth, &ry);
3662
3663 ret = d_simple_new_internal(klass,
3664 nth, 0,
3665 GREGORIAN,
3666 ry, m, d,
3667 HAVE_CIVIL);
3668 {
3669 get_d1(ret);
3670 set_sg(dat, sg);
3671 }
3672 return ret;
3673 }
3674
3675 #define set_hash0(k,v) rb_hash_aset(hash, k, v)
3676 #define ref_hash0(k) rb_hash_aref(hash, k)
3677 #define del_hash0(k) rb_hash_delete(hash, k)
3678
3679 #define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k)), v)
3680 #define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k)))
3681 #define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k)))
3682
3683 static VALUE
3684 rt_rewrite_frags(VALUE hash)
3685 {
3686 VALUE seconds;
3687
3688 seconds = ref_hash("seconds");
3689 if (!NIL_P(seconds)) {
3690 VALUE d, h, min, s, fr;
3691
3692 d = f_idiv(seconds, INT2FIX(DAY_IN_SECONDS));
3693 fr = f_mod(seconds, INT2FIX(DAY_IN_SECONDS));
3694
3695 h = f_idiv(fr, INT2FIX(HOUR_IN_SECONDS));
3696 fr = f_mod(fr, INT2FIX(HOUR_IN_SECONDS));
3697
3698 min = f_idiv(fr, INT2FIX(MINUTE_IN_SECONDS));
3699 fr = f_mod(fr, INT2FIX(MINUTE_IN_SECONDS));
3700
3701 s = f_idiv(fr, INT2FIX(1));
3702 fr = f_mod(fr, INT2FIX(1));
3703
3704 set_hash("jd", f_add(UNIX_EPOCH_IN_CJD, d));
3705 set_hash("hour", h);
3706 set_hash("min", min);
3707 set_hash("sec", s);
3708 set_hash("sec_fraction", fr);
3709 del_hash("seconds");
3710 del_hash("offset");
3711 }
3712 return hash;
3713 }
3714
3715 #define sym(x) ID2SYM(rb_intern(x))
3716
3717 static VALUE d_lite_year(VALUE);
3718 static VALUE d_lite_wday(VALUE);
3719 static VALUE d_lite_jd(VALUE);
3720
3721 static VALUE
3722 rt_complete_frags(VALUE klass, VALUE hash)
3723 {
3724 static VALUE tab = Qnil;
3725 int g, e;
3726 VALUE k, a, d;
3727
3728 if (NIL_P(tab)) {
3729 tab = rb_ary_new3(11,
3730 rb_ary_new3(2,
3731 sym("time"),
3732 rb_ary_new3(3,
3733 sym("hour"),
3734 sym("min"),
3735 sym("sec"))),
3736 rb_ary_new3(2,
3737 Qnil,
3738 rb_ary_new3(1,
3739 sym("jd"))),
3740 rb_ary_new3(2,
3741 sym("ordinal"),
3742 rb_ary_new3(5,
3743 sym("year"),
3744 sym("yday"),
3745 sym("hour"),
3746 sym("min"),
3747 sym("sec"))),
3748 rb_ary_new3(2,
3749 sym("civil"),
3750 rb_ary_new3(6,
3751 sym("year"),
3752 sym("mon"),
3753 sym("mday"),
3754 sym("hour"),
3755 sym("min"),
3756 sym("sec"))),
3757 rb_ary_new3(2,
3758 sym("commercial"),
3759 rb_ary_new3(6,
3760 sym("cwyear"),
3761 sym("cweek"),
3762 sym("cwday"),
3763 sym("hour"),
3764 sym("min"),
3765 sym("sec"))),
3766 rb_ary_new3(2,
3767 sym("wday"),
3768 rb_ary_new3(4,
3769 sym("wday"),
3770 sym("hour"),
3771 sym("min"),
3772 sym("sec"))),
3773 rb_ary_new3(2,
3774 sym("wnum0"),
3775 rb_ary_new3(6,
3776 sym("year"),
3777 sym("wnum0"),
3778 sym("wday"),
3779 sym("hour"),
3780 sym("min"),
3781 sym("sec"))),
3782 rb_ary_new3(2,
3783 sym("wnum1"),
3784 rb_ary_new3(6,
3785 sym("year"),
3786 sym("wnum1"),
3787 sym("wday"),
3788 sym("hour"),
3789 sym("min"),
3790 sym("sec"))),
3791 rb_ary_new3(2,
3792 Qnil,
3793 rb_ary_new3(6,
3794 sym("cwyear"),
3795 sym("cweek"),
3796 sym("wday"),
3797 sym("hour"),
3798 sym("min"),
3799 sym("sec"))),
3800 rb_ary_new3(2,
3801 Qnil,
3802 rb_ary_new3(6,
3803 sym("year"),
3804 sym("wnum0"),
3805 sym("cwday"),
3806 sym("hour"),
3807 sym("min"),
3808 sym("sec"))),
3809 rb_ary_new3(2,
3810 Qnil,
3811 rb_ary_new3(6,
3812 sym("year"),
3813 sym("wnum1"),
3814 sym("cwday"),
3815 sym("hour"),
3816 sym("min"),
3817 sym("sec"))));
3818 rb_gc_register_mark_object(tab);
3819 }
3820
3821 {
3822 int i, eno = 0, idx = 0;
3823
3824 for (i = 0; i < RARRAY_LENINT(tab); i++) {
3825 VALUE x, a;
3826
3827 x = RARRAY_PTR(tab)[i];
3828 a = RARRAY_PTR(x)[1];
3829
3830 {
3831 int j, n = 0;
3832
3833 for (j = 0; j < RARRAY_LENINT(a); j++)
3834 if (!NIL_P(ref_hash0(RARRAY_PTR(a)[j])))
3835 n++;
3836 if (n > eno) {
3837 eno = n;
3838 idx = i;
3839 }
3840 }
3841 }
3842 if (eno == 0)
3843 g = 0;
3844 else {
3845 g = 1;
3846 k = RARRAY_PTR(RARRAY_PTR(tab)[idx])[0];
3847 a = RARRAY_PTR(RARRAY_PTR(tab)[idx])[1];
3848 e = eno;
3849 }
3850 }
3851
3852 d = Qnil;
3853
3854 if (g && !NIL_P(k) && (RARRAY_LENINT(a) - e)) {
3855 if (k == sym("ordinal")) {
3856 if (NIL_P(ref_hash("year"))) {
3857 if (NIL_P(d))
3858 d = date_s_today(0, (VALUE *)0, cDate);
3859 set_hash("year", d_lite_year(d));
3860 }
3861 if (NIL_P(ref_hash("yday")))
3862 set_hash("yday", INT2FIX(1));
3863 }
3864 else if (k == sym("civil")) {
3865 int i;
3866
3867 for (i = 0; i < RARRAY_LENINT(a); i++) {
3868 VALUE e = RARRAY_PTR(a)[i];
3869
3870 if (!NIL_P(ref_hash0(e)))
3871 break;
3872 if (NIL_P(d))
3873 d = date_s_today(0, (VALUE *)0, cDate);
3874 set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
3875 }
3876 if (NIL_P(ref_hash("mon")))
3877 set_hash("mon", INT2FIX(1));
3878 if (NIL_P(ref_hash("mday")))
3879 set_hash("mday", INT2FIX(1));
3880 }
3881 else if (k == sym("commercial")) {
3882 int i;
3883
3884 for (i = 0; i < RARRAY_LENINT(a); i++) {
3885 VALUE e = RARRAY_PTR(a)[i];
3886
3887 if (!NIL_P(ref_hash0(e)))
3888 break;
3889 if (NIL_P(d))
3890 d = date_s_today(0, (VALUE *)0, cDate);
3891 set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
3892 }
3893 if (NIL_P(ref_hash("cweek")))
3894 set_hash("cweek", INT2FIX(1));
3895 if (NIL_P(ref_hash("cwday")))
3896 set_hash("cwday", INT2FIX(1));
3897 }
3898 else if (k == sym("wday")) {
3899 if (NIL_P(d))
3900 d = date_s_today(0, (VALUE *)0, cDate);
3901 set_hash("jd", d_lite_jd(f_add(f_sub(d,
3902 d_lite_wday(d)),
3903 ref_hash("wday"))));
3904 }
3905 else if (k == sym("wnum0")) {
3906 int i;
3907
3908 for (i = 0; i < RARRAY_LENINT(a); i++) {
3909 VALUE e = RARRAY_PTR(a)[i];
3910
3911 if (!NIL_P(ref_hash0(e)))
3912 break;
3913 if (NIL_P(d))
3914 d = date_s_today(0, (VALUE *)0, cDate);
3915 set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
3916 }
3917 if (NIL_P(ref_hash("wnum0")))
3918 set_hash("wnum0", INT2FIX(0));
3919 if (NIL_P(ref_hash("wday")))
3920 set_hash("wday", INT2FIX(0));
3921 }
3922 else if (k == sym("wnum1")) {
3923 int i;
3924
3925 for (i = 0; i < RARRAY_LENINT(a); i++) {
3926 VALUE e = RARRAY_PTR(a)[i];
3927
3928 if (!NIL_P(ref_hash0(e)))
3929 break;
3930 if (NIL_P(d))
3931 d = date_s_today(0, (VALUE *)0, cDate);
3932 set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
3933 }
3934 if (NIL_P(ref_hash("wnum1")))
3935 set_hash("wnum1", INT2FIX(0));
3936 if (NIL_P(ref_hash("wday")))
3937 set_hash("wday", INT2FIX(1));
3938 }
3939 }
3940
3941 if (g && k == sym("time")) {
3942 if (f_le_p(klass, cDateTime)) {
3943 if (NIL_P(d))
3944 d = date_s_today(0, (VALUE *)0, cDate);
3945 if (NIL_P(ref_hash("jd")))
3946 set_hash("jd", d_lite_jd(d));
3947 }
3948 }
3949
3950 if (NIL_P(ref_hash("hour")))
3951 set_hash("hour", INT2FIX(0));
3952 if (NIL_P(ref_hash("min")))
3953 set_hash("min", INT2FIX(0));
3954 if (NIL_P(ref_hash("sec")))
3955 set_hash("sec", INT2FIX(0));
3956 else if (f_gt_p(ref_hash("sec"), INT2FIX(59)))
3957 set_hash("sec", INT2FIX(59));
3958
3959 return hash;
3960 }
3961
3962 static VALUE
3963 rt__valid_jd_p(VALUE jd, VALUE sg)
3964 {
3965 return jd;
3966 }
3967
3968 static VALUE
3969 rt__valid_ordinal_p(VALUE y, VALUE d, VALUE sg)
3970 {
3971 VALUE nth, rjd2;
3972 int ry, rd, rjd, ns;
3973
3974 if (!valid_ordinal_p(y, NUM2INT(d), NUM2DBL(sg),
3975 &nth, &ry,
3976 &rd, &rjd,
3977 &ns))
3978 return Qnil;
3979 encode_jd(nth, rjd, &rjd2);
3980 return rjd2;
3981 }
3982
3983 static VALUE
3984 rt__valid_civil_p(VALUE y, VALUE m, VALUE d, VALUE sg)
3985 {
3986 VALUE nth, rjd2;
3987 int ry, rm, rd, rjd, ns;
3988
3989 if (!valid_civil_p(y, NUM2INT(m), NUM2INT(d), NUM2DBL(sg),
3990 &nth, &ry,
3991 &rm, &rd, &rjd,
3992 &ns))
3993 return Qnil;
3994 encode_jd(nth, rjd, &rjd2);
3995 return rjd2;
3996 }
3997
3998 static VALUE
3999 rt__valid_commercial_p(VALUE y, VALUE w, VALUE d, VALUE sg)
4000 {
4001 VALUE nth, rjd2;
4002 int ry, rw, rd, rjd, ns;
4003
4004 if (!valid_commercial_p(y, NUM2INT(w), NUM2INT(d), NUM2DBL(sg),
4005 &nth, &ry,
4006 &rw, &rd, &rjd,
4007 &ns))
4008 return Qnil;
4009 encode_jd(nth, rjd, &rjd2);
4010 return rjd2;
4011 }
4012
4013 static VALUE
4014 rt__valid_weeknum_p(VALUE y, VALUE w, VALUE d, VALUE f, VALUE sg)
4015 {
4016 VALUE nth, rjd2;
4017 int ry, rw, rd, rjd, ns;
4018
4019 if (!valid_weeknum_p(y, NUM2INT(w), NUM2INT(d), NUM2INT(f), NUM2DBL(sg),
4020 &nth, &ry,
4021 &rw, &rd, &rjd,
4022 &ns))
4023 return Qnil;
4024 encode_jd(nth, rjd, &rjd2);
4025 return rjd2;
4026 }
4027
4028 static VALUE
4029 rt__valid_date_frags_p(VALUE hash, VALUE sg)
4030 {
4031 {
4032 VALUE vjd;
4033
4034 if (!NIL_P(vjd = ref_hash("jd"))) {
4035 VALUE jd = rt__valid_jd_p(vjd, sg);
4036 if (!NIL_P(jd))
4037 return jd;
4038 }
4039 }
4040
4041 {
4042 VALUE year, yday;
4043
4044 if (!NIL_P(yday = ref_hash("yday")) &&
4045 !NIL_P(year = ref_hash("year"))) {
4046 VALUE jd = rt__valid_ordinal_p(year, yday, sg);
4047 if (!NIL_P(jd))
4048 return jd;
4049 }
4050 }
4051
4052 {
4053 VALUE year, mon, mday;
4054
4055 if (!NIL_P(mday = ref_hash("mday")) &&
4056 !NIL_P(mon = ref_hash("mon")) &&
4057 !NIL_P(year = ref_hash("year"))) {
4058 VALUE jd = rt__valid_civil_p(year, mon, mday, sg);
4059 if (!NIL_P(jd))
4060 return jd;
4061 }
4062 }
4063
4064 {
4065 VALUE year, week, wday;
4066
4067 wday = ref_hash("cwday");
4068 if (NIL_P(wday)) {
4069 wday = ref_hash("wday");
4070 if (!NIL_P(wday))
4071 if (f_zero_p(wday))
4072 wday = INT2FIX(7);
4073 }
4074
4075 if (!NIL_P(wday) &&
4076 !NIL_P(week = ref_hash("cweek")) &&
4077 !NIL_P(year = ref_hash("cwyear"))) {
4078 VALUE jd = rt__valid_commercial_p(year, week, wday, sg);
4079 if (!NIL_P(jd))
4080 return jd;
4081 }
4082 }
4083
4084 {
4085 VALUE year, week, wday;
4086
4087 wday = ref_hash("wday");
4088 if (NIL_P(wday)) {
4089 wday = ref_hash("cwday");
4090 if (!NIL_P(wday))
4091 if (f_eqeq_p(wday, INT2FIX(7)))
4092 wday = INT2FIX(0);
4093 }
4094
4095 if (!NIL_P(wday) &&
4096 !NIL_P(week = ref_hash("wnum0")) &&
4097 !NIL_P(year = ref_hash("year"))) {
4098 VALUE jd = rt__valid_weeknum_p(year, week, wday, INT2FIX(0), sg);
4099 if (!NIL_P(jd))
4100 return jd;
4101 }
4102 }
4103
4104 {
4105 VALUE year, week, wday;
4106
4107 wday = ref_hash("wday");
4108 if (NIL_P(wday))
4109 wday = ref_hash("cwday");
4110 if (!NIL_P(wday))
4111 wday = f_mod(f_sub(wday, INT2FIX(1)),
4112 INT2FIX(7));
4113
4114 if (!NIL_P(wday) &&
4115 !NIL_P(week = ref_hash("wnum1")) &&
4116 !NIL_P(year = ref_hash("year"))) {
4117 VALUE jd = rt__valid_weeknum_p(year, week, wday, INT2FIX(1), sg);
4118 if (!NIL_P(jd))
4119 return jd;
4120 }
4121 }
4122 return Qnil;
4123 }
4124
4125 static VALUE
4126 d_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
4127 {
4128 VALUE jd;
4129
4130 if (!c_valid_start_p(NUM2DBL(sg))) {
4131 sg = INT2FIX(DEFAULT_SG);
4132 rb_warning("invalid start is ignored");
4133 }
4134
4135 if (NIL_P(hash))
4136 rb_raise(rb_eArgError, "invalid date");
4137
4138 if (NIL_P(ref_hash("jd")) &&
4139 NIL_P(ref_hash("yday")) &&
4140 !NIL_P(ref_hash("year")) &&
4141 !NIL_P(ref_hash("mon")) &&
4142 !NIL_P(ref_hash("mday")))
4143 jd = rt__valid_civil_p(ref_hash("year"),
4144 ref_hash("mon"),
4145 ref_hash("mday"), sg);
4146 else {
4147 hash = rt_rewrite_frags(hash);
4148 hash = rt_complete_frags(klass, hash);
4149 jd = rt__valid_date_frags_p(hash, sg);
4150 }
4151
4152 if (NIL_P(jd))
4153 rb_raise(rb_eArgError, "invalid date");
4154 {
4155 VALUE nth;
4156 int rjd;
4157
4158 decode_jd(jd, &nth, &rjd);
4159 return d_simple_new_internal(klass,
4160 nth, rjd,
4161 NUM2DBL(sg),
4162 0, 0, 0,
4163 HAVE_JD);
4164 }
4165 }
4166
4167 VALUE date__strptime(const char *str, size_t slen,
4168 const char *fmt, size_t flen, VALUE hash);
4169
4170 static VALUE
4171 date_s__strptime_internal(int argc, VALUE *argv, VALUE klass,
4172 const char *default_fmt)
4173 {
4174 VALUE vstr, vfmt, hash;
4175 const char *str, *fmt;
4176 size_t slen, flen;
4177
4178 rb_scan_args(argc, argv, "11", &vstr, &vfmt);
4179
4180 StringValue(vstr);
4181 if (!rb_enc_str_asciicompat_p(vstr))
4182 rb_raise(rb_eArgError,
4183 "string should have ASCII compatible encoding");
4184 str = RSTRING_PTR(vstr);
4185 slen = RSTRING_LEN(vstr);
4186 if (argc < 2) {
4187 fmt = default_fmt;
4188 flen = strlen(default_fmt);
4189 }
4190 else {
4191 StringValue(vfmt);
4192 if (!rb_enc_str_asciicompat_p(vfmt))
4193 rb_raise(rb_eArgError,
4194 "format should have ASCII compatible encoding");
4195 fmt = RSTRING_PTR(vfmt);
4196 flen = RSTRING_LEN(vfmt);
4197 }
4198 hash = rb_hash_new();
4199 if (NIL_P(date__strptime(str, slen, fmt, flen, hash)))
4200 return Qnil;
4201
4202 {
4203 VALUE zone = ref_hash("zone");
4204 VALUE left = ref_hash("leftover");
4205
4206 if (!NIL_P(zone)) {
4207 rb_enc_copy(zone, vstr);
4208 OBJ_INFECT(zone, vstr);
4209 set_hash("zone", zone);
4210 }
4211 if (!NIL_P(left)) {
4212 rb_enc_copy(left, vstr);
4213 OBJ_INFECT(left, vstr);
4214 set_hash("leftover", left);
4215 }
4216 }
4217
4218 return hash;
4219 }
4220
4221 /*
4222 * call-seq:
4223 * Date._strptime(string[, format='%F']) -> hash
4224 *
4225 * Parses the given representation of date and time with the given
4226 * template, and returns a hash of parsed elements. _strptime does
4227 * not support specification of flags and width unlike strftime.
4228 *
4229 * Date._strptime('2001-02-03', '%Y-%m-%d')
4230 * #=> {:year=>2001, :mon=>2, :mday=>3}
4231 *
4232 * See also strptime(3) and strftime.
4233 */
4234 static VALUE
4235 date_s__strptime(int argc, VALUE *argv, VALUE klass)
4236 {
4237 return date_s__strptime_internal(argc, argv, klass, "%F");
4238 }
4239
4240 /*
4241 * call-seq:
4242 * Date.strptime([string='-4712-01-01'[, format='%F'[, start=ITALY]]]) -> date
4243 *
4244 * Parses the given representation of date and time with the given
4245 * template, and creates a date object. strptime does not support
4246 * specification of flags and width unlike strftime.
4247 *
4248 * Date.strptime('2001-02-03', '%Y-%m-%d') #=> #<Date: 2001-02-03 ...>
4249 * Date.strptime('03-02-2001', '%d-%m-%Y') #=> #<Date: 2001-02-03 ...>
4250 * Date.strptime('2001-034', '%Y-%j') #=> #<Date: 2001-02-03 ...>
4251 * Date.strptime('2001-W05-6', '%G-W%V-%u') #=> #<Date: 2001-02-03 ...>
4252 * Date.strptime('2001 04 6', '%Y %U %w') #=> #<Date: 2001-02-03 ...>
4253 * Date.strptime('2001 05 6', '%Y %W %u') #=> #<Date: 2001-02-03 ...>
4254 * Date.strptime('sat3feb01', '%a%d%b%y') #=> #<Date: 2001-02-03 ...>
4255 *
4256 * See also strptime(3) and strftime.
4257 */
4258 static VALUE
4259 date_s_strptime(int argc, VALUE *argv, VALUE klass)
4260 {
4261 VALUE str, fmt, sg;
4262
4263 rb_scan_args(argc, argv, "03", &str, &fmt, &sg);
4264
4265 switch (argc) {
4266 case 0:
4267 str = rb_str_new2("-4712-01-01");
4268 case 1:
4269 fmt = rb_str_new2("%F");
4270 case 2:
4271 sg = INT2FIX(DEFAULT_SG);
4272 }
4273
4274 {
4275 VALUE argv2[2], hash;
4276
4277 argv2[0] = str;
4278 argv2[1] = fmt;
4279 hash = date_s__strptime(2, argv2, klass);
4280 return d_new_by_frags(klass, hash, sg);
4281 }
4282 }
4283
4284 VALUE date__parse(VALUE str, VALUE comp);
4285
4286 static VALUE
4287 date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
4288 {
4289 VALUE vstr, vcomp, hash;
4290
4291 rb_scan_args(argc, argv, "11", &vstr, &vcomp);
4292 StringValue(vstr);
4293 if (!rb_enc_str_asciicompat_p(vstr))
4294 rb_raise(rb_eArgError,
4295 "string should have ASCII compatible encoding");
4296 if (argc < 2)
4297 vcomp = Qtrue;
4298
4299 hash = date__parse(vstr, vcomp);
4300
4301 {
4302 VALUE zone = ref_hash("zone");
4303
4304 if (!NIL_P(zone)) {
4305 rb_enc_copy(zone, vstr);
4306 OBJ_INFECT(zone, vstr);
4307 set_hash("zone", zone);
4308 }
4309 }
4310
4311 return hash;
4312 }
4313
4314 /*
4315 * call-seq:
4316 * Date._parse(string[, comp=true]) -> hash
4317 *
4318 * Parses the given representation of date and time, and returns a
4319 * hash of parsed elements. This method does not function as a
4320 * validator.
4321 *
4322 * If the optional second argument is true and the detected year is in
4323 * the range "00" to "99", considers the year a 2-digit form and makes
4324 * it full.
4325 *
4326 * Date._parse('2001-02-03') #=> {:year=>2001, :mon=>2, :mday=>3}
4327 */
4328 static VALUE
4329 date_s__parse(int argc, VALUE *argv, VALUE klass)
4330 {
4331 return date_s__parse_internal(argc, argv, klass);
4332 }
4333
4334 /*
4335 * call-seq:
4336 * Date.parse(string='-4712-01-01'[, comp=true[, start=ITALY]]) -> date
4337 *
4338 * Parses the given representation of date and time, and creates a
4339 * date object. This method does not function as a validator.
4340 *
4341 * If the optional second argument is true and the detected year is in
4342 * the range "00" to "99", considers the year a 2-digit form and makes
4343 * it full.
4344 *
4345 * Date.parse('2001-02-03') #=> #<Date: 2001-02-03 ...>
4346 * Date.parse('20010203') #=> #<Date: 2001-02-03 ...>
4347 * Date.parse('3rd Feb 2001') #=> #<Date: 2001-02-03 ...>
4348 */
4349 static VALUE
4350 date_s_parse(int argc, VALUE *argv, VALUE klass)
4351 {
4352 VALUE str, comp, sg;
4353
4354 rb_scan_args(argc, argv, "03", &str, &comp, &sg);
4355
4356 switch (argc) {
4357 case 0:
4358 str = rb_str_new2("-4712-01-01");
4359 case 1:
4360 comp = Qtrue;
4361 case 2:
4362 sg = INT2FIX(DEFAULT_SG);
4363 }
4364
4365 {
4366 VALUE argv2[2], hash;
4367
4368 argv2[0] = str;
4369 argv2[1] = comp;
4370 hash = date_s__parse(2, argv2, klass);
4371 return d_new_by_frags(klass, hash, sg);
4372 }
4373 }
4374
4375 VALUE date__iso8601(VALUE);
4376 VALUE date__rfc3339(VALUE);
4377 VALUE date__xmlschema(VALUE);
4378 VALUE date__rfc2822(VALUE);
4379 VALUE date__httpdate(VALUE);
4380 VALUE date__jisx0301(VALUE);
4381
4382 /*
4383 * call-seq:
4384 * Date._iso8601(string) -> hash
4385 *
4386 * Returns a hash of parsed elements.
4387 */
4388 static VALUE
4389 date_s__iso8601(VALUE klass, VALUE str)
4390 {
4391 return date__iso8601(str);
4392 }
4393
4394 /*
4395 * call-seq:
4396 * Date.iso8601(string='-4712-01-01'[, start=ITALY]) -> date
4397 *
4398 * Creates a new Date object by parsing from a string according to
4399 * some typical ISO 8601 formats.
4400 *
4401 * Date.iso8601('2001-02-03') #=> #<Date: 2001-02-03 ...>
4402 * Date.iso8601('20010203') #=> #<Date: 2001-02-03 ...>
4403 * Date.iso8601('2001-W05-6') #=> #<Date: 2001-02-03 ...>
4404 */
4405 static VALUE
4406 date_s_iso8601(int argc, VALUE *argv, VALUE klass)
4407 {
4408 VALUE str, sg;
4409
4410 rb_scan_args(argc, argv, "02", &str, &sg);
4411
4412 switch (argc) {
4413 case 0:
4414 str = rb_str_new2("-4712-01-01");
4415 case 1:
4416 sg = INT2FIX(DEFAULT_SG);
4417 }
4418
4419 {
4420 VALUE hash = date_s__iso8601(klass, str);
4421 return d_new_by_frags(klass, hash, sg);
4422 }
4423 }
4424
4425 /*
4426 * call-seq:
4427 * Date._rfc3339(string) -> hash
4428 *
4429 * Returns a hash of parsed elements.
4430 */
4431 static VALUE
4432 date_s__rfc3339(VALUE klass, VALUE str)
4433 {
4434 return date__rfc3339(str);
4435 }
4436
4437 /*
4438 * call-seq:
4439 * Date.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=ITALY]) -> date
4440 *
4441 * Creates a new Date object by parsing from a string according to
4442 * some typical RFC 3339 formats.
4443 *
4444 * Date.rfc3339('2001-02-03T04:05:06+07:00') #=> #<Date: 2001-02-03 ...>
4445 */
4446 static VALUE
4447 date_s_rfc3339(int argc, VALUE *argv, VALUE klass)
4448 {
4449 VALUE str, sg;
4450
4451 rb_scan_args(argc, argv, "02", &str, &sg);
4452
4453 switch (argc) {
4454 case 0:
4455 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
4456 case 1:
4457 sg = INT2FIX(DEFAULT_SG);
4458 }
4459
4460 {
4461 VALUE hash = date_s__rfc3339(klass, str);
4462 return d_new_by_frags(klass, hash, sg);
4463 }
4464 }
4465
4466 /*
4467 * call-seq:
4468 * Date._xmlschema(string) -> hash
4469 *
4470 * Returns a hash of parsed elements.
4471 */
4472 static VALUE
4473 date_s__xmlschema(VALUE klass, VALUE str)
4474 {
4475 return date__xmlschema(str);
4476 }
4477
4478 /*
4479 * call-seq:
4480 * Date.xmlschema(string='-4712-01-01'[, start=ITALY]) -> date
4481 *
4482 * Creates a new Date object by parsing from a string according to
4483 * some typical XML Schema formats.
4484 *
4485 * Date.xmlschema('2001-02-03') #=> #<Date: 2001-02-03 ...>
4486 */
4487 static VALUE
4488 date_s_xmlschema(int argc, VALUE *argv, VALUE klass)
4489 {
4490 VALUE str, sg;
4491
4492 rb_scan_args(argc, argv, "02", &str, &sg);
4493
4494 switch (argc) {
4495 case 0:
4496 str = rb_str_new2("-4712-01-01");
4497 case 1:
4498 sg = INT2FIX(DEFAULT_SG);
4499 }
4500
4501 {
4502 VALUE hash = date_s__xmlschema(klass, str);
4503 return d_new_by_frags(klass, hash, sg);
4504 }
4505 }
4506
4507 /*
4508 * call-seq:
4509 * Date._rfc2822(string) -> hash
4510 * Date._rfc822(string) -> hash
4511 *
4512 * Returns a hash of parsed elements.
4513 */
4514 static VALUE
4515 date_s__rfc2822(VALUE klass, VALUE str)
4516 {
4517 return date__rfc2822(str);
4518 }
4519
4520 /*
4521 * call-seq:
4522 * Date.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=ITALY]) -> date
4523 * Date.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=ITALY]) -> date
4524 *
4525 * Creates a new Date object by parsing from a string according to
4526 * some typical RFC 2822 formats.
4527 *
4528 * Date.rfc2822('Sat, 3 Feb 2001 00:00:00 +0000')
4529 * #=> #<Date: 2001-02-03 ...>
4530 */
4531 static VALUE
4532 date_s_rfc2822(int argc, VALUE *argv, VALUE klass)
4533 {
4534 VALUE str, sg;
4535
4536 rb_scan_args(argc, argv, "02", &str, &sg);
4537
4538 switch (argc) {
4539 case 0:
4540 str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000");
4541 case 1:
4542 sg = INT2FIX(DEFAULT_SG);
4543 }
4544
4545 {
4546 VALUE hash = date_s__rfc2822(klass, str);
4547 return d_new_by_frags(klass, hash, sg);
4548 }
4549 }
4550
4551 /*
4552 * call-seq:
4553 * Date._httpdate(string) -> hash
4554 *
4555 * Returns a hash of parsed elements.
4556 */
4557 static VALUE
4558 date_s__httpdate(VALUE klass, VALUE str)
4559 {
4560 return date__httpdate(str);
4561 }
4562
4563 /*
4564 * call-seq:
4565 * Date.httpdate(string='Mon, 01 Jan -4712 00:00:00 GMT'[, start=ITALY]) -> date
4566 *
4567 * Creates a new Date object by parsing from a string according to
4568 * some RFC 2616 format.
4569 *
4570 * Date.httpdate('Sat, 03 Feb 2001 00:00:00 GMT')
4571 * #=> #<Date: 2001-02-03 ...>
4572 */
4573 static VALUE
4574 date_s_httpdate(int argc, VALUE *argv, VALUE klass)
4575 {
4576 VALUE str, sg;
4577
4578 rb_scan_args(argc, argv, "02", &str, &sg);
4579
4580 switch (argc) {
4581 case 0:
4582 str = rb_str_new2("Mon, 01 Jan -4712 00:00:00 GMT");
4583 case 1:
4584 sg = INT2FIX(DEFAULT_SG);
4585 }
4586
4587 {
4588 VALUE hash = date_s__httpdate(klass, str);
4589 return d_new_by_frags(klass, hash, sg);
4590 }
4591 }
4592
4593 /*
4594 * call-seq:
4595 * Date._jisx0301(string) -> hash
4596 *
4597 * Returns a hash of parsed elements.
4598 */
4599 static VALUE
4600 date_s__jisx0301(VALUE klass, VALUE str)
4601 {
4602 return date__jisx0301(str);
4603 }
4604
4605 /*
4606 * call-seq:
4607 * Date.jisx0301(string='-4712-01-01'[, start=ITALY]) -> date
4608 *
4609 * Creates a new Date object by parsing from a string according to
4610 * some typical JIS X 0301 formats.
4611 *
4612 * Date.jisx0301('H13.02.03') #=> #<Date: 2001-02-03 ...>
4613 */
4614 static VALUE
4615 date_s_jisx0301(int argc, VALUE *argv, VALUE klass)
4616 {
4617 VALUE str, sg;
4618
4619 rb_scan_args(argc, argv, "02", &str, &sg);
4620
4621 switch (argc) {
4622 case 0:
4623 str = rb_str_new2("-4712-01-01");
4624 case 1:
4625 sg = INT2FIX(DEFAULT_SG);
4626 }
4627
4628 {
4629 VALUE hash = date_s__jisx0301(klass, str);
4630 return d_new_by_frags(klass, hash, sg);
4631 }
4632 }
4633
4634 static VALUE
4635 dup_obj(VALUE self)
4636 {
4637 get_d1a(self);
4638
4639 if (simple_dat_p(adat)) {
4640 VALUE new = d_lite_s_alloc_simple(rb_obj_class(self));
4641 {
4642 get_d1b(new);
4643 bdat->s = adat->s;
4644 return new;
4645 }
4646 }
4647 else {
4648 VALUE new = d_lite_s_alloc_complex(rb_obj_class(self));
4649 {
4650 get_d1b(new);
4651 bdat->c = adat->c;
4652 return new;
4653 }
4654 }
4655 }
4656
4657 static VALUE
4658 dup_obj_as_complex(VALUE self)
4659 {
4660 get_d1a(self);
4661
4662 if (simple_dat_p(adat)) {
4663 VALUE new = d_lite_s_alloc_complex(rb_obj_class(self));
4664 {
4665 get_d1b(new);
4666 copy_simple_to_complex(&bdat->c, &adat->s);
4667 bdat->c.flags |= HAVE_DF | COMPLEX_DAT;
4668 return new;
4669 }
4670 }
4671 else {
4672 VALUE new = d_lite_s_alloc_complex(rb_obj_class(self));
4673 {
4674 get_d1b(new);
4675 bdat->c = adat->c;
4676 return new;
4677 }
4678 }
4679 }
4680
4681 #define val2off(vof,iof) \
4682 {\
4683 if (!offset_to_sec(vof, &iof)) {\
4684 iof = 0;\
4685 rb_warning("invalid offset is ignored");\
4686 }\
4687 }
4688
4689 #ifndef NDEBUG
4690 static VALUE
4691 d_lite_initialize(int argc, VALUE *argv, VALUE self)
4692 {
4693 VALUE jd, vjd, vdf, sf, vsf, vof, vsg;
4694 int df, of;
4695 double sg;
4696
4697 rb_check_frozen(self);
4698 rb_check_trusted(self);
4699
4700 rb_scan_args(argc, argv, "05", &vjd, &vdf, &vsf, &vof, &vsg);
4701
4702 jd = INT2FIX(0);
4703 df = 0;
4704 sf = INT2FIX(0);
4705 of = 0;
4706 sg = DEFAULT_SG;
4707
4708 switch (argc) {
4709 case 5:
4710 val2sg(vsg, sg);
4711 case 4:
4712 val2off(vof, of);
4713 case 3:
4714 sf = vsf;
4715 if (f_lt_p(sf, INT2FIX(0)) ||
4716 f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS)))
4717 rb_raise(rb_eArgError, "invalid second fraction");
4718 case 2:
4719 df = NUM2INT(vdf);
4720 if (df < 0 || df >= DAY_IN_SECONDS)
4721 rb_raise(rb_eArgError, "invalid day fraction");
4722 case 1:
4723 jd = vjd;
4724 }
4725
4726 {
4727 VALUE nth;
4728 int rjd;
4729
4730 get_d1(self);
4731
4732 decode_jd(jd, &nth, &rjd);
4733 if (!df && f_zero_p(sf) && !of) {
4734 set_to_simple(&dat->s, nth, rjd, sg, 0, 0, 0, HAVE_JD);
4735 }
4736 else {
4737 if (!complex_dat_p(dat))
4738 rb_raise(rb_eArgError,
4739 "cannot load complex into simple");
4740
4741 set_to_complex(&dat->c, nth, rjd, df, sf, of, sg,
4742 0, 0, 0, 0, 0, 0, HAVE_JD | HAVE_DF | COMPLEX_DAT);
4743 }
4744 }
4745 return self;
4746 }
4747 #endif
4748
4749 /* :nodoc: */
4750 static VALUE
4751 d_lite_initialize_copy(VALUE copy, VALUE date)
4752 {
4753 rb_check_frozen(copy);
4754 rb_check_trusted(copy);
4755
4756 if (copy == date)
4757 return copy;
4758 {
4759 get_d2(copy, date);
4760 if (simple_dat_p(bdat)) {
4761 adat->s = bdat->s;
4762 adat->s.flags &= ~COMPLEX_DAT;
4763 }
4764 else {
4765 if (!complex_dat_p(adat))
4766 rb_raise(rb_eArgError,
4767 "cannot load complex into simple");
4768
4769 adat->c = bdat->c;
4770 adat->c.flags |= COMPLEX_DAT;
4771 }
4772 }
4773 return copy;
4774 }
4775
4776 #ifndef NDEBUG
4777 static VALUE
4778 d_lite_fill(VALUE self)
4779 {
4780 get_d1(self);
4781
4782 if (simple_dat_p(dat)) {
4783 get_s_jd(dat);
4784 get_s_civil(dat);
4785 }
4786 else {
4787 get_c_jd(dat);
4788 get_c_civil(dat);
4789 get_c_df(dat);
4790 get_c_time(dat);
4791 }
4792 return self;
4793 }
4794 #endif
4795
4796 /*
4797 * call-seq:
4798 * d.ajd -> rational
4799 *
4800 * Returns the astronomical Julian day number. This is a fractional
4801 * number, which is not adjusted by the offset.
4802 *
4803 * DateTime.new(2001,2,3,4,5,6,'+7').ajd #=> (11769328217/4800)
4804 * DateTime.new(2001,2,2,14,5,6,'-7').ajd #=> (11769328217/4800)
4805 */
4806 static VALUE
4807 d_lite_ajd(VALUE self)
4808 {
4809 get_d1(self);
4810 return m_ajd(dat);
4811 }
4812
4813 /*
4814 * call-seq:
4815 * d.amjd -> rational
4816 *
4817 * Returns the astronomical modified Julian day number. This is
4818 * a fractional number, which is not adjusted by the offset.
4819 *
4820 * DateTime.new(2001,2,3,4,5,6,'+7').amjd #=> (249325817/4800)
4821 * DateTime.new(2001,2,2,14,5,6,'-7').amjd #=> (249325817/4800)
4822 */
4823 static VALUE
4824 d_lite_amjd(VALUE self)
4825 {
4826 get_d1(self);
4827 return m_amjd(dat);
4828 }
4829
4830 /*
4831 * call-seq:
4832 * d.jd -> integer
4833 *
4834 * Returns the Julian day number. This is a whole number, which is
4835 * adjusted by the offset as the local time.
4836 *
4837 * DateTime.new(2001,2,3,4,5,6,'+7').jd #=> 2451944
4838 * DateTime.new(2001,2,3,4,5,6,'-7').jd #=> 2451944
4839 */
4840 static VALUE
4841 d_lite_jd(VALUE self)
4842 {
4843 get_d1(self);
4844 return m_real_local_jd(dat);
4845 }
4846
4847 /*
4848 * call-seq:
4849 * d.mjd -> integer
4850 *
4851 * Returns the modified Julian day number. This is a whole number,
4852 * which is adjusted by the offset as the local time.
4853 *
4854 * DateTime.new(2001,2,3,4,5,6,'+7').mjd #=> 51943
4855 * DateTime.new(2001,2,3,4,5,6,'-7').mjd #=> 51943
4856 */
4857 static VALUE
4858 d_lite_mjd(VALUE self)
4859 {
4860 get_d1(self);
4861 return f_sub(m_real_local_jd(dat), INT2FIX(2400001));
4862 }
4863
4864 /*
4865 * call-seq:
4866 * d.ld -> integer
4867 *
4868 * Returns the Lilian day number. This is a whole number, which is
4869 * adjusted by the offset as the local time.
4870 *
4871 * Date.new(2001,2,3).ld #=> 152784
4872 */
4873 static VALUE
4874 d_lite_ld(VALUE self)
4875 {
4876 get_d1(self);
4877 return f_sub(m_real_local_jd(dat), INT2FIX(2299160));
4878 }
4879
4880 /*
4881 * call-seq:
4882 * d.year -> integer
4883 *
4884 * Returns the year.
4885 *
4886 * Date.new(2001,2,3).year #=> 2001
4887 * (Date.new(1,1,1) - 1).year #=> 0
4888 */
4889 static VALUE
4890 d_lite_year(VALUE self)
4891 {
4892 get_d1(self);
4893 return m_real_year(dat);
4894 }
4895
4896 /*
4897 * call-seq:
4898 * d.yday -> fixnum
4899 *
4900 * Returns the day of the year (1-366).
4901 *
4902 * Date.new(2001,2,3).yday #=> 34
4903 */
4904 static VALUE
4905 d_lite_yday(VALUE self)
4906 {
4907 get_d1(self);
4908 return INT2FIX(m_yday(dat));
4909 }
4910
4911 /*
4912 * call-seq:
4913 * d.mon -> fixnum
4914 * d.month -> fixnum
4915 *
4916 * Returns the month (1-12).
4917 *
4918 * Date.new(2001,2,3).mon #=> 2
4919 */
4920 static VALUE
4921 d_lite_mon(VALUE self)
4922 {
4923 get_d1(self);
4924 return INT2FIX(m_mon(dat));
4925 }
4926
4927 /*
4928 * call-seq:
4929 * d.mday -> fixnum
4930 * d.day -> fixnum
4931 *
4932 * Returns the day of the month (1-31).
4933 *
4934 * Date.new(2001,2,3).mday #=> 3
4935 */
4936 static VALUE
4937 d_lite_mday(VALUE self)
4938 {
4939 get_d1(self);
4940 return INT2FIX(m_mday(dat));
4941 }
4942
4943 /*
4944 * call-seq:
4945 * d.day_fraction -> rational
4946 *
4947 * Returns the fractional part of the day.
4948 *
4949 * DateTime.new(2001,2,3,12).day_fraction #=> (1/2)
4950 */
4951 static VALUE
4952 d_lite_day_fraction(VALUE self)
4953 {
4954 get_d1(self);
4955 if (simple_dat_p(dat))
4956 return INT2FIX(0);
4957 return m_fr(dat);
4958 }
4959
4960 /*
4961 * call-seq:
4962 * d.cwyear -> integer
4963 *
4964 * Returns the calendar week based year.
4965 *
4966 * Date.new(2001,2,3).cwyear #=> 2001
4967 * Date.new(2000,1,1).cwyear #=> 1999
4968 */
4969 static VALUE
4970 d_lite_cwyear(VALUE self)
4971 {
4972 get_d1(self);
4973 return m_real_cwyear(dat);
4974 }
4975
4976 /*
4977 * call-seq:
4978 * d.cweek -> fixnum
4979 *
4980 * Returns the calendar week number (1-53).
4981 *
4982 * Date.new(2001,2,3).cweek #=> 5
4983 */
4984 static VALUE
4985 d_lite_cweek(VALUE self)
4986 {
4987 get_d1(self);
4988 return INT2FIX(m_cweek(dat));
4989 }
4990
4991 /*
4992 * call-seq:
4993 * d.cwday -> fixnum
4994 *
4995 * Returns the day of calendar week (1-7, Monday is 1).
4996 *
4997 * Date.new(2001,2,3).cwday #=> 6
4998 */
4999 static VALUE
5000 d_lite_cwday(VALUE self)
5001 {
5002 get_d1(self);
5003 return INT2FIX(m_cwday(dat));
5004 }
5005
5006 #ifndef NDEBUG
5007 static VALUE
5008 d_lite_wnum0(VALUE self)
5009 {
5010 get_d1(self);
5011 return INT2FIX(m_wnum0(dat));
5012 }
5013
5014 static VALUE
5015 d_lite_wnum1(VALUE self)
5016 {
5017 get_d1(self);
5018 return INT2FIX(m_wnum1(dat));
5019 }
5020 #endif
5021
5022 /*
5023 * call-seq:
5024 * d.wday -> fixnum
5025 *
5026 * Returns the day of week (0-6, Sunday is zero).
5027 *
5028 * Date.new(2001,2,3).wday #=> 6
5029 */
5030 static VALUE
5031 d_lite_wday(VALUE self)
5032 {
5033 get_d1(self);
5034 return INT2FIX(m_wday(dat));
5035 }
5036
5037 /*
5038 * call-seq:
5039 * d.sunday? -> bool
5040 *
5041 * Returns true if the date is Sunday.
5042 */
5043 static VALUE
5044 d_lite_sunday_p(VALUE self)
5045 {
5046 get_d1(self);
5047 return f_boolcast(m_wday(dat) == 0);
5048 }
5049
5050 /*
5051 * call-seq:
5052 * d.monday? -> bool
5053 *
5054 * Returns true if the date is Monday.
5055 */
5056 static VALUE
5057 d_lite_monday_p(VALUE self)
5058 {
5059 get_d1(self);
5060 return f_boolcast(m_wday(dat) == 1);
5061 }
5062
5063 /*
5064 * call-seq:
5065 * d.tuesday? -> bool
5066 *
5067 * Returns true if the date is Tuesday.
5068 */
5069 static VALUE
5070 d_lite_tuesday_p(VALUE self)
5071 {
5072 get_d1(self);
5073 return f_boolcast(m_wday(dat) == 2);
5074 }
5075
5076 /*
5077 * call-seq:
5078 * d.wednesday? -> bool
5079 *
5080 * Returns true if the date is Wednesday.
5081 */
5082 static VALUE
5083 d_lite_wednesday_p(VALUE self)
5084 {
5085 get_d1(self);
5086 return f_boolcast(m_wday(dat) == 3);
5087 }
5088
5089 /*
5090 * call-seq:
5091 * d.thursday? -> bool
5092 *
5093 * Returns true if the date is Thursday.
5094 */
5095 static VALUE
5096 d_lite_thursday_p(VALUE self)
5097 {
5098 get_d1(self);
5099 return f_boolcast(m_wday(dat) == 4);
5100 }
5101
5102 /*
5103 * call-seq:
5104 * d.friday? -> bool
5105 *
5106 * Returns true if the date is Friday.
5107 */
5108 static VALUE
5109 d_lite_friday_p(VALUE self)
5110 {
5111 get_d1(self);
5112 return f_boolcast(m_wday(dat) == 5);
5113 }
5114
5115 /*
5116 * call-seq:
5117 * d.saturday? -> bool
5118 *
5119 * Returns true if the date is Saturday.
5120 */
5121 static VALUE
5122 d_lite_saturday_p(VALUE self)
5123 {
5124 get_d1(self);
5125 return f_boolcast(m_wday(dat) == 6);
5126 }
5127
5128 #ifndef NDEBUG
5129 static VALUE
5130 d_lite_nth_kday_p(VALUE self, VALUE n, VALUE k)
5131 {
5132 int rjd, ns;
5133
5134 get_d1(self);
5135
5136 if (NUM2INT(k) != m_wday(dat))
5137 return Qfalse;
5138
5139 c_nth_kday_to_jd(m_year(dat), m_mon(dat),
5140 NUM2INT(n), NUM2INT(k), m_virtual_sg(dat), /* !=m_sg() */
5141 &rjd, &ns);
5142 if (m_local_jd(dat) != rjd)
5143 return Qfalse;
5144 return Qtrue;
5145 }
5146 #endif
5147
5148 /*
5149 * call-seq:
5150 * d.hour -> fixnum
5151 *
5152 * Returns the hour (0-23).
5153 *
5154 * DateTime.new(2001,2,3,4,5,6).hour #=> 4
5155 */
5156 static VALUE
5157 d_lite_hour(VALUE self)
5158 {
5159 get_d1(self);
5160 return INT2FIX(m_hour(dat));
5161 }
5162
5163 /*
5164 * call-seq:
5165 * d.min -> fixnum
5166 * d.minute -> fixnum
5167 *
5168 * Returns the minute (0-59).
5169 *
5170 * DateTime.new(2001,2,3,4,5,6).min #=> 5
5171 */
5172 static VALUE
5173 d_lite_min(VALUE self)
5174 {
5175 get_d1(self);
5176 return INT2FIX(m_min(dat));
5177 }
5178
5179 /*
5180 * call-seq:
5181 * d.sec -> fixnum
5182 * d.second -> fixnum
5183 *
5184 * Returns the second (0-59).
5185 *
5186 * DateTime.new(2001,2,3,4,5,6).sec #=> 6
5187 */
5188 static VALUE
5189 d_lite_sec(VALUE self)
5190 {
5191 get_d1(self);
5192 return INT2FIX(m_sec(dat));
5193 }
5194
5195 /*
5196 * call-seq:
5197 * d.sec_fraction -> rational
5198 * d.second_fraction -> rational
5199 *
5200 * Returns the fractional part of the second.
5201 *
5202 * DateTime.new(2001,2,3,4,5,6.5).sec_fraction #=> (1/2)
5203 */
5204 static VALUE
5205 d_lite_sec_fraction(VALUE self)
5206 {
5207 get_d1(self);
5208 return m_sf_in_sec(dat);
5209 }
5210
5211 /*
5212 * call-seq:
5213 * d.offset -> rational
5214 *
5215 * Returns the offset.
5216 *
5217 * DateTime.parse('04pm+0730').offset #=> (5/16)
5218 */
5219 static VALUE
5220 d_lite_offset(VALUE self)
5221 {
5222 get_d1(self);
5223 return m_of_in_day(dat);
5224 }
5225
5226 /*
5227 * call-seq:
5228 * d.zone -> string
5229 *
5230 * Returns the timezone.
5231 *
5232 * DateTime.parse('04pm+0730').zone #=> "+07:30"
5233 */
5234 static VALUE
5235 d_lite_zone(VALUE self)
5236 {
5237 get_d1(self);
5238 return m_zone(dat);
5239 }
5240
5241 /*
5242 * call-seq:
5243 * d.julian? -> bool
5244 *
5245 * Retruns true if the date is before the day of calendar reform.
5246 *
5247 * Date.new(1582,10,15).julian? #=> false
5248 * (Date.new(1582,10,15) - 1).julian? #=> true
5249 */
5250 static VALUE
5251 d_lite_julian_p(VALUE self)
5252 {
5253 get_d1(self);
5254 return f_boolcast(m_julian_p(dat));
5255 }
5256
5257 /*
5258 * call-seq:
5259 * d.gregorian? -> bool
5260 *
5261 * Retunrs true if the date is on or after the day of calendar reform.
5262 *
5263 * Date.new(1582,10,15).gregorian? #=> true
5264 * (Date.new(1582,10,15) - 1).gregorian? #=> false
5265 */
5266 static VALUE
5267 d_lite_gregorian_p(VALUE self)
5268 {
5269 get_d1(self);
5270 return f_boolcast(m_gregorian_p(dat));
5271 }
5272
5273 /*
5274 * call-seq:
5275 * d.leap? -> bool
5276 *
5277 * Returns true if the year is a leap year.
5278 *
5279 * Date.new(2000).leap? #=> true
5280 * Date.new(2001).leap? #=> false
5281 */
5282 static VALUE
5283 d_lite_leap_p(VALUE self)
5284 {
5285 int rjd, ns, ry, rm, rd;
5286
5287 get_d1(self);
5288 if (m_gregorian_p(dat))
5289 return f_boolcast(c_gregorian_leap_p(m_year(dat)));
5290
5291 c_civil_to_jd(m_year(dat), 3, 1, m_virtual_sg(dat),
5292 &rjd, &ns);
5293 c_jd_to_civil(rjd - 1, m_virtual_sg(dat), &ry, &rm, &rd);
5294 return f_boolcast(rd == 29);
5295 }
5296
5297 /*
5298 * call-seq:
5299 * d.start -> float
5300 *
5301 * Returns the Julian day number denoting the day of calendar reform.
5302 *
5303 * Date.new(2001,2,3).start #=> 2299161.0
5304 * Date.new(2001,2,3,Date::GREGORIAN).start #=> -Infinity
5305 */
5306 static VALUE
5307 d_lite_start(VALUE self)
5308 {
5309 get_d1(self);
5310 return DBL2NUM(m_sg(dat));
5311 }
5312
5313 static void
5314 clear_civil(union DateData *x)
5315 {
5316 if (simple_dat_p(x)) {
5317 x->s.year = 0;
5318 #ifndef USE_PACK
5319 x->s.mon = 0;
5320 x->s.mday = 0;
5321 #else
5322 x->s.pc = 0;
5323 #endif
5324 x->s.flags &= ~HAVE_CIVIL;
5325 }
5326 else {
5327 x->c.year = 0;
5328 #ifndef USE_PACK
5329 x->c.mon = 0;
5330 x->c.mday = 0;
5331 x->c.hour = 0;
5332 x->c.min = 0;
5333 x->c.sec = 0;
5334 #else
5335 x->c.pc = 0;
5336 #endif
5337 x->c.flags &= ~(HAVE_CIVIL | HAVE_TIME);
5338 }
5339 }
5340
5341 static void
5342 set_sg(union DateData *x, double sg)
5343 {
5344 if (simple_dat_p(x)) {
5345 get_s_jd(x);
5346 clear_civil(x);
5347 x->s.sg = (date_sg_t)sg;
5348 } else {
5349 get_c_jd(x);
5350 get_c_df(x);
5351 clear_civil(x);
5352 x->c.sg = (date_sg_t)sg;
5353 }
5354 }
5355
5356 static VALUE
5357 dup_obj_with_new_start(VALUE obj, double sg)
5358 {
5359 volatile VALUE dup = dup_obj(obj);
5360 {
5361 get_d1(dup);
5362 set_sg(dat, sg);
5363 }
5364 return dup;
5365 }
5366
5367 /*
5368 * call-seq:
5369 * d.new_start([start=Date::ITALY]) -> date
5370 *
5371 * Duplicates self and resets its the day of calendar reform.
5372 *
5373 * d = Date.new(1582,10,15)
5374 * d.new_start(Date::JULIAN) #=> #<Date: 1582-10-05 ...>
5375 */
5376 static VALUE
5377 d_lite_new_start(int argc, VALUE *argv, VALUE self)
5378 {
5379 VALUE vsg;
5380 double sg;
5381
5382 rb_scan_args(argc, argv, "01", &vsg);
5383
5384 sg = DEFAULT_SG;
5385 if (argc >= 1)
5386 val2sg(vsg, sg);
5387
5388 return dup_obj_with_new_start(self, sg);
5389 }
5390
5391 /*
5392 * call-seq:
5393 * d.italy -> date
5394 *
5395 * This method is equivalent to new_start(Date::ITALY).
5396 */
5397 static VALUE
5398 d_lite_italy(VALUE self)
5399 {
5400 return dup_obj_with_new_start(self, ITALY);
5401 }
5402
5403 /*
5404 * call-seq:
5405 * d.england -> date
5406 *
5407 * This method is equivalent to new_start(Date::ENGLAND).
5408 */
5409 static VALUE
5410 d_lite_england(VALUE self)
5411 {
5412 return dup_obj_with_new_start(self, ENGLAND);
5413 }
5414
5415 /*
5416 * call-seq:
5417 * d.julian -> date
5418 *
5419 * This method is equivalent to new_start(Date::JULIAN).
5420 */
5421 static VALUE
5422 d_lite_julian(VALUE self)
5423 {
5424 return dup_obj_with_new_start(self, JULIAN);
5425 }
5426
5427 /*
5428 * call-seq:
5429 * d.gregorian -> date
5430 *
5431 * This method is equivalent to new_start(Date::GREGORIAN).
5432 */
5433 static VALUE
5434 d_lite_gregorian(VALUE self)
5435 {
5436 return dup_obj_with_new_start(self, GREGORIAN);
5437 }
5438
5439 static void
5440 set_of(union DateData *x, int of)
5441 {
5442 assert(complex_dat_p(x));
5443 get_c_jd(x);
5444 get_c_df(x);
5445 clear_civil(x);
5446 x->c.of = of;
5447 }
5448
5449 static VALUE
5450 dup_obj_with_new_offset(VALUE obj, int of)
5451 {
5452 volatile VALUE dup = dup_obj_as_complex(obj);
5453 {
5454 get_d1(dup);
5455 set_of(dat, of);
5456 }
5457 return dup;
5458 }
5459
5460 /*
5461 * call-seq:
5462 * d.new_offset([offset=0]) -> date
5463 *
5464 * Duplicates self and resets its offset.
5465 *
5466 * d = DateTime.new(2001,2,3,4,5,6,'-02:00')
5467 * #=> #<DateTime: 2001-02-03T04:05:06-02:00 ...>
5468 * d.new_offset('+09:00') #=> #<DateTime: 2001-02-03T15:05:06+09:00 ...>
5469 */
5470 static VALUE
5471 d_lite_new_offset(int argc, VALUE *argv, VALUE self)
5472 {
5473 VALUE vof;
5474 int rof;
5475
5476 rb_scan_args(argc, argv, "01", &vof);
5477
5478 rof = 0;
5479 if (argc >= 1)
5480 val2off(vof, rof);
5481
5482 return dup_obj_with_new_offset(self, rof);
5483 }
5484
5485 /*
5486 * call-seq:
5487 * d + other -> date
5488 *
5489 * Returns a date object pointing other days after self. The other
5490 * should be a numeric value. If the other is flonum, assumes its
5491 * precision is at most nanosecond.
5492 *
5493 * Date.new(2001,2,3) + 1 #=> #<Date: 2001-02-04 ...>
5494 * DateTime.new(2001,2,3) + Rational(1,2)
5495 * #=> #<DateTime: 2001-02-03T12:00:00+00:00 ...>
5496 * DateTime.new(2001,2,3) + Rational(-1,2)
5497 * #=> #<DateTime: 2001-02-02T12:00:00+00:00 ...>
5498 * DateTime.jd(0,12) + DateTime.new(2001,2,3).ajd
5499 * #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...>
5500 */
5501 static VALUE
5502 d_lite_plus(VALUE self, VALUE other)
5503 {
5504 get_d1(self);
5505
5506 switch (TYPE(other)) {
5507 case T_FIXNUM:
5508 {
5509 VALUE nth;
5510 long t;
5511 int jd;
5512
5513 nth = m_nth(dat);
5514 t = FIX2LONG(other);
5515 if (DIV(t, CM_PERIOD)) {
5516 nth = f_add(nth, INT2FIX(DIV(t, CM_PERIOD)));
5517 t = MOD(t, CM_PERIOD);
5518 }
5519
5520 if (!t)
5521 jd = m_jd(dat);
5522 else {
5523 jd = m_jd(dat) + (int)t;
5524 canonicalize_jd(nth, jd);
5525 }
5526
5527 if (simple_dat_p(dat))
5528 return d_simple_new_internal(rb_obj_class(self),
5529 nth, jd,
5530 dat->s.sg,
5531 0, 0, 0,
5532 (dat->s.flags | HAVE_JD) &
5533 ~HAVE_CIVIL);
5534 else
5535 return d_complex_new_internal(rb_obj_class(self),
5536 nth, jd,
5537 dat->c.df, dat->c.sf,
5538 dat->c.of, dat->c.sg,
5539 0, 0, 0,
5540 #ifndef USE_PACK
5541 dat->c.hour,
5542 dat->c.min,
5543 dat->c.sec,
5544 #else
5545 EX_HOUR(dat->c.pc),
5546 EX_MIN(dat->c.pc),
5547 EX_SEC(dat->c.pc),
5548 #endif
5549 (dat->c.flags | HAVE_JD) &
5550 ~HAVE_CIVIL);
5551 }
5552 break;
5553 case T_BIGNUM:
5554 {
5555 VALUE nth;
5556 int jd, s;
5557
5558 if (f_positive_p(other))
5559 s = +1;
5560 else {
5561 s = -1;
5562 other = f_negate(other);
5563 }
5564
5565 nth = f_idiv(other, INT2FIX(CM_PERIOD));
5566 jd = FIX2INT(f_mod(other, INT2FIX(CM_PERIOD)));
5567
5568 if (s < 0) {
5569 nth = f_negate(nth);
5570 jd = -jd;
5571 }
5572
5573 if (!jd)
5574 jd = m_jd(dat);
5575 else {
5576 jd = m_jd(dat) + jd;
5577 canonicalize_jd(nth, jd);
5578 }
5579
5580 if (f_zero_p(nth))
5581 nth = m_nth(dat);
5582 else
5583 nth = f_add(m_nth(dat), nth);
5584
5585 if (simple_dat_p(dat))
5586 return d_simple_new_internal(rb_obj_class(self),
5587 nth, jd,
5588 dat->s.sg,
5589 0, 0, 0,
5590 (dat->s.flags | HAVE_JD) &
5591 ~HAVE_CIVIL);
5592 else
5593 return d_complex_new_internal(rb_obj_class(self),
5594 nth, jd,
5595 dat->c.df, dat->c.sf,
5596 dat->c.of, dat->c.sg,
5597 0, 0, 0,
5598 #ifndef USE_PACK
5599 dat->c.hour,
5600 dat->c.min,
5601 dat->c.sec,
5602 #else
5603 EX_HOUR(dat->c.pc),
5604 EX_MIN(dat->c.pc),
5605 EX_SEC(dat->c.pc),
5606 #endif
5607 (dat->c.flags | HAVE_JD) &
5608 ~HAVE_CIVIL);
5609 }
5610 break;
5611 case T_FLOAT:
5612 {
5613 double jd, o, tmp;
5614 int s, df;
5615 VALUE nth, sf;
5616
5617 o = RFLOAT_VALUE(other);
5618
5619 if (o > 0)
5620 s = +1;
5621 else {
5622 s = -1;
5623 o = -o;
5624 }
5625
5626 o = modf(o, &tmp);
5627
5628 if (!floor(tmp / CM_PERIOD)) {
5629 nth = INT2FIX(0);
5630 jd = (int)tmp;
5631 }
5632 else {
5633 double i, f;
5634
5635 f = modf(tmp / CM_PERIOD, &i);
5636 nth = f_floor(DBL2NUM(i));
5637 jd = (int)(f * CM_PERIOD);
5638 }
5639
5640 o *= DAY_IN_SECONDS;
5641 o = modf(o, &tmp);
5642 df = (int)tmp;
5643 o *= SECOND_IN_NANOSECONDS;
5644 sf = INT2FIX((int)round(o));
5645
5646 if (s < 0) {
5647 jd = -jd;
5648 df = -df;
5649 sf = f_negate(sf);
5650 }
5651
5652 if (f_zero_p(sf))
5653 sf = m_sf(dat);
5654 else {
5655 sf = f_add(m_sf(dat), sf);
5656 if (f_lt_p(sf, INT2FIX(0))) {
5657 df -= 1;
5658 sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS));
5659 }
5660 else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) {
5661 df += 1;
5662 sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS));
5663 }
5664 }
5665
5666 if (!df)
5667 df = m_df(dat);
5668 else {
5669 df = m_df(dat) + df;
5670 if (df < 0) {
5671 jd -= 1;
5672 df += DAY_IN_SECONDS;
5673 }
5674 else if (df >= DAY_IN_SECONDS) {
5675 jd += 1;
5676 df -= DAY_IN_SECONDS;
5677 }
5678 }
5679
5680 if (!jd)
5681 jd = m_jd(dat);
5682 else {
5683 jd = m_jd(dat) + jd;
5684 canonicalize_jd(nth, jd);
5685 }
5686
5687 if (f_zero_p(nth))
5688 nth = m_nth(dat);
5689 else
5690 nth = f_add(m_nth(dat), nth);
5691
5692 if (!df && f_zero_p(sf) && !m_of(dat))
5693 return d_simple_new_internal(rb_obj_class(self),
5694 nth, (int)jd,
5695 m_sg(dat),
5696 0, 0, 0,
5697 (dat->s.flags | HAVE_JD) &
5698 ~(HAVE_CIVIL | HAVE_TIME |
5699 COMPLEX_DAT));
5700 else
5701 return d_complex_new_internal(rb_obj_class(self),
5702 nth, (int)jd,
5703 df, sf,
5704 m_of(dat), m_sg(dat),
5705 0, 0, 0,
5706 0, 0, 0,
5707 (dat->c.flags |
5708 HAVE_JD | HAVE_DF) &
5709 ~(HAVE_CIVIL | HAVE_TIME));
5710 }
5711 break;
5712 default:
5713 if (!k_numeric_p(other))
5714 rb_raise(rb_eTypeError, "expected numeric");
5715 other = f_to_r(other);
5716 #ifdef CANONICALIZATION_FOR_MATHN
5717 if (!k_rational_p(other))
5718 return d_lite_plus(self, other);
5719 #endif
5720 /* fall through */
5721 case T_RATIONAL:
5722 {
5723 VALUE nth, sf, t;
5724 int jd, df, s;
5725
5726 if (wholenum_p(other))
5727 return d_lite_plus(self, RRATIONAL(other)->num);
5728
5729 if (f_positive_p(other))
5730 s = +1;
5731 else {
5732 s = -1;
5733 other = f_negate(other);
5734 }
5735
5736 nth = f_idiv(other, INT2FIX(CM_PERIOD));
5737 t = f_mod(other, INT2FIX(CM_PERIOD));
5738
5739 jd = FIX2INT(f_idiv(t, INT2FIX(1)));
5740 t = f_mod(t, INT2FIX(1));
5741
5742 t = f_mul(t, INT2FIX(DAY_IN_SECONDS));
5743 df = FIX2INT(f_idiv(t, INT2FIX(1)));
5744 t = f_mod(t, INT2FIX(1));
5745
5746 sf = f_mul(t, INT2FIX(SECOND_IN_NANOSECONDS));
5747
5748 if (s < 0) {
5749 nth = f_negate(nth);
5750 jd = -jd;
5751 df = -df;
5752 sf = f_negate(sf);
5753 }
5754
5755 if (f_zero_p(sf))
5756 sf = m_sf(dat);
5757 else {
5758 sf = f_add(m_sf(dat), sf);
5759 if (f_lt_p(sf, INT2FIX(0))) {
5760 df -= 1;
5761 sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS));
5762 }
5763 else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) {
5764 df += 1;
5765 sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS));
5766 }
5767 }
5768
5769 if (!df)
5770 df = m_df(dat);
5771 else {
5772 df = m_df(dat) + df;
5773 if (df < 0) {
5774 jd -= 1;
5775 df += DAY_IN_SECONDS;
5776 }
5777 else if (df >= DAY_IN_SECONDS) {
5778 jd += 1;
5779 df -= DAY_IN_SECONDS;
5780 }
5781 }
5782
5783 if (!jd)
5784 jd = m_jd(dat);
5785 else {
5786 jd = m_jd(dat) + jd;
5787 canonicalize_jd(nth, jd);
5788 }
5789
5790 if (f_zero_p(nth))
5791 nth = m_nth(dat);
5792 else
5793 nth = f_add(m_nth(dat), nth);
5794
5795 if (!df && f_zero_p(sf) && !m_of(dat))
5796 return d_simple_new_internal(rb_obj_class(self),
5797 nth, jd,
5798 m_sg(dat),
5799 0, 0, 0,
5800 (dat->s.flags | HAVE_JD) &
5801 ~(HAVE_CIVIL | HAVE_TIME |
5802 COMPLEX_DAT));
5803 else
5804 return d_complex_new_internal(rb_obj_class(self),
5805 nth, jd,
5806 df, sf,
5807 m_of(dat), m_sg(dat),
5808 0, 0, 0,
5809 0, 0, 0,
5810 (dat->c.flags |
5811 HAVE_JD | HAVE_DF) &
5812 ~(HAVE_CIVIL | HAVE_TIME));
5813 }
5814 break;
5815 }
5816 }
5817
5818 static VALUE
5819 minus_dd(VALUE self, VALUE other)
5820 {
5821 get_d2(self, other);
5822
5823 {
5824 int d, df;
5825 VALUE n, sf, r;
5826
5827 n = f_sub(m_nth(adat), m_nth(bdat));
5828 d = m_jd(adat) - m_jd(bdat);
5829 df = m_df(adat) - m_df(bdat);
5830 sf = f_sub(m_sf(adat), m_sf(bdat));
5831 canonicalize_jd(n, d);
5832
5833 if (df < 0) {
5834 d -= 1;
5835 df += DAY_IN_SECONDS;
5836 }
5837 else if (df >= DAY_IN_SECONDS) {
5838 d += 1;
5839 df -= DAY_IN_SECONDS;
5840 }
5841
5842 if (f_lt_p(sf, INT2FIX(0))) {
5843 df -= 1;
5844 sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS));
5845 }
5846 else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) {
5847 df += 1;
5848 sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS));
5849 }
5850
5851 if (f_zero_p(n))
5852 r = INT2FIX(0);
5853 else
5854 r = f_mul(n, INT2FIX(CM_PERIOD));
5855
5856 if (d)
5857 r = f_add(r, rb_rational_new1(INT2FIX(d)));
5858 if (df)
5859 r = f_add(r, isec_to_day(df));
5860 if (f_nonzero_p(sf))
5861 r = f_add(r, ns_to_day(sf));
5862
5863 if (TYPE(r) == T_RATIONAL)
5864 return r;
5865 return rb_rational_new1(r);
5866 }
5867 }
5868
5869 /*
5870 * call-seq:
5871 * d - other -> date or rational
5872 *
5873 * Returns the difference between the two dates if the other is a date
5874 * object. If the other is a numeric value, returns a date object
5875 * pointing other days before self. If the other is flonum, assumes
5876 * its precision is at most nanosecond.
5877 *
5878 * Date.new(2001,2,3) - 1 #=> #<Date: 2001-02-02 ...>
5879 * DateTime.new(2001,2,3) - Rational(1,2)
5880 * #=> #<DateTime: 2001-02-02T12:00:00+00:00 ...>
5881 * Date.new(2001,2,3) - Date.new(2001)
5882 * #=> (33/1)
5883 * DateTime.new(2001,2,3) - DateTime.new(2001,2,2,12)
5884 * #=> (1/2)
5885 */
5886 static VALUE
5887 d_lite_minus(VALUE self, VALUE other)
5888 {
5889 if (k_date_p(other))
5890 return minus_dd(self, other);
5891
5892 switch (TYPE(other)) {
5893 case T_FIXNUM:
5894 return d_lite_plus(self, LONG2NUM(-FIX2LONG(other)));
5895 case T_FLOAT:
5896 return d_lite_plus(self, DBL2NUM(-RFLOAT_VALUE(other)));
5897 default:
5898 if (!k_numeric_p(other))
5899 rb_raise(rb_eTypeError, "expected numeric");
5900 /* fall through */
5901 case T_BIGNUM:
5902 case T_RATIONAL:
5903 return d_lite_plus(self, f_negate(other));
5904 }
5905 }
5906
5907 /*
5908 * call-seq:
5909 * d.next_day([n=1]) -> date
5910 *
5911 * This method is equivalent to d + n.
5912 */
5913 static VALUE
5914 d_lite_next_day(int argc, VALUE *argv, VALUE self)
5915 {
5916 VALUE n;
5917
5918 rb_scan_args(argc, argv, "01", &n);
5919 if (argc < 1)
5920 n = INT2FIX(1);
5921 return d_lite_plus(self, n);
5922 }
5923
5924 /*
5925 * call-seq:
5926 * d.prev_day([n=1]) -> date
5927 *
5928 * This method is equivalent to d - n.
5929 */
5930 static VALUE
5931 d_lite_prev_day(int argc, VALUE *argv, VALUE self)
5932 {
5933 VALUE n;
5934
5935 rb_scan_args(argc, argv, "01", &n);
5936 if (argc < 1)
5937 n = INT2FIX(1);
5938 return d_lite_minus(self, n);
5939 }
5940
5941 /*
5942 * call-seq:
5943 * d.next -> date
5944 *
5945 * Returns a date object denoting the following day.
5946 */
5947 static VALUE
5948 d_lite_next(VALUE self)
5949 {
5950 return d_lite_next_day(0, (VALUE *)NULL, self);
5951 }
5952
5953 /*
5954 * call-seq:
5955 * d >> n -> date
5956 *
5957 * Returns a date object pointing n months after self. The n should
5958 * be a numeric value.
5959 *
5960 * Date.new(2001,2,3) >> 1 #=> #<Date: 2001-03-03 ...>
5961 * Date.new(2001,1,31) >> 1 #=> #<Date: 2001-02-28 ...>
5962 * Date.new(2001,2,3) >> -2 #=> #<Date: 2000-12-03 ...>
5963 */
5964 static VALUE
5965 d_lite_rshift(VALUE self, VALUE other)
5966 {
5967 VALUE t, y, nth, rjd2;
5968 int m, d, rjd;
5969 double sg;
5970
5971 get_d1(self);
5972 t = f_add3(f_mul(m_real_year(dat), INT2FIX(12)),
5973 INT2FIX(m_mon(dat) - 1),
5974 other);
5975 if (FIXNUM_P(t)) {
5976 long it = FIX2LONG(t);
5977 y = LONG2NUM(DIV(it, 12));
5978 it = MOD(it, 12);
5979 m = (int)it + 1;
5980 }
5981 else {
5982 y = f_idiv(t, INT2FIX(12));
5983 t = f_mod(t, INT2FIX(12));
5984 m = FIX2INT(t) + 1;
5985 }
5986 d = m_mday(dat);
5987 sg = m_sg(dat);
5988
5989 while (1) {
5990 int ry, rm, rd, ns;
5991
5992 if (valid_civil_p(y, m, d, sg,
5993 &nth, &ry,
5994 &rm, &rd, &rjd, &ns))
5995 break;
5996 if (--d < 1)
5997 rb_raise(rb_eArgError, "invalid date");
5998 }
5999 encode_jd(nth, rjd, &rjd2);
6000 return d_lite_plus(self, f_sub(rjd2, m_real_local_jd(dat)));
6001 }
6002
6003 /*
6004 * call-seq:
6005 * d << n -> date
6006 *
6007 * Returns a date object pointing n months before self. The n should
6008 * be a numeric value.
6009 *
6010 * Date.new(2001,2,3) << 1 #=> #<Date: 2001-01-03 ...>
6011 * Date.new(2001,1,31) << 11 #=> #<Date: 2000-02-29 ...>
6012 * Date.new(2001,2,3) << -1 #=> #<Date: 2001-03-03 ...>
6013 */
6014 static VALUE
6015 d_lite_lshift(VALUE self, VALUE other)
6016 {
6017 return d_lite_rshift(self, f_negate(other));
6018 }
6019
6020 /*
6021 * call-seq:
6022 * d.next_month([n=1]) -> date
6023 *
6024 * This method is equivalent to d >> n
6025 */
6026 static VALUE
6027 d_lite_next_month(int argc, VALUE *argv, VALUE self)
6028 {
6029 VALUE n;
6030
6031 rb_scan_args(argc, argv, "01", &n);
6032 if (argc < 1)
6033 n = INT2FIX(1);
6034 return d_lite_rshift(self, n);
6035 }
6036
6037 /*
6038 * call-seq:
6039 * d.prev_month([n=1]) -> date
6040 *
6041 * This method is equivalent to d << n
6042 */
6043 static VALUE
6044 d_lite_prev_month(int argc, VALUE *argv, VALUE self)
6045 {
6046 VALUE n;
6047
6048 rb_scan_args(argc, argv, "01", &n);
6049 if (argc < 1)
6050 n = INT2FIX(1);
6051 return d_lite_lshift(self, n);
6052 }
6053
6054 /*
6055 * call-seq:
6056 * d.next_year([n=1]) -> date
6057 *
6058 * This method is equivalent to d >> (n * 12)
6059 */
6060 static VALUE
6061 d_lite_next_year(int argc, VALUE *argv, VALUE self)
6062 {
6063 VALUE n;
6064
6065 rb_scan_args(argc, argv, "01", &n);
6066 if (argc < 1)
6067 n = INT2FIX(1);
6068 return d_lite_rshift(self, f_mul(n, INT2FIX(12)));
6069 }
6070
6071 /*
6072 * call-seq:
6073 * d.prev_year([n=1]) -> date
6074 *
6075 * This method is equivalent to d << (n * 12)
6076 */
6077 static VALUE
6078 d_lite_prev_year(int argc, VALUE *argv, VALUE self)
6079 {
6080 VALUE n;
6081
6082 rb_scan_args(argc, argv, "01", &n);
6083 if (argc < 1)
6084 n = INT2FIX(1);
6085 return d_lite_lshift(self, f_mul(n, INT2FIX(12)));
6086 }
6087
6088 static VALUE d_lite_cmp(VALUE, VALUE);
6089
6090 /*
6091 * call-seq:
6092 * d.step(limit[, step=1]) -> enumerator
6093 * d.step(limit[, step=1]){|date| ...} -> self
6094 *
6095 * Iterates evaluation of the given block, which takes a date object.
6096 * The limit should be a date object.
6097 *
6098 * Date.new(2001).step(Date.new(2001,-1,-1)).select{|d| d.sunday?}.size
6099 * #=> 52
6100 */
6101 static VALUE
6102 d_lite_step(int argc, VALUE *argv, VALUE self)
6103 {
6104 VALUE limit, step, date;
6105
6106 rb_scan_args(argc, argv, "11", &limit, &step);
6107
6108 if (argc < 2)
6109 step = INT2FIX(1);
6110
6111 #if 0
6112 if (f_zero_p(step))
6113 rb_raise(rb_eArgError, "step can't be 0");
6114 #endif
6115
6116 RETURN_ENUMERATOR(self, argc, argv);
6117
6118 date = self;
6119 switch (FIX2INT(f_cmp(step, INT2FIX(0)))) {
6120 case -1:
6121 while (FIX2INT(d_lite_cmp(date, limit)) >= 0) {
6122 rb_yield(date);
6123 date = d_lite_plus(date, step);
6124 }
6125 break;
6126 case 0:
6127 while (1)
6128 rb_yield(date);
6129 break;
6130 case 1:
6131 while (FIX2INT(d_lite_cmp(date, limit)) <= 0) {
6132 rb_yield(date);
6133 date = d_lite_plus(date, step);
6134 }
6135 break;
6136 default:
6137 abort();
6138 }
6139 return self;
6140 }
6141
6142 /*
6143 * call-seq:
6144 * d.upto(max) -> enumerator
6145 * d.upto(max){|date| ...} -> self
6146 *
6147 * This method is equivalent to step(max, 1){|date| ...}.
6148 */
6149 static VALUE
6150 d_lite_upto(VALUE self, VALUE max)
6151 {
6152 VALUE date;
6153
6154 RETURN_ENUMERATOR(self, 1, &max);
6155
6156 date = self;
6157 while (FIX2INT(d_lite_cmp(date, max)) <= 0) {
6158 rb_yield(date);
6159 date = d_lite_plus(date, INT2FIX(1));
6160 }
6161 return self;
6162 }
6163
6164 /*
6165 * call-seq:
6166 * d.downto(min) -> enumerator
6167 * d.downto(min){|date| ...} -> self
6168 *
6169 * This method is equivalent to step(min, -1){|date| ...}.
6170 */
6171 static VALUE
6172 d_lite_downto(VALUE self, VALUE min)
6173 {
6174 VALUE date;
6175
6176 RETURN_ENUMERATOR(self, 1, &min);
6177
6178 date = self;
6179 while (FIX2INT(d_lite_cmp(date, min)) >= 0) {
6180 rb_yield(date);
6181 date = d_lite_plus(date, INT2FIX(-1));
6182 }
6183 return self;
6184 }
6185
6186 static VALUE
6187 cmp_gen(VALUE self, VALUE other)
6188 {
6189 get_d1(self);
6190
6191 if (k_numeric_p(other))
6192 return f_cmp(m_ajd(dat), other);
6193 else if (k_date_p(other))
6194 return f_cmp(m_ajd(dat), f_ajd(other));
6195 return rb_num_coerce_cmp(self, other, rb_intern("<=>"));
6196 }
6197
6198 static VALUE
6199 cmp_dd(VALUE self, VALUE other)
6200 {
6201 get_d2(self, other);
6202
6203 {
6204 VALUE a_nth, b_nth,
6205 a_sf, b_sf;
6206 int a_jd, b_jd,
6207 a_df, b_df;
6208
6209 m_canonicalize_jd(adat);
6210 m_canonicalize_jd(bdat);
6211 a_nth = m_nth(adat);
6212 b_nth = m_nth(bdat);
6213 if (f_eqeq_p(a_nth, b_nth)) {
6214 a_jd = m_jd(adat);
6215 b_jd = m_jd(bdat);
6216 if (a_jd == b_jd) {
6217 a_df = m_df(adat);
6218 b_df = m_df(bdat);
6219 if (a_df == b_df) {
6220 a_sf = m_sf(adat);
6221 b_sf = m_sf(bdat);
6222 if (f_eqeq_p(a_sf, b_sf)) {
6223 return INT2FIX(0);
6224 }
6225 else if (f_lt_p(a_sf, b_sf)) {
6226 return INT2FIX(-1);
6227 }
6228 else {
6229 return INT2FIX(1);
6230 }
6231 }
6232 else if (a_df < b_df) {
6233 return INT2FIX(-1);
6234 }
6235 else {
6236 return INT2FIX(1);
6237 }
6238 }
6239 else if (a_jd < b_jd) {
6240 return INT2FIX(-1);
6241 }
6242 else {
6243 return INT2FIX(1);
6244 }
6245 }
6246 else if (f_lt_p(a_nth, b_nth)) {
6247 return INT2FIX(-1);
6248 }
6249 else {
6250 return INT2FIX(1);
6251 }
6252 }
6253 }
6254
6255 /*
6256 * call-seq:
6257 * d <=> other -> -1, 0, +1 or nil
6258 *
6259 * Compares the two dates and returns -1, zero, 1 or nil. The other
6260 * should be a date object or a numeric value as an astronomical
6261 * Julian day number.
6262 *
6263 * Date.new(2001,2,3) <=> Date.new(2001,2,4) #=> -1
6264 * Date.new(2001,2,3) <=> Date.new(2001,2,3) #=> 0
6265 * Date.new(2001,2,3) <=> Date.new(2001,2,2) #=> 1
6266 * Date.new(2001,2,3) <=> Object.new #=> nil
6267 * Date.new(2001,2,3) <=> Rational(4903887,2)#=> 0
6268 *
6269 * See also Comparable.
6270 */
6271 static VALUE
6272 d_lite_cmp(VALUE self, VALUE other)
6273 {
6274 if (!k_date_p(other))
6275 return cmp_gen(self, other);
6276
6277 {
6278 get_d2(self, other);
6279
6280 if (!(simple_dat_p(adat) && simple_dat_p(bdat) &&
6281 m_gregorian_p(adat) == m_gregorian_p(bdat)))
6282 return cmp_dd(self, other);
6283
6284 if (have_jd_p(adat) &&
6285 have_jd_p(bdat)) {
6286 VALUE a_nth, b_nth;
6287 int a_jd, b_jd;
6288
6289 m_canonicalize_jd(adat);
6290 m_canonicalize_jd(bdat);
6291 a_nth = m_nth(adat);
6292 b_nth = m_nth(bdat);
6293 if (f_eqeq_p(a_nth, b_nth)) {
6294 a_jd = m_jd(adat);
6295 b_jd = m_jd(bdat);
6296 if (a_jd == b_jd) {
6297 return INT2FIX(0);
6298 }
6299 else if (a_jd < b_jd) {
6300 return INT2FIX(-1);
6301 }
6302 else {
6303 return INT2FIX(1);
6304 }
6305 }
6306 else if (a_nth < b_nth) {
6307 return INT2FIX(-1);
6308 }
6309 else {
6310 return INT2FIX(1);
6311 }
6312 }
6313 else {
6314 #ifndef USE_PACK
6315 VALUE a_nth, b_nth;
6316 int a_year, b_year,
6317 a_mon, b_mon,
6318 a_mday, b_mday;
6319 #else
6320 VALUE a_nth, b_nth;
6321 int a_year, b_year,
6322 a_pd, b_pd;
6323 #endif
6324
6325 m_canonicalize_jd(adat);
6326 m_canonicalize_jd(bdat);
6327 a_nth = m_nth(adat);
6328 b_nth = m_nth(bdat);
6329 if (f_eqeq_p(a_nth, b_nth)) {
6330 a_year = m_year(adat);
6331 b_year = m_year(bdat);
6332 if (a_year == b_year) {
6333 #ifndef USE_PACK
6334 a_mon = m_mon(adat);
6335 b_mon = m_mon(bdat);
6336 if (a_mon == b_mon) {
6337 a_mday = m_mday(adat);
6338 b_mday = m_mday(bdat);
6339 if (a_mday == b_mday) {
6340 return INT2FIX(0);
6341 }
6342 else if (a_mday < b_mday) {
6343 return INT2FIX(-1);
6344 }
6345 else {
6346 return INT2FIX(1);
6347 }
6348 }
6349 else if (a_mon < b_mon) {
6350 return INT2FIX(-1);
6351 }
6352 else {
6353 return INT2FIX(1);
6354 }
6355 #else
6356 a_pd = m_pc(adat);
6357 b_pd = m_pc(bdat);
6358 if (a_pd == b_pd) {
6359 return INT2FIX(0);
6360 }
6361 else if (a_pd < b_pd) {
6362 return INT2FIX(-1);
6363 }
6364 else {
6365 return INT2FIX(1);
6366 }
6367 #endif
6368 }
6369 else if (a_year < b_year) {
6370 return INT2FIX(-1);
6371 }
6372 else {
6373 return INT2FIX(1);
6374 }
6375 }
6376 else if (f_lt_p(a_nth, b_nth)) {
6377 return INT2FIX(-1);
6378 }
6379 else {
6380 return INT2FIX(1);
6381 }
6382 }
6383 }
6384 }
6385
6386 static VALUE
6387 equal_gen(VALUE self, VALUE other)
6388 {
6389 get_d1(self);
6390
6391 if (k_numeric_p(other))
6392 return f_eqeq_p(m_real_local_jd(dat), other);
6393 else if (k_date_p(other))
6394 return f_eqeq_p(m_real_local_jd(dat), f_jd(other));
6395 return rb_num_coerce_cmp(self, other, rb_intern("=="));
6396 }
6397
6398 /*
6399 * call-seq:
6400 * d === other -> bool
6401 *
6402 * Returns true if they are the same day.
6403 *
6404 * Date.new(2001,2,3) === Date.new(2001,2,3)
6405 * #=> true
6406 * Date.new(2001,2,3) === Date.new(2001,2,4)
6407 * #=> false
6408 * DateTime.new(2001,2,3) === DateTime.new(2001,2,3,12)
6409 * #=> true
6410 * DateTime.new(2001,2,3) === DateTime.new(2001,2,3,0,0,0,'+24:00')
6411 * #=> true
6412 * DateTime.new(2001,2,3) === DateTime.new(2001,2,4,0,0,0,'+24:00')
6413 * #=> false
6414 */
6415 static VALUE
6416 d_lite_equal(VALUE self, VALUE other)
6417 {
6418 if (!k_date_p(other))
6419 return equal_gen(self, other);
6420
6421 {
6422 get_d2(self, other);
6423
6424 if (!(m_gregorian_p(adat) == m_gregorian_p(bdat)))
6425 return equal_gen(self, other);
6426
6427 if (have_jd_p(adat) &&
6428 have_jd_p(bdat)) {
6429 VALUE a_nth, b_nth;
6430 int a_jd, b_jd;
6431
6432 m_canonicalize_jd(adat);
6433 m_canonicalize_jd(bdat);
6434 a_nth = m_nth(adat);
6435 b_nth = m_nth(bdat);
6436 a_jd = m_local_jd(adat);
6437 b_jd = m_local_jd(bdat);
6438 if (f_eqeq_p(a_nth, b_nth) &&
6439 a_jd == b_jd)
6440 return Qtrue;
6441 return Qfalse;
6442 }
6443 else {
6444 #ifndef USE_PACK
6445 VALUE a_nth, b_nth;
6446 int a_year, b_year,
6447 a_mon, b_mon,
6448 a_mday, b_mday;
6449 #else
6450 VALUE a_nth, b_nth;
6451 int a_year, b_year,
6452 a_pd, b_pd;
6453 #endif
6454
6455 m_canonicalize_jd(adat);
6456 m_canonicalize_jd(bdat);
6457 a_nth = m_nth(adat);
6458 b_nth = m_nth(bdat);
6459 if (f_eqeq_p(a_nth, b_nth)) {
6460 a_year = m_year(adat);
6461 b_year = m_year(bdat);
6462 if (a_year == b_year) {
6463 #ifndef USE_PACK
6464 a_mon = m_mon(adat);
6465 b_mon = m_mon(bdat);
6466 if (a_mon == b_mon) {
6467 a_mday = m_mday(adat);
6468 b_mday = m_mday(bdat);
6469 if (a_mday == b_mday)
6470 return Qtrue;
6471 }
6472 #else
6473 /* mon and mday only */
6474 a_pd = (m_pc(adat) >> MDAY_SHIFT);
6475 b_pd = (m_pc(bdat) >> MDAY_SHIFT);
6476 if (a_pd == b_pd) {
6477 return Qtrue;
6478 }
6479 #endif
6480 }
6481 }
6482 return Qfalse;
6483 }
6484 }
6485 }
6486
6487 /* :nodoc: */
6488 static VALUE
6489 d_lite_eql_p(VALUE self, VALUE other)
6490 {
6491 if (!k_date_p(other))
6492 return Qfalse;
6493 return f_zero_p(d_lite_cmp(self, other));
6494 }
6495
6496 /* :nodoc: */
6497 static VALUE
6498 d_lite_hash(VALUE self)
6499 {
6500 st_index_t v, h[4];
6501
6502 get_d1(self);
6503 h[0] = m_nth(dat);
6504 h[1] = m_jd(dat);
6505 h[2] = m_df(dat);
6506 h[3] = m_sf(dat);
6507 v = rb_memhash(h, sizeof(h));
6508 return LONG2FIX(v);
6509 }
6510
6511 #include "date_tmx.h"
6512 static void set_tmx(VALUE, struct tmx *);
6513 static VALUE strftimev(const char *, VALUE,
6514 void (*)(VALUE, struct tmx *));
6515
6516 /*
6517 * call-seq:
6518 * d.to_s -> string
6519 *
6520 * Returns a string in an ISO 8601 format (This method doesn't use the
6521 * expanded representations).
6522 *
6523 * Date.new(2001,2,3).to_s #=> "2001-02-03"
6524 */
6525 static VALUE
6526 d_lite_to_s(VALUE self)
6527 {
6528 return strftimev("%Y-%m-%d", self, set_tmx);
6529 }
6530
6531 #ifndef NDEBUG
6532 static VALUE
6533 mk_inspect_flags(union DateData *x)
6534 {
6535 return rb_enc_sprintf(rb_usascii_encoding(),
6536 "%c%c%c%c%c",
6537 (x->flags & COMPLEX_DAT) ? 'C' : 'S',
6538 (x->flags & HAVE_JD) ? 'j' : '-',
6539 (x->flags & HAVE_DF) ? 'd' : '-',
6540 (x->flags & HAVE_CIVIL) ? 'c' : '-',
6541 (x->flags & HAVE_TIME) ? 't' : '-');
6542 }
6543
6544 static VALUE
6545 mk_inspect_raw(union DateData *x, const char *klass)
6546 {
6547 if (simple_dat_p(x)) {
6548 VALUE nth, flags;
6549
6550 RB_GC_GUARD(nth) = f_inspect(x->s.nth);
6551 RB_GC_GUARD(flags) = mk_inspect_flags(x);
6552
6553 return rb_enc_sprintf(rb_usascii_encoding(),
6554 "#<%s: "
6555 "(%sth,%dj),+0s,%.0fj; "
6556 "%dy%dm%dd; %s>",
6557 klass ? klass : "?",
6558 RSTRING_PTR(nth), x->s.jd, x->s.sg,
6559 #ifndef USE_PACK
6560 x->s.year, x->s.mon, x->s.mday,
6561 #else
6562 x->s.year,
6563 EX_MON(x->s.pc), EX_MDAY(x->s.pc),
6564 #endif
6565 RSTRING_PTR(flags));
6566 }
6567 else {
6568 VALUE nth, sf, flags;
6569
6570 RB_GC_GUARD(nth) = f_inspect(x->c.nth);
6571 RB_GC_GUARD(sf) = f_inspect(x->c.sf);
6572 RB_GC_GUARD(flags) = mk_inspect_flags(x);
6573
6574 return rb_enc_sprintf(rb_usascii_encoding(),
6575 "#<%s: "
6576 "(%sth,%dj,%ds,%sn),%+ds,%.0fj; "
6577 "%dy%dm%dd %dh%dm%ds; %s>",
6578 klass ? klass : "?",
6579 RSTRING_PTR(nth), x->c.jd, x->c.df,
6580 RSTRING_PTR(sf),
6581 x->c.of, x->c.sg,
6582 #ifndef USE_PACK
6583 x->c.year, x->c.mon, x->c.mday,
6584 x->c.hour, x->c.min, x->c.sec,
6585 #else
6586 x->c.year,
6587 EX_MON(x->c.pc), EX_MDAY(x->c.pc),
6588 EX_HOUR(x->c.pc), EX_MIN(x->c.pc),
6589 EX_SEC(x->c.pc),
6590 #endif
6591 RSTRING_PTR(flags));
6592 }
6593 }
6594
6595 static VALUE
6596 d_lite_inspect_raw(VALUE self)
6597 {
6598 get_d1(self);
6599 return mk_inspect_raw(dat, rb_obj_classname(self));
6600 }
6601 #endif
6602
6603 static VALUE
6604 mk_inspect(union DateData *x, const char *klass, const char *to_s)
6605 {
6606 VALUE jd, sf;
6607
6608 RB_GC_GUARD(jd) = f_inspect(m_real_jd(x));
6609 RB_GC_GUARD(sf) = f_inspect(m_sf(x));
6610
6611 return rb_enc_sprintf(rb_usascii_encoding(),
6612 "#<%s: %s ((%sj,%ds,%sn),%+ds,%.0fj)>",
6613 klass ? klass : "?",
6614 to_s ? to_s : "?",
6615 RSTRING_PTR(jd), m_df(x), RSTRING_PTR(sf),
6616 m_of(x), m_sg(x));
6617 }
6618
6619 /*
6620 * call-seq:
6621 * d.inspect -> string
6622 *
6623 * Returns the value as a string for inspection.
6624 *
6625 * Date.new(2001,2,3).inspect
6626 * #=> "#<Date: 2001-02-03 ((2451944j,0s,0n),+0s,2299161j)>"
6627 * DateTime.new(2001,2,3,4,5,6,'-7').inspect
6628 * #=> "#<DateTime: 2001-02-03T04:05:06-07:00 ((2451944j,39906s,0n),-25200s,2299161j)>"
6629 */
6630 static VALUE
6631 d_lite_inspect(VALUE self)
6632 {
6633 get_d1(self);
6634 {
6635 VALUE to_s;
6636
6637 RB_GC_GUARD(to_s) = f_to_s(self);
6638 return mk_inspect(dat, rb_obj_classname(self), RSTRING_PTR(to_s));
6639 }
6640 }
6641
6642 #include <errno.h>
6643 #include "date_tmx.h"
6644
6645 size_t date_strftime(char *s, size_t maxsize, const char *format,
6646 const struct tmx *tmx);
6647
6648 #define SMALLBUF 100
6649 static size_t
6650 date_strftime_alloc(char **buf, const char *format,
6651 struct tmx *tmx)
6652 {
6653 size_t size, len, flen;
6654
6655 (*buf)[0] = '\0';
6656 flen = strlen(format);
6657 if (flen == 0) {
6658 return 0;
6659 }
6660 errno = 0;
6661 len = date_strftime(*buf, SMALLBUF, format, tmx);
6662 if (len != 0 || (**buf == '\0' && errno != ERANGE)) return len;
6663 for (size=1024; ; size*=2) {
6664 *buf = xmalloc(size);
6665 (*buf)[0] = '\0';
6666 len = date_strftime(*buf, size, format, tmx);
6667 /*
6668 * buflen can be zero EITHER because there's not enough
6669 * room in the string, or because the control command
6670 * goes to the empty string. Make a reasonable guess that
6671 * if the buffer is 1024 times bigger than the length of the
6672 * format string, it's not failing for lack of room.
6673 */
6674 if (len > 0) break;
6675 xfree(*buf);
6676 if (size >= 1024 * flen) {
6677 rb_sys_fail(format);
6678 break;
6679 }
6680 }
6681 return len;
6682 }
6683
6684 static VALUE
6685 tmx_m_secs(union DateData *x)
6686 {
6687 VALUE s;
6688 int df;
6689
6690 s = day_to_sec(f_sub(m_real_jd(x),
6691 UNIX_EPOCH_IN_CJD));
6692 if (simple_dat_p(x))
6693 return s;
6694 df = m_df(x);
6695 if (df)
6696 s = f_add(s, INT2FIX(df));
6697 return s;
6698 }
6699
6700 #define MILLISECOND_IN_NANOSECONDS 1000000
6701
6702 static VALUE
6703 tmx_m_msecs(union DateData *x)
6704 {
6705 VALUE s, sf;
6706
6707 s = sec_to_ms(tmx_m_secs(x));
6708 if (simple_dat_p(x))
6709 return s;
6710 sf = m_sf(x);
6711 if (f_nonzero_p(sf))
6712 s = f_add(s, f_div(sf, INT2FIX(MILLISECOND_IN_NANOSECONDS)));
6713 return s;
6714 }
6715
6716 static int
6717 tmx_m_of(union DateData *x)
6718 {
6719 return m_of(x);
6720 }
6721
6722 static char *
6723 tmx_m_zone(union DateData *x)
6724 {
6725 return RSTRING_PTR(m_zone(x));
6726 }
6727
6728 static struct tmx_funcs tmx_funcs = {
6729 (VALUE (*)(void *))m_real_year,
6730 (int (*)(void *))m_yday,
6731 (int (*)(void *))m_mon,
6732 (int (*)(void *))m_mday,
6733 (VALUE (*)(void *))m_real_cwyear,
6734 (int (*)(void *))m_cweek,
6735 (int (*)(void *))m_cwday,
6736 (int (*)(void *))m_wnum0,
6737 (int (*)(void *))m_wnum1,
6738 (int (*)(void *))m_wday,
6739 (int (*)(void *))m_hour,
6740 (int (*)(void *))m_min,
6741 (int (*)(void *))m_sec,
6742 (VALUE (*)(void *))m_sf_in_sec,
6743 (VALUE (*)(void *))tmx_m_secs,
6744 (VALUE (*)(void *))tmx_m_msecs,
6745 (int (*)(void *))tmx_m_of,
6746 (char *(*)(void *))tmx_m_zone
6747 };
6748
6749 static void
6750 set_tmx(VALUE self, struct tmx *tmx)
6751 {
6752 get_d1(self);
6753 tmx->dat = (void *)dat;
6754 tmx->funcs = &tmx_funcs;
6755 }
6756
6757 static VALUE
6758 date_strftime_internal(int argc, VALUE *argv, VALUE self,
6759 const char *default_fmt,
6760 void (*func)(VALUE, struct tmx *))
6761 {
6762 VALUE vfmt;
6763 const char *fmt;
6764 long len;
6765 char buffer[SMALLBUF], *buf = buffer;
6766 struct tmx tmx;
6767 VALUE str;
6768
6769 rb_scan_args(argc, argv, "01", &vfmt);
6770
6771 if (argc < 1)
6772 vfmt = rb_usascii_str_new2(default_fmt);
6773 else {
6774 StringValue(vfmt);
6775 if (!rb_enc_str_asciicompat_p(vfmt)) {
6776 rb_raise(rb_eArgError,
6777 "format should have ASCII compatible encoding");
6778 }
6779 }
6780 fmt = RSTRING_PTR(vfmt);
6781 len = RSTRING_LEN(vfmt);
6782 (*func)(self, &tmx);
6783 if (memchr(fmt, '\0', len)) {
6784 /* Ruby string may contain \0's. */
6785 const char *p = fmt, *pe = fmt + len;
6786
6787 str = rb_str_new(0, 0);
6788 while (p < pe) {
6789 len = date_strftime_alloc(&buf, p, &tmx);
6790 rb_str_cat(str, buf, len);
6791 p += strlen(p);
6792 if (buf != buffer) {
6793 xfree(buf);
6794 buf = buffer;
6795 }
6796 for (fmt = p; p < pe && !*p; ++p);
6797 if (p > fmt) rb_str_cat(str, fmt, p - fmt);
6798 }
6799 rb_enc_copy(str, vfmt);
6800 OBJ_INFECT(str, vfmt);
6801 return str;
6802 }
6803 else
6804 len = date_strftime_alloc(&buf, fmt, &tmx);
6805
6806 str = rb_str_new(buf, len);
6807 if (buf != buffer) xfree(buf);
6808 rb_enc_copy(str, vfmt);
6809 OBJ_INFECT(str, vfmt);
6810 return str;
6811 }
6812
6813 /*
6814 * call-seq:
6815 * d.strftime([format='%F']) -> string
6816 *
6817 * Formats date according to the directives in the given format
6818 * string.
6819 * The directives begins with a percent (%) character.
6820 * Any text not listed as a directive will be passed through to the
6821 * output string.
6822 *
6823 * The directive consists of a percent (%) character,
6824 * zero or more flags, optional minimum field width,
6825 * optional modifier and a conversion specifier
6826 * as follows.
6827 *
6828 * %<flags><width><modifier><conversion>
6829 *
6830 * Flags:
6831 * - don't pad a numerical output.
6832 * _ use spaces for padding.
6833 * 0 use zeros for padding.
6834 * ^ upcase the result string.
6835 * # change case.
6836 *
6837 * The minimum field width specifies the minimum width.
6838 *
6839 * The modifiers are "E", "O", ":", "::" and ":::".
6840 * "E" and "O" are ignored. No effect to result currently.
6841 *
6842 * Format directives:
6843 *
6844 * Date (Year, Month, Day):
6845 * %Y - Year with century (can be negative, 4 digits at least)
6846 * -0001, 0000, 1995, 2009, 14292, etc.
6847 * %C - year / 100 (round down. 20 in 2009)
6848 * %y - year % 100 (00..99)
6849 *
6850 * %m - Month of the year, zero-padded (01..12)
6851 * %_m blank-padded ( 1..12)
6852 * %-m no-padded (1..12)
6853 * %B - The full month name (``January'')
6854 * %^B uppercased (``JANUARY'')
6855 * %b - The abbreviated month name (``Jan'')
6856 * %^b uppercased (``JAN'')
6857 * %h - Equivalent to %b
6858 *
6859 * %d - Day of the month, zero-padded (01..31)
6860 * %-d no-padded (1..31)
6861 * %e - Day of the month, blank-padded ( 1..31)
6862 *
6863 * %j - Day of the year (001..366)
6864 *
6865 * Time (Hour, Minute, Second, Subsecond):
6866 * %H - Hour of the day, 24-hour clock, zero-padded (00..23)
6867 * %k - Hour of the day, 24-hour clock, blank-padded ( 0..23)
6868 * %I - Hour of the day, 12-hour clock, zero-padded (01..12)
6869 * %l - Hour of the day, 12-hour clock, blank-padded ( 1..12)
6870 * %P - Meridian indicator, lowercase (``am'' or ``pm'')
6871 * %p - Meridian indicator, uppercase (``AM'' or ``PM'')
6872 *
6873 * %M - Minute of the hour (00..59)
6874 *
6875 * %S - Second of the minute (00..59)
6876 *
6877 * %L - Millisecond of the second (000..999)
6878 * %N - Fractional seconds digits, default is 9 digits (nanosecond)
6879 * %3N millisecond (3 digits) %15N femtosecond (15 digits)
6880 * %6N microsecond (6 digits) %18N attosecond (18 digits)
6881 * %9N nanosecond (9 digits) %21N zeptosecond (21 digits)
6882 * %12N picosecond (12 digits) %24N yoctosecond (24 digits)
6883 *
6884 * Time zone:
6885 * %z - Time zone as hour and minute offset from UTC (e.g. +0900)
6886 * %:z - hour and minute offset from UTC with a colon (e.g. +09:00)
6887 * %::z - hour, minute and second offset from UTC (e.g. +09:00:00)
6888 * %:::z - hour, minute and second offset from UTC
6889 * (e.g. +09, +09:30, +09:30:30)
6890 * %Z - Time zone abbreviation name or something similar information.
6891 *
6892 * Weekday:
6893 * %A - The full weekday name (``Sunday'')
6894 * %^A uppercased (``SUNDAY'')
6895 * %a - The abbreviated name (``Sun'')
6896 * %^a uppercased (``SUN'')
6897 * %u - Day of the week (Monday is 1, 1..7)
6898 * %w - Day of the week (Sunday is 0, 0..6)
6899 *
6900 * ISO 8601 week-based year and week number:
6901 * The week 1 of YYYY starts with a Monday and includes YYYY-01-04.
6902 * The days in the year before the first week are in the last week of
6903 * the previous year.
6904 * %G - The week-based year
6905 * %g - The last 2 digits of the week-based year (00..99)
6906 * %V - Week number of the week-based year (01..53)
6907 *
6908 * Week number:
6909 * The week 1 of YYYY starts with a Sunday or Monday (according to %U
6910 * or %W). The days in the year before the first week are in week 0.
6911 * %U - Week number of the year. The week starts with Sunday. (00..53)
6912 * %W - Week number of the year. The week starts with Monday. (00..53)
6913 *
6914 * Seconds since the Unix Epoch:
6915 * %s - Number of seconds since 1970-01-01 00:00:00 UTC.
6916 * %Q - Number of milliseconds since 1970-01-01 00:00:00 UTC.
6917 *
6918 * Literal string:
6919 * %n - Newline character (\n)
6920 * %t - Tab character (\t)
6921 * %% - Literal ``%'' character
6922 *
6923 * Combination:
6924 * %c - date and time (%a %b %e %T %Y)
6925 * %D - Date (%m/%d/%y)
6926 * %F - The ISO 8601 date format (%Y-%m-%d)
6927 * %v - VMS date (%e-%b-%Y)
6928 * %x - Same as %D
6929 * %X - Same as %T
6930 * %r - 12-hour time (%I:%M:%S %p)
6931 * %R - 24-hour time (%H:%M)
6932 * %T - 24-hour time (%H:%M:%S)
6933 * %+ - date(1) (%a %b %e %H:%M:%S %Z %Y)
6934 *
6935 * This method is similar to strftime() function defined in ISO C and POSIX.
6936 * Several directives (%a, %A, %b, %B, %c, %p, %r, %x, %X, %E*, %O* and %Z)
6937 * are locale dependent in the function.
6938 * However this method is locale independent.
6939 * So, the result may differ even if a same format string is used in other
6940 * systems such as C.
6941 * It is good practice to avoid %x and %X because there are corresponding
6942 * locale independent representations, %D and %T.
6943 *
6944 * Examples:
6945 *
6946 * d = DateTime.new(2007,11,19,8,37,48,"-06:00")
6947 * #=> #<DateTime: 2007-11-19T08:37:48-0600 ...>
6948 * d.strftime("Printed on %m/%d/%Y") #=> "Printed on 11/19/2007"
6949 * d.strftime("at %I:%M%p") #=> "at 08:37AM"
6950 *
6951 * Various ISO 8601 formats:
6952 * %Y%m%d => 20071119 Calendar date (basic)
6953 * %F => 2007-11-19 Calendar date (extended)
6954 * %Y-%m => 2007-11 Calendar date, reduced accuracy, specific month
6955 * %Y => 2007 Calendar date, reduced accuracy, specific year
6956 * %C => 20 Calendar date, reduced accuracy, specific century
6957 * %Y%j => 2007323 Ordinal date (basic)
6958 * %Y-%j => 2007-323 Ordinal date (extended)
6959 * %GW%V%u => 2007W471 Week date (basic)
6960 * %G-W%V-%u => 2007-W47-1 Week date (extended)
6961 * %GW%V => 2007W47 Week date, reduced accuracy, specific week (basic)
6962 * %G-W%V => 2007-W47 Week date, reduced accuracy, specific week (extended)
6963 * %H%M%S => 083748 Local time (basic)
6964 * %T => 08:37:48 Local time (extended)
6965 * %H%M => 0837 Local time, reduced accuracy, specific minute (basic)
6966 * %H:%M => 08:37 Local time, reduced accuracy, specific minute (extended)
6967 * %H => 08 Local time, reduced accuracy, specific hour
6968 * %H%M%S,%L => 083748,000 Local time with decimal fraction, comma as decimal sign (basic)
6969 * %T,%L => 08:37:48,000 Local time with decimal fraction, comma as decimal sign (extended)
6970 * %H%M%S.%L => 083748.000 Local time with decimal fraction, full stop as decimal sign (basic)
6971 * %T.%L => 08:37:48.000 Local time with decimal fraction, full stop as decimal sign (extended)
6972 * %H%M%S%z => 083748-0600 Local time and the difference from UTC (basic)
6973 * %T%:z => 08:37:48-06:00 Local time and the difference from UTC (extended)
6974 * %Y%m%dT%H%M%S%z => 20071119T083748-0600 Date and time of day for calendar date (basic)
6975 * %FT%T%:z => 2007-11-19T08:37:48-06:00 Date and time of day for calendar date (extended)
6976 * %Y%jT%H%M%S%z => 2007323T083748-0600 Date and time of day for ordinal date (basic)
6977 * %Y-%jT%T%:z => 2007-323T08:37:48-06:00 Date and time of day for ordinal date (extended)
6978 * %GW%V%uT%H%M%S%z => 2007W471T083748-0600 Date and time of day for week date (basic)
6979 * %G-W%V-%uT%T%:z => 2007-W47-1T08:37:48-06:00 Date and time of day for week date (extended)
6980 * %Y%m%dT%H%M => 20071119T0837 Calendar date and local time (basic)
6981 * %FT%R => 2007-11-19T08:37 Calendar date and local time (extended)
6982 * %Y%jT%H%MZ => 2007323T0837Z Ordinal date and UTC of day (basic)
6983 * %Y-%jT%RZ => 2007-323T08:37Z Ordinal date and UTC of day (extended)
6984 * %GW%V%uT%H%M%z => 2007W471T0837-0600 Week date and local time and difference from UTC (basic)
6985 * %G-W%V-%uT%R%:z => 2007-W47-1T08:37-06:00 Week date and local time and difference from UTC (extended)
6986 *
6987 * See also strftime(3) and strptime.
6988 */
6989 static VALUE
6990 d_lite_strftime(int argc, VALUE *argv, VALUE self)
6991 {
6992 return date_strftime_internal(argc, argv, self,
6993 "%Y-%m-%d", set_tmx);
6994 }
6995
6996 static VALUE
6997 strftimev(const char *fmt, VALUE self,
6998 void (*func)(VALUE, struct tmx *))
6999 {
7000 char buffer[SMALLBUF], *buf = buffer;
7001 struct tmx tmx;
7002 long len;
7003 VALUE str;
7004
7005 (*func)(self, &tmx);
7006 len = date_strftime_alloc(&buf, fmt, &tmx);
7007 str = rb_usascii_str_new(buf, len);
7008 if (buf != buffer) xfree(buf);
7009 return str;
7010 }
7011
7012 /*
7013 * call-seq:
7014 * d.asctime -> string
7015 * d.ctime -> string
7016 *
7017 * Returns a string in asctime(3) format (but without "\n\0" at the
7018 * end). This method is equivalent to strftime('%c').
7019 *
7020 * See also asctime(3) or ctime(3).
7021 */
7022 static VALUE
7023 d_lite_asctime(VALUE self)
7024 {
7025 return strftimev("%a %b %e %H:%M:%S %Y", self, set_tmx);
7026 }
7027
7028 /*
7029 * call-seq:
7030 * d.iso8601 -> string
7031 * d.xmlschema -> string
7032 *
7033 * This method is equivalent to strftime('%F').
7034 */
7035 static VALUE
7036 d_lite_iso8601(VALUE self)
7037 {
7038 return strftimev("%Y-%m-%d", self, set_tmx);
7039 }
7040
7041 /*
7042 * call-seq:
7043 * d.rfc3339 -> string
7044 *
7045 * This method is equivalent to strftime('%FT%T%:z').
7046 */
7047 static VALUE
7048 d_lite_rfc3339(VALUE self)
7049 {
7050 return strftimev("%Y-%m-%dT%H:%M:%S%:z", self, set_tmx);
7051 }
7052
7053 /*
7054 * call-seq:
7055 * d.rfc2822 -> string
7056 * d.rfc822 -> string
7057 *
7058 * This method is equivalent to strftime('%a, %-d %b %Y %T %z').
7059 */
7060 static VALUE
7061 d_lite_rfc2822(VALUE self)
7062 {
7063 return strftimev("%a, %-d %b %Y %T %z", self, set_tmx);
7064 }
7065
7066 /*
7067 * call-seq:
7068 * d.httpdate -> string
7069 *
7070 * This method is equivalent to strftime('%a, %d %b %Y %T GMT').
7071 * See also RFC 2616.
7072 */
7073 static VALUE
7074 d_lite_httpdate(VALUE self)
7075 {
7076 volatile VALUE dup = dup_obj_with_new_offset(self, 0);
7077 return strftimev("%a, %d %b %Y %T GMT", dup, set_tmx);
7078 }
7079
7080 static VALUE
7081 jisx0301_date(VALUE jd, VALUE y)
7082 {
7083 VALUE a[2];
7084
7085 if (f_lt_p(jd, INT2FIX(2405160)))
7086 return rb_usascii_str_new2("%Y-%m-%d");
7087 if (f_lt_p(jd, INT2FIX(2419614))) {
7088 a[0] = rb_usascii_str_new2("M%02d" ".%%m.%%d");
7089 a[1] = f_sub(y, INT2FIX(1867));
7090 }
7091 else if (f_lt_p(jd, INT2FIX(2424875))) {
7092 a[0] = rb_usascii_str_new2("T%02d" ".%%m.%%d");
7093 a[1] = f_sub(y, INT2FIX(1911));
7094 }
7095 else if (f_lt_p(jd, INT2FIX(2447535))) {
7096 a[0] = rb_usascii_str_new2("S%02d" ".%%m.%%d");
7097 a[1] = f_sub(y, INT2FIX(1925));
7098 }
7099 else {
7100 a[0] = rb_usascii_str_new2("H%02d" ".%%m.%%d");
7101 a[1] = f_sub(y, INT2FIX(1988));
7102 }
7103 return rb_f_sprintf(2, a);
7104 }
7105
7106 /*
7107 * call-seq:
7108 * d.jisx0301 -> string
7109 *
7110 * Returns a string in a JIS X 0301 format.
7111 *
7112 * Date.new(2001,2,3).jisx0301 #=> "H13.02.03"
7113 */
7114 static VALUE
7115 d_lite_jisx0301(VALUE self)
7116 {
7117 VALUE s;
7118
7119 get_d1(self);
7120 s = jisx0301_date(m_real_local_jd(dat),
7121 m_real_year(dat));
7122 return strftimev(RSTRING_PTR(s), self, set_tmx);
7123 }
7124
7125 #ifndef NDEBUG
7126 static VALUE
7127 d_lite_marshal_dump_old(VALUE self)
7128 {
7129 VALUE a;
7130
7131 get_d1(self);
7132
7133 a = rb_ary_new3(3,
7134 m_ajd(dat),
7135 m_of_in_day(dat),
7136 DBL2NUM(m_sg(dat)));
7137
7138 if (FL_TEST(self, FL_EXIVAR)) {
7139 rb_copy_generic_ivar(a, self);
7140 FL_SET(a, FL_EXIVAR);
7141 }
7142
7143 return a;
7144 }
7145 #endif
7146
7147 /* :nodoc: */
7148 static VALUE
7149 d_lite_marshal_dump(VALUE self)
7150 {
7151 VALUE a;
7152
7153 get_d1(self);
7154
7155 a = rb_ary_new3(6,
7156 m_nth(dat),
7157 INT2FIX(m_jd(dat)),
7158 INT2FIX(m_df(dat)),
7159 m_sf(dat),
7160 INT2FIX(m_of(dat)),
7161 DBL2NUM(m_sg(dat)));
7162
7163 if (FL_TEST(self, FL_EXIVAR)) {
7164 rb_copy_generic_ivar(a, self);
7165 FL_SET(a, FL_EXIVAR);
7166 }
7167
7168 return a;
7169 }
7170
7171 /* :nodoc: */
7172 static VALUE
7173 d_lite_marshal_load(VALUE self, VALUE a)
7174 {
7175 get_d1(self);
7176
7177 rb_check_frozen(self);
7178 rb_check_trusted(self);
7179
7180 if (TYPE(a) != T_ARRAY)
7181 rb_raise(rb_eTypeError, "expected an array");
7182
7183 switch (RARRAY_LEN(a)) {
7184 case 2: /* 1.6.x */
7185 case 3: /* 1.8.x, 1.9.2 */
7186 {
7187 VALUE ajd, of, sg, nth, sf;
7188 int jd, df, rof;
7189 double rsg;
7190
7191
7192 if (RARRAY_LEN(a) == 2) {
7193 ajd = f_sub(RARRAY_PTR(a)[0], half_days_in_day);
7194 of = INT2FIX(0);
7195 sg = RARRAY_PTR(a)[1];
7196 if (!k_numeric_p(sg))
7197 sg = DBL2NUM(RTEST(sg) ? GREGORIAN : JULIAN);
7198 }
7199 else {
7200 ajd = RARRAY_PTR(a)[0];
7201 of = RARRAY_PTR(a)[1];
7202 sg = RARRAY_PTR(a)[2];
7203 }
7204
7205 old_to_new(ajd, of, sg,
7206 &nth, &jd, &df, &sf, &rof, &rsg);
7207
7208 if (!df && f_zero_p(sf) && !rof) {
7209 set_to_simple(&dat->s, nth, jd, rsg, 0, 0, 0, HAVE_JD);
7210 } else {
7211 if (!complex_dat_p(dat))
7212 rb_raise(rb_eArgError,
7213 "cannot load complex into simple");
7214
7215 set_to_complex(&dat->c, nth, jd, df, sf, rof, rsg,
7216 0, 0, 0, 0, 0, 0,
7217 HAVE_JD | HAVE_DF | COMPLEX_DAT);
7218 }
7219 }
7220 break;
7221 case 6:
7222 {
7223 VALUE nth, sf;
7224 int jd, df, of;
7225 double sg;
7226
7227 nth = RARRAY_PTR(a)[0];
7228 jd = NUM2INT(RARRAY_PTR(a)[1]);
7229 df = NUM2INT(RARRAY_PTR(a)[2]);
7230 sf = RARRAY_PTR(a)[3];
7231 of = NUM2INT(RARRAY_PTR(a)[4]);
7232 sg = NUM2DBL(RARRAY_PTR(a)[5]);
7233 if (!df && f_zero_p(sf) && !of) {
7234 set_to_simple(&dat->s, nth, jd, sg, 0, 0, 0, HAVE_JD);
7235 } else {
7236 if (!complex_dat_p(dat))
7237 rb_raise(rb_eArgError,
7238 "cannot load complex into simple");
7239
7240 set_to_complex(&dat->c, nth, jd, df, sf, of, sg,
7241 0, 0, 0, 0, 0, 0,
7242 HAVE_JD | HAVE_DF | COMPLEX_DAT);
7243 }
7244 }
7245 break;
7246 default:
7247 rb_raise(rb_eTypeError, "invalid size");
7248 break;
7249 }
7250
7251 if (FL_TEST(a, FL_EXIVAR)) {
7252 rb_copy_generic_ivar(self, a);
7253 FL_SET(self, FL_EXIVAR);
7254 }
7255
7256 return self;
7257 }
7258
7259 /* :nodoc: */
7260 static VALUE
7261 date_s__load(VALUE klass, VALUE s)
7262 {
7263 VALUE a, obj;
7264
7265 a = rb_marshal_load(s);
7266 obj = d_lite_s_alloc(klass);
7267 return d_lite_marshal_load(obj, a);
7268 }
7269
7270 /* datetime */
7271
7272 /*
7273 * call-seq:
7274 * DateTime.jd([jd=0[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]) -> datetime
7275 *
7276 * Creates a datetime object denoting the given chronological Julian
7277 * day number.
7278 *
7279 * DateTime.jd(2451944) #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...>
7280 * DateTime.jd(2451945) #=> #<DateTime: 2001-02-04T00:00:00+00:00 ...>
7281 * DateTime.jd(Rational('0.5'))
7282 * #=> #<DateTime: -4712-01-01T12:00:00+00:00 ...>
7283 */
7284 static VALUE
7285 datetime_s_jd(int argc, VALUE *argv, VALUE klass)
7286 {
7287 VALUE vjd, vh, vmin, vs, vof, vsg, jd, fr, fr2, ret;
7288 int h, min, s, rof;
7289 double sg;
7290
7291 rb_scan_args(argc, argv, "06", &vjd, &vh, &vmin, &vs, &vof, &vsg);
7292
7293 jd = INT2FIX(0);
7294
7295 h = min = s = 0;
7296 fr2 = INT2FIX(0);
7297 rof = 0;
7298 sg = DEFAULT_SG;
7299
7300 switch (argc) {
7301 case 6:
7302 val2sg(vsg, sg);
7303 case 5:
7304 val2off(vof, rof);
7305 case 4:
7306 num2int_with_frac(s, positive_inf);
7307 case 3:
7308 num2int_with_frac(min, 3);
7309 case 2:
7310 num2int_with_frac(h, 2);
7311 case 1:
7312 num2num_with_frac(jd, 1);
7313 }
7314
7315 {
7316 VALUE nth;
7317 int rh, rmin, rs, rjd, rjd2;
7318
7319 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7320 rb_raise(rb_eArgError, "invalid date");
7321 canon24oc();
7322
7323 decode_jd(jd, &nth, &rjd);
7324 rjd2 = jd_local_to_utc(rjd,
7325 time_to_df(rh, rmin, rs),
7326 rof);
7327
7328 ret = d_complex_new_internal(klass,
7329 nth, rjd2,
7330 0, INT2FIX(0),
7331 rof, sg,
7332 0, 0, 0,
7333 rh, rmin, rs,
7334 HAVE_JD | HAVE_TIME);
7335 }
7336 add_frac();
7337 return ret;
7338 }
7339
7340 /*
7341 * call-seq:
7342 * DateTime.ordinal([year=-4712[, yday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]) -> datetime
7343 *
7344 * Creates a date-time object denoting the given ordinal date.
7345 *
7346 * DateTime.ordinal(2001,34) #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...>
7347 * DateTime.ordinal(2001,34,4,5,6,'+7')
7348 * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7349 * DateTime.ordinal(2001,-332,-20,-55,-54,'+7')
7350 * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7351 */
7352 static VALUE
7353 datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
7354 {
7355 VALUE vy, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
7356 int d, h, min, s, rof;
7357 double sg;
7358
7359 rb_scan_args(argc, argv, "07", &vy, &vd, &vh, &vmin, &vs, &vof, &vsg);
7360
7361 y = INT2FIX(-4712);
7362 d = 1;
7363
7364 h = min = s = 0;
7365 fr2 = INT2FIX(0);
7366 rof = 0;
7367 sg = DEFAULT_SG;
7368
7369 switch (argc) {
7370 case 7:
7371 val2sg(vsg, sg);
7372 case 6:
7373 val2off(vof, rof);
7374 case 5:
7375 num2int_with_frac(s, positive_inf);
7376 case 4:
7377 num2int_with_frac(min, 4);
7378 case 3:
7379 num2int_with_frac(h, 3);
7380 case 2:
7381 num2int_with_frac(d, 2);
7382 case 1:
7383 y = vy;
7384 }
7385
7386 {
7387 VALUE nth;
7388 int ry, rd, rh, rmin, rs, rjd, rjd2, ns;
7389
7390 if (!valid_ordinal_p(y, d, sg,
7391 &nth, &ry,
7392 &rd, &rjd,
7393 &ns))
7394 rb_raise(rb_eArgError, "invalid date");
7395 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7396 rb_raise(rb_eArgError, "invalid date");
7397 canon24oc();
7398
7399 rjd2 = jd_local_to_utc(rjd,
7400 time_to_df(rh, rmin, rs),
7401 rof);
7402
7403 ret = d_complex_new_internal(klass,
7404 nth, rjd2,
7405 0, INT2FIX(0),
7406 rof, sg,
7407 0, 0, 0,
7408 rh, rmin, rs,
7409 HAVE_JD | HAVE_TIME);
7410 }
7411 add_frac();
7412 return ret;
7413 }
7414
7415 /*
7416 * call-seq:
7417 * DateTime.civil([year=-4712[, month=1[, mday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]]) -> datetime
7418 * DateTime.new([year=-4712[, month=1[, mday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]]) -> datetime
7419 *
7420 * Creates a date-time object denoting the given calendar date.
7421 *
7422 * DateTime.new(2001,2,3) #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...>
7423 * DateTime.new(2001,2,3,4,5,6,'+7')
7424 * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7425 * DateTime.new(2001,-11,-26,-20,-55,-54,'+7')
7426 * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7427 */
7428 static VALUE
7429 datetime_s_civil(int argc, VALUE *argv, VALUE klass)
7430 {
7431 VALUE vy, vm, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
7432 int m, d, h, min, s, rof;
7433 double sg;
7434
7435 rb_scan_args(argc, argv, "08", &vy, &vm, &vd, &vh, &vmin, &vs, &vof, &vsg);
7436
7437 y = INT2FIX(-4712);
7438 m = 1;
7439 d = 1;
7440
7441 h = min = s = 0;
7442 fr2 = INT2FIX(0);
7443 rof = 0;
7444 sg = DEFAULT_SG;
7445
7446 switch (argc) {
7447 case 8:
7448 val2sg(vsg, sg);
7449 case 7:
7450 val2off(vof, rof);
7451 case 6:
7452 num2int_with_frac(s, positive_inf);
7453 case 5:
7454 num2int_with_frac(min, 5);
7455 case 4:
7456 num2int_with_frac(h, 4);
7457 case 3:
7458 num2int_with_frac(d, 3);
7459 case 2:
7460 m = NUM2INT(vm);
7461 case 1:
7462 y = vy;
7463 }
7464
7465 if (guess_style(y, sg) < 0) {
7466 VALUE nth;
7467 int ry, rm, rd, rh, rmin, rs;
7468
7469 if (!valid_gregorian_p(y, m, d,
7470 &nth, &ry,
7471 &rm, &rd))
7472 rb_raise(rb_eArgError, "invalid date");
7473 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7474 rb_raise(rb_eArgError, "invalid date");
7475 canon24oc();
7476
7477 ret = d_complex_new_internal(klass,
7478 nth, 0,
7479 0, INT2FIX(0),
7480 rof, sg,
7481 ry, rm, rd,
7482 rh, rmin, rs,
7483 HAVE_CIVIL | HAVE_TIME);
7484 }
7485 else {
7486 VALUE nth;
7487 int ry, rm, rd, rh, rmin, rs, rjd, rjd2, ns;
7488
7489 if (!valid_civil_p(y, m, d, sg,
7490 &nth, &ry,
7491 &rm, &rd, &rjd,
7492 &ns))
7493 rb_raise(rb_eArgError, "invalid date");
7494 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7495 rb_raise(rb_eArgError, "invalid date");
7496 canon24oc();
7497
7498 rjd2 = jd_local_to_utc(rjd,
7499 time_to_df(rh, rmin, rs),
7500 rof);
7501
7502 ret = d_complex_new_internal(klass,
7503 nth, rjd2,
7504 0, INT2FIX(0),
7505 rof, sg,
7506 ry, rm, rd,
7507 rh, rmin, rs,
7508 HAVE_JD | HAVE_CIVIL | HAVE_TIME);
7509 }
7510 add_frac();
7511 return ret;
7512 }
7513
7514 /*
7515 * call-seq:
7516 * DateTime.commercial([cwyear=-4712[, cweek=1[, cwday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]]) -> datetime
7517 *
7518 * Creates a date-time object denoting the given week date.
7519 *
7520 * DateTime.commercial(2001) #=> #<DateTime: 2001-01-01T00:00:00+00:00 ...>
7521 * DateTime.commercial(2002) #=> #<DateTime: 2001-12-31T00:00:00+00:00 ...>
7522 * DateTime.commercial(2001,5,6,4,5,6,'+7')
7523 * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7524 */
7525 static VALUE
7526 datetime_s_commercial(int argc, VALUE *argv, VALUE klass)
7527 {
7528 VALUE vy, vw, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
7529 int w, d, h, min, s, rof;
7530 double sg;
7531
7532 rb_scan_args(argc, argv, "08", &vy, &vw, &vd, &vh, &vmin, &vs, &vof, &vsg);
7533
7534 y = INT2FIX(-4712);
7535 w = 1;
7536 d = 1;
7537
7538 h = min = s = 0;
7539 fr2 = INT2FIX(0);
7540 rof = 0;
7541 sg = DEFAULT_SG;
7542
7543 switch (argc) {
7544 case 8:
7545 val2sg(vsg, sg);
7546 case 7:
7547 val2off(vof, rof);
7548 case 6:
7549 num2int_with_frac(s, positive_inf);
7550 case 5:
7551 num2int_with_frac(min, 5);
7552 case 4:
7553 num2int_with_frac(h, 4);
7554 case 3:
7555 num2int_with_frac(d, 3);
7556 case 2:
7557 w = NUM2INT(vw);
7558 case 1:
7559 y = vy;
7560 }
7561
7562 {
7563 VALUE nth;
7564 int ry, rw, rd, rh, rmin, rs, rjd, rjd2, ns;
7565
7566 if (!valid_commercial_p(y, w, d, sg,
7567 &nth, &ry,
7568 &rw, &rd, &rjd,
7569 &ns))
7570 rb_raise(rb_eArgError, "invalid date");
7571 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7572 rb_raise(rb_eArgError, "invalid date");
7573 canon24oc();
7574
7575 rjd2 = jd_local_to_utc(rjd,
7576 time_to_df(rh, rmin, rs),
7577 rof);
7578
7579 ret = d_complex_new_internal(klass,
7580 nth, rjd2,
7581 0, INT2FIX(0),
7582 rof, sg,
7583 0, 0, 0,
7584 rh, rmin, rs,
7585 HAVE_JD | HAVE_TIME);
7586 }
7587 add_frac();
7588 return ret;
7589 }
7590
7591 #ifndef NDEBUG
7592 static VALUE
7593 datetime_s_weeknum(int argc, VALUE *argv, VALUE klass)
7594 {
7595 VALUE vy, vw, vd, vf, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
7596 int w, d, f, h, min, s, rof;
7597 double sg;
7598
7599 rb_scan_args(argc, argv, "09", &vy, &vw, &vd, &vf,
7600 &vh, &vmin, &vs, &vof, &vsg);
7601
7602 y = INT2FIX(-4712);
7603 w = 0;
7604 d = 1;
7605 f = 0;
7606
7607 h = min = s = 0;
7608 fr2 = INT2FIX(0);
7609 rof = 0;
7610 sg = DEFAULT_SG;
7611
7612 switch (argc) {
7613 case 9:
7614 val2sg(vsg, sg);
7615 case 8:
7616 val2off(vof, rof);
7617 case 7:
7618 num2int_with_frac(s, positive_inf);
7619 case 6:
7620 num2int_with_frac(min, 6);
7621 case 5:
7622 num2int_with_frac(h, 5);
7623 case 4:
7624 f = NUM2INT(vf);
7625 case 3:
7626 num2int_with_frac(d, 4);
7627 case 2:
7628 w = NUM2INT(vw);
7629 case 1:
7630 y = vy;
7631 }
7632
7633 {
7634 VALUE nth;
7635 int ry, rw, rd, rh, rmin, rs, rjd, rjd2, ns;
7636
7637 if (!valid_weeknum_p(y, w, d, f, sg,
7638 &nth, &ry,
7639 &rw, &rd, &rjd,
7640 &ns))
7641 rb_raise(rb_eArgError, "invalid date");
7642 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7643 rb_raise(rb_eArgError, "invalid date");
7644 canon24oc();
7645
7646 rjd2 = jd_local_to_utc(rjd,
7647 time_to_df(rh, rmin, rs),
7648 rof);
7649 ret = d_complex_new_internal(klass,
7650 nth, rjd2,
7651 0, INT2FIX(0),
7652 rof, sg,
7653 0, 0, 0,
7654 rh, rmin, rs,
7655 HAVE_JD | HAVE_TIME);
7656 }
7657 add_frac();
7658 return ret;
7659 }
7660
7661 static VALUE
7662 datetime_s_nth_kday(int argc, VALUE *argv, VALUE klass)
7663 {
7664 VALUE vy, vm, vn, vk, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
7665 int m, n, k, h, min, s, rof;
7666 double sg;
7667
7668 rb_scan_args(argc, argv, "09", &vy, &vm, &vn, &vk,
7669 &vh, &vmin, &vs, &vof, &vsg);
7670
7671 y = INT2FIX(-4712);
7672 m = 1;
7673 n = 1;
7674 k = 1;
7675
7676 h = min = s = 0;
7677 fr2 = INT2FIX(0);
7678 rof = 0;
7679 sg = DEFAULT_SG;
7680
7681 switch (argc) {
7682 case 9:
7683 val2sg(vsg, sg);
7684 case 8:
7685 val2off(vof, rof);
7686 case 7:
7687 num2int_with_frac(s, positive_inf);
7688 case 6:
7689 num2int_with_frac(min, 6);
7690 case 5:
7691 num2int_with_frac(h, 5);
7692 case 4:
7693 num2int_with_frac(k, 4);
7694 case 3:
7695 n = NUM2INT(vn);
7696 case 2:
7697 m = NUM2INT(vm);
7698 case 1:
7699 y = vy;
7700 }
7701
7702 {
7703 VALUE nth;
7704 int ry, rm, rn, rk, rh, rmin, rs, rjd, rjd2, ns;
7705
7706 if (!valid_nth_kday_p(y, m, n, k, sg,
7707 &nth, &ry,
7708 &rm, &rn, &rk, &rjd,
7709 &ns))
7710 rb_raise(rb_eArgError, "invalid date");
7711 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7712 rb_raise(rb_eArgError, "invalid date");
7713 canon24oc();
7714
7715 rjd2 = jd_local_to_utc(rjd,
7716 time_to_df(rh, rmin, rs),
7717 rof);
7718 ret = d_complex_new_internal(klass,
7719 nth, rjd2,
7720 0, INT2FIX(0),
7721 rof, sg,
7722 0, 0, 0,
7723 rh, rmin, rs,
7724 HAVE_JD | HAVE_TIME);
7725 }
7726 add_frac();
7727 return ret;
7728 }
7729 #endif
7730
7731 /*
7732 * call-seq:
7733 * DateTime.now([start=Date::ITALY]) -> datetime
7734 *
7735 * Creates a date-time object denoting the present time.
7736 *
7737 * DateTime.now #=> #<DateTime: 2011-06-11T21:20:44+09:00 ...>
7738 */
7739 static VALUE
7740 datetime_s_now(int argc, VALUE *argv, VALUE klass)
7741 {
7742 VALUE vsg, nth, ret;
7743 double sg;
7744 #ifdef HAVE_CLOCK_GETTIME
7745 struct timespec ts;
7746 #else
7747 struct timeval tv;
7748 #endif
7749 time_t sec;
7750 struct tm tm;
7751 long sf, of;
7752 int y, ry, m, d, h, min, s;
7753
7754 rb_scan_args(argc, argv, "01", &vsg);
7755
7756 if (argc < 1)
7757 sg = DEFAULT_SG;
7758 else
7759 sg = NUM2DBL(vsg);
7760
7761 #ifdef HAVE_CLOCK_GETTIME
7762 if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
7763 rb_sys_fail("clock_gettime");
7764 sec = ts.tv_sec;
7765 #else
7766 if (gettimeofday(&tv, NULL) == -1)
7767 rb_sys_fail("gettimeofday");
7768 sec = tv.tv_sec;
7769 #endif
7770 tzset();
7771 if (!localtime_r(&sec, &tm))
7772 rb_sys_fail("localtime");
7773
7774 y = tm.tm_year + 1900;
7775 m = tm.tm_mon + 1;
7776 d = tm.tm_mday;
7777 h = tm.tm_hour;
7778 min = tm.tm_min;
7779 s = tm.tm_sec;
7780 if (s == 60)
7781 s = 59;
7782 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
7783 of = tm.tm_gmtoff;
7784 #elif defined(HAVE_VAR_TIMEZONE)
7785 #ifdef HAVE_VAR_ALTZONE
7786 of = (long)-((tm.tm_isdst > 0) ? altzone : timezone);
7787 #else
7788 of = (long)-timezone;
7789 if (tm.tm_isdst) {
7790 time_t sec2;
7791
7792 tm.tm_isdst = 0;
7793 sec2 = mktime(&tm);
7794 of += (long)difftime(sec2, sec);
7795 }
7796 #endif
7797 #elif defined(HAVE_TIMEGM)
7798 {
7799 time_t sec2;
7800
7801 sec2 = timegm(&tm);
7802 of = (long)difftime(sec2, sec);
7803 }
7804 #else
7805 {
7806 struct tm tm2;
7807 time_t sec2;
7808
7809 if (!gmtime_r(&sec, &tm2))
7810 rb_sys_fail("gmtime");
7811 tm2.tm_isdst = tm.tm_isdst;
7812 sec2 = mktime(&tm2);
7813 of = (long)difftime(sec, sec2);
7814 }
7815 #endif
7816 #ifdef HAVE_CLOCK_GETTIME
7817 sf = ts.tv_nsec;
7818 #else
7819 sf = tv.tv_usec * 1000;
7820 #endif
7821
7822 if (of < -DAY_IN_SECONDS || of > DAY_IN_SECONDS) {
7823 of = 0;
7824 rb_warning("invalid offset is ignored");
7825 }
7826
7827 decode_year(INT2FIX(y), -1, &nth, &ry);
7828
7829 ret = d_complex_new_internal(klass,
7830 nth, 0,
7831 0, LONG2NUM(sf),
7832 (int)of, GREGORIAN,
7833 ry, m, d,
7834 h, min, s,
7835 HAVE_CIVIL | HAVE_TIME);
7836 {
7837 get_d1(ret);
7838 set_sg(dat, sg);
7839 }
7840 return ret;
7841 }
7842
7843 static VALUE
7844 dt_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
7845 {
7846 VALUE jd, sf, t;
7847 int df, of;
7848
7849 if (!c_valid_start_p(NUM2DBL(sg))) {
7850 sg = INT2FIX(DEFAULT_SG);
7851 rb_warning("invalid start is ignored");
7852 }
7853
7854 if (NIL_P(hash))
7855 rb_raise(rb_eArgError, "invalid date");
7856
7857 if (NIL_P(ref_hash("jd")) &&
7858 NIL_P(ref_hash("yday")) &&
7859 !NIL_P(ref_hash("year")) &&
7860 !NIL_P(ref_hash("mon")) &&
7861 !NIL_P(ref_hash("mday"))) {
7862 jd = rt__valid_civil_p(ref_hash("year"),
7863 ref_hash("mon"),
7864 ref_hash("mday"), sg);
7865
7866 if (NIL_P(ref_hash("hour")))
7867 set_hash("hour", INT2FIX(0));
7868 if (NIL_P(ref_hash("min")))
7869 set_hash("min", INT2FIX(0));
7870 if (NIL_P(ref_hash("sec")))
7871 set_hash("sec", INT2FIX(0));
7872 else if (f_eqeq_p(ref_hash("sec"), INT2FIX(60)))
7873 set_hash("sec", INT2FIX(59));
7874 }
7875 else {
7876 hash = rt_rewrite_frags(hash);
7877 hash = rt_complete_frags(klass, hash);
7878 jd = rt__valid_date_frags_p(hash, sg);
7879 }
7880
7881 if (NIL_P(jd))
7882 rb_raise(rb_eArgError, "invalid date");
7883
7884 {
7885 int rh, rmin, rs;
7886
7887 if (!c_valid_time_p(NUM2INT(ref_hash("hour")),
7888 NUM2INT(ref_hash("min")),
7889 NUM2INT(ref_hash("sec")),
7890 &rh, &rmin, &rs))
7891 rb_raise(rb_eArgError, "invalid date");
7892
7893 df = time_to_df(rh, rmin, rs);
7894 }
7895
7896 t = ref_hash("sec_fraction");
7897 if (NIL_P(t))
7898 sf = INT2FIX(0);
7899 else
7900 sf = sec_to_ns(t);
7901
7902 t = ref_hash("offset");
7903 if (NIL_P(t))
7904 of = 0;
7905 else {
7906 of = NUM2INT(t);
7907 if (of < -DAY_IN_SECONDS || of > DAY_IN_SECONDS) {
7908 of = 0;
7909 rb_warning("invalid offset is ignored");
7910 }
7911 }
7912 {
7913 VALUE nth;
7914 int rjd, rjd2;
7915
7916 decode_jd(jd, &nth, &rjd);
7917 rjd2 = jd_local_to_utc(rjd, df, of);
7918 df = df_local_to_utc(df, of);
7919
7920 return d_complex_new_internal(klass,
7921 nth, rjd2,
7922 df, sf,
7923 of, NUM2DBL(sg),
7924 0, 0, 0,
7925 0, 0, 0,
7926 HAVE_JD | HAVE_DF);
7927 }
7928 }
7929
7930 /*
7931 * call-seq:
7932 * DateTime._strptime(string[, format='%FT%T%z']) -> hash
7933 *
7934 * Parses the given representation of date and time with the given
7935 * template, and returns a hash of parsed elements. _strptime does
7936 * not support specification of flags and width unlike strftime.
7937 *
7938 * See also strptime(3) and strftime.
7939 */
7940 static VALUE
7941 datetime_s__strptime(int argc, VALUE *argv, VALUE klass)
7942 {
7943 return date_s__strptime_internal(argc, argv, klass, "%FT%T%z");
7944 }
7945
7946 /*
7947 * call-seq:
7948 * DateTime.strptime([string='-4712-01-01T00:00:00+00:00'[, format='%FT%T%z'[ ,start=ITALY]]]) -> datetime
7949 *
7950 * Parses the given representation of date and time with the given
7951 * template, and creates a date object. strptime does not support
7952 * specification of flags and width unlike strftime.
7953 *
7954 * DateTime.strptime('2001-02-03T04:05:06+07:00', '%Y-%m-%dT%H:%M:%S%z')
7955 * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7956 * DateTime.strptime('03-02-2001 04:05:06 PM', '%d-%m-%Y %I:%M:%S %p')
7957 * #=> #<DateTime: 2001-02-03T16:05:06+00:00 ...>
7958 * DateTime.strptime('2001-W05-6T04:05:06+07:00', '%G-W%V-%uT%H:%M:%S%z')
7959 * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7960 * DateTime.strptime('2001 04 6 04 05 06 +7', '%Y %U %w %H %M %S %z')
7961 * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7962 * DateTime.strptime('2001 05 6 04 05 06 +7', '%Y %W %u %H %M %S %z')
7963 * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7964 * DateTime.strptime('-1', '%s')
7965 * #=> #<DateTime: 1969-12-31T23:59:59+00:00 ...>
7966 * DateTime.strptime('-1000', '%Q')
7967 * #=> #<DateTime: 1969-12-31T23:59:59+00:00 ...>
7968 * DateTime.strptime('sat3feb014pm+7', '%a%d%b%y%H%p%z')
7969 * #=> #<DateTime: 2001-02-03T16:00:00+07:00 ...>
7970 *
7971 * See also strptime(3) and strftime.
7972 */
7973 static VALUE
7974 datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
7975 {
7976 VALUE str, fmt, sg;
7977
7978 rb_scan_args(argc, argv, "03", &str, &fmt, &sg);
7979
7980 switch (argc) {
7981 case 0:
7982 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
7983 case 1:
7984 fmt = rb_str_new2("%FT%T%z");
7985 case 2:
7986 sg = INT2FIX(DEFAULT_SG);
7987 }
7988
7989 {
7990 VALUE argv2[2], hash;
7991
7992 argv2[0] = str;
7993 argv2[1] = fmt;
7994 hash = date_s__strptime(2, argv2, klass);
7995 return dt_new_by_frags(klass, hash, sg);
7996 }
7997 }
7998
7999 /*
8000 * call-seq:
8001 * DateTime.parse(string='-4712-01-01T00:00:00+00:00'[, comp=true[, start=ITALY]]) -> datetime
8002 *
8003 * Parses the given representation of date and time, and creates a
8004 * date object. This method does not function as a validator.
8005 *
8006 * If the optional second argument is true and the detected year is in
8007 * the range "00" to "99", makes it full.
8008 *
8009 * DateTime.parse('2001-02-03T04:05:06+07:00')
8010 * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8011 * DateTime.parse('20010203T040506+0700')
8012 * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8013 * DateTime.parse('3rd Feb 2001 04:05:06 PM')
8014 * #=> #<DateTime: 2001-02-03T16:05:06+00:00 ...>
8015 */
8016 static VALUE
8017 datetime_s_parse(int argc, VALUE *argv, VALUE klass)
8018 {
8019 VALUE str, comp, sg;
8020
8021 rb_scan_args(argc, argv, "03", &str, &comp, &sg);
8022
8023 switch (argc) {
8024 case 0:
8025 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
8026 case 1:
8027 comp = Qtrue;
8028 case 2:
8029 sg = INT2FIX(DEFAULT_SG);
8030 }
8031
8032 {
8033 VALUE argv2[2], hash;
8034
8035 argv2[0] = str;
8036 argv2[1] = comp;
8037 hash = date_s__parse(2, argv2, klass);
8038 return dt_new_by_frags(klass, hash, sg);
8039 }
8040 }
8041
8042 /*
8043 * call-seq:
8044 * DateTime.iso8601(string='-4712-01-01T00:00:00+00:00'[, start=ITALY]) -> datetime
8045 *
8046 * Creates a new Date object by parsing from a string according to
8047 * some typical ISO 8601 formats.
8048 *
8049 * DateTime.iso8601('2001-02-03T04:05:06+07:00')
8050 * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8051 * DateTime.iso8601('20010203T040506+0700')
8052 * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8053 * DateTime.iso8601('2001-W05-6T04:05:06+07:00')
8054 * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8055 */
8056 static VALUE
8057 datetime_s_iso8601(int argc, VALUE *argv, VALUE klass)
8058 {
8059 VALUE str, sg;
8060
8061 rb_scan_args(argc, argv, "02", &str, &sg);
8062
8063 switch (argc) {
8064 case 0:
8065 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
8066 case 1:
8067 sg = INT2FIX(DEFAULT_SG);
8068 }
8069
8070 {
8071 VALUE hash = date_s__iso8601(klass, str);
8072 return dt_new_by_frags(klass, hash, sg);
8073 }
8074 }
8075
8076 /*
8077 * call-seq:
8078 * DateTime.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=ITALY]) -> datetime
8079 *
8080 * Creates a new Date object by parsing from a string according to
8081 * some typical RFC 3339 formats.
8082 *
8083 * DateTime.rfc3339('2001-02-03T04:05:06+07:00')
8084 * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8085 */
8086 static VALUE
8087 datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass)
8088 {
8089 VALUE str, sg;
8090
8091 rb_scan_args(argc, argv, "02", &str, &sg);
8092
8093 switch (argc) {
8094 case 0:
8095 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
8096 case 1:
8097 sg = INT2FIX(DEFAULT_SG);
8098 }
8099
8100 {
8101 VALUE hash = date_s__rfc3339(klass, str);
8102 return dt_new_by_frags(klass, hash, sg);
8103 }
8104 }
8105
8106 /*
8107 * call-seq:
8108 * DateTime.xmlschema(string='-4712-01-01T00:00:00+00:00'[, start=ITALY]) -> datetime
8109 *
8110 * Creates a new Date object by parsing from a string according to
8111 * some typical XML Schema formats.
8112 *
8113 * DateTime.xmlschema('2001-02-03T04:05:06+07:00')
8114 * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8115 */
8116 static VALUE
8117 datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass)
8118 {
8119 VALUE str, sg;
8120
8121 rb_scan_args(argc, argv, "02", &str, &sg);
8122
8123 switch (argc) {
8124 case 0:
8125 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
8126 case 1:
8127 sg = INT2FIX(DEFAULT_SG);
8128 }
8129
8130 {
8131 VALUE hash = date_s__xmlschema(klass, str);
8132 return dt_new_by_frags(klass, hash, sg);
8133 }
8134 }
8135
8136 /*
8137 * call-seq:
8138 * DateTime.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=ITALY]) -> datetime
8139 * DateTime.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=ITALY]) -> datetime
8140 *
8141 * Creates a new Date object by parsing from a string according to
8142 * some typical RFC 2822 formats.
8143 *
8144 * DateTime.rfc2822('Sat, 3 Feb 2001 04:05:06 +0700')
8145 * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8146 */
8147 static VALUE
8148 datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
8149 {
8150 VALUE str, sg;
8151
8152 rb_scan_args(argc, argv, "02", &str, &sg);
8153
8154 switch (argc) {
8155 case 0:
8156 str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000");
8157 case 1:
8158 sg = INT2FIX(DEFAULT_SG);
8159 }
8160
8161 {
8162 VALUE hash = date_s__rfc2822(klass, str);
8163 return dt_new_by_frags(klass, hash, sg);
8164 }
8165 }
8166
8167 /*
8168 * call-seq:
8169 * DateTime.httpdate(string='Mon, 01 Jan -4712 00:00:00 GMT'[, start=ITALY]) -> datetime
8170 *
8171 * Creates a new Date object by parsing from a string according to
8172 * some RFC 2616 format.
8173 *
8174 * DateTime.httpdate('Sat, 03 Feb 2001 04:05:06 GMT')
8175 * #=> #<DateTime: 2001-02-03T04:05:06+00:00 ...>
8176 */
8177 static VALUE
8178 datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
8179 {
8180 VALUE str, sg;
8181
8182 rb_scan_args(argc, argv, "02", &str, &sg);
8183
8184 switch (argc) {
8185 case 0:
8186 str = rb_str_new2("Mon, 01 Jan -4712 00:00:00 GMT");
8187 case 1:
8188 sg = INT2FIX(DEFAULT_SG);
8189 }
8190
8191 {
8192 VALUE hash = date_s__httpdate(klass, str);
8193 return dt_new_by_frags(klass, hash, sg);
8194 }
8195 }
8196
8197 /*
8198 * call-seq:
8199 * DateTime.jisx0301(string='-4712-01-01T00:00:00+00:00'[, start=ITALY]) -> datetime
8200 *
8201 * Creates a new Date object by parsing from a string according to
8202 * some typical JIS X 0301 formats.
8203 *
8204 * DateTime.jisx0301('H13.02.03T04:05:06+07:00')
8205 * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8206 */
8207 static VALUE
8208 datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass)
8209 {
8210 VALUE str, sg;
8211
8212 rb_scan_args(argc, argv, "02", &str, &sg);
8213
8214 switch (argc) {
8215 case 0:
8216 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
8217 case 1:
8218 sg = INT2FIX(DEFAULT_SG);
8219 }
8220
8221 {
8222 VALUE hash = date_s__jisx0301(klass, str);
8223 return dt_new_by_frags(klass, hash, sg);
8224 }
8225 }
8226
8227 /*
8228 * call-seq:
8229 * dt.to_s -> string
8230 *
8231 * Returns a string in an ISO 8601 format (This method doesn't use the
8232 * expanded representations).
8233 *
8234 * DateTime.new(2001,2,3,4,5,6,'-7').to_s
8235 * #=> "2001-02-03T04:05:06-07:00"
8236 */
8237 static VALUE
8238 dt_lite_to_s(VALUE self)
8239 {
8240 return strftimev("%Y-%m-%dT%H:%M:%S%:z", self, set_tmx);
8241 }
8242
8243 /*
8244 * call-seq:
8245 * dt.strftime([format='%FT%T%:z']) -> string
8246 *
8247 * Formats date according to the directives in the given format
8248 * string.
8249 * The directives begins with a percent (%) character.
8250 * Any text not listed as a directive will be passed through to the
8251 * output string.
8252 *
8253 * The directive consists of a percent (%) character,
8254 * zero or more flags, optional minimum field width,
8255 * optional modifier and a conversion specifier
8256 * as follows.
8257 *
8258 * %<flags><width><modifier><conversion>
8259 *
8260 * Flags:
8261 * - don't pad a numerical output.
8262 * _ use spaces for padding.
8263 * 0 use zeros for padding.
8264 * ^ upcase the result string.
8265 * # change case.
8266 * : use colons for %z.
8267 *
8268 * The minimum field width specifies the minimum width.
8269 *
8270 * The modifier is "E" and "O".
8271 * They are ignored.
8272 *
8273 * Format directives:
8274 *
8275 * Date (Year, Month, Day):
8276 * %Y - Year with century (can be negative, 4 digits at least)
8277 * -0001, 0000, 1995, 2009, 14292, etc.
8278 * %C - year / 100 (round down. 20 in 2009)
8279 * %y - year % 100 (00..99)
8280 *
8281 * %m - Month of the year, zero-padded (01..12)
8282 * %_m blank-padded ( 1..12)
8283 * %-m no-padded (1..12)
8284 * %B - The full month name (``January'')
8285 * %^B uppercased (``JANUARY'')
8286 * %b - The abbreviated month name (``Jan'')
8287 * %^b uppercased (``JAN'')
8288 * %h - Equivalent to %b
8289 *
8290 * %d - Day of the month, zero-padded (01..31)
8291 * %-d no-padded (1..31)
8292 * %e - Day of the month, blank-padded ( 1..31)
8293 *
8294 * %j - Day of the year (001..366)
8295 *
8296 * Time (Hour, Minute, Second, Subsecond):
8297 * %H - Hour of the day, 24-hour clock, zero-padded (00..23)
8298 * %k - Hour of the day, 24-hour clock, blank-padded ( 0..23)
8299 * %I - Hour of the day, 12-hour clock, zero-padded (01..12)
8300 * %l - Hour of the day, 12-hour clock, blank-padded ( 1..12)
8301 * %P - Meridian indicator, lowercase (``am'' or ``pm'')
8302 * %p - Meridian indicator, uppercase (``AM'' or ``PM'')
8303 *
8304 * %M - Minute of the hour (00..59)
8305 *
8306 * %S - Second of the minute (00..59)
8307 *
8308 * %L - Millisecond of the second (000..999)
8309 * %N - Fractional seconds digits, default is 9 digits (nanosecond)
8310 * %3N millisecond (3 digits) %15N femtosecond (15 digits)
8311 * %6N microsecond (6 digits) %18N attosecond (18 digits)
8312 * %9N nanosecond (9 digits) %21N zeptosecond (21 digits)
8313 * %12N picosecond (12 digits) %24N yoctosecond (24 digits)
8314 *
8315 * Time zone:
8316 * %z - Time zone as hour and minute offset from UTC (e.g. +0900)
8317 * %:z - hour and minute offset from UTC with a colon (e.g. +09:00)
8318 * %::z - hour, minute and second offset from UTC (e.g. +09:00:00)
8319 * %:::z - hour, minute and second offset from UTC
8320 * (e.g. +09, +09:30, +09:30:30)
8321 * %Z - Time zone abbreviation name or something similar information.
8322 *
8323 * Weekday:
8324 * %A - The full weekday name (``Sunday'')
8325 * %^A uppercased (``SUNDAY'')
8326 * %a - The abbreviated name (``Sun'')
8327 * %^a uppercased (``SUN'')
8328 * %u - Day of the week (Monday is 1, 1..7)
8329 * %w - Day of the week (Sunday is 0, 0..6)
8330 *
8331 * ISO 8601 week-based year and week number:
8332 * The week 1 of YYYY starts with a Monday and includes YYYY-01-04.
8333 * The days in the year before the first week are in the last week of
8334 * the previous year.
8335 * %G - The week-based year
8336 * %g - The last 2 digits of the week-based year (00..99)
8337 * %V - Week number of the week-based year (01..53)
8338 *
8339 * Week number:
8340 * The week 1 of YYYY starts with a Sunday or Monday (according to %U
8341 * or %W). The days in the year before the first week are in week 0.
8342 * %U - Week number of the year. The week starts with Sunday. (00..53)
8343 * %W - Week number of the year. The week starts with Monday. (00..53)
8344 *
8345 * Seconds since the Unix Epoch:
8346 * %s - Number of seconds since 1970-01-01 00:00:00 UTC.
8347 * %Q - Number of milliseconds since 1970-01-01 00:00:00 UTC.
8348 *
8349 * Literal string:
8350 * %n - Newline character (\n)
8351 * %t - Tab character (\t)
8352 * %% - Literal ``%'' character
8353 *
8354 * Combination:
8355 * %c - date and time (%a %b %e %T %Y)
8356 * %D - Date (%m/%d/%y)
8357 * %F - The ISO 8601 date format (%Y-%m-%d)
8358 * %v - VMS date (%e-%b-%Y)
8359 * %x - Same as %D
8360 * %X - Same as %T
8361 * %r - 12-hour time (%I:%M:%S %p)
8362 * %R - 24-hour time (%H:%M)
8363 * %T - 24-hour time (%H:%M:%S)
8364 * %+ - date(1) (%a %b %e %H:%M:%S %Z %Y)
8365 *
8366 * This method is similar to strftime() function defined in ISO C and POSIX.
8367 * Several directives (%a, %A, %b, %B, %c, %p, %r, %x, %X, %E*, %O* and %Z)
8368 * are locale dependent in the function.
8369 * However this method is locale independent.
8370 * So, the result may differ even if a same format string is used in other
8371 * systems such as C.
8372 * It is good practice to avoid %x and %X because there are corresponding
8373 * locale independent representations, %D and %T.
8374 *
8375 * Examples:
8376 *
8377 * d = DateTime.new(2007,11,19,8,37,48,"-06:00")
8378 * #=> #<DateTime: 2007-11-19T08:37:48-0600 ...>
8379 * d.strftime("Printed on %m/%d/%Y") #=> "Printed on 11/19/2007"
8380 * d.strftime("at %I:%M%p") #=> "at 08:37AM"
8381 *
8382 * Various ISO 8601 formats:
8383 * %Y%m%d => 20071119 Calendar date (basic)
8384 * %F => 2007-11-19 Calendar date (extended)
8385 * %Y-%m => 2007-11 Calendar date, reduced accuracy, specific month
8386 * %Y => 2007 Calendar date, reduced accuracy, specific year
8387 * %C => 20 Calendar date, reduced accuracy, specific century
8388 * %Y%j => 2007323 Ordinal date (basic)
8389 * %Y-%j => 2007-323 Ordinal date (extended)
8390 * %GW%V%u => 2007W471 Week date (basic)
8391 * %G-W%V-%u => 2007-W47-1 Week date (extended)
8392 * %GW%V => 2007W47 Week date, reduced accuracy, specific week (basic)
8393 * %G-W%V => 2007-W47 Week date, reduced accuracy, specific week (extended)
8394 * %H%M%S => 083748 Local time (basic)
8395 * %T => 08:37:48 Local time (extended)
8396 * %H%M => 0837 Local time, reduced accuracy, specific minute (basic)
8397 * %H:%M => 08:37 Local time, reduced accuracy, specific minute (extended)
8398 * %H => 08 Local time, reduced accuracy, specific hour
8399 * %H%M%S,%L => 083748,000 Local time with decimal fraction, comma as decimal sign (basic)
8400 * %T,%L => 08:37:48,000 Local time with decimal fraction, comma as decimal sign (extended)
8401 * %H%M%S.%L => 083748.000 Local time with decimal fraction, full stop as decimal sign (basic)
8402 * %T.%L => 08:37:48.000 Local time with decimal fraction, full stop as decimal sign (extended)
8403 * %H%M%S%z => 083748-0600 Local time and the difference from UTC (basic)
8404 * %T%:z => 08:37:48-06:00 Local time and the difference from UTC (extended)
8405 * %Y%m%dT%H%M%S%z => 20071119T083748-0600 Date and time of day for calendar date (basic)
8406 * %FT%T%:z => 2007-11-19T08:37:48-06:00 Date and time of day for calendar date (extended)
8407 * %Y%jT%H%M%S%z => 2007323T083748-0600 Date and time of day for ordinal date (basic)
8408 * %Y-%jT%T%:z => 2007-323T08:37:48-06:00 Date and time of day for ordinal date (extended)
8409 * %GW%V%uT%H%M%S%z => 2007W471T083748-0600 Date and time of day for week date (basic)
8410 * %G-W%V-%uT%T%:z => 2007-W47-1T08:37:48-06:00 Date and time of day for week date (extended)
8411 * %Y%m%dT%H%M => 20071119T0837 Calendar date and local time (basic)
8412 * %FT%R => 2007-11-19T08:37 Calendar date and local time (extended)
8413 * %Y%jT%H%MZ => 2007323T0837Z Ordinal date and UTC of day (basic)
8414 * %Y-%jT%RZ => 2007-323T08:37Z Ordinal date and UTC of day (extended)
8415 * %GW%V%uT%H%M%z => 2007W471T0837-0600 Week date and local time and difference from UTC (basic)
8416 * %G-W%V-%uT%R%:z => 2007-W47-1T08:37-06:00 Week date and local time and difference from UTC (extended)
8417 *
8418 * See also strftime(3) and strptime.
8419 */
8420 static VALUE
8421 dt_lite_strftime(int argc, VALUE *argv, VALUE self)
8422 {
8423 return date_strftime_internal(argc, argv, self,
8424 "%Y-%m-%dT%H:%M:%S%:z", set_tmx);
8425 }
8426
8427 static VALUE
8428 iso8601_timediv(VALUE self, VALUE n)
8429 {
8430 VALUE fmt;
8431
8432 n = to_integer(n);
8433 fmt = rb_usascii_str_new2("T%H:%M:%S");
8434 if (f_gt_p(n, INT2FIX(0))) {
8435 VALUE argv[3];
8436
8437 get_d1(self);
8438
8439 argv[0] = rb_usascii_str_new2(".%0*d");
8440 argv[1] = n;
8441 argv[2] = f_round(f_quo(m_sf_in_sec(dat),
8442 f_quo(INT2FIX(1),
8443 f_expt(INT2FIX(10), n))));
8444 rb_str_append(fmt, rb_f_sprintf(3, argv));
8445 }
8446 rb_str_append(fmt, rb_usascii_str_new2("%:z"));
8447 return strftimev(RSTRING_PTR(fmt), self, set_tmx);
8448 }
8449
8450 /*
8451 * call-seq:
8452 * dt.iso8601([n=0]) -> string
8453 * dt.xmlschema([n=0]) -> string
8454 *
8455 * This method is equivalent to strftime('%FT%T'). The optional
8456 * argument n is length of fractional seconds.
8457 *
8458 * DateTime.parse('2001-02-03T04:05:06.123456789+07:00').iso8601(9)
8459 * #=> "2001-02-03T04:05:06.123456789+07:00"
8460 */
8461 static VALUE
8462 dt_lite_iso8601(int argc, VALUE *argv, VALUE self)
8463 {
8464 VALUE n;
8465
8466 rb_scan_args(argc, argv, "01", &n);
8467
8468 if (argc < 1)
8469 n = INT2FIX(0);
8470
8471 return f_add(strftimev("%Y-%m-%d", self, set_tmx),
8472 iso8601_timediv(self, n));
8473 }
8474
8475 /*
8476 * call-seq:
8477 * dt.rfc3339([n=0]) -> string
8478 *
8479 * This method is equivalent to strftime('%FT%T'). The optional
8480 * argument n is length of fractional seconds.
8481 *
8482 * DateTime.parse('2001-02-03T04:05:06.123456789+07:00').rfc3339(9)
8483 * #=> "2001-02-03T04:05:06.123456789+07:00"
8484 */
8485 static VALUE
8486 dt_lite_rfc3339(int argc, VALUE *argv, VALUE self)
8487 {
8488 return dt_lite_iso8601(argc, argv, self);
8489 }
8490
8491 /*
8492 * call-seq:
8493 * dt.jisx0301([n=0]) -> string
8494 *
8495 * Returns a string in a JIS X 0301 format. The optional argument n
8496 * is length of fractional seconds.
8497 *
8498 * DateTime.parse('2001-02-03T04:05:06.123456789+07:00').jisx0301(9)
8499 * #=> "H13.02.03T04:05:06.123456789+07:00"
8500 */
8501 static VALUE
8502 dt_lite_jisx0301(int argc, VALUE *argv, VALUE self)
8503 {
8504 VALUE n, s;
8505
8506 rb_scan_args(argc, argv, "01", &n);
8507
8508 if (argc < 1)
8509 n = INT2FIX(0);
8510
8511 {
8512 get_d1(self);
8513 s = jisx0301_date(m_real_local_jd(dat),
8514 m_real_year(dat));
8515 return rb_str_append(strftimev(RSTRING_PTR(s), self, set_tmx),
8516 iso8601_timediv(self, n));
8517 }
8518 }
8519
8520 /* conversions */
8521
8522 #define f_getlocal(x) rb_funcall(x, rb_intern("getlocal"), 0)
8523 #define f_subsec(x) rb_funcall(x, rb_intern("subsec"), 0)
8524 #define f_utc_offset(x) rb_funcall(x, rb_intern("utc_offset"), 0)
8525 #define f_local3(x,y,m,d) rb_funcall(x, rb_intern("local"), 3, y, m, d)
8526 #define f_utc6(x,y,m,d,h,min,s) rb_funcall(x, rb_intern("utc"), 6,\
8527 y, m, d, h, min, s)
8528
8529 /*
8530 * call-seq:
8531 * t.to_time -> time
8532 *
8533 * Returns a copy of self as local mode.
8534 */
8535 static VALUE
8536 time_to_time(VALUE self)
8537 {
8538 return f_getlocal(self);
8539 }
8540
8541 /*
8542 * call-seq:
8543 * t.to_date -> date
8544 *
8545 * Returns a Date object which denotes self.
8546 */
8547 static VALUE
8548 time_to_date(VALUE self)
8549 {
8550 VALUE y, nth, ret;
8551 int ry, m, d;
8552
8553 y = f_year(self);
8554 m = FIX2INT(f_mon(self));
8555 d = FIX2INT(f_mday(self));
8556
8557 decode_year(y, -1, &nth, &ry);
8558
8559 ret = d_simple_new_internal(cDate,
8560 nth, 0,
8561 GREGORIAN,
8562 ry, m, d,
8563 HAVE_CIVIL);
8564 {
8565 get_d1(ret);
8566 set_sg(dat, DEFAULT_SG);
8567 }
8568 return ret;
8569 }
8570
8571 /*
8572 * call-seq:
8573 * t.to_datetime -> datetime
8574 *
8575 * Returns a DateTime object which denotes self.
8576 */
8577 static VALUE
8578 time_to_datetime(VALUE self)
8579 {
8580 VALUE y, sf, nth, ret;
8581 int ry, m, d, h, min, s, of;
8582
8583 y = f_year(self);
8584 m = FIX2INT(f_mon(self));
8585 d = FIX2INT(f_mday(self));
8586
8587 h = FIX2INT(f_hour(self));
8588 min = FIX2INT(f_min(self));
8589 s = FIX2INT(f_sec(self));
8590 if (s == 60)
8591 s = 59;
8592
8593 sf = sec_to_ns(f_subsec(self));
8594 of = FIX2INT(f_utc_offset(self));
8595
8596 decode_year(y, -1, &nth, &ry);
8597
8598 ret = d_complex_new_internal(cDateTime,
8599 nth, 0,
8600 0, sf,
8601 of, DEFAULT_SG,
8602 ry, m, d,
8603 h, min, s,
8604 HAVE_CIVIL | HAVE_TIME);
8605 {
8606 get_d1(ret);
8607 set_sg(dat, DEFAULT_SG);
8608 }
8609 return ret;
8610 }
8611
8612 /*
8613 * call-seq:
8614 * d.to_time -> time
8615 *
8616 * Returns a Time object which denotes self.
8617 */
8618 static VALUE
8619 date_to_time(VALUE self)
8620 {
8621 get_d1(self);
8622
8623 return f_local3(rb_cTime,
8624 m_real_year(dat),
8625 INT2FIX(m_mon(dat)),
8626 INT2FIX(m_mday(dat)));
8627 }
8628
8629 /*
8630 * call-seq:
8631 * d.to_date -> self
8632 *
8633 * Returns self;
8634 */
8635 static VALUE
8636 date_to_date(VALUE self)
8637 {
8638 return self;
8639 }
8640
8641 /*
8642 * call-seq:
8643 * d.to_datetime -> datetime
8644 *
8645 * Returns a DateTime object which denotes self.
8646 */
8647 static VALUE
8648 date_to_datetime(VALUE self)
8649 {
8650 get_d1a(self);
8651
8652 if (simple_dat_p(adat)) {
8653 VALUE new = d_lite_s_alloc_simple(cDateTime);
8654 {
8655 get_d1b(new);
8656 bdat->s = adat->s;
8657 return new;
8658 }
8659 }
8660 else {
8661 VALUE new = d_lite_s_alloc_complex(cDateTime);
8662 {
8663 get_d1b(new);
8664 bdat->c = adat->c;
8665 bdat->c.df = 0;
8666 bdat->c.sf = INT2FIX(0);
8667 #ifndef USE_PACK
8668 bdat->c.hour = 0;
8669 bdat->c.min = 0;
8670 bdat->c.sec = 0;
8671 #else
8672 bdat->c.pc = PACK5(EX_MON(adat->c.pc), EX_MDAY(adat->c.pc),
8673 0, 0, 0);
8674 bdat->c.flags |= HAVE_DF | HAVE_TIME;
8675 #endif
8676 return new;
8677 }
8678 }
8679 }
8680
8681 /*
8682 * call-seq:
8683 * dt.to_time -> time
8684 *
8685 * Returns a Time object which denotes self.
8686 */
8687 static VALUE
8688 datetime_to_time(VALUE self)
8689 {
8690 volatile VALUE dup = dup_obj_with_new_offset(self, 0);
8691 {
8692 VALUE t;
8693
8694 get_d1(dup);
8695
8696 t = f_utc6(rb_cTime,
8697 m_real_year(dat),
8698 INT2FIX(m_mon(dat)),
8699 INT2FIX(m_mday(dat)),
8700 INT2FIX(m_hour(dat)),
8701 INT2FIX(m_min(dat)),
8702 f_add(INT2FIX(m_sec(dat)),
8703 m_sf_in_sec(dat)));
8704 return f_getlocal(t);
8705 }
8706 }
8707
8708 /*
8709 * call-seq:
8710 * dt.to_date -> date
8711 *
8712 * Returns a Date object which denotes self.
8713 */
8714 static VALUE
8715 datetime_to_date(VALUE self)
8716 {
8717 get_d1a(self);
8718
8719 if (simple_dat_p(adat)) {
8720 VALUE new = d_lite_s_alloc_simple(cDate);
8721 {
8722 get_d1b(new);
8723 bdat->s = adat->s;
8724 bdat->s.jd = m_local_jd(adat);
8725 return new;
8726 }
8727 }
8728 else {
8729 VALUE new = d_lite_s_alloc_simple(cDate);
8730 {
8731 get_d1b(new);
8732 copy_complex_to_simple(&bdat->s, &adat->c)
8733 bdat->s.jd = m_local_jd(adat);
8734 bdat->s.flags &= ~(HAVE_DF | HAVE_TIME | COMPLEX_DAT);
8735 return new;
8736 }
8737 }
8738 }
8739
8740 /*
8741 * call-seq:
8742 * dt.to_datetime -> self
8743 *
8744 * Returns self.
8745 */
8746 static VALUE
8747 datetime_to_datetime(VALUE self)
8748 {
8749 return self;
8750 }
8751
8752 #ifndef NDEBUG
8753 /* tests */
8754
8755 #define MIN_YEAR -4713
8756 #define MAX_YEAR 1000000
8757 #define MIN_JD -327
8758 #define MAX_JD 366963925
8759
8760 static int
8761 test_civil(int from, int to, double sg)
8762 {
8763 int j;
8764
8765 fprintf(stderr, "test_civil: %d...%d (%d) - %.0f\n",
8766 from, to, to - from, sg);
8767 for (j = from; j <= to; j++) {
8768 int y, m, d, rj, ns;
8769
8770 c_jd_to_civil(j, sg, &y, &m, &d);
8771 c_civil_to_jd(y, m, d, sg, &rj, &ns);
8772 if (j != rj) {
8773 fprintf(stderr, "%d != %d\n", j, rj);
8774 return 0;
8775 }
8776 }
8777 return 1;
8778 }
8779
8780 static VALUE
8781 date_s_test_civil(VALUE klass)
8782 {
8783 if (!test_civil(MIN_JD, MIN_JD + 366, GREGORIAN))
8784 return Qfalse;
8785 if (!test_civil(2305814, 2598007, GREGORIAN))
8786 return Qfalse;
8787 if (!test_civil(MAX_JD - 366, MAX_JD, GREGORIAN))
8788 return Qfalse;
8789
8790 if (!test_civil(MIN_JD, MIN_JD + 366, ITALY))
8791 return Qfalse;
8792 if (!test_civil(2305814, 2598007, ITALY))
8793 return Qfalse;
8794 if (!test_civil(MAX_JD - 366, MAX_JD, ITALY))
8795 return Qfalse;
8796
8797 return Qtrue;
8798 }
8799
8800 static int
8801 test_ordinal(int from, int to, double sg)
8802 {
8803 int j;
8804
8805 fprintf(stderr, "test_ordinal: %d...%d (%d) - %.0f\n",
8806 from, to, to - from, sg);
8807 for (j = from; j <= to; j++) {
8808 int y, d, rj, ns;
8809
8810 c_jd_to_ordinal(j, sg, &y, &d);
8811 c_ordinal_to_jd(y, d, sg, &rj, &ns);
8812 if (j != rj) {
8813 fprintf(stderr, "%d != %d\n", j, rj);
8814 return 0;
8815 }
8816 }
8817 return 1;
8818 }
8819
8820 static VALUE
8821 date_s_test_ordinal(VALUE klass)
8822 {
8823 if (!test_ordinal(MIN_JD, MIN_JD + 366, GREGORIAN))
8824 return Qfalse;
8825 if (!test_ordinal(2305814, 2598007, GREGORIAN))
8826 return Qfalse;
8827 if (!test_ordinal(MAX_JD - 366, MAX_JD, GREGORIAN))
8828 return Qfalse;
8829
8830 if (!test_ordinal(MIN_JD, MIN_JD + 366, ITALY))
8831 return Qfalse;
8832 if (!test_ordinal(2305814, 2598007, ITALY))
8833 return Qfalse;
8834 if (!test_ordinal(MAX_JD - 366, MAX_JD, ITALY))
8835 return Qfalse;
8836
8837 return Qtrue;
8838 }
8839
8840 static int
8841 test_commercial(int from, int to, double sg)
8842 {
8843 int j;
8844
8845 fprintf(stderr, "test_commercial: %d...%d (%d) - %.0f\n",
8846 from, to, to - from, sg);
8847 for (j = from; j <= to; j++) {
8848 int y, w, d, rj, ns;
8849
8850 c_jd_to_commercial(j, sg, &y, &w, &d);
8851 c_commercial_to_jd(y, w, d, sg, &rj, &ns);
8852 if (j != rj) {
8853 fprintf(stderr, "%d != %d\n", j, rj);
8854 return 0;
8855 }
8856 }
8857 return 1;
8858 }
8859
8860 static VALUE
8861 date_s_test_commercial(VALUE klass)
8862 {
8863 if (!test_commercial(MIN_JD, MIN_JD + 366, GREGORIAN))
8864 return Qfalse;
8865 if (!test_commercial(2305814, 2598007, GREGORIAN))
8866 return Qfalse;
8867 if (!test_commercial(MAX_JD - 366, MAX_JD, GREGORIAN))
8868 return Qfalse;
8869
8870 if (!test_commercial(MIN_JD, MIN_JD + 366, ITALY))
8871 return Qfalse;
8872 if (!test_commercial(2305814, 2598007, ITALY))
8873 return Qfalse;
8874 if (!test_commercial(MAX_JD - 366, MAX_JD, ITALY))
8875 return Qfalse;
8876
8877 return Qtrue;
8878 }
8879
8880 static int
8881 test_weeknum(int from, int to, int f, double sg)
8882 {
8883 int j;
8884
8885 fprintf(stderr, "test_weeknum: %d...%d (%d) - %.0f\n",
8886 from, to, to - from, sg);
8887 for (j = from; j <= to; j++) {
8888 int y, w, d, rj, ns;
8889
8890 c_jd_to_weeknum(j, f, sg, &y, &w, &d);
8891 c_weeknum_to_jd(y, w, d, f, sg, &rj, &ns);
8892 if (j != rj) {
8893 fprintf(stderr, "%d != %d\n", j, rj);
8894 return 0;
8895 }
8896 }
8897 return 1;
8898 }
8899
8900 static VALUE
8901 date_s_test_weeknum(VALUE klass)
8902 {
8903 int f;
8904
8905 for (f = 0; f <= 1; f++) {
8906 if (!test_weeknum(MIN_JD, MIN_JD + 366, f, GREGORIAN))
8907 return Qfalse;
8908 if (!test_weeknum(2305814, 2598007, f, GREGORIAN))
8909 return Qfalse;
8910 if (!test_weeknum(MAX_JD - 366, MAX_JD, f, GREGORIAN))
8911 return Qfalse;
8912
8913 if (!test_weeknum(MIN_JD, MIN_JD + 366, f, ITALY))
8914 return Qfalse;
8915 if (!test_weeknum(2305814, 2598007, f, ITALY))
8916 return Qfalse;
8917 if (!test_weeknum(MAX_JD - 366, MAX_JD, f, ITALY))
8918 return Qfalse;
8919 }
8920
8921 return Qtrue;
8922 }
8923
8924 static int
8925 test_nth_kday(int from, int to, double sg)
8926 {
8927 int j;
8928
8929 fprintf(stderr, "test_nth_kday: %d...%d (%d) - %.0f\n",
8930 from, to, to - from, sg);
8931 for (j = from; j <= to; j++) {
8932 int y, m, n, k, rj, ns;
8933
8934 c_jd_to_nth_kday(j, sg, &y, &m, &n, &k);
8935 c_nth_kday_to_jd(y, m, n, k, sg, &rj, &ns);
8936 if (j != rj) {
8937 fprintf(stderr, "%d != %d\n", j, rj);
8938 return 0;
8939 }
8940 }
8941 return 1;
8942 }
8943
8944 static VALUE
8945 date_s_test_nth_kday(VALUE klass)
8946 {
8947 if (!test_nth_kday(MIN_JD, MIN_JD + 366, GREGORIAN))
8948 return Qfalse;
8949 if (!test_nth_kday(2305814, 2598007, GREGORIAN))
8950 return Qfalse;
8951 if (!test_nth_kday(MAX_JD - 366, MAX_JD, GREGORIAN))
8952 return Qfalse;
8953
8954 if (!test_nth_kday(MIN_JD, MIN_JD + 366, ITALY))
8955 return Qfalse;
8956 if (!test_nth_kday(2305814, 2598007, ITALY))
8957 return Qfalse;
8958 if (!test_nth_kday(MAX_JD - 366, MAX_JD, ITALY))
8959 return Qfalse;
8960
8961 return Qtrue;
8962 }
8963
8964 static int
8965 test_unit_v2v(VALUE i,
8966 VALUE (* conv1)(VALUE),
8967 VALUE (* conv2)(VALUE))
8968 {
8969 VALUE c, o;
8970 c = (*conv1)(i);
8971 o = (*conv2)(c);
8972 return f_eqeq_p(o, i);
8973 }
8974
8975 static int
8976 test_unit_v2v_iter2(VALUE (* conv1)(VALUE),
8977 VALUE (* conv2)(VALUE))
8978 {
8979 if (!test_unit_v2v(INT2FIX(0), conv1, conv2))
8980 return 0;
8981 if (!test_unit_v2v(INT2FIX(1), conv1, conv2))
8982 return 0;
8983 if (!test_unit_v2v(INT2FIX(2), conv1, conv2))
8984 return 0;
8985 if (!test_unit_v2v(INT2FIX(3), conv1, conv2))
8986 return 0;
8987 if (!test_unit_v2v(INT2FIX(11), conv1, conv2))
8988 return 0;
8989 if (!test_unit_v2v(INT2FIX(65535), conv1, conv2))
8990 return 0;
8991 if (!test_unit_v2v(INT2FIX(1073741823), conv1, conv2))
8992 return 0;
8993 if (!test_unit_v2v(INT2NUM(1073741824), conv1, conv2))
8994 return 0;
8995 if (!test_unit_v2v(rb_rational_new2(INT2FIX(0), INT2FIX(1)), conv1, conv2))
8996 return 0;
8997 if (!test_unit_v2v(rb_rational_new2(INT2FIX(1), INT2FIX(1)), conv1, conv2))
8998 return 0;
8999 if (!test_unit_v2v(rb_rational_new2(INT2FIX(1), INT2FIX(2)), conv1, conv2))
9000 return 0;
9001 if (!test_unit_v2v(rb_rational_new2(INT2FIX(2), INT2FIX(3)), conv1, conv2))
9002 return 0;
9003 return 1;
9004 }
9005
9006 static int
9007 test_unit_v2v_iter(VALUE (* conv1)(VALUE),
9008 VALUE (* conv2)(VALUE))
9009 {
9010 if (!test_unit_v2v_iter2(conv1, conv2))
9011 return 0;
9012 if (!test_unit_v2v_iter2(conv2, conv1))
9013 return 0;
9014 return 1;
9015 }
9016
9017 static VALUE
9018 date_s_test_unit_conv(VALUE klass)
9019 {
9020 if (!test_unit_v2v_iter(sec_to_day, day_to_sec))
9021 return Qfalse;
9022 if (!test_unit_v2v_iter(ms_to_sec, sec_to_ms))
9023 return Qfalse;
9024 if (!test_unit_v2v_iter(ns_to_day, day_to_ns))
9025 return Qfalse;
9026 if (!test_unit_v2v_iter(ns_to_sec, sec_to_ns))
9027 return Qfalse;
9028 return Qtrue;
9029 }
9030
9031 static VALUE
9032 date_s_test_all(VALUE klass)
9033 {
9034 if (date_s_test_civil(klass) == Qfalse)
9035 return Qfalse;
9036 if (date_s_test_ordinal(klass) == Qfalse)
9037 return Qfalse;
9038 if (date_s_test_commercial(klass) == Qfalse)
9039 return Qfalse;
9040 if (date_s_test_weeknum(klass) == Qfalse)
9041 return Qfalse;
9042 if (date_s_test_nth_kday(klass) == Qfalse)
9043 return Qfalse;
9044 if (date_s_test_unit_conv(klass) == Qfalse)
9045 return Qfalse;
9046 return Qtrue;
9047 }
9048 #endif
9049
9050 static const char *monthnames[] = {
9051 NULL,
9052 "January", "February", "March",
9053 "April", "May", "June",
9054 "July", "August", "September",
9055 "October", "November", "December"
9056 };
9057
9058 static const char *abbr_monthnames[] = {
9059 NULL,
9060 "Jan", "Feb", "Mar", "Apr",
9061 "May", "Jun", "Jul", "Aug",
9062 "Sep", "Oct", "Nov", "Dec"
9063 };
9064
9065 static const char *daynames[] = {
9066 "Sunday", "Monday", "Tuesday", "Wednesday",
9067 "Thursday", "Friday", "Saturday"
9068 };
9069
9070 static const char *abbr_daynames[] = {
9071 "Sun", "Mon", "Tue", "Wed",
9072 "Thu", "Fri", "Sat"
9073 };
9074
9075 static VALUE
9076 mk_ary_of_str(long len, const char *a[])
9077 {
9078 VALUE o;
9079 long i;
9080
9081 o = rb_ary_new2(len);
9082 for (i = 0; i < len; i++) {
9083 VALUE e;
9084
9085 if (!a[i])
9086 e = Qnil;
9087 else {
9088 e = rb_usascii_str_new2(a[i]);
9089 rb_obj_freeze(e);
9090 }
9091 rb_ary_push(o, e);
9092 }
9093 rb_obj_freeze(o);
9094 return o;
9095 }
9096
9097 void
9098 Init_date_core(void)
9099 {
9100 #undef rb_intern
9101 #define rb_intern(str) rb_intern_const(str)
9102
9103 assert(fprintf(stderr, "assert() is now active\n"));
9104
9105 id_cmp = rb_intern("<=>");
9106 id_le_p = rb_intern("<=");
9107 id_ge_p = rb_intern(">=");
9108 id_eqeq_p = rb_intern("==");
9109
9110 half_days_in_day = rb_rational_new2(INT2FIX(1), INT2FIX(2));
9111
9112 #if (LONG_MAX / DAY_IN_SECONDS) > SECOND_IN_NANOSECONDS
9113 day_in_nanoseconds = LONG2NUM((long)DAY_IN_SECONDS *
9114 SECOND_IN_NANOSECONDS);
9115 #elif defined HAVE_LONG_LONG
9116 day_in_nanoseconds = LL2NUM((LONG_LONG)DAY_IN_SECONDS *
9117 SECOND_IN_NANOSECONDS);
9118 #else
9119 day_in_nanoseconds = f_mul(INT2FIX(DAY_IN_SECONDS),
9120 INT2FIX(SECOND_IN_NANOSECONDS));
9121 #endif
9122
9123 rb_gc_register_mark_object(half_days_in_day);
9124 rb_gc_register_mark_object(day_in_nanoseconds);
9125
9126 positive_inf = +INFINITY;
9127 negative_inf = -INFINITY;
9128
9129 /*
9130 * date and datetime class - Tadayoshi Funaba 1998-2011
9131 *
9132 * 'date' provides two classes Date and DateTime.
9133 *
9134 * == Terms and definitions
9135 *
9136 * Some terms and definitions are based on ISO 8601 and JIS X 0301.
9137 *
9138 * === calendar date
9139 *
9140 * The calendar date is a particular day of a calendar year,
9141 * identified by its ordinal number within a calendar month within
9142 * that year.
9143 *
9144 * In those classes, this is so-called "civil".
9145 *
9146 * === ordinal date
9147 *
9148 * The ordinal date is a particular day of a calendar year identified
9149 * by its ordinal number within the year.
9150 *
9151 * In those classes, this is so-called "ordinal".
9152 *
9153 * === week date
9154 *
9155 * The week date is a date identified by calendar week and day numbers.
9156 *
9157 * The calendar week is a seven day period within a calendar year,
9158 * starting on a Monday and identified by its ordinal number within
9159 * the year; the first calendar week of the year is the one that
9160 * includes the first Thursday of that year. In the Gregorian
9161 * calendar, this is equivalent to the week which includes January 4.
9162 *
9163 * In those classes, this so-called "commercial".
9164 *
9165 * === julian day number
9166 *
9167 * The Julian day number is in elapsed days since noon (Greenwich mean
9168 * time) on January 1, 4713 BCE (in the Julian calendar).
9169 *
9170 * In this document, the astronomical Julian day number is same as the
9171 * original Julian day number. And the chronological Julian day
9172 * number is a variation of the Julian day number. Its days begin at
9173 * midnight on local time.
9174 *
9175 * In this document, when the term "Julian day number" simply appears,
9176 * it just refers to "chronological Julian day number", not the
9177 * original.
9178 *
9179 * In those classes, those are so-called "ajd" and "jd".
9180 *
9181 * === modified julian day number
9182 *
9183 * The modified Julian day number is in elapsed days since midnight
9184 * (Coordinated universal time) on November 17, 1858 CE (in the
9185 * Gregorian calendar).
9186 *
9187 * In this document, the astronomical modified Julian day number is
9188 * same as the original modified Julian day number. And the
9189 * chronological modified Julian day number is a variation of the
9190 * modified Julian day number. Its days begin at midnight on local
9191 * time.
9192 *
9193 * In this document, when the term "modified Julian day number" simply
9194 * appears, it just refers to "chronological modified Julian day
9195 * number", not the original.
9196 *
9197 * In those classes, this is so-called "mjd".
9198 *
9199 *
9200 * == Date
9201 *
9202 * A subclass of Object includes Comparable module, easily handles
9203 * date.
9204 *
9205 * Date object is created with Date::new, Date::jd, Date::ordinal,
9206 * Date::commercial, Date::parse, Date::strptime, Date::today,
9207 * Time#to_date or etc.
9208 *
9209 * require 'date'
9210 *
9211 * Date.new(2001,2,3) #=> #<Date: 2001-02-03 ...>
9212 * Date.jd(2451944) #=> #<Date: 2001-02-03 ...>
9213 * Date.ordinal(2001,34) #=> #<Date: 2001-02-03 ...>
9214 * Date.commercial(2001,5,6) #=> #<Date: 2001-02-03 ...>
9215 * Date.parse('2001-02-03') #=> #<Date: 2001-02-03 ...>
9216 * Date.strptime('03-02-2001', '%d-%m-%Y')
9217 * #=> #<Date: 2001-02-03 ...>
9218 * Time.new(2001,2,3).to_date #=> #<Date: 2001-02-03 ...>
9219 *
9220 * All date objects are immutable; hence cannot modify themselves.
9221 *
9222 * The concept of this date object can be represented as a tuple
9223 * of the day count, the offset and the day of calendar reform.
9224 *
9225 * The day count denotes the absolute position of a temporal
9226 * dimension. The offset is relative adjustment, which determines
9227 * decoded local time with the day count. The day of calendar
9228 * reform denotes the start day of the new style. The old style
9229 * of the West is the Julian calendar which was adopted by
9230 * Caersar. The new style is the Gregorian calendar, which is the
9231 * current civil calendar of many countries.
9232 *
9233 * The day count is virtually the astronomical Julian day number.
9234 * The offset in this class is usually zero, and cannot be
9235 * specified directly.
9236 *
9237 * An optional argument the day of calendar reform (start) as a
9238 * Julian day number, which should be 2298874 to 2426355 or -/+oo.
9239 * The default value is Date::ITALY (2299161=1582-10-15). See
9240 * also sample/cal.rb.
9241 *
9242 * $ ruby sample/cal.rb -c it 10 1582
9243 * October 1582
9244 * S M Tu W Th F S
9245 * 1 2 3 4 15 16
9246 * 17 18 19 20 21 22 23
9247 * 24 25 26 27 28 29 30
9248 * 31
9249 *
9250 * $ ruby sample/cal.rb -c gb 9 1752
9251 * September 1752
9252 * S M Tu W Th F S
9253 * 1 2 14 15 16
9254 * 17 18 19 20 21 22 23
9255 * 24 25 26 27 28 29 30
9256 *
9257 * Date object has various methods. See each reference.
9258 *
9259 * d = Date.parse('3rd Feb 2001')
9260 * #=> #<Date: 2001-02-03 ...>
9261 * d.year #=> 2001
9262 * d.mon #=> 2
9263 * d.mday #=> 3
9264 * d.wday #=> 6
9265 * d += 1 #=> #<Date: 2001-02-04 ...>
9266 * d.strftime('%a %d %b %Y') #=> "Sun 04 Feb 2001"
9267 *
9268 *
9269 * == DateTime
9270 *
9271 * A subclass of Date easily handles date, hour, minute, second and
9272 * offset.
9273 *
9274 * DateTime does not consider any leapseconds, does not track
9275 * any summer time rules.
9276 *
9277 * DateTime object is created with DateTime::new, DateTime::jd,
9278 * DateTime::ordinal, DateTime::commercial, DateTime::parse,
9279 * DateTime::strptime, DateTime::now, Time#to_datetime or etc.
9280 *
9281 * require 'date'
9282 *
9283 * DateTime.new(2001,2,3,4,5,6)
9284 * #=> #<DateTime: 2001-02-03T04:05:06+00:00 ...>
9285 *
9286 * The last element of day, hour, minute or senond can be
9287 * fractional number. The fractional number's precision is assumed
9288 * at most nanosecond.
9289 *
9290 * DateTime.new(2001,2,3.5)
9291 * #=> #<DateTime: 2001-02-03T12:00:00+00:00 ...>
9292 *
9293 * An optional argument the offset indicates the difference
9294 * between the local time and UTC. For example, Rational(3,24)
9295 * represents ahead of 3 hours of UTC, Rational(-5,24) represents
9296 * behind of 5 hours of UTC. The offset should be -1 to +1, and
9297 * its precision is assumed at most second. The default value is
9298 * zero (equals to UTC).
9299 *
9300 * DateTime.new(2001,2,3,4,5,6,Rational(3,24))
9301 * #=> #<DateTime: 2001-02-03T04:05:06+03:00 ...>
9302 * also accepts string form.
9303 *
9304 * DateTime.new(2001,2,3,4,5,6,'+03:00')
9305 * #=> #<DateTime: 2001-02-03T04:05:06+03:00 ...>
9306 *
9307 * An optional argument the day of calendar reform (start) denotes
9308 * a Julian day number, which should be 2298874 to 2426355 or
9309 * -/+oo. The default value is Date::ITALY (2299161=1582-10-15).
9310 *
9311 * DateTime object has various methods. See each reference.
9312 *
9313 * d = DateTime.parse('3rd Feb 2001 04:05:06+03:30')
9314 * #=> #<DateTime: 2001-02-03T04:05:06+03:30 ...>
9315 * d.hour #=> 4
9316 * d.min #=> 5
9317 * d.sec #=> 6
9318 * d.offset #=> (7/48)
9319 * d.zone #=> "+03:30"
9320 * d += Rational('1.5')
9321 * #=> #<DateTime: 2001-02-04%16:05:06+03:30 ...>
9322 * d = d.new_offset('+09:00')
9323 * #=> #<DateTime: 2001-02-04%21:35:06+09:00 ...>
9324 * d.strftime('%I:%M:%S %p')
9325 * #=> "09:35:06 PM"
9326 * d > DateTime.new(1999)
9327 * #=> true
9328 */
9329 cDate = rb_define_class("Date", rb_cObject);
9330
9331 rb_include_module(cDate, rb_mComparable);
9332
9333 /* An array of stirng of full month name in English. The first
9334 * element is nil.
9335 */
9336 rb_define_const(cDate, "MONTHNAMES", mk_ary_of_str(13, monthnames));
9337
9338 /* An array of string of abbreviated month name in English. The
9339 * first element is nil.
9340 */
9341 rb_define_const(cDate, "ABBR_MONTHNAMES",
9342 mk_ary_of_str(13, abbr_monthnames));
9343
9344 /* An array of string of full name of days of the week in English.
9345 * The first is "Sunday".
9346 */
9347 rb_define_const(cDate, "DAYNAMES", mk_ary_of_str(7, daynames));
9348
9349 /* An array of string of abbreviated day name in English. The
9350 * first is "Sun".
9351 */
9352 rb_define_const(cDate, "ABBR_DAYNAMES", mk_ary_of_str(7, abbr_daynames));
9353
9354 /* The Julian day number of the day of calendar reform for Italy
9355 * and some catholic countries.
9356 */
9357 rb_define_const(cDate, "ITALY", INT2FIX(ITALY));
9358
9359 /* The Julian day number of the day of calendar reform for England
9360 * and her colonies.
9361 */
9362 rb_define_const(cDate, "ENGLAND", INT2FIX(ENGLAND));
9363
9364 /* The Julian day number of the day of calendar reform for the
9365 * proleptic Julian calendar
9366 */
9367 rb_define_const(cDate, "JULIAN", DBL2NUM(JULIAN));
9368
9369 /* The Julian day number of the day of calendar reform for the
9370 * proleptic Gregorian calendar
9371 */
9372 rb_define_const(cDate, "GREGORIAN", DBL2NUM(GREGORIAN));
9373
9374 rb_define_alloc_func(cDate, d_lite_s_alloc);
9375
9376 #ifndef NDEBUG
9377 #define de_define_private_method rb_define_private_method
9378 de_define_private_method(CLASS_OF(cDate), "_valid_jd?",
9379 date_s__valid_jd_p, -1);
9380 de_define_private_method(CLASS_OF(cDate), "_valid_ordinal?",
9381 date_s__valid_ordinal_p, -1);
9382 de_define_private_method(CLASS_OF(cDate), "_valid_civil?",
9383 date_s__valid_civil_p, -1);
9384 de_define_private_method(CLASS_OF(cDate), "_valid_date?",
9385 date_s__valid_civil_p, -1);
9386 de_define_private_method(CLASS_OF(cDate), "_valid_commercial?",
9387 date_s__valid_commercial_p, -1);
9388 de_define_private_method(CLASS_OF(cDate), "_valid_weeknum?",
9389 date_s__valid_weeknum_p, -1);
9390 de_define_private_method(CLASS_OF(cDate), "_valid_nth_kday?",
9391 date_s__valid_nth_kday_p, -1);
9392 #endif
9393
9394 rb_define_singleton_method(cDate, "valid_jd?", date_s_valid_jd_p, -1);
9395 rb_define_singleton_method(cDate, "valid_ordinal?",
9396 date_s_valid_ordinal_p, -1);
9397 rb_define_singleton_method(cDate, "valid_civil?", date_s_valid_civil_p, -1);
9398 rb_define_singleton_method(cDate, "valid_date?", date_s_valid_civil_p, -1);
9399 rb_define_singleton_method(cDate, "valid_commercial?",
9400 date_s_valid_commercial_p, -1);
9401
9402 #ifndef NDEBUG
9403 de_define_private_method(CLASS_OF(cDate), "valid_weeknum?",
9404 date_s_valid_weeknum_p, -1);
9405 de_define_private_method(CLASS_OF(cDate), "valid_nth_kday?",
9406 date_s_valid_nth_kday_p, -1);
9407 de_define_private_method(CLASS_OF(cDate), "zone_to_diff",
9408 date_s_zone_to_diff, 1);
9409 #endif
9410
9411 rb_define_singleton_method(cDate, "julian_leap?", date_s_julian_leap_p, 1);
9412 rb_define_singleton_method(cDate, "gregorian_leap?",
9413 date_s_gregorian_leap_p, 1);
9414 rb_define_singleton_method(cDate, "leap?",
9415 date_s_gregorian_leap_p, 1);
9416
9417 #ifndef NDEBUG
9418 #define de_define_singleton_method rb_define_singleton_method
9419 #define de_define_alias rb_define_alias
9420 de_define_singleton_method(cDate, "new!", date_s_new_bang, -1);
9421 de_define_alias(rb_singleton_class(cDate), "new_l!", "new");
9422 #endif
9423
9424 rb_define_singleton_method(cDate, "jd", date_s_jd, -1);
9425 rb_define_singleton_method(cDate, "ordinal", date_s_ordinal, -1);
9426 rb_define_singleton_method(cDate, "civil", date_s_civil, -1);
9427 rb_define_singleton_method(cDate, "new", date_s_civil, -1);
9428 rb_define_singleton_method(cDate, "commercial", date_s_commercial, -1);
9429
9430 #ifndef NDEBUG
9431 de_define_singleton_method(cDate, "weeknum", date_s_weeknum, -1);
9432 de_define_singleton_method(cDate, "nth_kday", date_s_nth_kday, -1);
9433 #endif
9434
9435 rb_define_singleton_method(cDate, "today", date_s_today, -1);
9436 rb_define_singleton_method(cDate, "_strptime", date_s__strptime, -1);
9437 rb_define_singleton_method(cDate, "strptime", date_s_strptime, -1);
9438 rb_define_singleton_method(cDate, "_parse", date_s__parse, -1);
9439 rb_define_singleton_method(cDate, "parse", date_s_parse, -1);
9440 rb_define_singleton_method(cDate, "_iso8601", date_s__iso8601, 1);
9441 rb_define_singleton_method(cDate, "iso8601", date_s_iso8601, -1);
9442 rb_define_singleton_method(cDate, "_rfc3339", date_s__rfc3339, 1);
9443 rb_define_singleton_method(cDate, "rfc3339", date_s_rfc3339, -1);
9444 rb_define_singleton_method(cDate, "_xmlschema", date_s__xmlschema, 1);
9445 rb_define_singleton_method(cDate, "xmlschema", date_s_xmlschema, -1);
9446 rb_define_singleton_method(cDate, "_rfc2822", date_s__rfc2822, 1);
9447 rb_define_singleton_method(cDate, "_rfc822", date_s__rfc2822, 1);
9448 rb_define_singleton_method(cDate, "rfc2822", date_s_rfc2822, -1);
9449 rb_define_singleton_method(cDate, "rfc822", date_s_rfc2822, -1);
9450 rb_define_singleton_method(cDate, "_httpdate", date_s__httpdate, 1);
9451 rb_define_singleton_method(cDate, "httpdate", date_s_httpdate, -1);
9452 rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, 1);
9453 rb_define_singleton_method(cDate, "jisx0301", date_s_jisx0301, -1);
9454
9455 #ifndef NDEBUG
9456 #define de_define_method rb_define_method
9457 de_define_method(cDate, "initialize", d_lite_initialize, -1);
9458 #endif
9459 rb_define_method(cDate, "initialize_copy", d_lite_initialize_copy, 1);
9460
9461 #ifndef NDEBUG
9462 de_define_method(cDate, "fill", d_lite_fill, 0);
9463 #endif
9464
9465 rb_define_method(cDate, "ajd", d_lite_ajd, 0);
9466 rb_define_method(cDate, "amjd", d_lite_amjd, 0);
9467 rb_define_method(cDate, "jd", d_lite_jd, 0);
9468 rb_define_method(cDate, "mjd", d_lite_mjd, 0);
9469 rb_define_method(cDate, "ld", d_lite_ld, 0);
9470
9471 rb_define_method(cDate, "year", d_lite_year, 0);
9472 rb_define_method(cDate, "yday", d_lite_yday, 0);
9473 rb_define_method(cDate, "mon", d_lite_mon, 0);
9474 rb_define_method(cDate, "month", d_lite_mon, 0);
9475 rb_define_method(cDate, "mday", d_lite_mday, 0);
9476 rb_define_method(cDate, "day", d_lite_mday, 0);
9477 rb_define_method(cDate, "day_fraction", d_lite_day_fraction, 0);
9478
9479 rb_define_method(cDate, "cwyear", d_lite_cwyear, 0);
9480 rb_define_method(cDate, "cweek", d_lite_cweek, 0);
9481 rb_define_method(cDate, "cwday", d_lite_cwday, 0);
9482
9483 #ifndef NDEBUG
9484 de_define_private_method(cDate, "wnum0", d_lite_wnum0, 0);
9485 de_define_private_method(cDate, "wnum1", d_lite_wnum1, 0);
9486 #endif
9487
9488 rb_define_method(cDate, "wday", d_lite_wday, 0);
9489
9490 rb_define_method(cDate, "sunday?", d_lite_sunday_p, 0);
9491 rb_define_method(cDate, "monday?", d_lite_monday_p, 0);
9492 rb_define_method(cDate, "tuesday?", d_lite_tuesday_p, 0);
9493 rb_define_method(cDate, "wednesday?", d_lite_wednesday_p, 0);
9494 rb_define_method(cDate, "thursday?", d_lite_thursday_p, 0);
9495 rb_define_method(cDate, "friday?", d_lite_friday_p, 0);
9496 rb_define_method(cDate, "saturday?", d_lite_saturday_p, 0);
9497
9498 #ifndef NDEBUG
9499 de_define_method(cDate, "nth_kday?", d_lite_nth_kday_p, 2);
9500 #endif
9501
9502 rb_define_private_method(cDate, "hour", d_lite_hour, 0);
9503 rb_define_private_method(cDate, "min", d_lite_min, 0);
9504 rb_define_private_method(cDate, "minute", d_lite_min, 0);
9505 rb_define_private_method(cDate, "sec", d_lite_sec, 0);
9506 rb_define_private_method(cDate, "second", d_lite_sec, 0);
9507 rb_define_private_method(cDate, "sec_fraction", d_lite_sec_fraction, 0);
9508 rb_define_private_method(cDate, "second_fraction", d_lite_sec_fraction, 0);
9509 rb_define_private_method(cDate, "offset", d_lite_offset, 0);
9510 rb_define_private_method(cDate, "zone", d_lite_zone, 0);
9511
9512 rb_define_method(cDate, "julian?", d_lite_julian_p, 0);
9513 rb_define_method(cDate, "gregorian?", d_lite_gregorian_p, 0);
9514 rb_define_method(cDate, "leap?", d_lite_leap_p, 0);
9515
9516 rb_define_method(cDate, "start", d_lite_start, 0);
9517 rb_define_method(cDate, "new_start", d_lite_new_start, -1);
9518 rb_define_method(cDate, "italy", d_lite_italy, 0);
9519 rb_define_method(cDate, "england", d_lite_england, 0);
9520 rb_define_method(cDate, "julian", d_lite_julian, 0);
9521 rb_define_method(cDate, "gregorian", d_lite_gregorian, 0);
9522
9523 rb_define_private_method(cDate, "new_offset", d_lite_new_offset, -1);
9524
9525 rb_define_method(cDate, "+", d_lite_plus, 1);
9526 rb_define_method(cDate, "-", d_lite_minus, 1);
9527
9528 rb_define_method(cDate, "next_day", d_lite_next_day, -1);
9529 rb_define_method(cDate, "prev_day", d_lite_prev_day, -1);
9530 rb_define_method(cDate, "next", d_lite_next, 0);
9531 rb_define_method(cDate, "succ", d_lite_next, 0);
9532
9533 rb_define_method(cDate, ">>", d_lite_rshift, 1);
9534 rb_define_method(cDate, "<<", d_lite_lshift, 1);
9535
9536 rb_define_method(cDate, "next_month", d_lite_next_month, -1);
9537 rb_define_method(cDate, "prev_month", d_lite_prev_month, -1);
9538 rb_define_method(cDate, "next_year", d_lite_next_year, -1);
9539 rb_define_method(cDate, "prev_year", d_lite_prev_year, -1);
9540
9541 rb_define_method(cDate, "step", d_lite_step, -1);
9542 rb_define_method(cDate, "upto", d_lite_upto, 1);
9543 rb_define_method(cDate, "downto", d_lite_downto, 1);
9544
9545 rb_define_method(cDate, "<=>", d_lite_cmp, 1);
9546 rb_define_method(cDate, "===", d_lite_equal, 1);
9547 rb_define_method(cDate, "eql?", d_lite_eql_p, 1);
9548 rb_define_method(cDate, "hash", d_lite_hash, 0);
9549
9550 rb_define_method(cDate, "to_s", d_lite_to_s, 0);
9551 #ifndef NDEBUG
9552 de_define_method(cDate, "inspect_raw", d_lite_inspect_raw, 0);
9553 #endif
9554 rb_define_method(cDate, "inspect", d_lite_inspect, 0);
9555
9556 rb_define_method(cDate, "strftime", d_lite_strftime, -1);
9557
9558 rb_define_method(cDate, "asctime", d_lite_asctime, 0);
9559 rb_define_method(cDate, "ctime", d_lite_asctime, 0);
9560 rb_define_method(cDate, "iso8601", d_lite_iso8601, 0);
9561 rb_define_method(cDate, "xmlschema", d_lite_iso8601, 0);
9562 rb_define_method(cDate, "rfc3339", d_lite_rfc3339, 0);
9563 rb_define_method(cDate, "rfc2822", d_lite_rfc2822, 0);
9564 rb_define_method(cDate, "rfc822", d_lite_rfc2822, 0);
9565 rb_define_method(cDate, "httpdate", d_lite_httpdate, 0);
9566 rb_define_method(cDate, "jisx0301", d_lite_jisx0301, 0);
9567
9568 #ifndef NDEBUG
9569 de_define_method(cDate, "marshal_dump_old", d_lite_marshal_dump_old, 0);
9570 #endif
9571 rb_define_method(cDate, "marshal_dump", d_lite_marshal_dump, 0);
9572 rb_define_method(cDate, "marshal_load", d_lite_marshal_load, 1);
9573 rb_define_singleton_method(cDate, "_load", date_s__load, 1);
9574
9575 /* datetime */
9576
9577 cDateTime = rb_define_class("DateTime", cDate);
9578
9579 rb_define_singleton_method(cDateTime, "jd", datetime_s_jd, -1);
9580 rb_define_singleton_method(cDateTime, "ordinal", datetime_s_ordinal, -1);
9581 rb_define_singleton_method(cDateTime, "civil", datetime_s_civil, -1);
9582 rb_define_singleton_method(cDateTime, "new", datetime_s_civil, -1);
9583 rb_define_singleton_method(cDateTime, "commercial",
9584 datetime_s_commercial, -1);
9585
9586 #ifndef NDEBUG
9587 de_define_singleton_method(cDateTime, "weeknum",
9588 datetime_s_weeknum, -1);
9589 de_define_singleton_method(cDateTime, "nth_kday",
9590 datetime_s_nth_kday, -1);
9591 #endif
9592
9593 rb_undef_method(CLASS_OF(cDateTime), "today");
9594
9595 rb_define_singleton_method(cDateTime, "now", datetime_s_now, -1);
9596 rb_define_singleton_method(cDateTime, "_strptime",
9597 datetime_s__strptime, -1);
9598 rb_define_singleton_method(cDateTime, "strptime",
9599 datetime_s_strptime, -1);
9600 rb_define_singleton_method(cDateTime, "parse",
9601 datetime_s_parse, -1);
9602 rb_define_singleton_method(cDateTime, "iso8601",
9603 datetime_s_iso8601, -1);
9604 rb_define_singleton_method(cDateTime, "rfc3339",
9605 datetime_s_rfc3339, -1);
9606 rb_define_singleton_method(cDateTime, "xmlschema",
9607 datetime_s_xmlschema, -1);
9608 rb_define_singleton_method(cDateTime, "rfc2822",
9609 datetime_s_rfc2822, -1);
9610 rb_define_singleton_method(cDateTime, "rfc822",
9611 datetime_s_rfc2822, -1);
9612 rb_define_singleton_method(cDateTime, "httpdate",
9613 datetime_s_httpdate, -1);
9614 rb_define_singleton_method(cDateTime, "jisx0301",
9615 datetime_s_jisx0301, -1);
9616
9617 #define f_public(m,s) rb_funcall(m, rb_intern("public"), 1,\
9618 ID2SYM(rb_intern(s)))
9619
9620 f_public(cDateTime, "hour");
9621 f_public(cDateTime, "min");
9622 f_public(cDateTime, "minute");
9623 f_public(cDateTime, "sec");
9624 f_public(cDateTime, "second");
9625 f_public(cDateTime, "sec_fraction");
9626 f_public(cDateTime, "second_fraction");
9627 f_public(cDateTime, "offset");
9628 f_public(cDateTime, "zone");
9629 f_public(cDateTime, "new_offset");
9630
9631 rb_define_method(cDateTime, "to_s", dt_lite_to_s, 0);
9632
9633 rb_define_method(cDateTime, "strftime", dt_lite_strftime, -1);
9634
9635 rb_define_method(cDateTime, "iso8601", dt_lite_iso8601, -1);
9636 rb_define_method(cDateTime, "xmlschema", dt_lite_iso8601, -1);
9637 rb_define_method(cDateTime, "rfc3339", dt_lite_rfc3339, -1);
9638 rb_define_method(cDateTime, "jisx0301", dt_lite_jisx0301, -1);
9639
9640 /* conversions */
9641
9642 rb_define_method(rb_cTime, "to_time", time_to_time, 0);
9643 rb_define_method(rb_cTime, "to_date", time_to_date, 0);
9644 rb_define_method(rb_cTime, "to_datetime", time_to_datetime, 0);
9645
9646 rb_define_method(cDate, "to_time", date_to_time, 0);
9647 rb_define_method(cDate, "to_date", date_to_date, 0);
9648 rb_define_method(cDate, "to_datetime", date_to_datetime, 0);
9649
9650 rb_define_method(cDateTime, "to_time", datetime_to_time, 0);
9651 rb_define_method(cDateTime, "to_date", datetime_to_date, 0);
9652 rb_define_method(cDateTime, "to_datetime", datetime_to_datetime, 0);
9653
9654 #ifndef NDEBUG
9655 /* tests */
9656
9657 de_define_singleton_method(cDate, "test_civil", date_s_test_civil, 0);
9658 de_define_singleton_method(cDate, "test_ordinal", date_s_test_ordinal, 0);
9659 de_define_singleton_method(cDate, "test_commercial",
9660 date_s_test_commercial, 0);
9661 de_define_singleton_method(cDate, "test_weeknum", date_s_test_weeknum, 0);
9662 de_define_singleton_method(cDate, "test_nth_kday", date_s_test_nth_kday, 0);
9663 de_define_singleton_method(cDate, "test_unit_conv",
9664 date_s_test_unit_conv, 0);
9665 de_define_singleton_method(cDate, "test_all", date_s_test_all, 0);
9666 #endif
9667 }
9668
9669 /*
9670 Local variables:
9671 c-file-style: "ruby"
9672 End:
9673 */
d_lite_gregorian_p
static VALUE d_lite_gregorian_p(VALUE self)
Definition: date_core.c:5267
FIXNUM_MAX
#define FIXNUM_MAX
RB_TYPE_P
#define RB_TYPE_P(obj, type)
date_s__rfc3339
static VALUE date_s__rfc3339(VALUE klass, VALUE str)
Definition: date_core.c:4432
m_of_in_day
static VALUE m_of_in_day(union DateData *x)
Definition: date_core.c:1627
datetime_s_ordinal
static VALUE datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:7353
RARRAY_PTR
RARRAY_PTR(q->result)[0]
datetime_s_rfc2822
static VALUE datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:8148
date_s__load
static VALUE date_s__load(VALUE klass, VALUE s)
Definition: date_core.c:7261
tmp
volatile VALUE tmp
Definition: tcltklib.c:10209
d_lite_strftime
static VALUE d_lite_strftime(int argc, VALUE *argv, VALUE self)
Definition: date_core.c:6990
datetime_s__strptime
static VALUE datetime_s__strptime(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:7941
c_julian_last_day_of_month
static int c_julian_last_day_of_month(int y, int m)
Definition: date_core.c:686
n
ssize_t n
Definition: bigdecimal.c:5655
day_in_nanoseconds
static VALUE day_in_nanoseconds
Definition: date_core.c:21
strftimev
static VALUE strftimev(const char *, VALUE, void(*)(VALUE, struct tmx *))
Definition: date_core.c:6997
d_lite_minus
static VALUE d_lite_minus(VALUE self, VALUE other)
Definition: date_core.c:5887
d_lite_initialize_copy
static VALUE d_lite_initialize_copy(VALUE copy, VALUE date)
Definition: date_core.c:4751
k_numeric_p
static VALUE k_numeric_p(VALUE x)
Definition: date_core.c:1986
datetime_s_jd
static VALUE datetime_s_jd(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:7285
MOD
#define MOD(n, d)
Definition: date_core.c:147
int
VP_EXPORT int
Definition: bigdecimal.c:5050
m_proleptic_julian_p
static int m_proleptic_julian_p(union DateData *x)
Definition: date_core.c:1671
d_lite_amjd
static VALUE d_lite_amjd(VALUE self)
Definition: date_core.c:4824
f_jd
#define f_jd(x)
Definition: date_core.c:134
d_lite_sec_fraction
static VALUE d_lite_sec_fraction(VALUE self)
Definition: date_core.c:5205
tmx_m_secs
static VALUE tmx_m_secs(union DateData *x)
Definition: date_core.c:6685
gettimeofday
int gettimeofday(struct timeval *, struct timezone *)
Definition: win32.c:4013
half_days_in_day
static VALUE half_days_in_day
Definition: date_core.c:21
day_to_sec
static VALUE day_to_sec(VALUE d)
Definition: date_core.c:995
rb_enc_copy
void rb_enc_copy(VALUE obj1, VALUE obj2)
Definition: encoding.c:856
tmx
Definition: date_tmx.h:24
m_zone
static VALUE m_zone(union DateData *x)
Definition: date_core.c:1960
date_to_date
static VALUE date_to_date(VALUE self)
Definition: date_core.c:8636
m_real_local_jd
static VALUE m_real_local_jd(union DateData *x)
Definition: date_core.c:1461
tmx::funcs
struct tmx_funcs * funcs
Definition: date_tmx.h:26
strlen
size_t strlen(const char *)
date_s__httpdate
static VALUE date_s__httpdate(VALUE klass, VALUE str)
Definition: date_core.c:4558
OBJ_INFECT
#define OBJ_INFECT(x, s)
d_lite_cwday
static VALUE d_lite_cwday(VALUE self)
Definition: date_core.c:5000
k_rational_p
static VALUE k_rational_p(VALUE x)
Definition: date_core.c:1992
rb_obj_classname
const char * rb_obj_classname(VALUE)
Definition: variable.c:396
get_d1
#define get_d1(x)
Definition: date_core.c:284
d_lite_leap_p
static VALUE d_lite_leap_p(VALUE self)
Definition: date_core.c:5283
m_real_jd
static VALUE m_real_jd(union DateData *x)
Definition: date_core.c:1434
p
Win32OLEIDispatch * p
Definition: win32ole.c:786
f_floor
#define f_floor(x)
Definition: date_core.c:37
canonicalize_jd
#define canonicalize_jd(_nth, _jd)
Definition: date_core.c:1107
FL_TEST
#define FL_TEST(x, f)
max
static int max(int a, int b)
Definition: strftime.c:141
rb_check_trusted
#define rb_check_trusted(obj)
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1497
m_julian_p
static int m_julian_p(union DateData *x)
Definition: date_core.c:1644
rt__valid_weeknum_p
static VALUE rt__valid_weeknum_p(VALUE y, VALUE w, VALUE d, VALUE f, VALUE sg)
Definition: date_core.c:4014
c_valid_civil_p
static int c_valid_civil_p(int, int, int, double, int *, int *, int *, int *)
Definition: date_core.c:738
d_lite_jd
static VALUE d_lite_jd(VALUE)
Definition: date_core.c:4841
FL_EXIVAR
#define FL_EXIVAR
del_hash
#define del_hash(k)
Definition: date_core.c:3681
f_sec
#define f_sec(x)
Definition: date_core.c:141
FL_SET
#define FL_SET(x, f)
datetime_s_xmlschema
static VALUE datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:8117
ComplexDateData::flags
unsigned flags
Definition: date_core.c:257
Data_Make_Struct
#define Data_Make_Struct(klass, type, mark, free, sval)
simple_dat_p
#define simple_dat_p(x)
Definition: date_core.c:160
DateData::c
struct ComplexDateData c
Definition: date_core.c:281
PACK5
#define PACK5(m, d, h, min, s)
Definition: date_core.c:209
to_integer
static VALUE to_integer(VALUE x)
Definition: date_core.c:3129
d_lite_offset
static VALUE d_lite_offset(VALUE self)
Definition: date_core.c:5220
func
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:108
rb_usascii_str_new2
#define rb_usascii_str_new2
d_lite_tuesday_p
static VALUE d_lite_tuesday_p(VALUE self)
Definition: date_core.c:5070
c_julian_leap_p
static int c_julian_leap_p(int y)
Definition: date_core.c:674
abbr_monthnames
static const char * abbr_monthnames[]
Definition: date_core.c:9058
EX_MDAY
#define EX_MDAY(x)
Definition: date_core.c:206
d_lite_next
static VALUE d_lite_next(VALUE self)
Definition: date_core.c:5948
d_lite_upto
static VALUE d_lite_upto(VALUE self, VALUE max)
Definition: date_core.c:6150
datetime_s_iso8601
static VALUE datetime_s_iso8601(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:8057
get_c_jd
static void get_c_jd(union DateData *x)
Definition: date_core.c:1224
c_find_ldom
static int c_find_ldom(int y, int m, double sg, int *rjd, int *ns)
Definition: date_core.c:465
i
ssize_t i
Definition: bigdecimal.c:5655
m_min
static int m_min(union DateData *x)
Definition: date_core.c:1912
date_s_httpdate
static VALUE date_s_httpdate(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:4574
d_lite_equal
static VALUE d_lite_equal(VALUE self, VALUE other)
Definition: date_core.c:6416
ComplexDateData::pc
unsigned pc
Definition: date_core.c:274
m_wnum1
static int m_wnum1(union DateData *x)
Definition: date_core.c:1891
rb_check_frozen
#define rb_check_frozen(obj)
rb_cTime
RUBY_EXTERN VALUE rb_cTime
Definition: ripper.y:1460
ComplexDateData::sf
VALUE sf
Definition: date_core.c:261
f_ge_p
static VALUE f_ge_p(VALUE x, VALUE y)
Definition: date_core.c:89
CM_PERIOD_JCY
#define CM_PERIOD_JCY
Definition: date_core.c:180
equal_gen
static VALUE equal_gen(VALUE self, VALUE other)
Definition: date_core.c:6387
RFLOAT_VALUE
#define RFLOAT_VALUE(v)
ruby.h
d_lite_lshift
static VALUE d_lite_lshift(VALUE self, VALUE other)
Definition: date_core.c:6015
ret
int ret
Definition: tcltklib.c:280
rb_define_private_method
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1356
DIV
#define DIV(n, d)
Definition: date_core.c:146
m_hour
static int m_hour(union DateData *x)
Definition: date_core.c:1897
d_lite_mon
static VALUE d_lite_mon(VALUE self)
Definition: date_core.c:4921
date_s_rfc2822
static VALUE date_s_rfc2822(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:4532
date_s_iso8601
static VALUE date_s_iso8601(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:4406
a
Real * a
Definition: bigdecimal.c:1182
rb_obj_freeze
VALUE rb_obj_freeze(VALUE)
Definition: object.c:989
dt_new_by_frags
static VALUE dt_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
Definition: date_core.c:7844
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:511
s_virtual_sg
static double s_virtual_sg(union DateData *x)
Definition: date_core.c:1075
val2sg
#define val2sg(vsg, dsg)
Definition: date_core.c:3240
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
jisx0301_date
static VALUE jisx0301_date(VALUE jd, VALUE y)
Definition: date_core.c:7081
d_lite_s_alloc_complex
static VALUE d_lite_s_alloc_complex(VALUE klass)
Definition: date_core.c:3009
EX_MON
#define EX_MON(x)
Definition: date_core.c:207
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:822
rt__valid_commercial_p
static VALUE rt__valid_commercial_p(VALUE y, VALUE w, VALUE d, VALUE sg)
Definition: date_core.c:3999
d_lite_new_offset
static VALUE d_lite_new_offset(int argc, VALUE *argv, VALUE self)
Definition: date_core.c:5471
SimpleDateData::flags
unsigned flags
Definition: date_core.c:234
TYPE
#define TYPE(x)
dt_lite_strftime
static VALUE dt_lite_strftime(int argc, VALUE *argv, VALUE self)
Definition: date_core.c:8421
RSTRING_PTR
#define RSTRING_PTR(str)
d_lite_cmp
static VALUE d_lite_cmp(VALUE, VALUE)
Definition: date_core.c:6272
CLASS_OF
#define CLASS_OF(v)
NIL_P
NIL_P(eventloop_thread)
Definition: tcltklib.c:4068
f_kind_of_p
static VALUE f_kind_of_p(VALUE x, VALUE c)
Definition: date_core.c:1968
decode_offset
#define decode_offset(of, s, h, m)
Definition: date_core.c:1941
T_ARRAY
#define T_ARRAY
localtime_r
static struct tm * localtime_r(const time_t *t, struct tm *tm)
Definition: date_core.c:3616
m_virtual_sg
static double m_virtual_sg(union DateData *x)
Definition: date_core.c:1099
xfree
#define xfree
cDateTime
static VALUE cDateTime
Definition: date_core.c:20
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:774
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1780
decode_day
static void decode_day(VALUE d, VALUE *jd, VALUE *df, VALUE *sf)
Definition: date_core.c:1065
m_wnumx
static int m_wnumx(union DateData *x, int f)
Definition: date_core.c:1875
datetime_to_time
static VALUE datetime_to_time(VALUE self)
Definition: date_core.c:8688
Qtrue
return Qtrue
Definition: tcltklib.c:9610
EX_SEC
#define EX_SEC(x)
Definition: date_core.c:203
rb_obj_class
VALUE rb_obj_class(VALUE)
Definition: object.c:194
RETURN_ENUMERATOR
#define RETURN_ENUMERATOR(obj, argc, argv)
set_tmx
static void set_tmx(VALUE, struct tmx *)
Definition: date_core.c:6750
d_lite_downto
static VALUE d_lite_downto(VALUE self, VALUE min)
Definition: date_core.c:6172
d_lite_httpdate
static VALUE d_lite_httpdate(VALUE self)
Definition: date_core.c:7074
m_year
static int m_year(union DateData *x)
Definition: date_core.c:1693
JULIAN
#define JULIAN
Definition: date_core.c:164
rb_rational_new1
#define rb_rational_new1(x)
f_nonzero_p
#define f_nonzero_p(x)
Definition: date_core.c:121
set_to_complex
#define set_to_complex(x, _nth, _jd,_df, _sf, _of, _sg, _year, _mon, _mday, _hour, _min, _sec, _flags)
Definition: date_core.c:354
set_of
static void set_of(union DateData *x, int of)
Definition: date_core.c:5440
m_ajd
static VALUE m_ajd(union DateData *x)
Definition: date_core.c:1555
rb_ary_new3
VALUE rb_ary_new3(long n,...)
Definition: array.c:432
date_s_civil
static VALUE date_s_civil(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:3383
tmx_m_of
static int tmx_m_of(union DateData *x)
Definition: date_core.c:6717
m_of
static int m_of(union DateData *x)
Definition: date_core.c:1616
get_d2
#define get_d2(x, y)
Definition: date_core.c:296
d_lite_iso8601
static VALUE d_lite_iso8601(VALUE self)
Definition: date_core.c:7036
d_lite_start
static VALUE d_lite_start(VALUE self)
Definition: date_core.c:5307
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:695
date__rfc3339
VALUE date__rfc3339(VALUE)
Definition: date_parse.c:2668
DateData
Definition: date_core.c:278
date_s_valid_civil_p
static VALUE date_s_valid_civil_p(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:2568
r
r
Definition: bigdecimal.c:1196
c_jd_to_wday
static int c_jd_to_wday(int jd)
Definition: date_core.c:627
encode_jd
static void encode_jd(VALUE nth, int jd, VALUE *rjd)
Definition: date_core.c:1366
jd_utc_to_local
static int jd_utc_to_local(int jd, int df, int of)
Definition: date_core.c:902
rb_str_new2
#define rb_str_new2
CM_PERIOD_GCY
#define CM_PERIOD_GCY
Definition: date_core.c:181
DAY_IN_SECONDS
#define DAY_IN_SECONDS
Definition: date_core.c:172
m_mon
static int m_mon(union DateData *x)
Definition: date_core.c:1741
f_zero_p
static VALUE f_zero_p(VALUE x)
Definition: date_core.c:105
ComplexDateData::df
int df
Definition: date_core.c:260
timeval::tv_sec
long tv_sec
Definition: ossl_asn1.c:17
DateData::flags
unsigned flags
Definition: date_core.c:279
date_s_ordinal
static VALUE date_s_ordinal(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:3315
sec_to_ms
static VALUE sec_to_ms(VALUE s)
Definition: date_core.c:1011
last
unsigned int last
Definition: nkf.c:4310
MDAY_SHIFT
#define MDAY_SHIFT
Definition: date_core.c:198
d_lite_italy
static VALUE d_lite_italy(VALUE self)
Definition: date_core.c:5398
ComplexDateData::sg
date_sg_t sg
Definition: date_core.c:263
f_negative_p
static VALUE f_negative_p(VALUE x)
Definition: date_core.c:124
ComplexDateData::jd
int jd
Definition: date_core.c:259
round
RUBY_EXTERN double round(double)
Definition: numeric.c:84
T_FLOAT
#define T_FLOAT
get_s_civil
static void get_s_civil(union DateData *x)
Definition: date_core.c:1150
date_strftime
size_t date_strftime(char *s, size_t maxsize, const char *format, const struct tmx *tmx)
Definition: date_strftime.c:623
valid_ordinal_sub
static VALUE valid_ordinal_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
Definition: date_core.c:2589
valid_civil_p
static int valid_civil_p(VALUE y, int m, int d, double sg, VALUE *nth, int *ry, int *rm, int *rd, int *rjd, int *ns)
Definition: date_core.c:2214
gmtime_r
static struct tm * gmtime_r(const time_t *t, struct tm *tm)
Definition: date_core.c:3607
rb_undef_method
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1362
time_to_df
static int time_to_df(int h, int min, int s)
Definition: date_core.c:913
LONG2NUM
#define LONG2NUM(x)
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2121
of2str
static VALUE of2str(int of)
Definition: date_core.c:1951
d_lite_rshift
static VALUE d_lite_rshift(VALUE self, VALUE other)
Definition: date_core.c:5965
rb_f_sprintf
VALUE rb_f_sprintf(int, const VALUE *)
Definition: sprintf.c:433
k_datetime_p
static VALUE k_datetime_p(VALUE x)
Definition: date_core.c:1980
have_time_p
#define have_time_p(x)
Definition: date_core.c:158
get_d1a
#define get_d1a(x)
Definition: date_core.c:288
d
d
Definition: strlcat.c:58
rb_enc_sprintf
VALUE rb_enc_sprintf(rb_encoding *enc, const char *format,...)
Definition: sprintf.c:1251
f_hour
#define f_hour(x)
Definition: date_core.c:139
fmt
const char * fmt
Definition: tcltklib.c:841
date__jisx0301
VALUE date__jisx0301(VALUE)
Definition: date_parse.c:3107
ComplexDateData
Definition: date_core.c:255
SECOND_IN_MILLISECONDS
#define SECOND_IN_MILLISECONDS
Definition: date_core.c:173
timespec::tv_sec
time_t tv_sec
Definition: ripper.y:47
sym
#define sym(x)
Definition: date_core.c:3715
rb_copy_generic_ivar
void rb_copy_generic_ivar(VALUE, VALUE)
Definition: variable.c:1047
date_s_julian_leap_p
static VALUE date_s_julian_leap_p(VALUE klass, VALUE y)
Definition: date_core.c:2914
d_lite_cwyear
static VALUE d_lite_cwyear(VALUE self)
Definition: date_core.c:4970
id_ge_p
static ID id_ge_p
Definition: date_core.c:19
dt_lite_jisx0301
static VALUE dt_lite_jisx0301(int argc, VALUE *argv, VALUE self)
Definition: date_core.c:8502
d_lite_marshal_dump
static VALUE d_lite_marshal_dump(VALUE self)
Definition: date_core.c:7149
h_trunc
static VALUE h_trunc(VALUE h, VALUE *fr)
Definition: date_core.c:3156
d_lite_cweek
static VALUE d_lite_cweek(VALUE self)
Definition: date_core.c:4985
rb_usascii_str_new
VALUE rb_usascii_str_new(const char *, long)
Definition: string.c:431
rb_singleton_class
VALUE rb_singleton_class(VALUE obj)
Returns the singleton class of obj.
Definition: class.c:1470
date_s_rfc3339
static VALUE date_s_rfc3339(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:4447
REFORM_BEGIN_YEAR
#define REFORM_BEGIN_YEAR
Definition: date_core.c:183
d_simple_new_internal
static VALUE d_simple_new_internal(VALUE klass, VALUE nth, int jd, double sg, int y, int m, int d, unsigned flags)
Definition: date_core.c:2957
datetime_s_rfc3339
static VALUE datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:8087
have_jd_p
#define have_jd_p(x)
Definition: date_core.c:155
wholenum_p
static int wholenum_p(VALUE x)
Definition: date_core.c:3105
c_commercial_to_jd
static void c_commercial_to_jd(int y, int w, int d, double sg, int *rjd, int *ns)
Definition: date_core.c:550
hash
VALUE hash
Definition: tkutil.c:267
m_proleptic_gregorian_p
static int m_proleptic_gregorian_p(union DateData *x)
Definition: date_core.c:1682
c_valid_gregorian_p
static int c_valid_gregorian_p(int y, int m, int d, int *rm, int *rd)
Definition: date_core.c:719
SimpleDateData
Definition: date_core.c:232
f_add
#define f_add(x, y)
Definition: date_core.c:28
get_c_time
static void get_c_time(union DateData *x)
Definition: date_core.c:1189
f_mod
#define f_mod(x, y)
Definition: date_core.c:34
d_lite_ld
static VALUE d_lite_ld(VALUE self)
Definition: date_core.c:4874
d_lite_gregorian
static VALUE d_lite_gregorian(VALUE self)
Definition: date_core.c:5434
set_hash
#define set_hash(k, v)
Definition: date_core.c:3679
local_df
static int local_df(union DateData *x)
Definition: date_core.c:1294
Init_date_core
void Init_date_core(void)
Definition: date_core.c:9098
rb_mComparable
VALUE rb_mComparable
Definition: compar.c:14
m
BDIGIT m
Definition: bigdecimal.c:5085
date_s_xmlschema
static VALUE date_s_xmlschema(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:4488
f_to_i
#define f_to_i(x)
Definition: date_core.c:42
m_sf_in_sec
static VALUE m_sf_in_sec(union DateData *x)
Definition: date_core.c:1529
d_lite_prev_day
static VALUE d_lite_prev_day(int argc, VALUE *argv, VALUE self)
Definition: date_core.c:5931
Qfalse
return Qfalse
Definition: tcltklib.c:6779
FIXNUM_P
#define FIXNUM_P(f)
d_lite_julian
static VALUE d_lite_julian(VALUE self)
Definition: date_core.c:5422
d_lite_asctime
static VALUE d_lite_asctime(VALUE self)
Definition: date_core.c:7023
date_strftime_alloc
static size_t date_strftime_alloc(char **buf, const char *format, struct tmx *tmx)
Definition: date_core.c:6650
m_local_df
static int m_local_df(union DateData *x)
Definition: date_core.c:1493
RARRAY_LEN
#define RARRAY_LEN(a)
rt_complete_frags
static VALUE rt_complete_frags(VALUE klass, VALUE hash)
Definition: date_core.c:3722
cmp_gen
static VALUE cmp_gen(VALUE self, VALUE other)
Definition: date_core.c:6187
d_lite_year
static VALUE d_lite_year(VALUE)
Definition: date_core.c:4890
NUM2DBL
#define NUM2DBL(x)
Qnil
#define Qnil
Definition: tcltklib.c:1896
m_jd
static int m_jd(union DateData *x)
Definition: date_core.c:1421
d_trunc
static VALUE d_trunc(VALUE d, VALUE *fr)
Definition: date_core.c:3137
date_s_gregorian_leap_p
static VALUE date_s_gregorian_leap_p(VALUE klass, VALUE y)
Definition: date_core.c:2935
dt_lite_rfc3339
static VALUE dt_lite_rfc3339(int argc, VALUE *argv, VALUE self)
Definition: date_core.c:8486
timeval::tv_usec
long tv_usec
Definition: ossl_asn1.c:18
f_le_p
static VALUE f_le_p(VALUE x, VALUE y)
Definition: date_core.c:81
f_year
#define f_year(x)
Definition: date_core.c:135
m_sg
static double m_sg(union DateData *x)
Definition: date_core.c:1633
c_valid_commercial_p
static int c_valid_commercial_p(int y, int w, int d, double sg, int *rw, int *rd, int *rjd, int *ns)
Definition: date_core.c:761
str
static VALUE char * str
Definition: tcltklib.c:3547
rb_cRational
RUBY_EXTERN VALUE rb_cRational
Definition: ripper.y:1452
SMALLBUF
#define SMALLBUF
Definition: date_core.c:6648
datetime_to_date
static VALUE datetime_to_date(VALUE self)
Definition: date_core.c:8715
flags
int flags
Definition: tcltklib.c:3023
date_s__rfc2822
static VALUE date_s__rfc2822(VALUE klass, VALUE str)
Definition: date_core.c:4515
ID
unsigned long ID
Definition: ripper.y:105
ComplexDateData::of
int of
Definition: date_core.c:262
encode_year
static void encode_year(VALUE nth, int y, double style, VALUE *ry)
Definition: date_core.c:1334
monthtab
static const int monthtab[2][13]
Definition: date_core.c:668
T_RATIONAL
#define T_RATIONAL
rb_gc_mark
void rb_gc_mark(VALUE)
Definition: gc.c:2598
negative_inf
static double negative_inf
Definition: date_core.c:22
yeartab
static const int yeartab[2][13]
Definition: date_core.c:1782
d_lite_wednesday_p
static VALUE d_lite_wednesday_p(VALUE self)
Definition: date_core.c:5083
rb_define_const
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2202
timespec::tv_nsec
long tv_nsec
Definition: ripper.y:48
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:499
local_jd
static int local_jd(union DateData *x)
Definition: date_core.c:1285
obj
static VALUE VALUE obj
Definition: tcltklib.c:3158
RSTRING_LEN
#define RSTRING_LEN(str)
FIX2INT
#define FIX2INT(x)
m_local_jd
static int m_local_jd(union DateData *x)
Definition: date_core.c:1447
INT2FIX
#define INT2FIX(i)
idx
int idx
Definition: tcltklib.c:9716
valid_sg
#define valid_sg(sg)
Definition: date_core.c:2433
FIX2LONG
#define FIX2LONG(x)
FIXNUM_MIN
#define FIXNUM_MIN
canon24oc
#define canon24oc()
Definition: date_core.c:3226
num2int_with_frac
#define num2int_with_frac(s, n)
Definition: date_core.c:3216
valid_commercial_p
static int valid_commercial_p(VALUE y, int w, int d, double sg, VALUE *nth, int *ry, int *rw, int *rd, int *rjd, int *ns)
Definition: date_core.c:2250
d_lite_mday
static VALUE d_lite_mday(VALUE self)
Definition: date_core.c:4937
T_STRING
#define T_STRING
date_s__strptime_internal
static VALUE date_s__strptime_internal(int argc, VALUE *argv, VALUE klass, const char *default_fmt)
Definition: date_core.c:4171
m_yday
static int m_yday(union DateData *x)
Definition: date_core.c:1802
f_utc6
#define f_utc6(x, y, m, d, h, min, s)
Definition: date_core.c:8526
canonicalize_s_jd
static void canonicalize_s_jd(union DateData *x)
Definition: date_core.c:1120
xmalloc
#define xmalloc
s_trunc
static VALUE s_trunc(VALUE s, VALUE *fr)
Definition: date_core.c:3190
f_cmp
static VALUE f_cmp(VALUE x, VALUE y)
Definition: date_core.c:51
c_ordinal_to_jd
static void c_ordinal_to_jd(int y, int d, double sg, int *rjd, int *ns)
Definition: date_core.c:530
cDate
static VALUE cDate
Definition: date_core.c:20
d_lite_new_start
static VALUE d_lite_new_start(int argc, VALUE *argv, VALUE self)
Definition: date_core.c:5377
f_lt_p
static VALUE f_lt_p(VALUE x, VALUE y)
Definition: date_core.c:65
valid_weeknum_p
static int valid_weeknum_p(VALUE y, int w, int d, int f, double sg, VALUE *nth, int *ry, int *rw, int *rd, int *rjd, int *ns)
Definition: date_core.c:2280
date_s_parse
static VALUE date_s_parse(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:4350
c_gregorian_leap_p
static int c_gregorian_leap_p(int y)
Definition: date_core.c:680
m_canonicalize_jd
static void m_canonicalize_jd(union DateData *x)
Definition: date_core.c:1397
c_jd_to_weeknum
static void c_jd_to_weeknum(int jd, int f, double sg, int *ry, int *rw, int *rd)
Definition: date_core.c:595
date__parse
VALUE date__parse(VALUE str, VALUE comp)
Definition: date_parse.c:2179
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
date_strftime_internal
static VALUE date_strftime_internal(int argc, VALUE *argv, VALUE self, const char *default_fmt, void(*func)(VALUE, struct tmx *))
Definition: date_core.c:6758
complex_dat_p
#define complex_dat_p(x)
Definition: date_core.c:159
rb_num_coerce_cmp
VALUE rb_num_coerce_cmp(VALUE, VALUE, ID)
Definition: numeric.c:276
SimpleDateData::pc
unsigned pc
Definition: date_core.c:251
DBL2NUM
#define DBL2NUM(dbl)
m_real_cwyear
static VALUE m_real_cwyear(union DateData *x)
Definition: date_core.c:1836
ComplexDateData::year
int year
Definition: date_core.c:265
c_jd_to_commercial
static void c_jd_to_commercial(int jd, double sg, int *ry, int *rw, int *rd)
Definition: date_core.c:564
c_julian_to_yday
static int c_julian_to_yday(int y, int m, int d)
Definition: date_core.c:1788
encoding.h
date_tmx.h
datetime_s_commercial
static VALUE datetime_s_commercial(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:7526
f_mul
#define f_mul(x, y)
Definition: date_core.c:30
d_lite_marshal_load
static VALUE d_lite_marshal_load(VALUE self, VALUE a)
Definition: date_core.c:7173
ITALY
#define ITALY
Definition: date_core.c:162
min_trunc
static VALUE min_trunc(VALUE min, VALUE *fr)
Definition: date_core.c:3173
RRATIONAL
#define RRATIONAL(obj)
c_weeknum_to_jd
static void c_weeknum_to_jd(int y, int w, int d, int f, double sg, int *rjd, int *ns)
Definition: date_core.c:584
f_min
#define f_min(x)
Definition: date_core.c:140
EX_HOUR
#define EX_HOUR(x)
Definition: date_core.c:205
argv
VALUE * argv
Definition: tcltklib.c:1971
decode_year
static void decode_year(VALUE y, double style, VALUE *nth, int *ry)
Definition: date_core.c:1302
f_inspect
#define f_inspect(x)
Definition: date_core.c:45
date_s__jisx0301
static VALUE date_s__jisx0301(VALUE klass, VALUE str)
Definition: date_core.c:4600
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:934
sec_to_day
static VALUE sec_to_day(VALUE s)
Definition: date_core.c:928
RTEST
#define RTEST(v)
d_lite_next_month
static VALUE d_lite_next_month(int argc, VALUE *argv, VALUE self)
Definition: date_core.c:6027
d_lite_step
static VALUE d_lite_step(int argc, VALUE *argv, VALUE self)
Definition: date_core.c:6102
HALF_DAYS_IN_SECONDS
#define HALF_DAYS_IN_SECONDS
Definition: date_core.c:1552
rb_marshal_load
VALUE rb_marshal_load(VALUE)
Definition: marshal.c:2123
timeval
Definition: ossl_asn1.c:16
errno
int errno
time_to_date
static VALUE time_to_date(VALUE self)
Definition: date_core.c:8548
isec_to_day
static VALUE isec_to_day(int s)
Definition: date_core.c:936
f_to_s
#define f_to_s(x)
Definition: date_core.c:44
f_ajd
#define f_ajd(x)
Definition: date_core.c:133
f_boolcast
#define f_boolcast(x)
Definition: date_core.c:24
m_df
static int m_df(union DateData *x)
Definition: date_core.c:1474
c_jd_to_civil
static void c_jd_to_civil(int jd, double sg, int *ry, int *rm, int *rdom)
Definition: date_core.c:500
StringValue
#define StringValue(v)
div_day
static VALUE div_day(VALUE d, VALUE *f)
Definition: date_core.c:1035
m_amjd
static VALUE m_amjd(union DateData *x)
Definition: date_core.c:1587
d_lite_thursday_p
static VALUE d_lite_thursday_p(VALUE self)
Definition: date_core.c:5096
s
register char * s
Definition: os2.c:56
get_c_df
static void get_c_df(union DateData *x)
Definition: date_core.c:1170
d_lite_inspect
static VALUE d_lite_inspect(VALUE self)
Definition: date_core.c:6631
datetime_to_datetime
static VALUE datetime_to_datetime(VALUE self)
Definition: date_core.c:8747
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE)
Definition: gc.c:2980
date__iso8601
VALUE date__iso8601(VALUE)
Definition: date_parse.c:2600
d_lite_next_day
static VALUE d_lite_next_day(int argc, VALUE *argv, VALUE self)
Definition: date_core.c:5914
d_lite_day_fraction
static VALUE d_lite_day_fraction(VALUE self)
Definition: date_core.c:4952
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1570
mk_ary_of_str
static VALUE mk_ary_of_str(long len, const char *a[])
Definition: date_core.c:9076
min
static int min(int a, int b)
Definition: strftime.c:131
rb_usascii_encoding
rb_encoding * rb_usascii_encoding(void)
Definition: encoding.c:1183
decode_jd
static void decode_jd(VALUE jd, VALUE *nth, int *rjd)
Definition: date_core.c:1353
date_s__strptime
static VALUE date_s__strptime(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:4235
d_new_by_frags
static VALUE d_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
Definition: date_core.c:4126
RB_GC_GUARD
#define RB_GC_GUARD(v)
d_lite_next_year
static VALUE d_lite_next_year(int argc, VALUE *argv, VALUE self)
Definition: date_core.c:6061
f_mon
#define f_mon(x)
Definition: date_core.c:136
T_FIXNUM
#define T_FIXNUM
argc
int argc
Definition: tcltklib.c:1970
HAVE_CIVIL
#define HAVE_CIVIL
Definition: date_core.c:151
datetime_s_jisx0301
static VALUE datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:8208
d_lite_julian_p
static VALUE d_lite_julian_p(VALUE self)
Definition: date_core.c:5251
copy_simple_to_complex
#define copy_simple_to_complex(x, y)
Definition: date_core.c:387
tmx_m_msecs
static VALUE tmx_m_msecs(union DateData *x)
Definition: date_core.c:6703
time_to_time
static VALUE time_to_time(VALUE self)
Definition: date_core.c:8536
PACK2
#define PACK2(m, d)
Definition: date_core.c:213
rt_rewrite_frags
static VALUE rt_rewrite_frags(VALUE hash)
Definition: date_core.c:3684
dup_obj_with_new_offset
static VALUE dup_obj_with_new_offset(VALUE obj, int of)
Definition: date_core.c:5450
m_mday
static int m_mday(union DateData *x)
Definition: date_core.c:1762
SimpleDateData::sg
date_sg_t sg
Definition: date_core.c:240
d_lite_s_alloc_simple
static VALUE d_lite_s_alloc_simple(VALUE klass)
Definition: date_core.c:2999
rt__valid_date_frags_p
static VALUE rt__valid_date_frags_p(VALUE hash, VALUE sg)
Definition: date_core.c:4029
id_eqeq_p
static ID id_eqeq_p
Definition: date_core.c:19
canonicalize_c_jd
static void canonicalize_c_jd(union DateData *x)
Definition: date_core.c:1214
get_c_civil
static void get_c_civil(union DateData *x)
Definition: date_core.c:1256
INFINITY
#define INFINITY
Definition: missing.h:138
id_cmp
static ID id_cmp
Definition: date_core.c:19
isinf
RUBY_EXTERN int isinf(double)
Definition: isinf.c:56
isnan
#define isnan(x)
Definition: win32.h:327
dup_obj_as_complex
static VALUE dup_obj_as_complex(VALUE self)
Definition: date_core.c:4658
datetime_s_parse
static VALUE datetime_s_parse(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:8017
have_civil_p
#define have_civil_p(x)
Definition: date_core.c:157
dup_obj
static VALUE dup_obj(VALUE self)
Definition: date_core.c:4635
time_to_datetime
static VALUE time_to_datetime(VALUE self)
Definition: date_core.c:8578
DEFAULT_SG
#define DEFAULT_SG
Definition: date_core.c:166
rb_sys_fail
void rb_sys_fail(const char *mesg)
Definition: error.c:1899
f_div
#define f_div(x, y)
Definition: date_core.c:31
cmp_dd
static VALUE cmp_dd(VALUE self, VALUE other)
Definition: date_core.c:6199
dup_obj_with_new_start
static VALUE dup_obj_with_new_start(VALUE obj, double sg)
Definition: date_core.c:5357
b
Real * b
Definition: bigdecimal.c:1182
k_date_p
static VALUE k_date_p(VALUE x)
Definition: date_core.c:1974
c
VpDivd * c
Definition: bigdecimal.c:1205
m_wday
static int m_wday(union DateData *x)
Definition: date_core.c:1820
rt__valid_jd_p
static VALUE rt__valid_jd_p(VALUE jd, VALUE sg)
Definition: date_core.c:3963
f_sub
#define f_sub(x, y)
Definition: date_core.c:29
iso8601_timediv
static VALUE iso8601_timediv(VALUE self, VALUE n)
Definition: date_core.c:8428
T_BIGNUM
#define T_BIGNUM
rt__valid_civil_p
static VALUE rt__valid_civil_p(VALUE y, VALUE m, VALUE d, VALUE sg)
Definition: date_core.c:3984
datetime_s_strptime
static VALUE datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:7974
mk_inspect
static VALUE mk_inspect(union DateData *x, const char *klass, const char *to_s)
Definition: date_core.c:6604
c_gregorian_to_yday
static int c_gregorian_to_yday(int y, int m, int d)
Definition: date_core.c:1795
rb_enc_str_asciicompat_p
#define rb_enc_str_asciicompat_p(str)
date_sg_t
#define date_sg_t
Definition: date_core.c:224
REFORM_END_YEAR
#define REFORM_END_YEAR
Definition: date_core.c:184
m_cwday
static int m_cwday(union DateData *x)
Definition: date_core.c:1864
c_jd_to_ordinal
static void c_jd_to_ordinal(int jd, double sg, int *ry, int *rd)
Definition: date_core.c:540
f_local3
#define f_local3(x, y, m, d)
Definition: date_core.c:8525
d_lite_eql_p
static VALUE d_lite_eql_p(VALUE self, VALUE other)
Definition: date_core.c:6489
date_s_valid_ordinal_p
static VALUE date_s_valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:2649
datetime_s_now
static VALUE datetime_s_now(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:7740
date_s_strptime
static VALUE date_s_strptime(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:4259
rb_str_cat
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:1963
get_d1b
#define get_d1b(x)
Definition: date_core.c:292
div_df
static VALUE div_df(VALUE d, VALUE *f)
Definition: date_core.c:1043
df_to_time
static void df_to_time(int df, int *h, int *min, int *s)
Definition: date_core.c:919
size
int size
Definition: encoding.c:52
f
#define f
f_quo
#define f_quo(x, y)
Definition: date_core.c:32
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:582
HAVE_JD
#define HAVE_JD
Definition: date_core.c:149
tmx_funcs
static struct tmx_funcs tmx_funcs
Definition: date_core.c:6728
CM_PERIOD
#define CM_PERIOD
Definition: date_core.c:179
ComplexDateData::nth
VALUE nth
Definition: date_core.c:258
date_s_jisx0301
static VALUE date_s_jisx0301(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:4615
m_sf
static VALUE m_sf(union DateData *x)
Definition: date_core.c:1512
m_wnum0
static int m_wnum0(union DateData *x)
Definition: date_core.c:1885
f_utc_offset
#define f_utc_offset(x)
Definition: date_core.c:8524
date_s_commercial
static VALUE date_s_commercial(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:3460
d_lite_monday_p
static VALUE d_lite_monday_p(VALUE self)
Definition: date_core.c:5057
HOUR_IN_SECONDS
#define HOUR_IN_SECONDS
Definition: date_core.c:171
date_to_time
static VALUE date_to_time(VALUE self)
Definition: date_core.c:8619
m_sec
static int m_sec(union DateData *x)
Definition: date_core.c:1927
t
int t
Definition: ripper.c:14699
f_expt
#define f_expt(x, y)
Definition: date_core.c:36
rb_memhash
st_index_t rb_memhash(const void *ptr, long len)
Definition: random.c:1422
d_lite_friday_p
static VALUE d_lite_friday_p(VALUE self)
Definition: date_core.c:5109
c_find_ldoy
static int c_find_ldoy(int y, double sg, int *rjd, int *ns)
Definition: date_core.c:441
m_fr
static VALUE m_fr(union DateData *x)
Definition: date_core.c:1535
get_s_jd
static void get_s_jd(union DateData *x)
Definition: date_core.c:1130
date_s__parse
static VALUE date_s__parse(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:4329
f_getlocal
#define f_getlocal(x)
Definition: date_core.c:8522
val2off
#define val2off(vof, iof)
Definition: date_core.c:4681
f_mday
#define f_mday(x)
Definition: date_core.c:137
d_lite_sec
static VALUE d_lite_sec(VALUE self)
Definition: date_core.c:5189
m_cweek
static int m_cweek(union DateData *x)
Definition: date_core.c:1854
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ripper.y:1426
st_index_t
st_data_t st_index_t
Definition: ripper.y:63
LONG2FIX
#define LONG2FIX(i)
tmx_m_zone
static char * tmx_m_zone(union DateData *x)
Definition: date_core.c:6723
safe_mul_p
static int safe_mul_p(VALUE x, long m)
Definition: date_core.c:976
d_lite_yday
static VALUE d_lite_yday(VALUE self)
Definition: date_core.c:4905
minus_dd
static VALUE minus_dd(VALUE self, VALUE other)
Definition: date_core.c:5819
RARRAY_LENINT
#define RARRAY_LENINT(ary)
jd_local_to_utc
static int jd_local_to_utc(int jd, int df, int of)
Definition: date_core.c:891
HAVE_TIME
#define HAVE_TIME
Definition: date_core.c:152
d_lite_prev_year
static VALUE d_lite_prev_year(int argc, VALUE *argv, VALUE self)
Definition: date_core.c:6078
klass
klass
Definition: tcltklib.c:3504
abbr_daynames
static const char * abbr_daynames[]
Definition: date_core.c:9070
INT2NUM
#define INT2NUM(x)
f_eqeq_p
static VALUE f_eqeq_p(VALUE x, VALUE y)
Definition: date_core.c:97
valid_civil_sub
static VALUE valid_civil_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
Definition: date_core.c:2498
clear_civil
static void clear_civil(union DateData *x)
Definition: date_core.c:5314
f_subsec
#define f_subsec(x)
Definition: date_core.c:8523
USE_PACK
#define USE_PACK
Definition: date_core.c:17
add_frac
#define add_frac()
Definition: date_core.c:3234
date__httpdate
VALUE date__httpdate(VALUE)
Definition: date_parse.c:3033
timespec
Definition: ripper.y:46
zone
Definition: date_parse.c:336
SimpleDateData::nth
VALUE nth
Definition: date_core.c:235
SECOND_IN_NANOSECONDS
#define SECOND_IN_NANOSECONDS
Definition: date_core.c:174
rb_ary_new2
VALUE rb_ary_new2(long capa)
Definition: array.c:417
date_s_jd
static VALUE date_s_jd(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:3265
rb_str_new
VALUE rb_str_new(const char *, long)
Definition: string.c:425
m_real_year
static VALUE m_real_year(union DateData *x)
Definition: date_core.c:1706
d_lite_england
static VALUE d_lite_england(VALUE self)
Definition: date_core.c:5410
d_lite_saturday_p
static VALUE d_lite_saturday_p(VALUE self)
Definition: date_core.c:5122
d_lite_hash
static VALUE d_lite_hash(VALUE self)
Definition: date_core.c:6498
EX_MIN
#define EX_MIN(x)
Definition: date_core.c:204
df_local_to_utc
static int df_local_to_utc(int df, int of)
Definition: date_core.c:869
valid_jd_sub
static VALUE valid_jd_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
Definition: date_core.c:2442
MILLISECOND_IN_NANOSECONDS
#define MILLISECOND_IN_NANOSECONDS
Definition: date_core.c:6700
REFORM_END_JD
#define REFORM_END_JD
Definition: date_core.c:186
c_valid_weeknum_p
static int c_valid_weeknum_p(int y, int w, int d, int f, double sg, int *rw, int *rd, int *rjd, int *ns)
Definition: date_core.c:785
assert
#define assert(condition)
Definition: ossl.h:45
NUM2INT
#define NUM2INT(x)
d_lite_to_s
static VALUE d_lite_to_s(VALUE self)
Definition: date_core.c:6526
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:234
sec_to_ns
static VALUE sec_to_ns(VALUE s)
Definition: date_core.c:1019
d_lite_plus
static VALUE d_lite_plus(VALUE, VALUE)
Definition: date_core.c:5502
c_virtual_sg
static double c_virtual_sg(union DateData *x)
Definition: date_core.c:1087
date_to_datetime
static VALUE date_to_datetime(VALUE self)
Definition: date_core.c:8648
f_add3
#define f_add3(x, y, z)
Definition: date_core.c:47
canon
static VALUE canon(VALUE x)
Definition: date_core.c:302
m_gregorian_p
static int m_gregorian_p(union DateData *x)
Definition: date_core.c:1665
dt_lite_iso8601
static VALUE dt_lite_iso8601(int argc, VALUE *argv, VALUE self)
Definition: date_core.c:8462
date_s__iso8601
static VALUE date_s__iso8601(VALUE klass, VALUE str)
Definition: date_core.c:4389
rt__valid_ordinal_p
static VALUE rt__valid_ordinal_p(VALUE y, VALUE d, VALUE sg)
Definition: date_core.c:3969
SimpleDateData::jd
int jd
Definition: date_core.c:236
e
BDIGIT e
Definition: bigdecimal.c:5085
monthnames
static const char * monthnames[]
Definition: date_core.c:9050
date_s__parse_internal
static VALUE date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:4287
VALUE
unsigned long VALUE
Definition: ripper.y:104
tmx::dat
void * dat
Definition: date_tmx.h:25
date__rfc2822
VALUE date__rfc2822(VALUE)
Definition: date_parse.c:2887
daynames
static const char * daynames[]
Definition: date_core.c:9065
rb_warning
void rb_warning(const char *fmt,...)
Definition: error.c:229
d_lite_jisx0301
static VALUE d_lite_jisx0301(VALUE self)
Definition: date_core.c:7115
ix
ssize_t ix
Definition: bigdecimal.c:5655
date_s_valid_commercial_p
static VALUE date_s_valid_commercial_p(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:2731
COMPLEX_DAT
#define COMPLEX_DAT
Definition: date_core.c:153
c_valid_start_p
static int c_valid_start_p(double sg)
Definition: date_core.c:857
f_gt_p
static VALUE f_gt_p(VALUE x, VALUE y)
Definition: date_core.c:73
positive_inf
static double positive_inf
Definition: date_core.c:22
f_to_r
#define f_to_r(x)
Definition: date_core.c:43
date_s__xmlschema
static VALUE date_s__xmlschema(VALUE klass, VALUE str)
Definition: date_core.c:4473
datetime_s_httpdate
static VALUE datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:8178
c_valid_ordinal_p
static int c_valid_ordinal_p(int y, int d, double sg, int *rd, int *rjd, int *ns)
Definition: date_core.c:646
m_pc
static int m_pc(union DateData *x)
Definition: date_core.c:1726
date__xmlschema
VALUE date__xmlschema(VALUE)
Definition: date_parse.c:2814
copy_complex_to_simple
#define copy_complex_to_simple(x, y)
Definition: date_core.c:413
set_to_simple
#define set_to_simple(x, _nth, _jd,_sg, _year, _mon, _mday, _flags)
Definition: date_core.c:324
timezone
Definition: ripper.y:53
offset_to_sec
static int offset_to_sec(VALUE vof, int *rof)
Definition: date_core.c:2344
date_s_today
static VALUE date_s_today(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:3636
f_negate
#define f_negate(x)
Definition: date_core.c:27
c_gregorian_last_day_of_month
static int c_gregorian_last_day_of_month(int y, int m)
Definition: date_core.c:693
valid_commercial_sub
static VALUE valid_commercial_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
Definition: date_core.c:2669
m_nth
static VALUE m_nth(union DateData *x)
Definition: date_core.c:1410
d_lite_mjd
static VALUE d_lite_mjd(VALUE self)
Definition: date_core.c:4858
valid_ordinal_p
static int valid_ordinal_p(VALUE y, int d, double sg, VALUE *nth, int *ry, int *rd, int *rjd, int *ns)
Definition: date_core.c:2175
d_lite_rfc2822
static VALUE d_lite_rfc2822(VALUE self)
Definition: date_core.c:7061
rb_intern
#define rb_intern(str)
v
BDIGIT v
Definition: bigdecimal.c:5656
tmx_funcs
Definition: date_tmx.h:4
d_lite_s_alloc
static VALUE d_lite_s_alloc(VALUE klass)
Definition: date_core.c:3021
date__strptime
VALUE date__strptime(const char *str, size_t slen, const char *fmt, size_t flen, VALUE hash)
Definition: date_strptime.c:649
set_hash0
#define set_hash0(k, v)
Definition: date_core.c:3675
f_round
#define f_round(x)
Definition: date_core.c:40
f_public
#define f_public(m, s)
NULL
#define NULL
Definition: _sdbm.c:103
dt_lite_to_s
static VALUE dt_lite_to_s(VALUE self)
Definition: date_core.c:8238
time
VALUE time
Definition: tcltklib.c:1866
set_sg
static void set_sg(union DateData *, double)
Definition: date_core.c:5342
d_lite_min
static VALUE d_lite_min(VALUE self)
Definition: date_core.c:5173
d_complex_new_internal
static VALUE d_complex_new_internal(VALUE klass, VALUE nth, int jd, int df, VALUE sf, int of, double sg, int y, int m, int d, int h, int min, int s, unsigned flags)
Definition: date_core.c:2976
guess_style
static double guess_style(VALUE y, double sg)
Definition: date_core.c:1376
ref_hash
#define ref_hash(k)
Definition: date_core.c:3680
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1344
MINUTE_IN_SECONDS
#define MINUTE_IN_SECONDS
Definition: date_core.c:170
m_cwyear
static int m_cwyear(union DateData *x)
Definition: date_core.c:1826
id_le_p
static ID id_le_p
Definition: date_core.c:19
date_zone_to_diff
VALUE date_zone_to_diff(VALUE)
Definition: date_parse.c:420
num2num_with_frac
#define num2num_with_frac(s, n)
Definition: date_core.c:3206
SimpleDateData::year
int year
Definition: date_core.c:242
ns_to_day
static VALUE ns_to_day(VALUE n)
Definition: date_core.c:942
d_lite_prev_month
static VALUE d_lite_prev_month(int argc, VALUE *argv, VALUE self)
Definition: date_core.c:6044
UNIX_EPOCH_IN_CJD
#define UNIX_EPOCH_IN_CJD
Definition: date_core.c:168
f_idiv
#define f_idiv(x, y)
Definition: date_core.c:33
ref_hash0
#define ref_hash0(k)
Definition: date_core.c:3676
datetime_s_civil
static VALUE datetime_s_civil(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:7429
DateData::s
struct SimpleDateData s
Definition: date_core.c:280
SYM2ID
#define SYM2ID(x)
d_lite_hour
static VALUE d_lite_hour(VALUE self)
Definition: date_core.c:5157
c_valid_time_p
static int c_valid_time_p(int h, int min, int s, int *rh, int *rmin, int *rs)
Definition: date_core.c:839
rb_eArgError
VALUE rb_eArgError
Definition: error.c:512
rb_cNumeric
RUBY_EXTERN VALUE rb_cNumeric
Definition: ripper.y:1448
d_lite_wday
static VALUE d_lite_wday(VALUE)
Definition: date_core.c:5031
date_s_valid_jd_p
static VALUE date_s_valid_jd_p(int argc, VALUE *argv, VALUE klass)
Definition: date_core.c:2479
have_df_p
#define have_df_p(x)
Definition: date_core.c:156
GREGORIAN
#define GREGORIAN
Definition: date_core.c:165
c_valid_julian_p
static int c_valid_julian_p(int y, int m, int d, int *rm, int *rd)
Definition: date_core.c:700
d_lite_zone
static VALUE d_lite_zone(VALUE self)
Definition: date_core.c:5235
c_civil_to_jd
static void c_civil_to_jd(int y, int m, int d, double sg, int *rjd, int *ns)
Definition: date_core.c:476
d_lite_sunday_p
static VALUE d_lite_sunday_p(VALUE self)
Definition: date_core.c:5044
df_utc_to_local
static int df_utc_to_local(int df, int of)
Definition: date_core.c:880
d_lite_gc_mark
static void d_lite_gc_mark(union DateData *dat)
Definition: date_core.c:2945
f_positive_p
#define f_positive_p(x)
Definition: date_core.c:131
ENGLAND
#define ENGLAND
Definition: date_core.c:163
d_lite_rfc3339
static VALUE d_lite_rfc3339(VALUE self)
Definition: date_core.c:7048
HAVE_DF
#define HAVE_DF
Definition: date_core.c:150
rb_rational_new2
#define rb_rational_new2(x, y)
ns_to_sec
static VALUE ns_to_sec(VALUE n)
Definition: date_core.c:960
d_lite_ajd
static VALUE d_lite_ajd(VALUE self)
Definition: date_core.c:4807
old_to_new
static void old_to_new(VALUE ajd, VALUE of, VALUE sg, VALUE *rnth, int *rjd, int *rdf, VALUE *rsf, int *rof, double *rsg)
Definition: date_core.c:3027
valid_gregorian_p
static int valid_gregorian_p(VALUE y, int m, int d, VALUE *nth, int *ry, int *rm, int *rd)
Definition: date_core.c:2205
c_find_fdoy
static int c_find_fdoy(int y, double sg, int *rjd, int *ns)
Definition: date_core.c:430
len
size_t len
Definition: tcltklib.c:3568