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