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