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