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