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