00001
00002
00003
00004
00005 #include "ruby.h"
00006 #include "ruby/encoding.h"
00007 #include <math.h>
00008 #include <time.h>
00009
00010 #define NDEBUG
00011 #include <assert.h>
00012
00013 #ifdef RUBY_EXTCONF_H
00014 #include RUBY_EXTCONF_H
00015 #endif
00016
00017 #define USE_PACK
00018
00019 static ID id_cmp, id_le_p, id_ge_p, id_eqeq_p;
00020 static VALUE cDate, cDateTime;
00021 static VALUE half_days_in_day, day_in_nanoseconds;
00022 static double positive_inf, negative_inf;
00023
00024 #define f_boolcast(x) ((x) ? Qtrue : Qfalse)
00025
00026 #define f_abs(x) rb_funcall(x, rb_intern("abs"), 0)
00027 #define f_negate(x) rb_funcall(x, rb_intern("-@"), 0)
00028 #define f_add(x,y) rb_funcall(x, '+', 1, y)
00029 #define f_sub(x,y) rb_funcall(x, '-', 1, y)
00030 #define f_mul(x,y) rb_funcall(x, '*', 1, y)
00031 #define f_div(x,y) rb_funcall(x, '/', 1, y)
00032 #define f_quo(x,y) rb_funcall(x, rb_intern("quo"), 1, y)
00033 #define f_idiv(x,y) rb_funcall(x, rb_intern("div"), 1, y)
00034 #define f_mod(x,y) rb_funcall(x, '%', 1, y)
00035 #define f_remainder(x,y) rb_funcall(x, rb_intern("remainder"), 1, y)
00036 #define f_expt(x,y) rb_funcall(x, rb_intern("**"), 1, y)
00037 #define f_floor(x) rb_funcall(x, rb_intern("floor"), 0)
00038 #define f_ceil(x) rb_funcall(x, rb_intern("ceil"), 0)
00039 #define f_truncate(x) rb_funcall(x, rb_intern("truncate"), 0)
00040 #define f_round(x) rb_funcall(x, rb_intern("round"), 0)
00041
00042 #define f_to_i(x) rb_funcall(x, rb_intern("to_i"), 0)
00043 #define f_to_r(x) rb_funcall(x, rb_intern("to_r"), 0)
00044 #define f_to_s(x) rb_funcall(x, rb_intern("to_s"), 0)
00045 #define f_inspect(x) rb_funcall(x, rb_intern("inspect"), 0)
00046
00047 #define f_add3(x,y,z) f_add(f_add(x, y), z)
00048 #define f_sub3(x,y,z) f_sub(f_sub(x, y), z)
00049
00050 inline static VALUE
00051 f_cmp(VALUE x, VALUE y)
00052 {
00053 if (FIXNUM_P(x) && FIXNUM_P(y)) {
00054 long c = FIX2LONG(x) - FIX2LONG(y);
00055 if (c > 0)
00056 c = 1;
00057 else if (c < 0)
00058 c = -1;
00059 return INT2FIX(c);
00060 }
00061 return rb_funcall(x, id_cmp, 1, y);
00062 }
00063
00064 inline static VALUE
00065 f_lt_p(VALUE x, VALUE y)
00066 {
00067 if (FIXNUM_P(x) && FIXNUM_P(y))
00068 return f_boolcast(FIX2LONG(x) < FIX2LONG(y));
00069 return rb_funcall(x, '<', 1, y);
00070 }
00071
00072 inline static VALUE
00073 f_gt_p(VALUE x, VALUE y)
00074 {
00075 if (FIXNUM_P(x) && FIXNUM_P(y))
00076 return f_boolcast(FIX2LONG(x) > FIX2LONG(y));
00077 return rb_funcall(x, '>', 1, y);
00078 }
00079
00080 inline static VALUE
00081 f_le_p(VALUE x, VALUE y)
00082 {
00083 if (FIXNUM_P(x) && FIXNUM_P(y))
00084 return f_boolcast(FIX2LONG(x) <= FIX2LONG(y));
00085 return rb_funcall(x, id_le_p, 1, y);
00086 }
00087
00088 inline static VALUE
00089 f_ge_p(VALUE x, VALUE y)
00090 {
00091 if (FIXNUM_P(x) && FIXNUM_P(y))
00092 return f_boolcast(FIX2LONG(x) >= FIX2LONG(y));
00093 return rb_funcall(x, rb_intern(">="), 1, y);
00094 }
00095
00096 inline static VALUE
00097 f_eqeq_p(VALUE x, VALUE y)
00098 {
00099 if (FIXNUM_P(x) && FIXNUM_P(y))
00100 return f_boolcast(FIX2LONG(x) == FIX2LONG(y));
00101 return rb_funcall(x, rb_intern("=="), 1, y);
00102 }
00103
00104 inline static VALUE
00105 f_zero_p(VALUE x)
00106 {
00107 switch (TYPE(x)) {
00108 case T_FIXNUM:
00109 return f_boolcast(FIX2LONG(x) == 0);
00110 case T_BIGNUM:
00111 return Qfalse;
00112 case T_RATIONAL:
00113 {
00114 VALUE num = RRATIONAL(x)->num;
00115 return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 0);
00116 }
00117 }
00118 return rb_funcall(x, id_eqeq_p, 1, INT2FIX(0));
00119 }
00120
00121 #define f_nonzero_p(x) (!f_zero_p(x))
00122
00123 inline static VALUE
00124 f_negative_p(VALUE x)
00125 {
00126 if (FIXNUM_P(x))
00127 return f_boolcast(FIX2LONG(x) < 0);
00128 return rb_funcall(x, '<', 1, INT2FIX(0));
00129 }
00130
00131 #define f_positive_p(x) (!f_negative_p(x))
00132
00133 #define f_ajd(x) rb_funcall(x, rb_intern("ajd"), 0)
00134 #define f_jd(x) rb_funcall(x, rb_intern("jd"), 0)
00135 #define f_year(x) rb_funcall(x, rb_intern("year"), 0)
00136 #define f_mon(x) rb_funcall(x, rb_intern("mon"), 0)
00137 #define f_mday(x) rb_funcall(x, rb_intern("mday"), 0)
00138 #define f_wday(x) rb_funcall(x, rb_intern("wday"), 0)
00139 #define f_hour(x) rb_funcall(x, rb_intern("hour"), 0)
00140 #define f_min(x) rb_funcall(x, rb_intern("min"), 0)
00141 #define f_sec(x) rb_funcall(x, rb_intern("sec"), 0)
00142
00143
00144 #define NDIV(x,y) (-(-((x)+1)/(y))-1)
00145 #define NMOD(x,y) ((y)-(-((x)+1)%(y))-1)
00146 #define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d))
00147 #define MOD(n,d) ((n)<0 ? NMOD((n),(d)) : (n)%(d))
00148
00149 #define HAVE_JD (1 << 0)
00150 #define HAVE_DF (1 << 1)
00151 #define HAVE_CIVIL (1 << 2)
00152 #define HAVE_TIME (1 << 3)
00153 #define COMPLEX_DAT (1 << 7)
00154
00155 #define have_jd_p(x) ((x)->flags & HAVE_JD)
00156 #define have_df_p(x) ((x)->flags & HAVE_DF)
00157 #define have_civil_p(x) ((x)->flags & HAVE_CIVIL)
00158 #define have_time_p(x) ((x)->flags & HAVE_TIME)
00159 #define complex_dat_p(x) ((x)->flags & COMPLEX_DAT)
00160 #define simple_dat_p(x) (!complex_dat_p(x))
00161
00162 #define ITALY 2299161
00163 #define ENGLAND 2361222
00164 #define JULIAN positive_inf
00165 #define GREGORIAN negative_inf
00166 #define DEFAULT_SG ITALY
00167
00168 #define UNIX_EPOCH_IN_CJD INT2FIX(2440588)
00169
00170 #define MINUTE_IN_SECONDS 60
00171 #define HOUR_IN_SECONDS 3600
00172 #define DAY_IN_SECONDS 86400
00173 #define SECOND_IN_MILLISECONDS 1000
00174 #define SECOND_IN_NANOSECONDS 1000000000
00175
00176 #define JC_PERIOD0 1461
00177 #define GC_PERIOD0 146097
00178 #define CM_PERIOD0 71149239
00179 #define CM_PERIOD (0xfffffff / CM_PERIOD0 * CM_PERIOD0)
00180 #define CM_PERIOD_JCY (CM_PERIOD / JC_PERIOD0 * 4)
00181 #define CM_PERIOD_GCY (CM_PERIOD / GC_PERIOD0 * 400)
00182
00183 #define REFORM_BEGIN_YEAR 1582
00184 #define REFORM_END_YEAR 1930
00185 #define REFORM_BEGIN_JD 2298874
00186 #define REFORM_END_JD 2426355
00187
00188 #ifdef USE_PACK
00189 #define SEC_WIDTH 6
00190 #define MIN_WIDTH 6
00191 #define HOUR_WIDTH 5
00192 #define MDAY_WIDTH 5
00193 #define MON_WIDTH 4
00194
00195 #define SEC_SHIFT 0
00196 #define MIN_SHIFT SEC_WIDTH
00197 #define HOUR_SHIFT (MIN_WIDTH + SEC_WIDTH)
00198 #define MDAY_SHIFT (HOUR_WIDTH + MIN_WIDTH + SEC_WIDTH)
00199 #define MON_SHIFT (MDAY_WIDTH + HOUR_WIDTH + MIN_WIDTH + SEC_WIDTH)
00200
00201 #define PK_MASK(x) ((1 << (x)) - 1)
00202
00203 #define EX_SEC(x) (((x) >> SEC_SHIFT) & PK_MASK(SEC_WIDTH))
00204 #define EX_MIN(x) (((x) >> MIN_SHIFT) & PK_MASK(MIN_WIDTH))
00205 #define EX_HOUR(x) (((x) >> HOUR_SHIFT) & PK_MASK(HOUR_WIDTH))
00206 #define EX_MDAY(x) (((x) >> MDAY_SHIFT) & PK_MASK(MDAY_WIDTH))
00207 #define EX_MON(x) (((x) >> MON_SHIFT) & PK_MASK(MON_WIDTH))
00208
00209 #define PACK5(m,d,h,min,s) \
00210 (((m) << MON_SHIFT) | ((d) << MDAY_SHIFT) |\
00211 ((h) << HOUR_SHIFT) | ((min) << MIN_SHIFT) | ((s) << SEC_SHIFT))
00212
00213 #define PACK2(m,d) \
00214 (((m) << MON_SHIFT) | ((d) << MDAY_SHIFT))
00215 #endif
00216
00217 #ifdef HAVE_FLOAT_H
00218 #include <float.h>
00219 #endif
00220
00221 #if defined(FLT_RADIX) && defined(FLT_MANT_DIG)
00222 #if FLT_RADIX == 2 && FLT_MANT_DIG > 22
00223 #define USE_FLOAT
00224 #define sg_cast float
00225 #else
00226 #define sg_cast double
00227 #endif
00228 #endif
00229
00230
00231
00232
00233
00234
00235 struct SimpleDateData
00236 {
00237 unsigned flags;
00238 VALUE nth;
00239 int jd;
00240
00241
00242
00243 #ifndef USE_FLOAT
00244 double sg;
00245 #else
00246 float sg;
00247 #endif
00248
00249 int year;
00250 #ifndef USE_PACK
00251 int mon;
00252 int mday;
00253
00254
00255
00256 #else
00257
00258 unsigned pc;
00259 #endif
00260 };
00261
00262 struct ComplexDateData
00263 {
00264 unsigned flags;
00265 VALUE nth;
00266 int jd;
00267 int df;
00268 VALUE sf;
00269 int of;
00270 #ifndef USE_FLOAT
00271 double sg;
00272 #else
00273 float sg;
00274 #endif
00275
00276 int year;
00277 #ifndef USE_PACK
00278 int mon;
00279 int mday;
00280 int hour;
00281 int min;
00282 int sec;
00283 #else
00284
00285 unsigned pc;
00286 #endif
00287 };
00288
00289 union DateData {
00290 unsigned flags;
00291 struct SimpleDateData s;
00292 struct ComplexDateData c;
00293 };
00294
00295 #define get_d1(x)\
00296 union DateData *dat;\
00297 Data_Get_Struct(x, union DateData, dat);
00298
00299 #define get_d1a(x)\
00300 union DateData *adat;\
00301 Data_Get_Struct(x, union DateData, adat);
00302
00303 #define get_d1b(x)\
00304 union DateData *bdat;\
00305 Data_Get_Struct(x, union DateData, bdat);
00306
00307 #define get_d2(x,y)\
00308 union DateData *adat, *bdat;\
00309 Data_Get_Struct(x, union DateData, adat);\
00310 Data_Get_Struct(y, union DateData, bdat);
00311
00312 inline static VALUE
00313 canon(VALUE x)
00314 {
00315 if (TYPE(x) == T_RATIONAL) {
00316 VALUE den = RRATIONAL(x)->den;
00317 if (FIXNUM_P(den) && FIX2LONG(den) == 1)
00318 return RRATIONAL(x)->num;
00319 }
00320 return x;
00321 }
00322
00323 #ifndef USE_PACK
00324 #define set_to_simple(x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \
00325 {\
00326 (x)->nth = canon(_nth);\
00327 (x)->jd = _jd;\
00328 (x)->sg = (sg_cast)(_sg);\
00329 (x)->year = _year;\
00330 (x)->mon = _mon;\
00331 (x)->mday = _mday;\
00332 (x)->flags = _flags;\
00333 }
00334 #else
00335 #define set_to_simple(x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \
00336 {\
00337 (x)->nth = canon(_nth);\
00338 (x)->jd = _jd;\
00339 (x)->sg = (sg_cast)(_sg);\
00340 (x)->year = _year;\
00341 (x)->pc = PACK2(_mon, _mday);\
00342 (x)->flags = _flags;\
00343 }
00344 #endif
00345
00346 #ifndef USE_PACK
00347 #define set_to_complex(x, _nth, _jd ,_df, _sf, _of, _sg,\
00348 _year, _mon, _mday, _hour, _min, _sec, _flags) \
00349 {\
00350 (x)->nth = canon(_nth);\
00351 (x)->jd = _jd;\
00352 (x)->df = _df;\
00353 (x)->sf = canon(_sf);\
00354 (x)->of = _of;\
00355 (x)->sg = (sg_cast)(_sg);\
00356 (x)->year = _year;\
00357 (x)->mon = _mon;\
00358 (x)->mday = _mday;\
00359 (x)->hour = _hour;\
00360 (x)->min = _min;\
00361 (x)->sec = _sec;\
00362 (x)->flags = _flags;\
00363 }
00364 #else
00365 #define set_to_complex(x, _nth, _jd ,_df, _sf, _of, _sg,\
00366 _year, _mon, _mday, _hour, _min, _sec, _flags) \
00367 {\
00368 (x)->nth = canon(_nth);\
00369 (x)->jd = _jd;\
00370 (x)->df = _df;\
00371 (x)->sf = canon(_sf);\
00372 (x)->of = _of;\
00373 (x)->sg = (sg_cast)(_sg);\
00374 (x)->year = _year;\
00375 (x)->pc = PACK5(_mon, _mday, _hour, _min, _sec);\
00376 (x)->flags = _flags;\
00377 }
00378 #endif
00379
00380 #ifndef USE_PACK
00381 #define copy_simple_to_complex(x, y) \
00382 {\
00383 (x)->nth = (y)->nth;\
00384 (x)->jd = (y)->jd;\
00385 (x)->df = 0;\
00386 (x)->sf = INT2FIX(0);\
00387 (x)->of = 0;\
00388 (x)->sg = (sg_cast)((y)->sg);\
00389 (x)->year = (y)->year;\
00390 (x)->mon = (y)->mon;\
00391 (x)->mday = (y)->mday;\
00392 (x)->hour = 0;\
00393 (x)->min = 0;\
00394 (x)->sec = 0;\
00395 (x)->flags = (y)->flags;\
00396 }
00397 #else
00398 #define copy_simple_to_complex(x, y) \
00399 {\
00400 (x)->nth = (y)->nth;\
00401 (x)->jd = (y)->jd;\
00402 (x)->df = 0;\
00403 (x)->sf = INT2FIX(0);\
00404 (x)->of = 0;\
00405 (x)->sg = (sg_cast)((y)->sg);\
00406 (x)->year = (y)->year;\
00407 (x)->pc = PACK5(EX_MON((y)->pc), EX_MDAY((y)->pc), 0, 0, 0);\
00408 (x)->flags = (y)->flags;\
00409 }
00410 #endif
00411
00412 #ifndef USE_PACK
00413 #define copy_complex_to_simple(x, y) \
00414 {\
00415 (x)->nth = (y)->nth;\
00416 (x)->jd = (y)->jd;\
00417 (x)->sg = (sg_cast)((y)->sg);\
00418 (x)->year = (y)->year;\
00419 (x)->mon = (y)->mon;\
00420 (x)->mday = (y)->mday;\
00421 (x)->flags = (y)->flags;\
00422 }
00423 #else
00424 #define copy_complex_to_simple(x, y) \
00425 {\
00426 (x)->nth = (y)->nth;\
00427 (x)->jd = (y)->jd;\
00428 (x)->sg = (sg_cast)((y)->sg);\
00429 (x)->year = (y)->year;\
00430 (x)->pc = PACK2(EX_MON((y)->pc), EX_MDAY((y)->pc));\
00431 (x)->flags = (y)->flags;\
00432 }
00433 #endif
00434
00435
00436
00437 static int c_valid_civil_p(int, int, int, double,
00438 int *, int *, int *, int *);
00439
00440 static int
00441 c_find_fdoy(int y, double sg, int *rjd, int *ns)
00442 {
00443 int d, rm, rd;
00444
00445 for (d = 1; d < 31; d++)
00446 if (c_valid_civil_p(y, 1, d, sg, &rm, &rd, rjd, ns))
00447 return 1;
00448 return 0;
00449 }
00450
00451 static int
00452 c_find_ldoy(int y, double sg, int *rjd, int *ns)
00453 {
00454 int i, rm, rd;
00455
00456 for (i = 0; i < 30; i++)
00457 if (c_valid_civil_p(y, 12, 31 - i, sg, &rm, &rd, rjd, ns))
00458 return 1;
00459 return 0;
00460 }
00461
00462 #ifndef NDEBUG
00463 static int
00464 c_find_fdom(int y, int m, double sg, int *rjd, int *ns)
00465 {
00466 int d, rm, rd;
00467
00468 for (d = 1; d < 31; d++)
00469 if (c_valid_civil_p(y, m, d, sg, &rm, &rd, rjd, ns))
00470 return 1;
00471 return 0;
00472 }
00473 #endif
00474
00475 static int
00476 c_find_ldom(int y, int m, double sg, int *rjd, int *ns)
00477 {
00478 int i, rm, rd;
00479
00480 for (i = 0; i < 30; i++)
00481 if (c_valid_civil_p(y, m, 31 - i, sg, &rm, &rd, rjd, ns))
00482 return 1;
00483 return 0;
00484 }
00485
00486 static void
00487 c_civil_to_jd(int y, int m, int d, double sg, int *rjd, int *ns)
00488 {
00489 double a, b, jd;
00490
00491 if (m <= 2) {
00492 y -= 1;
00493 m += 12;
00494 }
00495 a = floor(y / 100.0);
00496 b = 2 - a + floor(a / 4.0);
00497 jd = floor(365.25 * (y + 4716)) +
00498 floor(30.6001 * (m + 1)) +
00499 d + b - 1524;
00500 if (jd < sg) {
00501 jd -= b;
00502 *ns = 0;
00503 }
00504 else
00505 *ns = 1;
00506
00507 *rjd = (int)jd;
00508 }
00509
00510 static void
00511 c_jd_to_civil(int jd, double sg, int *ry, int *rm, int *rdom)
00512 {
00513 double x, a, b, c, d, e, y, m, dom;
00514
00515 if (jd < sg)
00516 a = jd;
00517 else {
00518 x = floor((jd - 1867216.25) / 36524.25);
00519 a = jd + 1 + x - floor(x / 4.0);
00520 }
00521 b = a + 1524;
00522 c = floor((b - 122.1) / 365.25);
00523 d = floor(365.25 * c);
00524 e = floor((b - d) / 30.6001);
00525 dom = b - d - floor(30.6001 * e);
00526 if (e <= 13) {
00527 m = e - 1;
00528 y = c - 4716;
00529 }
00530 else {
00531 m = e - 13;
00532 y = c - 4715;
00533 }
00534
00535 *ry = (int)y;
00536 *rm = (int)m;
00537 *rdom = (int)dom;
00538 }
00539
00540 static void
00541 c_ordinal_to_jd(int y, int d, double sg, int *rjd, int *ns)
00542 {
00543 int ns2;
00544
00545 c_find_fdoy(y, sg, rjd, &ns2);
00546 *rjd += d - 1;
00547 *ns = (*rjd < sg) ? 0 : 1;
00548 }
00549
00550 static void
00551 c_jd_to_ordinal(int jd, double sg, int *ry, int *rd)
00552 {
00553 int rm2, rd2, rjd, ns;
00554
00555 c_jd_to_civil(jd, sg, ry, &rm2, &rd2);
00556 c_find_fdoy(*ry, sg, &rjd, &ns);
00557 *rd = (jd - rjd) + 1;
00558 }
00559
00560 static void
00561 c_commercial_to_jd(int y, int w, int d, double sg, int *rjd, int *ns)
00562 {
00563 int rjd2, ns2;
00564
00565 c_find_fdoy(y, sg, &rjd2, &ns2);
00566 rjd2 += 3;
00567 *rjd =
00568 (rjd2 - MOD((rjd2 - 1) + 1, 7)) +
00569 7 * (w - 1) +
00570 (d - 1);
00571 *ns = (*rjd < sg) ? 0 : 1;
00572 }
00573
00574 static void
00575 c_jd_to_commercial(int jd, double sg, int *ry, int *rw, int *rd)
00576 {
00577 int ry2, rm2, rd2, a, rjd2, ns2;
00578
00579 c_jd_to_civil(jd - 3, sg, &ry2, &rm2, &rd2);
00580 a = ry2;
00581 c_commercial_to_jd(a + 1, 1, 1, sg, &rjd2, &ns2);
00582 if (jd >= rjd2)
00583 *ry = a + 1;
00584 else {
00585 c_commercial_to_jd(a, 1, 1, sg, &rjd2, &ns2);
00586 *ry = a;
00587 }
00588 *rw = 1 + DIV(jd - rjd2, 7);
00589 *rd = MOD(jd + 1, 7);
00590 if (*rd == 0)
00591 *rd = 7;
00592 }
00593
00594 static void
00595 c_weeknum_to_jd(int y, int w, int d, int f, double sg, int *rjd, int *ns)
00596 {
00597 int rjd2, ns2;
00598
00599 c_find_fdoy(y, sg, &rjd2, &ns2);
00600 rjd2 += 6;
00601 *rjd = (rjd2 - MOD(((rjd2 - f) + 1), 7) - 7) + 7 * w + d;
00602 *ns = (*rjd < sg) ? 0 : 1;
00603 }
00604
00605 static void
00606 c_jd_to_weeknum(int jd, int f, double sg, int *ry, int *rw, int *rd)
00607 {
00608 int rm, rd2, rjd, ns, j;
00609
00610 c_jd_to_civil(jd, sg, ry, &rm, &rd2);
00611 c_find_fdoy(*ry, sg, &rjd, &ns);
00612 rjd += 6;
00613 j = jd - (rjd - MOD((rjd - f) + 1, 7)) + 7;
00614 *rw = (int)DIV(j, 7);
00615 *rd = (int)MOD(j, 7);
00616 }
00617
00618 #ifndef NDEBUG
00619 static void
00620 c_nth_kday_to_jd(int y, int m, int n, int k, double sg, int *rjd, int *ns)
00621 {
00622 int rjd2, ns2;
00623
00624 if (n > 0) {
00625 c_find_fdom(y, m, sg, &rjd2, &ns2);
00626 rjd2 -= 1;
00627 }
00628 else {
00629 c_find_ldom(y, m, sg, &rjd2, &ns2);
00630 rjd2 += 7;
00631 }
00632 *rjd = (rjd2 - MOD((rjd2 - k) + 1, 7)) + 7 * n;
00633 *ns = (*rjd < sg) ? 0 : 1;
00634 }
00635 #endif
00636
00637 inline static int
00638 c_jd_to_wday(int jd)
00639 {
00640 return MOD(jd + 1, 7);
00641 }
00642
00643 #ifndef NDEBUG
00644 static void
00645 c_jd_to_nth_kday(int jd, double sg, int *ry, int *rm, int *rn, int *rk)
00646 {
00647 int rd, rjd, ns2;
00648
00649 c_jd_to_civil(jd, sg, ry, rm, &rd);
00650 c_find_fdom(*ry, *rm, sg, &rjd, &ns2);
00651 *rn = DIV(jd - rjd, 7) + 1;
00652 *rk = c_jd_to_wday(jd);
00653 }
00654 #endif
00655
00656 static int
00657 c_valid_ordinal_p(int y, int d, double sg,
00658 int *rd, int *rjd, int *ns)
00659 {
00660 int ry2, rd2;
00661
00662 if (d < 0) {
00663 int rjd2, ns2;
00664
00665 if (!c_find_ldoy(y, sg, &rjd2, &ns2))
00666 return 0;
00667 c_jd_to_ordinal(rjd2 + d + 1, sg, &ry2, &rd2);
00668 if (ry2 != y)
00669 return 0;
00670 d = rd2;
00671 }
00672 c_ordinal_to_jd(y, d, sg, rjd, ns);
00673 c_jd_to_ordinal(*rjd, sg, &ry2, &rd2);
00674 if (ry2 != y || rd2 != d)
00675 return 0;
00676 return 1;
00677 }
00678
00679 static const int monthtab[2][13] = {
00680 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
00681 { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
00682 };
00683
00684 inline static int
00685 c_julian_leap_p(int y)
00686 {
00687 return MOD(y, 4) == 0;
00688 }
00689
00690 inline static int
00691 c_gregorian_leap_p(int y)
00692 {
00693 return MOD(y, 4) == 0 && y % 100 != 0 || MOD(y, 400) == 0;
00694 }
00695
00696 static int
00697 c_julian_last_day_of_month(int y, int m)
00698 {
00699 assert(m >= 1 && m <= 12);
00700 return monthtab[c_julian_leap_p(y) ? 1 : 0][m];
00701 }
00702
00703 static int
00704 c_gregorian_last_day_of_month(int y, int m)
00705 {
00706 assert(m >= 1 && m <= 12);
00707 return monthtab[c_gregorian_leap_p(y) ? 1 : 0][m];
00708 }
00709
00710 static int
00711 c_valid_julian_p(int y, int m, int d, int *rm, int *rd)
00712 {
00713 int last;
00714
00715 if (m < 0)
00716 m += 13;
00717 if (m < 1 || m > 12)
00718 return 0;
00719 last = c_julian_last_day_of_month(y, m);
00720 if (d < 0)
00721 d = last + d + 1;
00722 if (d < 1 || d > last)
00723 return 0;
00724 *rm = m;
00725 *rd = d;
00726 return 1;
00727 }
00728
00729 static int
00730 c_valid_gregorian_p(int y, int m, int d, int *rm, int *rd)
00731 {
00732 int last;
00733
00734 if (m < 0)
00735 m += 13;
00736 if (m < 1 || m > 12)
00737 return 0;
00738 last = c_gregorian_last_day_of_month(y, m);
00739 if (d < 0)
00740 d = last + d + 1;
00741 if (d < 1 || d > last)
00742 return 0;
00743 *rm = m;
00744 *rd = d;
00745 return 1;
00746 }
00747
00748 static int
00749 c_valid_civil_p(int y, int m, int d, double sg,
00750 int *rm, int *rd, int *rjd, int *ns)
00751 {
00752 int ry;
00753
00754 if (m < 0)
00755 m += 13;
00756 if (d < 0) {
00757 if (!c_find_ldom(y, m, sg, rjd, ns))
00758 return 0;
00759 c_jd_to_civil(*rjd + d + 1, sg, &ry, rm, rd);
00760 if (ry != y || *rm != m)
00761 return 0;
00762 d = *rd;
00763 }
00764 c_civil_to_jd(y, m, d, sg, rjd, ns);
00765 c_jd_to_civil(*rjd, sg, &ry, rm, rd);
00766 if (ry != y || *rm != m || *rd != d)
00767 return 0;
00768 return 1;
00769 }
00770
00771 static int
00772 c_valid_commercial_p(int y, int w, int d, double sg,
00773 int *rw, int *rd, int *rjd, int *ns)
00774 {
00775 int ns2, ry2, rw2, rd2;
00776
00777 if (d < 0)
00778 d += 8;
00779 if (w < 0) {
00780 int rjd2;
00781
00782 c_commercial_to_jd(y + 1, 1, 1, sg, &rjd2, &ns2);
00783 c_jd_to_commercial(rjd2 + w * 7, sg, &ry2, &rw2, &rd2);
00784 if (ry2 != y)
00785 return 0;
00786 w = rw2;
00787 }
00788 c_commercial_to_jd(y, w, d, sg, rjd, ns);
00789 c_jd_to_commercial(*rjd, sg, &ry2, rw, rd);
00790 if (y != ry2 || w != *rw || d != *rd)
00791 return 0;
00792 return 1;
00793 }
00794
00795 static int
00796 c_valid_weeknum_p(int y, int w, int d, int f, double sg,
00797 int *rw, int *rd, int *rjd, int *ns)
00798 {
00799 int ns2, ry2, rw2, rd2;
00800
00801 if (d < 0)
00802 d += 7;
00803 if (w < 0) {
00804 int rjd2;
00805
00806 c_weeknum_to_jd(y + 1, 1, f, f, sg, &rjd2, &ns2);
00807 c_jd_to_weeknum(rjd2 + w * 7, f, sg, &ry2, &rw2, &rd2);
00808 if (ry2 != y)
00809 return 0;
00810 w = rw2;
00811 }
00812 c_weeknum_to_jd(y, w, d, f, sg, rjd, ns);
00813 c_jd_to_weeknum(*rjd, f, sg, &ry2, rw, rd);
00814 if (y != ry2 || w != *rw || d != *rd)
00815 return 0;
00816 return 1;
00817 }
00818
00819 #ifndef NDEBUG
00820 static int
00821 c_valid_nth_kday_p(int y, int m, int n, int k, double sg,
00822 int *rm, int *rn, int *rk, int *rjd, int *ns)
00823 {
00824 int ns2, ry2, rm2, rn2, rk2;
00825
00826 if (k < 0)
00827 k += 7;
00828 if (n < 0) {
00829 int t, ny, nm, rjd2;
00830
00831 t = y * 12 + m;
00832 ny = DIV(t, 12);
00833 nm = MOD(t, 12) + 1;
00834
00835 c_nth_kday_to_jd(ny, nm, 1, k, sg, &rjd2, &ns2);
00836 c_jd_to_nth_kday(rjd2 + n * 7, sg, &ry2, &rm2, &rn2, &rk2);
00837 if (ry2 != y || rm2 != m)
00838 return 0;
00839 n = rn2;
00840 }
00841 c_nth_kday_to_jd(y, m, n, k, sg, rjd, ns);
00842 c_jd_to_nth_kday(*rjd, sg, &ry2, rm, rn, rk);
00843 if (y != ry2 || m != *rm || n != *rn || k != *rk)
00844 return 0;
00845 return 1;
00846 }
00847 #endif
00848
00849 static int
00850 c_valid_time_p(int h, int min, int s, int *rh, int *rmin, int *rs)
00851 {
00852 if (h < 0)
00853 h += 24;
00854 if (min < 0)
00855 min += 60;
00856 if (s < 0)
00857 s += 60;
00858 *rh = h;
00859 *rmin = min;
00860 *rs = s;
00861 return !(h < 0 || h > 24 ||
00862 min < 0 || min > 59 ||
00863 s < 0 || s > 59 ||
00864 (h == 24 && (min > 0 || s > 0)));
00865 }
00866
00867 inline static int
00868 c_valid_start_p(double sg)
00869 {
00870 if (isnan(sg))
00871 return 0;
00872 if (isinf(sg))
00873 return 1;
00874 if (sg < REFORM_BEGIN_JD || sg > REFORM_END_JD)
00875 return 0;
00876 return 1;
00877 }
00878
00879 inline static int
00880 df_local_to_utc(int df, int of)
00881 {
00882 df -= of;
00883 if (df < 0)
00884 df += DAY_IN_SECONDS;
00885 else if (df >= DAY_IN_SECONDS)
00886 df -= DAY_IN_SECONDS;
00887 return df;
00888 }
00889
00890 inline static int
00891 df_utc_to_local(int df, int of)
00892 {
00893 df += of;
00894 if (df < 0)
00895 df += DAY_IN_SECONDS;
00896 else if (df >= DAY_IN_SECONDS)
00897 df -= DAY_IN_SECONDS;
00898 return df;
00899 }
00900
00901 inline static int
00902 jd_local_to_utc(int jd, int df, int of)
00903 {
00904 df -= of;
00905 if (df < 0)
00906 jd -= 1;
00907 else if (df >= DAY_IN_SECONDS)
00908 jd += 1;
00909 return jd;
00910 }
00911
00912 inline static int
00913 jd_utc_to_local(int jd, int df, int of)
00914 {
00915 df += of;
00916 if (df < 0)
00917 jd -= 1;
00918 else if (df >= DAY_IN_SECONDS)
00919 jd += 1;
00920 return jd;
00921 }
00922
00923 inline static int
00924 time_to_df(int h, int min, int s)
00925 {
00926 return h * HOUR_IN_SECONDS + min * MINUTE_IN_SECONDS + s;
00927 }
00928
00929 inline static void
00930 df_to_time(int df, int *h, int *min, int *s)
00931 {
00932 *h = df / HOUR_IN_SECONDS;
00933 df %= HOUR_IN_SECONDS;
00934 *min = df / MINUTE_IN_SECONDS;
00935 *s = df % MINUTE_IN_SECONDS;
00936 }
00937
00938 static VALUE
00939 sec_to_day(VALUE s)
00940 {
00941 if (FIXNUM_P(s))
00942 return rb_rational_new2(s, INT2FIX(DAY_IN_SECONDS));
00943 return f_quo(s, INT2FIX(DAY_IN_SECONDS));
00944 }
00945
00946 inline static VALUE
00947 isec_to_day(int s)
00948 {
00949 return sec_to_day(INT2FIX(s));
00950 }
00951
00952 static VALUE
00953 ns_to_day(VALUE n)
00954 {
00955 if (FIXNUM_P(n))
00956 return rb_rational_new2(n, day_in_nanoseconds);
00957 return f_quo(n, day_in_nanoseconds);
00958 }
00959
00960 #ifndef NDEBUG
00961 static VALUE
00962 ms_to_sec(VALUE m)
00963 {
00964 if (FIXNUM_P(m))
00965 return rb_rational_new2(m, INT2FIX(SECOND_IN_MILLISECONDS));
00966 return f_quo(m, INT2FIX(SECOND_IN_MILLISECONDS));
00967 }
00968 #endif
00969
00970 static VALUE
00971 ns_to_sec(VALUE n)
00972 {
00973 if (FIXNUM_P(n))
00974 return rb_rational_new2(n, INT2FIX(SECOND_IN_NANOSECONDS));
00975 return f_quo(n, INT2FIX(SECOND_IN_NANOSECONDS));
00976 }
00977
00978 #ifndef NDEBUG
00979 inline static VALUE
00980 ins_to_day(int n)
00981 {
00982 return ns_to_day(INT2FIX(n));
00983 }
00984 #endif
00985
00986 static int
00987 safe_mul_p(VALUE x, long m)
00988 {
00989 long ix;
00990
00991 if (!FIXNUM_P(x))
00992 return 0;
00993 ix = FIX2LONG(x);
00994 if (ix < 0) {
00995 if (ix <= (FIXNUM_MIN / m))
00996 return 0;
00997 }
00998 else {
00999 if (ix >= (FIXNUM_MAX / m))
01000 return 0;
01001 }
01002 return 1;
01003 }
01004
01005 static VALUE
01006 day_to_sec(VALUE d)
01007 {
01008 if (safe_mul_p(d, DAY_IN_SECONDS))
01009 return LONG2FIX(FIX2LONG(d) * DAY_IN_SECONDS);
01010 return f_mul(d, INT2FIX(DAY_IN_SECONDS));
01011 }
01012
01013 #ifndef NDEBUG
01014 static VALUE
01015 day_to_ns(VALUE d)
01016 {
01017 return f_mul(d, day_in_nanoseconds);
01018 }
01019 #endif
01020
01021 static VALUE
01022 sec_to_ms(VALUE s)
01023 {
01024 if (safe_mul_p(s, SECOND_IN_MILLISECONDS))
01025 return LONG2FIX(FIX2LONG(s) * SECOND_IN_MILLISECONDS);
01026 return f_mul(s, INT2FIX(SECOND_IN_MILLISECONDS));
01027 }
01028
01029 static VALUE
01030 sec_to_ns(VALUE s)
01031 {
01032 if (safe_mul_p(s, SECOND_IN_NANOSECONDS))
01033 return LONG2FIX(FIX2LONG(s) * SECOND_IN_NANOSECONDS);
01034 return f_mul(s, INT2FIX(SECOND_IN_NANOSECONDS));
01035 }
01036
01037 #ifndef NDEBUG
01038 static VALUE
01039 isec_to_ns(int s)
01040 {
01041 return sec_to_ns(INT2FIX(s));
01042 }
01043 #endif
01044
01045 static VALUE
01046 div_day(VALUE d, VALUE *f)
01047 {
01048 if (f)
01049 *f = f_mod(d, INT2FIX(1));
01050 return f_floor(d);
01051 }
01052
01053 static VALUE
01054 div_df(VALUE d, VALUE *f)
01055 {
01056 VALUE s = day_to_sec(d);
01057
01058 if (f)
01059 *f = f_mod(s, INT2FIX(1));
01060 return f_floor(s);
01061 }
01062
01063 #ifndef NDEBUG
01064 static VALUE
01065 div_sf(VALUE s, VALUE *f)
01066 {
01067 VALUE n = sec_to_ns(s);
01068
01069 if (f)
01070 *f = f_mod(n, INT2FIX(1));
01071 return f_floor(n);
01072 }
01073 #endif
01074
01075 static void
01076 decode_day(VALUE d, VALUE *jd, VALUE *df, VALUE *sf)
01077 {
01078 VALUE f;
01079
01080 *jd = div_day(d, &f);
01081 *df = div_df(f, &f);
01082 *sf = sec_to_ns(f);
01083 }
01084
01085 inline static double
01086 s_virtual_sg(union DateData *x)
01087 {
01088 if (isinf(x->s.sg))
01089 return x->s.sg;
01090 if (f_zero_p(x->s.nth))
01091 return x->s.sg;
01092 else if (f_negative_p(x->s.nth))
01093 return positive_inf;
01094 return negative_inf;
01095 }
01096
01097 inline static double
01098 c_virtual_sg(union DateData *x)
01099 {
01100 if (isinf(x->c.sg))
01101 return x->c.sg;
01102 if (f_zero_p(x->c.nth))
01103 return x->c.sg;
01104 else if (f_negative_p(x->c.nth))
01105 return positive_inf;
01106 return negative_inf;
01107 }
01108
01109 inline static double
01110 m_virtual_sg(union DateData *x)
01111 {
01112 if (simple_dat_p(x))
01113 return s_virtual_sg(x);
01114 else
01115 return c_virtual_sg(x);
01116 }
01117
01118 #define canonicalize_jd(_nth, _jd) \
01119 {\
01120 if (_jd < 0) {\
01121 _nth = f_sub(_nth, INT2FIX(1));\
01122 _jd += CM_PERIOD;\
01123 }\
01124 if (_jd >= CM_PERIOD) {\
01125 _nth = f_add(_nth, INT2FIX(1));\
01126 _jd -= CM_PERIOD;\
01127 }\
01128 }
01129
01130 inline static void
01131 canonicalize_s_jd(union DateData *x)
01132 {
01133 int j = x->s.jd;
01134 assert(have_jd_p(x));
01135 canonicalize_jd(x->s.nth, x->s.jd);
01136 if (x->s.jd != j)
01137 x->flags &= ~HAVE_CIVIL;
01138 }
01139
01140 inline static void
01141 get_s_jd(union DateData *x)
01142 {
01143 assert(simple_dat_p(x));
01144 if (!have_jd_p(x)) {
01145 int jd, ns;
01146
01147 assert(have_civil_p(x));
01148 #ifndef USE_PACK
01149 c_civil_to_jd(x->s.year, x->s.mon, x->s.mday,
01150 s_virtual_sg(x), &jd, &ns);
01151 #else
01152 c_civil_to_jd(x->s.year, EX_MON(x->s.pc), EX_MDAY(x->s.pc),
01153 s_virtual_sg(x), &jd, &ns);
01154 #endif
01155 x->s.jd = jd;
01156 x->s.flags |= HAVE_JD;
01157 }
01158 }
01159
01160 inline static void
01161 get_s_civil(union DateData *x)
01162 {
01163 assert(simple_dat_p(x));
01164 if (!have_civil_p(x)) {
01165 int y, m, d;
01166
01167 assert(have_jd_p(x));
01168 c_jd_to_civil(x->s.jd, s_virtual_sg(x), &y, &m, &d);
01169 x->s.year = y;
01170 #ifndef USE_PACK
01171 x->s.mon = m;
01172 x->s.mday = d;
01173 #else
01174 x->s.pc = PACK2(m, d);
01175 #endif
01176 x->s.flags |= HAVE_CIVIL;
01177 }
01178 }
01179
01180 inline static void
01181 get_c_df(union DateData *x)
01182 {
01183 assert(complex_dat_p(x));
01184 if (!have_df_p(x)) {
01185 assert(have_time_p(x));
01186 #ifndef USE_PACK
01187 x->c.df = df_local_to_utc(time_to_df(x->c.hour, x->c.min, x->c.sec),
01188 x->c.of);
01189 #else
01190 x->c.df = df_local_to_utc(time_to_df(EX_HOUR(x->c.pc),
01191 EX_MIN(x->c.pc),
01192 EX_SEC(x->c.pc)),
01193 x->c.of);
01194 #endif
01195 x->c.flags |= HAVE_DF;
01196 }
01197 }
01198
01199 inline static void
01200 get_c_time(union DateData *x)
01201 {
01202 assert(complex_dat_p(x));
01203 if (!have_time_p(x)) {
01204 #ifndef USE_PACK
01205 int r;
01206 assert(have_df_p(x));
01207 r = df_utc_to_local(x->c.df, x->c.of);
01208 df_to_time(r, &x->c.hour, &x->c.min, &x->c.sec);
01209 x->c.flags |= HAVE_TIME;
01210 #else
01211 int r, m, d, h, min, s;
01212
01213 assert(have_df_p(x));
01214 m = EX_MON(x->c.pc);
01215 d = EX_MDAY(x->c.pc);
01216 r = df_utc_to_local(x->c.df, x->c.of);
01217 df_to_time(r, &h, &min, &s);
01218 x->c.pc = PACK5(m, d, h, min, s);
01219 x->c.flags |= HAVE_TIME;
01220 #endif
01221 }
01222 }
01223
01224 inline static void
01225 canonicalize_c_jd(union DateData *x)
01226 {
01227 int j = x->c.jd;
01228 assert(have_jd_p(x));
01229 canonicalize_jd(x->c.nth, x->c.jd);
01230 if (x->c.jd != j)
01231 x->flags &= ~HAVE_CIVIL;
01232 }
01233
01234 inline static void
01235 get_c_jd(union DateData *x)
01236 {
01237 assert(complex_dat_p(x));
01238 if (!have_jd_p(x)) {
01239 int jd, ns;
01240
01241 assert(have_civil_p(x));
01242 #ifndef USE_PACK
01243 c_civil_to_jd(x->c.year, x->c.mon, x->c.mday,
01244 c_virtual_sg(x), &jd, &ns);
01245 #else
01246 c_civil_to_jd(x->c.year, EX_MON(x->c.pc), EX_MDAY(x->c.pc),
01247 c_virtual_sg(x), &jd, &ns);
01248 #endif
01249
01250 get_c_time(x);
01251 #ifndef USE_PACK
01252 x->c.jd = jd_local_to_utc(jd,
01253 time_to_df(x->c.hour, x->c.min, x->c.sec),
01254 x->c.of);
01255 #else
01256 x->c.jd = jd_local_to_utc(jd,
01257 time_to_df(EX_HOUR(x->c.pc),
01258 EX_MIN(x->c.pc),
01259 EX_SEC(x->c.pc)),
01260 x->c.of);
01261 #endif
01262 x->c.flags |= HAVE_JD;
01263 }
01264 }
01265
01266 inline static void
01267 get_c_civil(union DateData *x)
01268 {
01269 assert(complex_dat_p(x));
01270 if (!have_civil_p(x)) {
01271 #ifndef USE_PACK
01272 int jd, y, m, d;
01273 #else
01274 int jd, y, m, d, h, min, s;
01275 #endif
01276
01277 assert(have_jd_p(x));
01278 get_c_df(x);
01279 jd = jd_utc_to_local(x->c.jd, x->c.df, x->c.of);
01280 c_jd_to_civil(jd, c_virtual_sg(x), &y, &m, &d);
01281 x->c.year = y;
01282 #ifndef USE_PACK
01283 x->c.mon = m;
01284 x->c.mday = d;
01285 #else
01286 h = EX_HOUR(x->c.pc);
01287 min = EX_MIN(x->c.pc);
01288 s = EX_SEC(x->c.pc);
01289 x->c.pc = PACK5(m, d, h, min, s);
01290 #endif
01291 x->c.flags |= HAVE_CIVIL;
01292 }
01293 }
01294
01295 inline static int
01296 local_jd(union DateData *x)
01297 {
01298 assert(complex_dat_p(x));
01299 assert(have_jd_p(x));
01300 assert(have_df_p(x));
01301 return jd_utc_to_local(x->c.jd, x->c.df, x->c.of);
01302 }
01303
01304 inline static int
01305 local_df(union DateData *x)
01306 {
01307 assert(complex_dat_p(x));
01308 assert(have_df_p(x));
01309 return df_utc_to_local(x->c.df, x->c.of);
01310 }
01311
01312 static void
01313 decode_year(VALUE y, double style,
01314 VALUE *nth, int *ry)
01315 {
01316 int period;
01317 VALUE t;
01318
01319 period = (style < 0) ?
01320 CM_PERIOD_GCY :
01321 CM_PERIOD_JCY;
01322 if (FIXNUM_P(y)) {
01323 long iy, it, inth;
01324
01325 iy = FIX2LONG(y);
01326 if (iy >= (FIXNUM_MAX - 4712))
01327 goto big;
01328 it = iy + 4712;
01329 inth = DIV(it, ((long)period));
01330 *nth = LONG2FIX(inth);
01331 if (inth)
01332 it = MOD(it, ((long)period));
01333 *ry = (int)it - 4712;
01334 return;
01335 }
01336 big:
01337 t = f_add(y, INT2FIX(4712));
01338 *nth = f_idiv(t, INT2FIX(period));
01339 if (f_nonzero_p(*nth))
01340 t = f_mod(t, INT2FIX(period));
01341 *ry = FIX2INT(t) - 4712;
01342 }
01343
01344 static void
01345 encode_year(VALUE nth, int y, double style,
01346 VALUE *ry)
01347 {
01348 int period;
01349 VALUE t;
01350
01351 period = (style < 0) ?
01352 CM_PERIOD_GCY :
01353 CM_PERIOD_JCY;
01354 if (f_zero_p(nth))
01355 *ry = INT2FIX(y);
01356 else {
01357 t = f_mul(INT2FIX(period), nth);
01358 t = f_add(t, INT2FIX(y));
01359 *ry = t;
01360 }
01361 }
01362
01363 static void
01364 decode_jd(VALUE jd, VALUE *nth, int *rjd)
01365 {
01366 assert(FIXNUM_P(jd) || RB_TYPE_P(jd, T_BIGNUM));
01367 *nth = f_idiv(jd, INT2FIX(CM_PERIOD));
01368 if (f_zero_p(*nth)) {
01369 assert(FIXNUM_P(jd));
01370 *rjd = FIX2INT(jd);
01371 return;
01372 }
01373 *rjd = FIX2INT(f_mod(jd, INT2FIX(CM_PERIOD)));
01374 }
01375
01376 static void
01377 encode_jd(VALUE nth, int jd, VALUE *rjd)
01378 {
01379 if (f_zero_p(nth)) {
01380 *rjd = INT2FIX(jd);
01381 return;
01382 }
01383 *rjd = f_add(f_mul(INT2FIX(CM_PERIOD), nth), INT2FIX(jd));
01384 }
01385
01386 inline static double
01387 guess_style(VALUE y, double sg)
01388 {
01389 double style = 0;
01390
01391 if (isinf(sg))
01392 style = sg;
01393 else if (!FIXNUM_P(y))
01394 style = f_positive_p(y) ? negative_inf : positive_inf;
01395 else {
01396 long iy = FIX2LONG(y);
01397
01398 assert(FIXNUM_P(y));
01399 if (iy < REFORM_BEGIN_YEAR)
01400 style = positive_inf;
01401 else if (iy > REFORM_END_YEAR)
01402 style = negative_inf;
01403 }
01404 return style;
01405 }
01406
01407 inline static void
01408 m_canonicalize_jd(union DateData *x)
01409 {
01410 if (simple_dat_p(x)) {
01411 get_s_jd(x);
01412 canonicalize_s_jd(x);
01413 }
01414 else {
01415 get_c_jd(x);
01416 canonicalize_c_jd(x);
01417 }
01418 }
01419
01420 inline static VALUE
01421 m_nth(union DateData *x)
01422 {
01423 if (simple_dat_p(x))
01424 return x->s.nth;
01425 else {
01426 get_c_civil(x);
01427 return x->c.nth;
01428 }
01429 }
01430
01431 inline static int
01432 m_jd(union DateData *x)
01433 {
01434 if (simple_dat_p(x)) {
01435 get_s_jd(x);
01436 return x->s.jd;
01437 }
01438 else {
01439 get_c_jd(x);
01440 return x->c.jd;
01441 }
01442 }
01443
01444 static VALUE
01445 m_real_jd(union DateData *x)
01446 {
01447 VALUE nth, rjd;
01448 int jd;
01449
01450 nth = m_nth(x);
01451 jd = m_jd(x);
01452
01453 encode_jd(nth, jd, &rjd);
01454 return rjd;
01455 }
01456
01457 static int
01458 m_local_jd(union DateData *x)
01459 {
01460 if (simple_dat_p(x)) {
01461 get_s_jd(x);
01462 return x->s.jd;
01463 }
01464 else {
01465 get_c_jd(x);
01466 get_c_df(x);
01467 return local_jd(x);
01468 }
01469 }
01470
01471 static VALUE
01472 m_real_local_jd(union DateData *x)
01473 {
01474 VALUE nth, rjd;
01475 int jd;
01476
01477 nth = m_nth(x);
01478 jd = m_local_jd(x);
01479
01480 encode_jd(nth, jd, &rjd);
01481 return rjd;
01482 }
01483
01484 inline static int
01485 m_df(union DateData *x)
01486 {
01487 if (simple_dat_p(x))
01488 return 0;
01489 else {
01490 get_c_df(x);
01491 return x->c.df;
01492 }
01493 }
01494
01495 #ifndef NDEBUG
01496 static VALUE
01497 m_df_in_day(union DateData *x)
01498 {
01499 return isec_to_day(m_df(x));
01500 }
01501 #endif
01502
01503 static int
01504 m_local_df(union DateData *x)
01505 {
01506 if (simple_dat_p(x))
01507 return 0;
01508 else {
01509 get_c_df(x);
01510 return local_df(x);
01511 }
01512 }
01513
01514 #ifndef NDEBUG
01515 static VALUE
01516 m_local_df_in_day(union DateData *x)
01517 {
01518 return isec_to_day(m_local_df(x));
01519 }
01520 #endif
01521
01522 inline static VALUE
01523 m_sf(union DateData *x)
01524 {
01525 if (simple_dat_p(x))
01526 return INT2FIX(0);
01527 else
01528 return x->c.sf;
01529 }
01530
01531 #ifndef NDEBUG
01532 static VALUE
01533 m_sf_in_day(union DateData *x)
01534 {
01535 return ns_to_day(m_sf(x));
01536 }
01537 #endif
01538
01539 static VALUE
01540 m_sf_in_sec(union DateData *x)
01541 {
01542 return ns_to_sec(m_sf(x));
01543 }
01544
01545 static VALUE
01546 m_fr(union DateData *x)
01547 {
01548 if (simple_dat_p(x))
01549 return INT2FIX(0);
01550 else {
01551 int df;
01552 VALUE sf, fr;
01553
01554 df = m_local_df(x);
01555 sf = m_sf(x);
01556 fr = isec_to_day(df);
01557 if (f_nonzero_p(sf))
01558 fr = f_add(fr, ns_to_day(sf));
01559 return fr;
01560 }
01561 }
01562
01563 #define HALF_DAYS_IN_SECONDS (DAY_IN_SECONDS / 2)
01564
01565 static VALUE
01566 m_ajd(union DateData *x)
01567 {
01568 VALUE r, sf;
01569 int df;
01570
01571 if (simple_dat_p(x)) {
01572 r = m_real_jd(x);
01573 if (FIXNUM_P(r) && FIX2LONG(r) <= (FIXNUM_MAX / 2)) {
01574 long ir = FIX2LONG(r);
01575 ir = ir * 2 - 1;
01576 return rb_rational_new2(LONG2FIX(ir), INT2FIX(2));
01577 }
01578 else
01579 return rb_rational_new2(f_sub(f_mul(r,
01580 INT2FIX(2)),
01581 INT2FIX(1)),
01582 INT2FIX(2));
01583 }
01584
01585 r = m_real_jd(x);
01586 df = m_df(x);
01587 df -= HALF_DAYS_IN_SECONDS;
01588 if (df)
01589 r = f_add(r, isec_to_day(df));
01590 sf = m_sf(x);
01591 if (f_nonzero_p(sf))
01592 r = f_add(r, ns_to_day(sf));
01593
01594 return r;
01595 }
01596
01597 static VALUE
01598 m_amjd(union DateData *x)
01599 {
01600 VALUE r, sf;
01601 int df;
01602
01603 r = m_real_jd(x);
01604 if (FIXNUM_P(r) && FIX2LONG(r) >= (FIXNUM_MIN + 2400001)) {
01605 long ir = FIX2LONG(r);
01606 ir -= 2400001;
01607 r = rb_rational_new1(LONG2FIX(ir));
01608 }
01609 else
01610 r = rb_rational_new1(f_sub(m_real_jd(x),
01611 INT2FIX(2400001)));
01612
01613 if (simple_dat_p(x))
01614 return r;
01615
01616 df = m_df(x);
01617 if (df)
01618 r = f_add(r, isec_to_day(df));
01619 sf = m_sf(x);
01620 if (f_nonzero_p(sf))
01621 r = f_add(r, ns_to_day(sf));
01622
01623 return r;
01624 }
01625
01626 inline static int
01627 m_of(union DateData *x)
01628 {
01629 if (simple_dat_p(x))
01630 return 0;
01631 else {
01632 get_c_jd(x);
01633 return x->c.of;
01634 }
01635 }
01636
01637 static VALUE
01638 m_of_in_day(union DateData *x)
01639 {
01640 return isec_to_day(m_of(x));
01641 }
01642
01643 inline static double
01644 m_sg(union DateData *x)
01645 {
01646 if (simple_dat_p(x))
01647 return x->s.sg;
01648 else {
01649 get_c_jd(x);
01650 return x->c.sg;
01651 }
01652 }
01653
01654 static int
01655 m_julian_p(union DateData *x)
01656 {
01657 int jd;
01658 double sg;
01659
01660 if (simple_dat_p(x)) {
01661 get_s_jd(x);
01662 jd = x->s.jd;
01663 sg = s_virtual_sg(x);
01664 }
01665 else {
01666 get_c_jd(x);
01667 jd = x->c.jd;
01668 sg = c_virtual_sg(x);
01669 }
01670 if (isinf(sg))
01671 return sg == positive_inf;
01672 return jd < sg;
01673 }
01674
01675 inline static int
01676 m_gregorian_p(union DateData *x)
01677 {
01678 return !m_julian_p(x);
01679 }
01680
01681 inline static int
01682 m_proleptic_julian_p(union DateData *x)
01683 {
01684 double sg;
01685
01686 sg = m_sg(x);
01687 if (isinf(sg) && sg > 0)
01688 return 1;
01689 return 0;
01690 }
01691
01692 inline static int
01693 m_proleptic_gregorian_p(union DateData *x)
01694 {
01695 double sg;
01696
01697 sg = m_sg(x);
01698 if (isinf(sg) && sg < 0)
01699 return 1;
01700 return 0;
01701 }
01702
01703 inline static int
01704 m_year(union DateData *x)
01705 {
01706 if (simple_dat_p(x)) {
01707 get_s_civil(x);
01708 return x->s.year;
01709 }
01710 else {
01711 get_c_civil(x);
01712 return x->c.year;
01713 }
01714 }
01715
01716 static VALUE
01717 m_real_year(union DateData *x)
01718 {
01719 VALUE nth, ry;
01720 int year;
01721
01722 nth = m_nth(x);
01723 year = m_year(x);
01724
01725 if (f_zero_p(nth))
01726 return INT2FIX(year);
01727
01728 encode_year(nth, year,
01729 m_gregorian_p(x) ? -1 : +1,
01730 &ry);
01731 return ry;
01732 }
01733
01734
01735 #ifdef USE_PACK
01736 inline static int
01737 m_pc(union DateData *x)
01738 {
01739 if (simple_dat_p(x)) {
01740 get_s_civil(x);
01741 return x->s.pc;
01742 }
01743 else {
01744 get_c_civil(x);
01745 get_c_time(x);
01746 return x->c.pc;
01747 }
01748 }
01749 #endif
01750
01751 inline static int
01752 m_mon(union DateData *x)
01753 {
01754 if (simple_dat_p(x)) {
01755 get_s_civil(x);
01756 #ifndef USE_PACK
01757 return x->s.mon;
01758 #else
01759 return EX_MON(x->s.pc);
01760 #endif
01761 }
01762 else {
01763 get_c_civil(x);
01764 #ifndef USE_PACK
01765 return x->c.mon;
01766 #else
01767 return EX_MON(x->c.pc);
01768 #endif
01769 }
01770 }
01771
01772 inline static int
01773 m_mday(union DateData *x)
01774 {
01775 if (simple_dat_p(x)) {
01776 get_s_civil(x);
01777 #ifndef USE_PACK
01778 return x->s.mday;
01779 #else
01780 return EX_MDAY(x->s.pc);
01781 #endif
01782 }
01783 else {
01784 get_c_civil(x);
01785 #ifndef USE_PACK
01786 return x->c.mday;
01787 #else
01788 return EX_MDAY(x->c.pc);
01789 #endif
01790 }
01791 }
01792
01793 static const int yeartab[2][13] = {
01794 { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
01795 { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
01796 };
01797
01798 static int
01799 c_julian_to_yday(int y, int m, int d)
01800 {
01801 assert(m >= 1 && m <= 12);
01802 return yeartab[c_julian_leap_p(y) ? 1 : 0][m] + d;
01803 }
01804
01805 static int
01806 c_gregorian_to_yday(int y, int m, int d)
01807 {
01808 assert(m >= 1 && m <= 12);
01809 return yeartab[c_gregorian_leap_p(y) ? 1 : 0][m] + d;
01810 }
01811
01812 static int
01813 m_yday(union DateData *x)
01814 {
01815 int jd, ry, rd;
01816 double sg;
01817
01818 jd = m_local_jd(x);
01819 sg = m_virtual_sg(x);
01820
01821 if (m_proleptic_gregorian_p(x) ||
01822 (jd - sg) > 366)
01823 return c_gregorian_to_yday(m_year(x), m_mon(x), m_mday(x));
01824 if (m_proleptic_julian_p(x))
01825 return c_julian_to_yday(m_year(x), m_mon(x), m_mday(x));
01826 c_jd_to_ordinal(jd, sg, &ry, &rd);
01827 return rd;
01828 }
01829
01830 static int
01831 m_wday(union DateData *x)
01832 {
01833 return c_jd_to_wday(m_local_jd(x));
01834 }
01835
01836 static int
01837 m_cwyear(union DateData *x)
01838 {
01839 int ry, rw, rd;
01840
01841 c_jd_to_commercial(m_local_jd(x), m_virtual_sg(x),
01842 &ry, &rw, &rd);
01843 return ry;
01844 }
01845
01846 static VALUE
01847 m_real_cwyear(union DateData *x)
01848 {
01849 VALUE nth, ry;
01850 int year;
01851
01852 nth = m_nth(x);
01853 year = m_cwyear(x);
01854
01855 if (f_zero_p(nth))
01856 return INT2FIX(year);
01857
01858 encode_year(nth, year,
01859 m_gregorian_p(x) ? -1 : +1,
01860 &ry);
01861 return ry;
01862 }
01863
01864 static int
01865 m_cweek(union DateData *x)
01866 {
01867 int ry, rw, rd;
01868
01869 c_jd_to_commercial(m_local_jd(x), m_virtual_sg(x),
01870 &ry, &rw, &rd);
01871 return rw;
01872 }
01873
01874 static int
01875 m_cwday(union DateData *x)
01876 {
01877 int w;
01878
01879 w = m_wday(x);
01880 if (w == 0)
01881 w = 7;
01882 return w;
01883 }
01884
01885 static int
01886 m_wnumx(union DateData *x, int f)
01887 {
01888 int ry, rw, rd;
01889
01890 c_jd_to_weeknum(m_local_jd(x), f, m_virtual_sg(x),
01891 &ry, &rw, &rd);
01892 return rw;
01893 }
01894
01895 static int
01896 m_wnum0(union DateData *x)
01897 {
01898 return m_wnumx(x, 0);
01899 }
01900
01901 static int
01902 m_wnum1(union DateData *x)
01903 {
01904 return m_wnumx(x, 1);
01905 }
01906
01907 inline static int
01908 m_hour(union DateData *x)
01909 {
01910 if (simple_dat_p(x))
01911 return 0;
01912 else {
01913 get_c_time(x);
01914 #ifndef USE_PACK
01915 return x->c.hour;
01916 #else
01917 return EX_HOUR(x->c.pc);
01918 #endif
01919 }
01920 }
01921
01922 inline static int
01923 m_min(union DateData *x)
01924 {
01925 if (simple_dat_p(x))
01926 return 0;
01927 else {
01928 get_c_time(x);
01929 #ifndef USE_PACK
01930 return x->c.min;
01931 #else
01932 return EX_MIN(x->c.pc);
01933 #endif
01934 }
01935 }
01936
01937 inline static int
01938 m_sec(union DateData *x)
01939 {
01940 if (simple_dat_p(x))
01941 return 0;
01942 else {
01943 get_c_time(x);
01944 #ifndef USE_PACK
01945 return x->c.sec;
01946 #else
01947 return EX_SEC(x->c.pc);
01948 #endif
01949 }
01950 }
01951
01952 #define decode_offset(of,s,h,m)\
01953 {\
01954 int a;\
01955 s = (of < 0) ? '-' : '+';\
01956 a = (of < 0) ? -of : of;\
01957 h = a / HOUR_IN_SECONDS;\
01958 m = a % HOUR_IN_SECONDS / MINUTE_IN_SECONDS;\
01959 }
01960
01961 static VALUE
01962 of2str(int of)
01963 {
01964 int s, h, m;
01965
01966 decode_offset(of, s, h, m);
01967 return rb_enc_sprintf(rb_usascii_encoding(), "%c%02d:%02d", s, h, m);
01968 }
01969
01970 static VALUE
01971 m_zone(union DateData *x)
01972 {
01973 if (simple_dat_p(x))
01974 return rb_usascii_str_new2("+00:00");
01975 return of2str(m_of(x));
01976 }
01977
01978 inline static VALUE
01979 f_kind_of_p(VALUE x, VALUE c)
01980 {
01981 return rb_obj_is_kind_of(x, c);
01982 }
01983
01984 inline static VALUE
01985 k_date_p(VALUE x)
01986 {
01987 return f_kind_of_p(x, cDate);
01988 }
01989
01990 inline static VALUE
01991 k_datetime_p(VALUE x)
01992 {
01993 return f_kind_of_p(x, cDateTime);
01994 }
01995
01996 inline static VALUE
01997 k_numeric_p(VALUE x)
01998 {
01999 return f_kind_of_p(x, rb_cNumeric);
02000 }
02001
02002 inline static VALUE
02003 k_rational_p(VALUE x)
02004 {
02005 return f_kind_of_p(x, rb_cRational);
02006 }
02007
02008 #ifndef NDEBUG
02009 static void
02010 civil_to_jd(VALUE y, int m, int d, double sg,
02011 VALUE *nth, int *ry,
02012 int *rjd,
02013 int *ns)
02014 {
02015 double style = guess_style(y, sg);
02016
02017 if (style == 0) {
02018 int jd;
02019
02020 c_civil_to_jd(FIX2INT(y), m, d, sg, &jd, ns);
02021 decode_jd(INT2FIX(jd), nth, rjd);
02022 if (f_zero_p(*nth))
02023 *ry = FIX2INT(y);
02024 else {
02025 VALUE nth2;
02026 decode_year(y, *ns ? -1 : +1, &nth2, ry);
02027 }
02028 }
02029 else {
02030 decode_year(y, style, nth, ry);
02031 c_civil_to_jd(*ry, m, d, style, rjd, ns);
02032 }
02033 }
02034
02035 static void
02036 jd_to_civil(VALUE jd, double sg,
02037 VALUE *nth, int *rjd,
02038 int *ry, int *rm, int *rd)
02039 {
02040 decode_jd(jd, nth, rjd);
02041 c_jd_to_civil(*rjd, sg, ry, rm, rd);
02042 }
02043
02044 static void
02045 ordinal_to_jd(VALUE y, int d, double sg,
02046 VALUE *nth, int *ry,
02047 int *rjd,
02048 int *ns)
02049 {
02050 double style = guess_style(y, sg);
02051
02052 if (style == 0) {
02053 int jd;
02054
02055 c_ordinal_to_jd(FIX2INT(y), d, sg, &jd, ns);
02056 decode_jd(INT2FIX(jd), nth, rjd);
02057 if (f_zero_p(*nth))
02058 *ry = FIX2INT(y);
02059 else {
02060 VALUE nth2;
02061 decode_year(y, *ns ? -1 : +1, &nth2, ry);
02062 }
02063 }
02064 else {
02065 decode_year(y, style, nth, ry);
02066 c_ordinal_to_jd(*ry, d, style, rjd, ns);
02067 }
02068 }
02069
02070 static void
02071 jd_to_ordinal(VALUE jd, double sg,
02072 VALUE *nth, int *rjd,
02073 int *ry, int *rd)
02074 {
02075 decode_jd(jd, nth, rjd);
02076 c_jd_to_ordinal(*rjd, sg, ry, rd);
02077 }
02078
02079 static void
02080 commercial_to_jd(VALUE y, int w, int d, double sg,
02081 VALUE *nth, int *ry,
02082 int *rjd,
02083 int *ns)
02084 {
02085 double style = guess_style(y, sg);
02086
02087 if (style == 0) {
02088 int jd;
02089
02090 c_commercial_to_jd(FIX2INT(y), w, d, sg, &jd, ns);
02091 decode_jd(INT2FIX(jd), nth, rjd);
02092 if (f_zero_p(*nth))
02093 *ry = FIX2INT(y);
02094 else {
02095 VALUE nth2;
02096 decode_year(y, *ns ? -1 : +1, &nth2, ry);
02097 }
02098 }
02099 else {
02100 decode_year(y, style, nth, ry);
02101 c_commercial_to_jd(*ry, w, d, style, rjd, ns);
02102 }
02103 }
02104
02105 static void
02106 jd_to_commercial(VALUE jd, double sg,
02107 VALUE *nth, int *rjd,
02108 int *ry, int *rw, int *rd)
02109 {
02110 decode_jd(jd, nth, rjd);
02111 c_jd_to_commercial(*rjd, sg, ry, rw, rd);
02112 }
02113
02114 static void
02115 weeknum_to_jd(VALUE y, int w, int d, int f, double sg,
02116 VALUE *nth, int *ry,
02117 int *rjd,
02118 int *ns)
02119 {
02120 double style = guess_style(y, sg);
02121
02122 if (style == 0) {
02123 int jd;
02124
02125 c_weeknum_to_jd(FIX2INT(y), w, d, f, sg, &jd, ns);
02126 decode_jd(INT2FIX(jd), nth, rjd);
02127 if (f_zero_p(*nth))
02128 *ry = FIX2INT(y);
02129 else {
02130 VALUE nth2;
02131 decode_year(y, *ns ? -1 : +1, &nth2, ry);
02132 }
02133 }
02134 else {
02135 decode_year(y, style, nth, ry);
02136 c_weeknum_to_jd(*ry, w, d, f, style, rjd, ns);
02137 }
02138 }
02139
02140 static void
02141 jd_to_weeknum(VALUE jd, int f, double sg,
02142 VALUE *nth, int *rjd,
02143 int *ry, int *rw, int *rd)
02144 {
02145 decode_jd(jd, nth, rjd);
02146 c_jd_to_weeknum(*rjd, f, sg, ry, rw, rd);
02147 }
02148
02149 static void
02150 nth_kday_to_jd(VALUE y, int m, int n, int k, double sg,
02151 VALUE *nth, int *ry,
02152 int *rjd,
02153 int *ns)
02154 {
02155 double style = guess_style(y, sg);
02156
02157 if (style == 0) {
02158 int jd;
02159
02160 c_nth_kday_to_jd(FIX2INT(y), m, n, k, sg, &jd, ns);
02161 decode_jd(INT2FIX(jd), nth, rjd);
02162 if (f_zero_p(*nth))
02163 *ry = FIX2INT(y);
02164 else {
02165 VALUE nth2;
02166 decode_year(y, *ns ? -1 : +1, &nth2, ry);
02167 }
02168 }
02169 else {
02170 decode_year(y, style, nth, ry);
02171 c_nth_kday_to_jd(*ry, m, n, k, style, rjd, ns);
02172 }
02173 }
02174
02175 static void
02176 jd_to_nth_kday(VALUE jd, double sg,
02177 VALUE *nth, int *rjd,
02178 int *ry, int *rm, int *rn, int *rk)
02179 {
02180 decode_jd(jd, nth, rjd);
02181 c_jd_to_nth_kday(*rjd, sg, ry, rm, rn, rk);
02182 }
02183 #endif
02184
02185 static int
02186 valid_ordinal_p(VALUE y, int d, double sg,
02187 VALUE *nth, int *ry,
02188 int *rd, int *rjd,
02189 int *ns)
02190 {
02191 double style = guess_style(y, sg);
02192 int r;
02193
02194 if (style == 0) {
02195 int jd;
02196
02197 r = c_valid_ordinal_p(FIX2INT(y), d, sg, rd, &jd, ns);
02198 if (!r)
02199 return 0;
02200 decode_jd(INT2FIX(jd), nth, rjd);
02201 if (f_zero_p(*nth))
02202 *ry = FIX2INT(y);
02203 else {
02204 VALUE nth2;
02205 decode_year(y, *ns ? -1 : +1, &nth2, ry);
02206 }
02207 }
02208 else {
02209 decode_year(y, style, nth, ry);
02210 r = c_valid_ordinal_p(*ry, d, style, rd, rjd, ns);
02211 }
02212 return r;
02213 }
02214
02215 static int
02216 valid_gregorian_p(VALUE y, int m, int d,
02217 VALUE *nth, int *ry,
02218 int *rm, int *rd)
02219 {
02220 decode_year(y, -1, nth, ry);
02221 return c_valid_gregorian_p(*ry, m, d, rm, rd);
02222 }
02223
02224 static int
02225 valid_civil_p(VALUE y, int m, int d, double sg,
02226 VALUE *nth, int *ry,
02227 int *rm, int *rd, int *rjd,
02228 int *ns)
02229 {
02230 double style = guess_style(y, sg);
02231 int r;
02232
02233 if (style == 0) {
02234 int jd;
02235
02236 r = c_valid_civil_p(FIX2INT(y), m, d, sg, rm, rd, &jd, ns);
02237 if (!r)
02238 return 0;
02239 decode_jd(INT2FIX(jd), nth, rjd);
02240 if (f_zero_p(*nth))
02241 *ry = FIX2INT(y);
02242 else {
02243 VALUE nth2;
02244 decode_year(y, *ns ? -1 : +1, &nth2, ry);
02245 }
02246 }
02247 else {
02248 decode_year(y, style, nth, ry);
02249 if (style < 0)
02250 r = c_valid_gregorian_p(*ry, m, d, rm, rd);
02251 else
02252 r = c_valid_julian_p(*ry, m, d, rm, rd);
02253 if (!r)
02254 return 0;
02255 c_civil_to_jd(*ry, *rm, *rd, style, rjd, ns);
02256 }
02257 return r;
02258 }
02259
02260 static int
02261 valid_commercial_p(VALUE y, int w, int d, double sg,
02262 VALUE *nth, int *ry,
02263 int *rw, int *rd, int *rjd,
02264 int *ns)
02265 {
02266 double style = guess_style(y, sg);
02267 int r;
02268
02269 if (style == 0) {
02270 int jd;
02271
02272 r = c_valid_commercial_p(FIX2INT(y), w, d, sg, rw, rd, &jd, ns);
02273 if (!r)
02274 return 0;
02275 decode_jd(INT2FIX(jd), nth, rjd);
02276 if (f_zero_p(*nth))
02277 *ry = FIX2INT(y);
02278 else {
02279 VALUE nth2;
02280 decode_year(y, *ns ? -1 : +1, &nth2, ry);
02281 }
02282 }
02283 else {
02284 decode_year(y, style, nth, ry);
02285 r = c_valid_commercial_p(*ry, w, d, style, rw, rd, rjd, ns);
02286 }
02287 return r;
02288 }
02289
02290 static int
02291 valid_weeknum_p(VALUE y, int w, int d, int f, double sg,
02292 VALUE *nth, int *ry,
02293 int *rw, int *rd, int *rjd,
02294 int *ns)
02295 {
02296 double style = guess_style(y, sg);
02297 int r;
02298
02299 if (style == 0) {
02300 int jd;
02301
02302 r = c_valid_weeknum_p(FIX2INT(y), w, d, f, sg, rw, rd, &jd, ns);
02303 if (!r)
02304 return 0;
02305 decode_jd(INT2FIX(jd), nth, rjd);
02306 if (f_zero_p(*nth))
02307 *ry = FIX2INT(y);
02308 else {
02309 VALUE nth2;
02310 decode_year(y, *ns ? -1 : +1, &nth2, ry);
02311 }
02312 }
02313 else {
02314 decode_year(y, style, nth, ry);
02315 r = c_valid_weeknum_p(*ry, w, d, f, style, rw, rd, rjd, ns);
02316 }
02317 return r;
02318 }
02319
02320 #ifndef NDEBUG
02321 static int
02322 valid_nth_kday_p(VALUE y, int m, int n, int k, double sg,
02323 VALUE *nth, int *ry,
02324 int *rm, int *rn, int *rk, int *rjd,
02325 int *ns)
02326 {
02327 double style = guess_style(y, sg);
02328 int r;
02329
02330 if (style == 0) {
02331 int jd;
02332
02333 r = c_valid_nth_kday_p(FIX2INT(y), m, n, k, sg, rm, rn, rk, &jd, ns);
02334 if (!r)
02335 return 0;
02336 decode_jd(INT2FIX(jd), nth, rjd);
02337 if (f_zero_p(*nth))
02338 *ry = FIX2INT(y);
02339 else {
02340 VALUE nth2;
02341 decode_year(y, *ns ? -1 : +1, &nth2, ry);
02342 }
02343 }
02344 else {
02345 decode_year(y, style, nth, ry);
02346 r = c_valid_nth_kday_p(*ry, m, n, k, style, rm, rn, rk, rjd, ns);
02347 }
02348 return r;
02349 }
02350 #endif
02351
02352 VALUE date_zone_to_diff(VALUE);
02353
02354 static int
02355 offset_to_sec(VALUE vof, int *rof)
02356 {
02357 switch (TYPE(vof)) {
02358 case T_FIXNUM:
02359 {
02360 long n;
02361
02362 n = FIX2LONG(vof);
02363 if (n != -1 && n != 0 && n != 1)
02364 return 0;
02365 *rof = (int)n * DAY_IN_SECONDS;
02366 return 1;
02367 }
02368 case T_FLOAT:
02369 {
02370 double n;
02371
02372 n = RFLOAT_VALUE(vof) * DAY_IN_SECONDS;
02373 if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
02374 return 0;
02375 *rof = (int)round(n);
02376 if (*rof != n)
02377 rb_warning("fraction of offset is ignored");
02378 return 1;
02379 }
02380 default:
02381 if (!k_numeric_p(vof))
02382 rb_raise(rb_eTypeError, "expected numeric");
02383 vof = f_to_r(vof);
02384 #ifdef CANONICALIZATION_FOR_MATHN
02385 if (!k_rational_p(vof))
02386 return offset_to_sec(vof, rof);
02387 #endif
02388
02389 case T_RATIONAL:
02390 {
02391 VALUE vs, vn, vd;
02392 long n;
02393
02394 vs = day_to_sec(vof);
02395
02396 #ifdef CANONICALIZATION_FOR_MATHN
02397 if (!k_rational_p(vs)) {
02398 if (!FIXNUM_P(vs))
02399 return 0;
02400 n = FIX2LONG(vs);
02401 if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
02402 return 0;
02403 *rof = (int)n;
02404 return 1;
02405 }
02406 #endif
02407 vn = RRATIONAL(vs)->num;
02408 vd = RRATIONAL(vs)->den;
02409
02410 if (FIXNUM_P(vn) && FIXNUM_P(vd) && (FIX2LONG(vd) == 1))
02411 n = FIX2LONG(vn);
02412 else {
02413 vn = f_round(vs);
02414 if (!f_eqeq_p(vn, vs))
02415 rb_warning("fraction of offset is ignored");
02416 if (!FIXNUM_P(vn))
02417 return 0;
02418 n = FIX2LONG(vn);
02419 if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
02420 return 0;
02421 }
02422 *rof = (int)n;
02423 return 1;
02424 }
02425 case T_STRING:
02426 {
02427 VALUE vs = date_zone_to_diff(vof);
02428 long n;
02429
02430 if (!FIXNUM_P(vs))
02431 return 0;
02432 n = FIX2LONG(vs);
02433 if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
02434 return 0;
02435 *rof = (int)n;
02436 return 1;
02437 }
02438 }
02439 return 0;
02440 }
02441
02442
02443
02444 #define valid_sg(sg) \
02445 {\
02446 if (!c_valid_start_p(sg)) {\
02447 sg = 0;\
02448 rb_warning("invalid start is ignored");\
02449 }\
02450 }
02451
02452 static VALUE
02453 valid_jd_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
02454 {
02455 double sg = NUM2DBL(argv[1]);
02456 valid_sg(sg);
02457 return argv[0];
02458 }
02459
02460 #ifndef NDEBUG
02461 static VALUE
02462 date_s__valid_jd_p(int argc, VALUE *argv, VALUE klass)
02463 {
02464 VALUE vjd, vsg;
02465 VALUE argv2[2];
02466
02467 rb_scan_args(argc, argv, "11", &vjd, &vsg);
02468
02469 argv2[0] = vjd;
02470 if (argc < 2)
02471 argv2[1] = DBL2NUM(GREGORIAN);
02472 else
02473 argv2[1] = vsg;
02474
02475 return valid_jd_sub(2, argv2, klass, 1);
02476 }
02477 #endif
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491 static VALUE
02492 date_s_valid_jd_p(int argc, VALUE *argv, VALUE klass)
02493 {
02494 VALUE vjd, vsg;
02495 VALUE argv2[2];
02496
02497 rb_scan_args(argc, argv, "11", &vjd, &vsg);
02498
02499 argv2[0] = vjd;
02500 if (argc < 2)
02501 argv2[1] = INT2FIX(DEFAULT_SG);
02502 else
02503 argv2[1] = vsg;
02504
02505 if (NIL_P(valid_jd_sub(2, argv2, klass, 0)))
02506 return Qfalse;
02507 return Qtrue;
02508 }
02509
02510 static VALUE
02511 valid_civil_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
02512 {
02513 VALUE nth, y;
02514 int m, d, ry, rm, rd;
02515 double sg;
02516
02517 y = argv[0];
02518 m = NUM2INT(argv[1]);
02519 d = NUM2INT(argv[2]);
02520 sg = NUM2DBL(argv[3]);
02521
02522 valid_sg(sg);
02523
02524 if (!need_jd && (guess_style(y, sg) < 0)) {
02525 if (!valid_gregorian_p(y, m, d,
02526 &nth, &ry,
02527 &rm, &rd))
02528 return Qnil;
02529 return INT2FIX(0);
02530 }
02531 else {
02532 int rjd, ns;
02533 VALUE rjd2;
02534
02535 if (!valid_civil_p(y, m, d, sg,
02536 &nth, &ry,
02537 &rm, &rd, &rjd,
02538 &ns))
02539 return Qnil;
02540 if (!need_jd)
02541 return INT2FIX(0);
02542 encode_jd(nth, rjd, &rjd2);
02543 return rjd2;
02544 }
02545 }
02546
02547 #ifndef NDEBUG
02548 static VALUE
02549 date_s__valid_civil_p(int argc, VALUE *argv, VALUE klass)
02550 {
02551 VALUE vy, vm, vd, vsg;
02552 VALUE argv2[4];
02553
02554 rb_scan_args(argc, argv, "31", &vy, &vm, &vd, &vsg);
02555
02556 argv2[0] = vy;
02557 argv2[1] = vm;
02558 argv2[2] = vd;
02559 if (argc < 4)
02560 argv2[3] = DBL2NUM(GREGORIAN);
02561 else
02562 argv2[3] = vsg;
02563
02564 return valid_civil_sub(4, argv2, klass, 1);
02565 }
02566 #endif
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582 static VALUE
02583 date_s_valid_civil_p(int argc, VALUE *argv, VALUE klass)
02584 {
02585 VALUE vy, vm, vd, vsg;
02586 VALUE argv2[4];
02587
02588 rb_scan_args(argc, argv, "31", &vy, &vm, &vd, &vsg);
02589
02590 argv2[0] = vy;
02591 argv2[1] = vm;
02592 argv2[2] = vd;
02593 if (argc < 4)
02594 argv2[3] = INT2FIX(DEFAULT_SG);
02595 else
02596 argv2[3] = vsg;
02597
02598 if (NIL_P(valid_civil_sub(4, argv2, klass, 0)))
02599 return Qfalse;
02600 return Qtrue;
02601 }
02602
02603 static VALUE
02604 valid_ordinal_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
02605 {
02606 VALUE nth, y;
02607 int d, ry, rd;
02608 double sg;
02609
02610 y = argv[0];
02611 d = NUM2INT(argv[1]);
02612 sg = NUM2DBL(argv[2]);
02613
02614 valid_sg(sg);
02615
02616 {
02617 int rjd, ns;
02618 VALUE rjd2;
02619
02620 if (!valid_ordinal_p(y, d, sg,
02621 &nth, &ry,
02622 &rd, &rjd,
02623 &ns))
02624 return Qnil;
02625 if (!need_jd)
02626 return INT2FIX(0);
02627 encode_jd(nth, rjd, &rjd2);
02628 return rjd2;
02629 }
02630 }
02631
02632 #ifndef NDEBUG
02633 static VALUE
02634 date_s__valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
02635 {
02636 VALUE vy, vd, vsg;
02637 VALUE argv2[3];
02638
02639 rb_scan_args(argc, argv, "21", &vy, &vd, &vsg);
02640
02641 argv2[0] = vy;
02642 argv2[1] = vd;
02643 if (argc < 3)
02644 argv2[2] = DBL2NUM(GREGORIAN);
02645 else
02646 argv2[2] = vsg;
02647
02648 return valid_ordinal_sub(3, argv2, klass, 1);
02649 }
02650 #endif
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665 static VALUE
02666 date_s_valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
02667 {
02668 VALUE vy, vd, vsg;
02669 VALUE argv2[3];
02670
02671 rb_scan_args(argc, argv, "21", &vy, &vd, &vsg);
02672
02673 argv2[0] = vy;
02674 argv2[1] = vd;
02675 if (argc < 3)
02676 argv2[2] = INT2FIX(DEFAULT_SG);
02677 else
02678 argv2[2] = vsg;
02679
02680 if (NIL_P(valid_ordinal_sub(3, argv2, klass, 0)))
02681 return Qfalse;
02682 return Qtrue;
02683 }
02684
02685 static VALUE
02686 valid_commercial_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
02687 {
02688 VALUE nth, y;
02689 int w, d, ry, rw, rd;
02690 double sg;
02691
02692 y = argv[0];
02693 w = NUM2INT(argv[1]);
02694 d = NUM2INT(argv[2]);
02695 sg = NUM2DBL(argv[3]);
02696
02697 valid_sg(sg);
02698
02699 {
02700 int rjd, ns;
02701 VALUE rjd2;
02702
02703 if (!valid_commercial_p(y, w, d, sg,
02704 &nth, &ry,
02705 &rw, &rd, &rjd,
02706 &ns))
02707 return Qnil;
02708 if (!need_jd)
02709 return INT2FIX(0);
02710 encode_jd(nth, rjd, &rjd2);
02711 return rjd2;
02712 }
02713 }
02714
02715 #ifndef NDEBUG
02716 static VALUE
02717 date_s__valid_commercial_p(int argc, VALUE *argv, VALUE klass)
02718 {
02719 VALUE vy, vw, vd, vsg;
02720 VALUE argv2[4];
02721
02722 rb_scan_args(argc, argv, "31", &vy, &vw, &vd, &vsg);
02723
02724 argv2[0] = vy;
02725 argv2[1] = vw;
02726 argv2[2] = vd;
02727 if (argc < 4)
02728 argv2[3] = DBL2NUM(GREGORIAN);
02729 else
02730 argv2[3] = vsg;
02731
02732 return valid_commercial_sub(4, argv2, klass, 1);
02733 }
02734 #endif
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749 static VALUE
02750 date_s_valid_commercial_p(int argc, VALUE *argv, VALUE klass)
02751 {
02752 VALUE vy, vw, vd, vsg;
02753 VALUE argv2[4];
02754
02755 rb_scan_args(argc, argv, "31", &vy, &vw, &vd, &vsg);
02756
02757 argv2[0] = vy;
02758 argv2[1] = vw;
02759 argv2[2] = vd;
02760 if (argc < 4)
02761 argv2[3] = INT2FIX(DEFAULT_SG);
02762 else
02763 argv2[3] = vsg;
02764
02765 if (NIL_P(valid_commercial_sub(4, argv2, klass, 0)))
02766 return Qfalse;
02767 return Qtrue;
02768 }
02769
02770 #ifndef NDEBUG
02771 static VALUE
02772 valid_weeknum_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
02773 {
02774 VALUE nth, y;
02775 int w, d, f, ry, rw, rd;
02776 double sg;
02777
02778 y = argv[0];
02779 w = NUM2INT(argv[1]);
02780 d = NUM2INT(argv[2]);
02781 f = NUM2INT(argv[3]);
02782 sg = NUM2DBL(argv[4]);
02783
02784 valid_sg(sg);
02785
02786 {
02787 int rjd, ns;
02788 VALUE rjd2;
02789
02790 if (!valid_weeknum_p(y, w, d, f, sg,
02791 &nth, &ry,
02792 &rw, &rd, &rjd,
02793 &ns))
02794 return Qnil;
02795 if (!need_jd)
02796 return INT2FIX(0);
02797 encode_jd(nth, rjd, &rjd2);
02798 return rjd2;
02799 }
02800 }
02801
02802 static VALUE
02803 date_s__valid_weeknum_p(int argc, VALUE *argv, VALUE klass)
02804 {
02805 VALUE vy, vw, vd, vf, vsg;
02806 VALUE argv2[5];
02807
02808 rb_scan_args(argc, argv, "41", &vy, &vw, &vd, &vf, &vsg);
02809
02810 argv2[0] = vy;
02811 argv2[1] = vw;
02812 argv2[2] = vd;
02813 argv2[3] = vf;
02814 if (argc < 5)
02815 argv2[4] = DBL2NUM(GREGORIAN);
02816 else
02817 argv2[4] = vsg;
02818
02819 return valid_weeknum_sub(5, argv2, klass, 1);
02820 }
02821
02822 static VALUE
02823 date_s_valid_weeknum_p(int argc, VALUE *argv, VALUE klass)
02824 {
02825 VALUE vy, vw, vd, vf, vsg;
02826 VALUE argv2[5];
02827
02828 rb_scan_args(argc, argv, "41", &vy, &vw, &vd, &vf, &vsg);
02829
02830 argv2[0] = vy;
02831 argv2[1] = vw;
02832 argv2[2] = vd;
02833 argv2[3] = vf;
02834 if (argc < 5)
02835 argv2[4] = INT2FIX(DEFAULT_SG);
02836 else
02837 argv2[4] = vsg;
02838
02839 if (NIL_P(valid_weeknum_sub(5, argv2, klass, 0)))
02840 return Qfalse;
02841 return Qtrue;
02842 }
02843
02844 static VALUE
02845 valid_nth_kday_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
02846 {
02847 VALUE nth, y;
02848 int m, n, k, ry, rm, rn, rk;
02849 double sg;
02850
02851 y = argv[0];
02852 m = NUM2INT(argv[1]);
02853 n = NUM2INT(argv[2]);
02854 k = NUM2INT(argv[3]);
02855 sg = NUM2DBL(argv[4]);
02856
02857 {
02858 int rjd, ns;
02859 VALUE rjd2;
02860
02861 if (!valid_nth_kday_p(y, m, n, k, sg,
02862 &nth, &ry,
02863 &rm, &rn, &rk, &rjd,
02864 &ns))
02865 return Qnil;
02866 if (!need_jd)
02867 return INT2FIX(0);
02868 encode_jd(nth, rjd, &rjd2);
02869 return rjd2;
02870 }
02871 }
02872
02873 static VALUE
02874 date_s__valid_nth_kday_p(int argc, VALUE *argv, VALUE klass)
02875 {
02876 VALUE vy, vm, vn, vk, vsg;
02877 VALUE argv2[5];
02878
02879 rb_scan_args(argc, argv, "41", &vy, &vm, &vn, &vk, &vsg);
02880
02881 argv2[0] = vy;
02882 argv2[1] = vm;
02883 argv2[2] = vn;
02884 argv2[3] = vk;
02885 if (argc < 5)
02886 argv2[4] = DBL2NUM(GREGORIAN);
02887 else
02888 argv2[4] = vsg;
02889
02890 return valid_nth_kday_sub(5, argv2, klass, 1);
02891 }
02892
02893 static VALUE
02894 date_s_valid_nth_kday_p(int argc, VALUE *argv, VALUE klass)
02895 {
02896 VALUE vy, vm, vn, vk, vsg;
02897 VALUE argv2[5];
02898
02899 rb_scan_args(argc, argv, "41", &vy, &vm, &vn, &vk, &vsg);
02900
02901 argv2[0] = vy;
02902 argv2[1] = vm;
02903 argv2[2] = vn;
02904 argv2[3] = vk;
02905 if (argc < 5)
02906 argv2[4] = INT2FIX(DEFAULT_SG);
02907 else
02908 argv2[4] = vsg;
02909
02910 if (NIL_P(valid_nth_kday_sub(5, argv2, klass, 0)))
02911 return Qfalse;
02912 return Qtrue;
02913 }
02914
02915 static VALUE
02916 date_s_zone_to_diff(VALUE klass, VALUE str)
02917 {
02918 return date_zone_to_diff(str);
02919 }
02920 #endif
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934 static VALUE
02935 date_s_julian_leap_p(VALUE klass, VALUE y)
02936 {
02937 VALUE nth;
02938 int ry;
02939
02940 decode_year(y, +1, &nth, &ry);
02941 return f_boolcast(c_julian_leap_p(ry));
02942 }
02943
02944
02945
02946
02947
02948
02949
02950
02951
02952
02953
02954
02955
02956
02957 static VALUE
02958 date_s_gregorian_leap_p(VALUE klass, VALUE y)
02959 {
02960 VALUE nth;
02961 int ry;
02962
02963 decode_year(y, -1, &nth, &ry);
02964 return f_boolcast(c_gregorian_leap_p(ry));
02965 }
02966
02967 static void
02968 d_lite_gc_mark(union DateData *dat)
02969 {
02970 if (simple_dat_p(dat))
02971 rb_gc_mark(dat->s.nth);
02972 else {
02973 rb_gc_mark(dat->c.nth);
02974 rb_gc_mark(dat->c.sf);
02975
02976 }
02977 }
02978
02979 inline static VALUE
02980 d_simple_new_internal(VALUE klass,
02981 VALUE nth, int jd,
02982 double sg,
02983 int y, int m, int d,
02984 unsigned flags)
02985 {
02986 struct SimpleDateData *dat;
02987 VALUE obj;
02988
02989 obj = Data_Make_Struct(klass, struct SimpleDateData,
02990 d_lite_gc_mark, -1, dat);
02991 set_to_simple(dat, nth, jd, sg, y, m, d, flags & ~COMPLEX_DAT);
02992
02993 assert(have_jd_p(dat) || have_civil_p(dat));
02994
02995 return obj;
02996 }
02997
02998 inline static VALUE
02999 d_complex_new_internal(VALUE klass,
03000 VALUE nth, int jd,
03001 int df, VALUE sf,
03002 int of, double sg,
03003 int y, int m, int d,
03004 int h, int min, int s,
03005 unsigned flags)
03006 {
03007 struct ComplexDateData *dat;
03008 VALUE obj;
03009
03010 obj = Data_Make_Struct(klass, struct ComplexDateData,
03011 d_lite_gc_mark, -1, dat);
03012 set_to_complex(dat, nth, jd, df, sf, of, sg,
03013 y, m, d, h, min, s, flags | COMPLEX_DAT);
03014
03015 assert(have_jd_p(dat) || have_civil_p(dat));
03016 assert(have_df_p(dat) || have_time_p(dat));
03017
03018 return obj;
03019 }
03020
03021 static VALUE
03022 d_lite_s_alloc_simple(VALUE klass)
03023 {
03024 return d_simple_new_internal(klass,
03025 INT2FIX(0), 0,
03026 DEFAULT_SG,
03027 0, 0, 0,
03028 HAVE_JD);
03029 }
03030
03031 static VALUE
03032 d_lite_s_alloc_complex(VALUE klass)
03033 {
03034 return d_complex_new_internal(klass,
03035 INT2FIX(0), 0,
03036 0, INT2FIX(0),
03037 0, DEFAULT_SG,
03038 0, 0, 0,
03039 0, 0, 0,
03040 HAVE_JD | HAVE_DF);
03041 }
03042
03043 static VALUE
03044 d_lite_s_alloc(VALUE klass)
03045 {
03046 return d_lite_s_alloc_complex(klass);
03047 }
03048
03049 static void
03050 old_to_new(VALUE ajd, VALUE of, VALUE sg,
03051 VALUE *rnth, int *rjd, int *rdf, VALUE *rsf,
03052 int *rof, double *rsg)
03053 {
03054 VALUE jd, df, sf, of2, t;
03055
03056 decode_day(f_add(ajd, half_days_in_day),
03057 &jd, &df, &sf);
03058 t = day_to_sec(of);
03059 of2 = f_round(t);
03060
03061 if (!f_eqeq_p(of2, t))
03062 rb_warning("fraction of offset is ignored");
03063
03064 decode_jd(jd, rnth, rjd);
03065
03066 *rdf = NUM2INT(df);
03067 *rsf = sf;
03068 *rof = NUM2INT(of2);
03069 *rsg = NUM2DBL(sg);
03070
03071 if (*rdf < 0 || *rdf >= DAY_IN_SECONDS)
03072 rb_raise(rb_eArgError, "invalid day fraction");
03073
03074 if (f_lt_p(*rsf, INT2FIX(0)) ||
03075 f_ge_p(*rsf, INT2FIX(SECOND_IN_NANOSECONDS)))
03076
03077 if (*rof < -DAY_IN_SECONDS || *rof > DAY_IN_SECONDS) {
03078 *rof = 0;
03079 rb_warning("invalid offset is ignored");
03080 }
03081
03082 if (!c_valid_start_p(*rsg)) {
03083 *rsg = DEFAULT_SG;
03084 rb_warning("invalid start is ignored");
03085 }
03086 }
03087
03088 #ifndef NDEBUG
03089 static VALUE
03090 date_s_new_bang(int argc, VALUE *argv, VALUE klass)
03091 {
03092 VALUE ajd, of, sg, nth, sf;
03093 int jd, df, rof;
03094 double rsg;
03095
03096 rb_scan_args(argc, argv, "03", &ajd, &of, &sg);
03097
03098 switch (argc) {
03099 case 0:
03100 ajd = INT2FIX(0);
03101 case 1:
03102 of = INT2FIX(0);
03103 case 2:
03104 sg = INT2FIX(DEFAULT_SG);
03105 }
03106
03107 old_to_new(ajd, of, sg,
03108 &nth, &jd, &df, &sf, &rof, &rsg);
03109
03110 if (!df && f_zero_p(sf) && !rof)
03111 return d_simple_new_internal(klass,
03112 nth, jd,
03113 rsg,
03114 0, 0, 0,
03115 HAVE_JD);
03116 else
03117 return d_complex_new_internal(klass,
03118 nth, jd,
03119 df, sf,
03120 rof, rsg,
03121 0, 0, 0,
03122 0, 0, 0,
03123 HAVE_JD | HAVE_DF);
03124 }
03125 #endif
03126
03127 inline static int
03128 wholenum_p(VALUE x)
03129 {
03130 if (FIXNUM_P(x))
03131 return 1;
03132 switch (TYPE(x)) {
03133 case T_BIGNUM:
03134 return 1;
03135 case T_FLOAT:
03136 {
03137 double d = RFLOAT_VALUE(x);
03138 return round(d) == d;
03139 }
03140 break;
03141 case T_RATIONAL:
03142 {
03143 VALUE den = RRATIONAL(x)->den;
03144 return FIXNUM_P(den) && FIX2LONG(den) == 1;
03145 }
03146 break;
03147 }
03148 return 0;
03149 }
03150
03151 inline static VALUE
03152 to_integer(VALUE x)
03153 {
03154 if (FIXNUM_P(x) || RB_TYPE_P(x, T_BIGNUM))
03155 return x;
03156 return f_to_i(x);
03157 }
03158
03159 inline static VALUE
03160 d_trunc(VALUE d, VALUE *fr)
03161 {
03162 VALUE rd;
03163
03164 if (wholenum_p(d)) {
03165 rd = to_integer(d);
03166 *fr = INT2FIX(0);
03167 }
03168 else {
03169 rd = f_idiv(d, INT2FIX(1));
03170 *fr = f_mod(d, INT2FIX(1));
03171 }
03172 return rd;
03173 }
03174
03175 #define jd_trunc d_trunc
03176 #define k_trunc d_trunc
03177
03178 inline static VALUE
03179 h_trunc(VALUE h, VALUE *fr)
03180 {
03181 VALUE rh;
03182
03183 if (wholenum_p(h)) {
03184 rh = to_integer(h);
03185 *fr = INT2FIX(0);
03186 }
03187 else {
03188 rh = f_idiv(h, INT2FIX(1));
03189 *fr = f_mod(h, INT2FIX(1));
03190 *fr = f_quo(*fr, INT2FIX(24));
03191 }
03192 return rh;
03193 }
03194
03195 inline static VALUE
03196 min_trunc(VALUE min, VALUE *fr)
03197 {
03198 VALUE rmin;
03199
03200 if (wholenum_p(min)) {
03201 rmin = to_integer(min);
03202 *fr = INT2FIX(0);
03203 }
03204 else {
03205 rmin = f_idiv(min, INT2FIX(1));
03206 *fr = f_mod(min, INT2FIX(1));
03207 *fr = f_quo(*fr, INT2FIX(1440));
03208 }
03209 return rmin;
03210 }
03211
03212 inline static VALUE
03213 s_trunc(VALUE s, VALUE *fr)
03214 {
03215 VALUE rs;
03216
03217 if (wholenum_p(s)) {
03218 rs = to_integer(s);
03219 *fr = INT2FIX(0);
03220 }
03221 else {
03222 rs = f_idiv(s, INT2FIX(1));
03223 *fr = f_mod(s, INT2FIX(1));
03224 *fr = f_quo(*fr, INT2FIX(86400));
03225 }
03226 return rs;
03227 }
03228
03229 #define num2num_with_frac(s,n) \
03230 {\
03231 s = s##_trunc(v##s, &fr);\
03232 if (f_nonzero_p(fr)) {\
03233 if (argc > n)\
03234 rb_raise(rb_eArgError, "invalid fraction");\
03235 fr2 = fr;\
03236 }\
03237 }
03238
03239 #define num2int_with_frac(s,n) \
03240 {\
03241 s = NUM2INT(s##_trunc(v##s, &fr));\
03242 if (f_nonzero_p(fr)) {\
03243 if (argc > n)\
03244 rb_raise(rb_eArgError, "invalid fraction");\
03245 fr2 = fr;\
03246 }\
03247 }
03248
03249 #define canon24oc() \
03250 {\
03251 if (rh == 24) {\
03252 rh = 0;\
03253 fr2 = f_add(fr2, INT2FIX(1));\
03254 }\
03255 }
03256
03257 #define add_frac() \
03258 {\
03259 if (f_nonzero_p(fr2))\
03260 ret = d_lite_plus(ret, fr2);\
03261 }
03262
03263 #define val2sg(vsg,dsg) \
03264 {\
03265 dsg = NUM2DBL(vsg);\
03266 if (!c_valid_start_p(dsg)) {\
03267 dsg = DEFAULT_SG;\
03268 rb_warning("invalid start is ignored");\
03269 }\
03270 }
03271
03272 static VALUE d_lite_plus(VALUE, VALUE);
03273
03274
03275
03276
03277
03278
03279
03280
03281
03282
03283
03284
03285
03286
03287
03288
03289 static VALUE
03290 date_s_jd(int argc, VALUE *argv, VALUE klass)
03291 {
03292 VALUE vjd, vsg, jd, fr, fr2, ret;
03293 double sg;
03294
03295 rb_scan_args(argc, argv, "02", &vjd, &vsg);
03296
03297 jd = INT2FIX(0);
03298 fr2 = INT2FIX(0);
03299 sg = DEFAULT_SG;
03300
03301 switch (argc) {
03302 case 2:
03303 val2sg(vsg, sg);
03304 case 1:
03305 num2num_with_frac(jd, positive_inf);
03306 }
03307
03308 {
03309 VALUE nth;
03310 int rjd;
03311
03312 decode_jd(jd, &nth, &rjd);
03313 ret = d_simple_new_internal(klass,
03314 nth, rjd,
03315 sg,
03316 0, 0, 0,
03317 HAVE_JD);
03318 }
03319 add_frac();
03320 return ret;
03321 }
03322
03323
03324
03325
03326
03327
03328
03329
03330
03331
03332
03333
03334
03335
03336
03337
03338
03339
03340
03341 static VALUE
03342 date_s_ordinal(int argc, VALUE *argv, VALUE klass)
03343 {
03344 VALUE vy, vd, vsg, y, fr, fr2, ret;
03345 int d;
03346 double sg;
03347
03348 rb_scan_args(argc, argv, "03", &vy, &vd, &vsg);
03349
03350 y = INT2FIX(-4712);
03351 d = 1;
03352 fr2 = INT2FIX(0);
03353 sg = DEFAULT_SG;
03354
03355 switch (argc) {
03356 case 3:
03357 val2sg(vsg, sg);
03358 case 2:
03359 num2int_with_frac(d, positive_inf);
03360 case 1:
03361 y = vy;
03362 }
03363
03364 {
03365 VALUE nth;
03366 int ry, rd, rjd, ns;
03367
03368 if (!valid_ordinal_p(y, d, sg,
03369 &nth, &ry,
03370 &rd, &rjd,
03371 &ns))
03372 rb_raise(rb_eArgError, "invalid date");
03373
03374 ret = d_simple_new_internal(klass,
03375 nth, rjd,
03376 sg,
03377 0, 0, 0,
03378 HAVE_JD);
03379 }
03380 add_frac();
03381 return ret;
03382 }
03383
03384
03385
03386
03387
03388
03389
03390
03391
03392
03393
03394
03395
03396
03397
03398
03399
03400
03401
03402
03403
03404
03405
03406
03407
03408
03409
03410
03411 static VALUE
03412 date_s_civil(int argc, VALUE *argv, VALUE klass)
03413 {
03414 VALUE vy, vm, vd, vsg, y, fr, fr2, ret;
03415 int m, d;
03416 double sg;
03417
03418 rb_scan_args(argc, argv, "04", &vy, &vm, &vd, &vsg);
03419
03420 y = INT2FIX(-4712);
03421 m = 1;
03422 d = 1;
03423 fr2 = INT2FIX(0);
03424 sg = DEFAULT_SG;
03425
03426 switch (argc) {
03427 case 4:
03428 val2sg(vsg, sg);
03429 case 3:
03430 num2int_with_frac(d, positive_inf);
03431 case 2:
03432 m = NUM2INT(vm);
03433 case 1:
03434 y = vy;
03435 }
03436
03437 if (guess_style(y, sg) < 0) {
03438 VALUE nth;
03439 int ry, rm, rd;
03440
03441 if (!valid_gregorian_p(y, m, d,
03442 &nth, &ry,
03443 &rm, &rd))
03444 rb_raise(rb_eArgError, "invalid date");
03445
03446 ret = d_simple_new_internal(klass,
03447 nth, 0,
03448 sg,
03449 ry, rm, rd,
03450 HAVE_CIVIL);
03451 }
03452 else {
03453 VALUE nth;
03454 int ry, rm, rd, rjd, ns;
03455
03456 if (!valid_civil_p(y, m, d, sg,
03457 &nth, &ry,
03458 &rm, &rd, &rjd,
03459 &ns))
03460 rb_raise(rb_eArgError, "invalid date");
03461
03462 ret = d_simple_new_internal(klass,
03463 nth, rjd,
03464 sg,
03465 ry, rm, rd,
03466 HAVE_JD | HAVE_CIVIL);
03467 }
03468 add_frac();
03469 return ret;
03470 }
03471
03472
03473
03474
03475
03476
03477
03478
03479
03480
03481
03482
03483
03484
03485
03486
03487
03488
03489
03490 static VALUE
03491 date_s_commercial(int argc, VALUE *argv, VALUE klass)
03492 {
03493 VALUE vy, vw, vd, vsg, y, fr, fr2, ret;
03494 int w, d;
03495 double sg;
03496
03497 rb_scan_args(argc, argv, "04", &vy, &vw, &vd, &vsg);
03498
03499 y = INT2FIX(-4712);
03500 w = 1;
03501 d = 1;
03502 fr2 = INT2FIX(0);
03503 sg = DEFAULT_SG;
03504
03505 switch (argc) {
03506 case 4:
03507 val2sg(vsg, sg);
03508 case 3:
03509 num2int_with_frac(d, positive_inf);
03510 case 2:
03511 w = NUM2INT(vw);
03512 case 1:
03513 y = vy;
03514 }
03515
03516 {
03517 VALUE nth;
03518 int ry, rw, rd, rjd, ns;
03519
03520 if (!valid_commercial_p(y, w, d, sg,
03521 &nth, &ry,
03522 &rw, &rd, &rjd,
03523 &ns))
03524 rb_raise(rb_eArgError, "invalid date");
03525
03526 ret = d_simple_new_internal(klass,
03527 nth, rjd,
03528 sg,
03529 0, 0, 0,
03530 HAVE_JD);
03531 }
03532 add_frac();
03533 return ret;
03534 }
03535
03536 #ifndef NDEBUG
03537 static VALUE
03538 date_s_weeknum(int argc, VALUE *argv, VALUE klass)
03539 {
03540 VALUE vy, vw, vd, vf, vsg, y, fr, fr2, ret;
03541 int w, d, f;
03542 double sg;
03543
03544 rb_scan_args(argc, argv, "05", &vy, &vw, &vd, &vf, &vsg);
03545
03546 y = INT2FIX(-4712);
03547 w = 0;
03548 d = 1;
03549 f = 0;
03550 fr2 = INT2FIX(0);
03551 sg = DEFAULT_SG;
03552
03553 switch (argc) {
03554 case 5:
03555 val2sg(vsg, sg);
03556 case 4:
03557 f = NUM2INT(vf);
03558 case 3:
03559 num2int_with_frac(d, positive_inf);
03560 case 2:
03561 w = NUM2INT(vw);
03562 case 1:
03563 y = vy;
03564 }
03565
03566 {
03567 VALUE nth;
03568 int ry, rw, rd, rjd, ns;
03569
03570 if (!valid_weeknum_p(y, w, d, f, sg,
03571 &nth, &ry,
03572 &rw, &rd, &rjd,
03573 &ns))
03574 rb_raise(rb_eArgError, "invalid date");
03575
03576 ret = d_simple_new_internal(klass,
03577 nth, rjd,
03578 sg,
03579 0, 0, 0,
03580 HAVE_JD);
03581 }
03582 add_frac();
03583 return ret;
03584 }
03585
03586 static VALUE
03587 date_s_nth_kday(int argc, VALUE *argv, VALUE klass)
03588 {
03589 VALUE vy, vm, vn, vk, vsg, y, fr, fr2, ret;
03590 int m, n, k;
03591 double sg;
03592
03593 rb_scan_args(argc, argv, "05", &vy, &vm, &vn, &vk, &vsg);
03594
03595 y = INT2FIX(-4712);
03596 m = 1;
03597 n = 1;
03598 k = 1;
03599 fr2 = INT2FIX(0);
03600 sg = DEFAULT_SG;
03601
03602 switch (argc) {
03603 case 5:
03604 val2sg(vsg, sg);
03605 case 4:
03606 num2int_with_frac(k, positive_inf);
03607 case 3:
03608 n = NUM2INT(vn);
03609 case 2:
03610 m = NUM2INT(vm);
03611 case 1:
03612 y = vy;
03613 }
03614
03615 {
03616 VALUE nth;
03617 int ry, rm, rn, rk, rjd, ns;
03618
03619 if (!valid_nth_kday_p(y, m, n, k, sg,
03620 &nth, &ry,
03621 &rm, &rn, &rk, &rjd,
03622 &ns))
03623 rb_raise(rb_eArgError, "invalid date");
03624
03625 ret = d_simple_new_internal(klass,
03626 nth, rjd,
03627 sg,
03628 0, 0, 0,
03629 HAVE_JD);
03630 }
03631 add_frac();
03632 return ret;
03633 }
03634 #endif
03635
03636 #if !defined(HAVE_GMTIME_R)
03637 static struct tm*
03638 gmtime_r(const time_t *t, struct tm *tm)
03639 {
03640 auto struct tm *tmp = gmtime(t);
03641 if (tmp)
03642 *tm = *tmp;
03643 return tmp;
03644 }
03645
03646 static struct tm*
03647 localtime_r(const time_t *t, struct tm *tm)
03648 {
03649 auto struct tm *tmp = localtime(t);
03650 if (tmp)
03651 *tm = *tmp;
03652 return tmp;
03653 }
03654 #endif
03655
03656 static void set_sg(union DateData *, double);
03657
03658
03659
03660
03661
03662
03663
03664
03665
03666
03667
03668 static VALUE
03669 date_s_today(int argc, VALUE *argv, VALUE klass)
03670 {
03671 VALUE vsg, nth, ret;
03672 double sg;
03673 time_t t;
03674 struct tm tm;
03675 int y, ry, m, d;
03676
03677 rb_scan_args(argc, argv, "01", &vsg);
03678
03679 if (argc < 1)
03680 sg = DEFAULT_SG;
03681 else
03682 val2sg(vsg, sg);
03683
03684 if (time(&t) == -1)
03685 rb_sys_fail("time");
03686 tzset();
03687 if (!localtime_r(&t, &tm))
03688 rb_sys_fail("localtime");
03689
03690 y = tm.tm_year + 1900;
03691 m = tm.tm_mon + 1;
03692 d = tm.tm_mday;
03693
03694 decode_year(INT2FIX(y), -1, &nth, &ry);
03695
03696 ret = d_simple_new_internal(klass,
03697 nth, 0,
03698 GREGORIAN,
03699 ry, m, d,
03700 HAVE_CIVIL);
03701 {
03702 get_d1(ret);
03703 set_sg(dat, sg);
03704 }
03705 return ret;
03706 }
03707
03708 #define set_hash0(k,v) rb_hash_aset(hash, k, v)
03709 #define ref_hash0(k) rb_hash_aref(hash, k)
03710 #define del_hash0(k) rb_hash_delete(hash, k)
03711
03712 #define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k)), v)
03713 #define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k)))
03714 #define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k)))
03715
03716 static VALUE
03717 rt_rewrite_frags(VALUE hash)
03718 {
03719 VALUE seconds;
03720
03721 seconds = ref_hash("seconds");
03722 if (!NIL_P(seconds)) {
03723 VALUE d, h, min, s, fr;
03724
03725 d = f_idiv(seconds, INT2FIX(DAY_IN_SECONDS));
03726 fr = f_mod(seconds, INT2FIX(DAY_IN_SECONDS));
03727
03728 h = f_idiv(fr, INT2FIX(HOUR_IN_SECONDS));
03729 fr = f_mod(fr, INT2FIX(HOUR_IN_SECONDS));
03730
03731 min = f_idiv(fr, INT2FIX(MINUTE_IN_SECONDS));
03732 fr = f_mod(fr, INT2FIX(MINUTE_IN_SECONDS));
03733
03734 s = f_idiv(fr, INT2FIX(1));
03735 fr = f_mod(fr, INT2FIX(1));
03736
03737 set_hash("jd", f_add(UNIX_EPOCH_IN_CJD, d));
03738 set_hash("hour", h);
03739 set_hash("min", min);
03740 set_hash("sec", s);
03741 set_hash("sec_fraction", fr);
03742 del_hash("seconds");
03743 del_hash("offset");
03744 }
03745 return hash;
03746 }
03747
03748 #define sym(x) ID2SYM(rb_intern(x))
03749
03750 static VALUE d_lite_year(VALUE);
03751 static VALUE d_lite_wday(VALUE);
03752 static VALUE d_lite_jd(VALUE);
03753
03754 static VALUE
03755 rt_complete_frags(VALUE klass, VALUE hash)
03756 {
03757 static VALUE tab = Qnil;
03758 int g, e;
03759 VALUE k, a, d;
03760
03761 if (NIL_P(tab)) {
03762 tab = rb_ary_new3(11,
03763 rb_ary_new3(2,
03764 sym("time"),
03765 rb_ary_new3(3,
03766 sym("hour"),
03767 sym("min"),
03768 sym("sec"))),
03769 rb_ary_new3(2,
03770 Qnil,
03771 rb_ary_new3(1,
03772 sym("jd"))),
03773 rb_ary_new3(2,
03774 sym("ordinal"),
03775 rb_ary_new3(5,
03776 sym("year"),
03777 sym("yday"),
03778 sym("hour"),
03779 sym("min"),
03780 sym("sec"))),
03781 rb_ary_new3(2,
03782 sym("civil"),
03783 rb_ary_new3(6,
03784 sym("year"),
03785 sym("mon"),
03786 sym("mday"),
03787 sym("hour"),
03788 sym("min"),
03789 sym("sec"))),
03790 rb_ary_new3(2,
03791 sym("commercial"),
03792 rb_ary_new3(6,
03793 sym("cwyear"),
03794 sym("cweek"),
03795 sym("cwday"),
03796 sym("hour"),
03797 sym("min"),
03798 sym("sec"))),
03799 rb_ary_new3(2,
03800 sym("wday"),
03801 rb_ary_new3(4,
03802 sym("wday"),
03803 sym("hour"),
03804 sym("min"),
03805 sym("sec"))),
03806 rb_ary_new3(2,
03807 sym("wnum0"),
03808 rb_ary_new3(6,
03809 sym("year"),
03810 sym("wnum0"),
03811 sym("wday"),
03812 sym("hour"),
03813 sym("min"),
03814 sym("sec"))),
03815 rb_ary_new3(2,
03816 sym("wnum1"),
03817 rb_ary_new3(6,
03818 sym("year"),
03819 sym("wnum1"),
03820 sym("wday"),
03821 sym("hour"),
03822 sym("min"),
03823 sym("sec"))),
03824 rb_ary_new3(2,
03825 Qnil,
03826 rb_ary_new3(6,
03827 sym("cwyear"),
03828 sym("cweek"),
03829 sym("wday"),
03830 sym("hour"),
03831 sym("min"),
03832 sym("sec"))),
03833 rb_ary_new3(2,
03834 Qnil,
03835 rb_ary_new3(6,
03836 sym("year"),
03837 sym("wnum0"),
03838 sym("cwday"),
03839 sym("hour"),
03840 sym("min"),
03841 sym("sec"))),
03842 rb_ary_new3(2,
03843 Qnil,
03844 rb_ary_new3(6,
03845 sym("year"),
03846 sym("wnum1"),
03847 sym("cwday"),
03848 sym("hour"),
03849 sym("min"),
03850 sym("sec"))));
03851 rb_gc_register_mark_object(tab);
03852 }
03853
03854 {
03855 int i, eno = 0, idx = 0;
03856
03857 for (i = 0; i < RARRAY_LENINT(tab); i++) {
03858 VALUE x, a;
03859
03860 x = RARRAY_PTR(tab)[i];
03861 a = RARRAY_PTR(x)[1];
03862
03863 {
03864 int j, n = 0;
03865
03866 for (j = 0; j < RARRAY_LENINT(a); j++)
03867 if (!NIL_P(ref_hash0(RARRAY_PTR(a)[j])))
03868 n++;
03869 if (n > eno) {
03870 eno = n;
03871 idx = i;
03872 }
03873 }
03874 }
03875 if (eno == 0)
03876 g = 0;
03877 else {
03878 g = 1;
03879 k = RARRAY_PTR(RARRAY_PTR(tab)[idx])[0];
03880 a = RARRAY_PTR(RARRAY_PTR(tab)[idx])[1];
03881 e = eno;
03882 }
03883 }
03884
03885 d = Qnil;
03886
03887 if (g && !NIL_P(k) && (RARRAY_LENINT(a) - e)) {
03888 if (k == sym("ordinal")) {
03889 if (NIL_P(ref_hash("year"))) {
03890 if (NIL_P(d))
03891 d = date_s_today(0, (VALUE *)0, cDate);
03892 set_hash("year", d_lite_year(d));
03893 }
03894 if (NIL_P(ref_hash("yday")))
03895 set_hash("yday", INT2FIX(1));
03896 }
03897 else if (k == sym("civil")) {
03898 int i;
03899
03900 for (i = 0; i < RARRAY_LENINT(a); i++) {
03901 VALUE e = RARRAY_PTR(a)[i];
03902
03903 if (!NIL_P(ref_hash0(e)))
03904 break;
03905 if (NIL_P(d))
03906 d = date_s_today(0, (VALUE *)0, cDate);
03907 set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
03908 }
03909 if (NIL_P(ref_hash("mon")))
03910 set_hash("mon", INT2FIX(1));
03911 if (NIL_P(ref_hash("mday")))
03912 set_hash("mday", INT2FIX(1));
03913 }
03914 else if (k == sym("commercial")) {
03915 int i;
03916
03917 for (i = 0; i < RARRAY_LENINT(a); i++) {
03918 VALUE e = RARRAY_PTR(a)[i];
03919
03920 if (!NIL_P(ref_hash0(e)))
03921 break;
03922 if (NIL_P(d))
03923 d = date_s_today(0, (VALUE *)0, cDate);
03924 set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
03925 }
03926 if (NIL_P(ref_hash("cweek")))
03927 set_hash("cweek", INT2FIX(1));
03928 if (NIL_P(ref_hash("cwday")))
03929 set_hash("cwday", INT2FIX(1));
03930 }
03931 else if (k == sym("wday")) {
03932 if (NIL_P(d))
03933 d = date_s_today(0, (VALUE *)0, cDate);
03934 set_hash("jd", d_lite_jd(f_add(f_sub(d,
03935 d_lite_wday(d)),
03936 ref_hash("wday"))));
03937 }
03938 else if (k == sym("wnum0")) {
03939 int i;
03940
03941 for (i = 0; i < RARRAY_LENINT(a); i++) {
03942 VALUE e = RARRAY_PTR(a)[i];
03943
03944 if (!NIL_P(ref_hash0(e)))
03945 break;
03946 if (NIL_P(d))
03947 d = date_s_today(0, (VALUE *)0, cDate);
03948 set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
03949 }
03950 if (NIL_P(ref_hash("wnum0")))
03951 set_hash("wnum0", INT2FIX(0));
03952 if (NIL_P(ref_hash("wday")))
03953 set_hash("wday", INT2FIX(0));
03954 }
03955 else if (k == sym("wnum1")) {
03956 int i;
03957
03958 for (i = 0; i < RARRAY_LENINT(a); i++) {
03959 VALUE e = RARRAY_PTR(a)[i];
03960
03961 if (!NIL_P(ref_hash0(e)))
03962 break;
03963 if (NIL_P(d))
03964 d = date_s_today(0, (VALUE *)0, cDate);
03965 set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
03966 }
03967 if (NIL_P(ref_hash("wnum1")))
03968 set_hash("wnum1", INT2FIX(0));
03969 if (NIL_P(ref_hash("wday")))
03970 set_hash("wday", INT2FIX(1));
03971 }
03972 }
03973
03974 if (g && k == sym("time")) {
03975 if (f_le_p(klass, cDateTime)) {
03976 if (NIL_P(d))
03977 d = date_s_today(0, (VALUE *)0, cDate);
03978 if (NIL_P(ref_hash("jd")))
03979 set_hash("jd", d_lite_jd(d));
03980 }
03981 }
03982
03983 if (NIL_P(ref_hash("hour")))
03984 set_hash("hour", INT2FIX(0));
03985 if (NIL_P(ref_hash("min")))
03986 set_hash("min", INT2FIX(0));
03987 if (NIL_P(ref_hash("sec")))
03988 set_hash("sec", INT2FIX(0));
03989 else if (f_gt_p(ref_hash("sec"), INT2FIX(59)))
03990 set_hash("sec", INT2FIX(59));
03991
03992 return hash;
03993 }
03994
03995 static VALUE
03996 rt__valid_jd_p(VALUE jd, VALUE sg)
03997 {
03998 return jd;
03999 }
04000
04001 static VALUE
04002 rt__valid_ordinal_p(VALUE y, VALUE d, VALUE sg)
04003 {
04004 VALUE nth, rjd2;
04005 int ry, rd, rjd, ns;
04006
04007 if (!valid_ordinal_p(y, NUM2INT(d), NUM2DBL(sg),
04008 &nth, &ry,
04009 &rd, &rjd,
04010 &ns))
04011 return Qnil;
04012 encode_jd(nth, rjd, &rjd2);
04013 return rjd2;
04014 }
04015
04016 static VALUE
04017 rt__valid_civil_p(VALUE y, VALUE m, VALUE d, VALUE sg)
04018 {
04019 VALUE nth, rjd2;
04020 int ry, rm, rd, rjd, ns;
04021
04022 if (!valid_civil_p(y, NUM2INT(m), NUM2INT(d), NUM2DBL(sg),
04023 &nth, &ry,
04024 &rm, &rd, &rjd,
04025 &ns))
04026 return Qnil;
04027 encode_jd(nth, rjd, &rjd2);
04028 return rjd2;
04029 }
04030
04031 static VALUE
04032 rt__valid_commercial_p(VALUE y, VALUE w, VALUE d, VALUE sg)
04033 {
04034 VALUE nth, rjd2;
04035 int ry, rw, rd, rjd, ns;
04036
04037 if (!valid_commercial_p(y, NUM2INT(w), NUM2INT(d), NUM2DBL(sg),
04038 &nth, &ry,
04039 &rw, &rd, &rjd,
04040 &ns))
04041 return Qnil;
04042 encode_jd(nth, rjd, &rjd2);
04043 return rjd2;
04044 }
04045
04046 static VALUE
04047 rt__valid_weeknum_p(VALUE y, VALUE w, VALUE d, VALUE f, VALUE sg)
04048 {
04049 VALUE nth, rjd2;
04050 int ry, rw, rd, rjd, ns;
04051
04052 if (!valid_weeknum_p(y, NUM2INT(w), NUM2INT(d), NUM2INT(f), NUM2DBL(sg),
04053 &nth, &ry,
04054 &rw, &rd, &rjd,
04055 &ns))
04056 return Qnil;
04057 encode_jd(nth, rjd, &rjd2);
04058 return rjd2;
04059 }
04060
04061 static VALUE
04062 rt__valid_date_frags_p(VALUE hash, VALUE sg)
04063 {
04064 {
04065 VALUE vjd;
04066
04067 if (!NIL_P(vjd = ref_hash("jd"))) {
04068 VALUE jd = rt__valid_jd_p(vjd, sg);
04069 if (!NIL_P(jd))
04070 return jd;
04071 }
04072 }
04073
04074 {
04075 VALUE year, yday;
04076
04077 if (!NIL_P(yday = ref_hash("yday")) &&
04078 !NIL_P(year = ref_hash("year"))) {
04079 VALUE jd = rt__valid_ordinal_p(year, yday, sg);
04080 if (!NIL_P(jd))
04081 return jd;
04082 }
04083 }
04084
04085 {
04086 VALUE year, mon, mday;
04087
04088 if (!NIL_P(mday = ref_hash("mday")) &&
04089 !NIL_P(mon = ref_hash("mon")) &&
04090 !NIL_P(year = ref_hash("year"))) {
04091 VALUE jd = rt__valid_civil_p(year, mon, mday, sg);
04092 if (!NIL_P(jd))
04093 return jd;
04094 }
04095 }
04096
04097 {
04098 VALUE year, week, wday;
04099
04100 wday = ref_hash("cwday");
04101 if (NIL_P(wday)) {
04102 wday = ref_hash("wday");
04103 if (!NIL_P(wday))
04104 if (f_zero_p(wday))
04105 wday = INT2FIX(7);
04106 }
04107
04108 if (!NIL_P(wday) &&
04109 !NIL_P(week = ref_hash("cweek")) &&
04110 !NIL_P(year = ref_hash("cwyear"))) {
04111 VALUE jd = rt__valid_commercial_p(year, week, wday, sg);
04112 if (!NIL_P(jd))
04113 return jd;
04114 }
04115 }
04116
04117 {
04118 VALUE year, week, wday;
04119
04120 wday = ref_hash("wday");
04121 if (NIL_P(wday)) {
04122 wday = ref_hash("cwday");
04123 if (!NIL_P(wday))
04124 if (f_eqeq_p(wday, INT2FIX(7)))
04125 wday = INT2FIX(0);
04126 }
04127
04128 if (!NIL_P(wday) &&
04129 !NIL_P(week = ref_hash("wnum0")) &&
04130 !NIL_P(year = ref_hash("year"))) {
04131 VALUE jd = rt__valid_weeknum_p(year, week, wday, INT2FIX(0), sg);
04132 if (!NIL_P(jd))
04133 return jd;
04134 }
04135 }
04136
04137 {
04138 VALUE year, week, wday;
04139
04140 wday = ref_hash("wday");
04141 if (NIL_P(wday))
04142 wday = ref_hash("cwday");
04143 if (!NIL_P(wday))
04144 wday = f_mod(f_sub(wday, INT2FIX(1)),
04145 INT2FIX(7));
04146
04147 if (!NIL_P(wday) &&
04148 !NIL_P(week = ref_hash("wnum1")) &&
04149 !NIL_P(year = ref_hash("year"))) {
04150 VALUE jd = rt__valid_weeknum_p(year, week, wday, INT2FIX(1), sg);
04151 if (!NIL_P(jd))
04152 return jd;
04153 }
04154 }
04155 return Qnil;
04156 }
04157
04158 static VALUE
04159 d_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
04160 {
04161 VALUE jd;
04162
04163 if (!c_valid_start_p(NUM2DBL(sg))) {
04164 sg = INT2FIX(DEFAULT_SG);
04165 rb_warning("invalid start is ignored");
04166 }
04167
04168 if (NIL_P(hash))
04169 rb_raise(rb_eArgError, "invalid date");
04170
04171 if (NIL_P(ref_hash("jd")) &&
04172 NIL_P(ref_hash("yday")) &&
04173 !NIL_P(ref_hash("year")) &&
04174 !NIL_P(ref_hash("mon")) &&
04175 !NIL_P(ref_hash("mday")))
04176 jd = rt__valid_civil_p(ref_hash("year"),
04177 ref_hash("mon"),
04178 ref_hash("mday"), sg);
04179 else {
04180 hash = rt_rewrite_frags(hash);
04181 hash = rt_complete_frags(klass, hash);
04182 jd = rt__valid_date_frags_p(hash, sg);
04183 }
04184
04185 if (NIL_P(jd))
04186 rb_raise(rb_eArgError, "invalid date");
04187 {
04188 VALUE nth;
04189 int rjd;
04190
04191 decode_jd(jd, &nth, &rjd);
04192 return d_simple_new_internal(klass,
04193 nth, rjd,
04194 NUM2DBL(sg),
04195 0, 0, 0,
04196 HAVE_JD);
04197 }
04198 }
04199
04200 VALUE date__strptime(const char *str, size_t slen,
04201 const char *fmt, size_t flen, VALUE hash);
04202
04203 static VALUE
04204 date_s__strptime_internal(int argc, VALUE *argv, VALUE klass,
04205 const char *default_fmt)
04206 {
04207 VALUE vstr, vfmt, hash;
04208 const char *str, *fmt;
04209 size_t slen, flen;
04210
04211 rb_scan_args(argc, argv, "11", &vstr, &vfmt);
04212
04213 StringValue(vstr);
04214 if (!rb_enc_str_asciicompat_p(vstr))
04215 rb_raise(rb_eArgError,
04216 "string should have ASCII compatible encoding");
04217 str = RSTRING_PTR(vstr);
04218 slen = RSTRING_LEN(vstr);
04219 if (argc < 2) {
04220 fmt = default_fmt;
04221 flen = strlen(default_fmt);
04222 }
04223 else {
04224 StringValue(vfmt);
04225 if (!rb_enc_str_asciicompat_p(vfmt))
04226 rb_raise(rb_eArgError,
04227 "format should have ASCII compatible encoding");
04228 fmt = RSTRING_PTR(vfmt);
04229 flen = RSTRING_LEN(vfmt);
04230 }
04231 hash = rb_hash_new();
04232 if (NIL_P(date__strptime(str, slen, fmt, flen, hash)))
04233 return Qnil;
04234
04235 {
04236 VALUE zone = ref_hash("zone");
04237 VALUE left = ref_hash("leftover");
04238
04239 if (!NIL_P(zone)) {
04240 rb_enc_copy(zone, vstr);
04241 OBJ_INFECT(zone, vstr);
04242 set_hash("zone", zone);
04243 }
04244 if (!NIL_P(left)) {
04245 rb_enc_copy(left, vstr);
04246 OBJ_INFECT(left, vstr);
04247 set_hash("leftover", left);
04248 }
04249 }
04250
04251 return hash;
04252 }
04253
04254
04255
04256
04257
04258
04259
04260
04261
04262
04263
04264
04265
04266
04267
04268 static VALUE
04269 date_s__strptime(int argc, VALUE *argv, VALUE klass)
04270 {
04271 return date_s__strptime_internal(argc, argv, klass, "%F");
04272 }
04273
04274
04275
04276
04277
04278
04279
04280
04281
04282
04283
04284
04285
04286
04287
04288
04289
04290
04291
04292
04293 static VALUE
04294 date_s_strptime(int argc, VALUE *argv, VALUE klass)
04295 {
04296 VALUE str, fmt, sg;
04297
04298 rb_scan_args(argc, argv, "03", &str, &fmt, &sg);
04299
04300 switch (argc) {
04301 case 0:
04302 str = rb_str_new2("-4712-01-01");
04303 case 1:
04304 fmt = rb_str_new2("%F");
04305 case 2:
04306 sg = INT2FIX(DEFAULT_SG);
04307 }
04308
04309 {
04310 VALUE argv2[2], hash;
04311
04312 argv2[0] = str;
04313 argv2[1] = fmt;
04314 hash = date_s__strptime(2, argv2, klass);
04315 return d_new_by_frags(klass, hash, sg);
04316 }
04317 }
04318
04319 VALUE date__parse(VALUE str, VALUE comp);
04320
04321 static VALUE
04322 date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
04323 {
04324 VALUE vstr, vcomp, hash;
04325
04326 rb_scan_args(argc, argv, "11", &vstr, &vcomp);
04327 StringValue(vstr);
04328 if (!rb_enc_str_asciicompat_p(vstr))
04329 rb_raise(rb_eArgError,
04330 "string should have ASCII compatible encoding");
04331 if (argc < 2)
04332 vcomp = Qtrue;
04333
04334 hash = date__parse(vstr, vcomp);
04335
04336 {
04337 VALUE zone = ref_hash("zone");
04338
04339 if (!NIL_P(zone)) {
04340 rb_enc_copy(zone, vstr);
04341 OBJ_INFECT(zone, vstr);
04342 set_hash("zone", zone);
04343 }
04344 }
04345
04346 return hash;
04347 }
04348
04349
04350
04351
04352
04353
04354
04355
04356
04357
04358
04359
04360
04361
04362
04363
04364 static VALUE
04365 date_s__parse(int argc, VALUE *argv, VALUE klass)
04366 {
04367 return date_s__parse_internal(argc, argv, klass);
04368 }
04369
04370
04371
04372
04373
04374
04375
04376
04377
04378
04379
04380
04381
04382
04383
04384
04385
04386
04387 static VALUE
04388 date_s_parse(int argc, VALUE *argv, VALUE klass)
04389 {
04390 VALUE str, comp, sg;
04391
04392 rb_scan_args(argc, argv, "03", &str, &comp, &sg);
04393
04394 switch (argc) {
04395 case 0:
04396 str = rb_str_new2("-4712-01-01");
04397 case 1:
04398 comp = Qtrue;
04399 case 2:
04400 sg = INT2FIX(DEFAULT_SG);
04401 }
04402
04403 {
04404 VALUE argv2[2], hash;
04405
04406 argv2[0] = str;
04407 argv2[1] = comp;
04408 hash = date_s__parse(2, argv2, klass);
04409 return d_new_by_frags(klass, hash, sg);
04410 }
04411 }
04412
04413 VALUE date__iso8601(VALUE);
04414 VALUE date__rfc3339(VALUE);
04415 VALUE date__xmlschema(VALUE);
04416 VALUE date__rfc2822(VALUE);
04417 VALUE date__httpdate(VALUE);
04418 VALUE date__jisx0301(VALUE);
04419
04420
04421
04422
04423
04424
04425
04426 static VALUE
04427 date_s__iso8601(VALUE klass, VALUE str)
04428 {
04429 return date__iso8601(str);
04430 }
04431
04432
04433
04434
04435
04436
04437
04438
04439
04440
04441
04442
04443
04444
04445 static VALUE
04446 date_s_iso8601(int argc, VALUE *argv, VALUE klass)
04447 {
04448 VALUE str, sg;
04449
04450 rb_scan_args(argc, argv, "02", &str, &sg);
04451
04452 switch (argc) {
04453 case 0:
04454 str = rb_str_new2("-4712-01-01");
04455 case 1:
04456 sg = INT2FIX(DEFAULT_SG);
04457 }
04458
04459 {
04460 VALUE hash = date_s__iso8601(klass, str);
04461 return d_new_by_frags(klass, hash, sg);
04462 }
04463 }
04464
04465
04466
04467
04468
04469
04470
04471 static VALUE
04472 date_s__rfc3339(VALUE klass, VALUE str)
04473 {
04474 return date__rfc3339(str);
04475 }
04476
04477
04478
04479
04480
04481
04482
04483
04484
04485
04486
04487
04488 static VALUE
04489 date_s_rfc3339(int argc, VALUE *argv, VALUE klass)
04490 {
04491 VALUE str, sg;
04492
04493 rb_scan_args(argc, argv, "02", &str, &sg);
04494
04495 switch (argc) {
04496 case 0:
04497 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
04498 case 1:
04499 sg = INT2FIX(DEFAULT_SG);
04500 }
04501
04502 {
04503 VALUE hash = date_s__rfc3339(klass, str);
04504 return d_new_by_frags(klass, hash, sg);
04505 }
04506 }
04507
04508
04509
04510
04511
04512
04513
04514 static VALUE
04515 date_s__xmlschema(VALUE klass, VALUE str)
04516 {
04517 return date__xmlschema(str);
04518 }
04519
04520
04521
04522
04523
04524
04525
04526
04527
04528
04529
04530
04531 static VALUE
04532 date_s_xmlschema(int argc, VALUE *argv, VALUE klass)
04533 {
04534 VALUE str, sg;
04535
04536 rb_scan_args(argc, argv, "02", &str, &sg);
04537
04538 switch (argc) {
04539 case 0:
04540 str = rb_str_new2("-4712-01-01");
04541 case 1:
04542 sg = INT2FIX(DEFAULT_SG);
04543 }
04544
04545 {
04546 VALUE hash = date_s__xmlschema(klass, str);
04547 return d_new_by_frags(klass, hash, sg);
04548 }
04549 }
04550
04551
04552
04553
04554
04555
04556
04557
04558 static VALUE
04559 date_s__rfc2822(VALUE klass, VALUE str)
04560 {
04561 return date__rfc2822(str);
04562 }
04563
04564
04565
04566
04567
04568
04569
04570
04571
04572
04573
04574
04575
04576
04577 static VALUE
04578 date_s_rfc2822(int argc, VALUE *argv, VALUE klass)
04579 {
04580 VALUE str, sg;
04581
04582 rb_scan_args(argc, argv, "02", &str, &sg);
04583
04584 switch (argc) {
04585 case 0:
04586 str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000");
04587 case 1:
04588 sg = INT2FIX(DEFAULT_SG);
04589 }
04590
04591 {
04592 VALUE hash = date_s__rfc2822(klass, str);
04593 return d_new_by_frags(klass, hash, sg);
04594 }
04595 }
04596
04597
04598
04599
04600
04601
04602
04603 static VALUE
04604 date_s__httpdate(VALUE klass, VALUE str)
04605 {
04606 return date__httpdate(str);
04607 }
04608
04609
04610
04611
04612
04613
04614
04615
04616
04617
04618
04619
04620
04621
04622 static VALUE
04623 date_s_httpdate(int argc, VALUE *argv, VALUE klass)
04624 {
04625 VALUE str, sg;
04626
04627 rb_scan_args(argc, argv, "02", &str, &sg);
04628
04629 switch (argc) {
04630 case 0:
04631 str = rb_str_new2("Mon, 01 Jan -4712 00:00:00 GMT");
04632 case 1:
04633 sg = INT2FIX(DEFAULT_SG);
04634 }
04635
04636 {
04637 VALUE hash = date_s__httpdate(klass, str);
04638 return d_new_by_frags(klass, hash, sg);
04639 }
04640 }
04641
04642
04643
04644
04645
04646
04647
04648 static VALUE
04649 date_s__jisx0301(VALUE klass, VALUE str)
04650 {
04651 return date__jisx0301(str);
04652 }
04653
04654
04655
04656
04657
04658
04659
04660
04661
04662
04663
04664
04665 static VALUE
04666 date_s_jisx0301(int argc, VALUE *argv, VALUE klass)
04667 {
04668 VALUE str, sg;
04669
04670 rb_scan_args(argc, argv, "02", &str, &sg);
04671
04672 switch (argc) {
04673 case 0:
04674 str = rb_str_new2("-4712-01-01");
04675 case 1:
04676 sg = INT2FIX(DEFAULT_SG);
04677 }
04678
04679 {
04680 VALUE hash = date_s__jisx0301(klass, str);
04681 return d_new_by_frags(klass, hash, sg);
04682 }
04683 }
04684
04685 static VALUE
04686 dup_obj(VALUE self)
04687 {
04688 get_d1a(self);
04689
04690 if (simple_dat_p(adat)) {
04691 VALUE new = d_lite_s_alloc_simple(rb_obj_class(self));
04692 {
04693 get_d1b(new);
04694 bdat->s = adat->s;
04695 return new;
04696 }
04697 }
04698 else {
04699 VALUE new = d_lite_s_alloc_complex(rb_obj_class(self));
04700 {
04701 get_d1b(new);
04702 bdat->c = adat->c;
04703 return new;
04704 }
04705 }
04706 }
04707
04708 static VALUE
04709 dup_obj_as_complex(VALUE self)
04710 {
04711 get_d1a(self);
04712
04713 if (simple_dat_p(adat)) {
04714 VALUE new = d_lite_s_alloc_complex(rb_obj_class(self));
04715 {
04716 get_d1b(new);
04717 copy_simple_to_complex(&bdat->c, &adat->s);
04718 bdat->c.flags |= HAVE_DF | COMPLEX_DAT;
04719 return new;
04720 }
04721 }
04722 else {
04723 VALUE new = d_lite_s_alloc_complex(rb_obj_class(self));
04724 {
04725 get_d1b(new);
04726 bdat->c = adat->c;
04727 return new;
04728 }
04729 }
04730 }
04731
04732 #define val2off(vof,iof) \
04733 {\
04734 if (!offset_to_sec(vof, &iof)) {\
04735 iof = 0;\
04736 rb_warning("invalid offset is ignored");\
04737 }\
04738 }
04739
04740 #ifndef NDEBUG
04741 static VALUE
04742 d_lite_initialize(int argc, VALUE *argv, VALUE self)
04743 {
04744 VALUE jd, vjd, vdf, sf, vsf, vof, vsg;
04745 int df, of;
04746 double sg;
04747
04748 rb_scan_args(argc, argv, "05", &vjd, &vdf, &vsf, &vof, &vsg);
04749
04750 jd = INT2FIX(0);
04751 df = 0;
04752 sf = INT2FIX(0);
04753 of = 0;
04754 sg = DEFAULT_SG;
04755
04756 switch (argc) {
04757 case 5:
04758 val2sg(vsg, sg);
04759 case 4:
04760 val2off(vof, of);
04761 case 3:
04762 sf = vsf;
04763 if (f_lt_p(sf, INT2FIX(0)) ||
04764 f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS)))
04765 rb_raise(rb_eArgError, "invalid second fraction");
04766 case 2:
04767 df = NUM2INT(vdf);
04768 if (df < 0 || df >= DAY_IN_SECONDS)
04769 rb_raise(rb_eArgError, "invalid day fraction");
04770 case 1:
04771 jd = vjd;
04772 }
04773
04774 {
04775 VALUE nth;
04776 int rjd;
04777
04778 get_d1(self);
04779
04780 decode_jd(jd, &nth, &rjd);
04781 if (!df && f_zero_p(sf) && !of) {
04782 set_to_simple(&dat->s, nth, rjd, sg, 0, 0, 0, HAVE_JD);
04783 }
04784 else {
04785 if (!complex_dat_p(dat))
04786 rb_raise(rb_eArgError,
04787 "cannot load complex into simple");
04788
04789 set_to_complex(&dat->c, nth, rjd, df, sf, of, sg,
04790 0, 0, 0, 0, 0, 0, HAVE_JD | HAVE_DF | COMPLEX_DAT);
04791 }
04792 }
04793 return self;
04794 }
04795 #endif
04796
04797
04798 static VALUE
04799 d_lite_initialize_copy(VALUE copy, VALUE date)
04800 {
04801 if (copy == date)
04802 return copy;
04803 {
04804 get_d2(copy, date);
04805 if (simple_dat_p(bdat)) {
04806 adat->s = bdat->s;
04807 adat->s.flags &= ~COMPLEX_DAT;
04808 }
04809 else {
04810 if (!complex_dat_p(adat))
04811 rb_raise(rb_eArgError,
04812 "cannot load complex into simple");
04813
04814 adat->c = bdat->c;
04815 adat->c.flags |= COMPLEX_DAT;
04816 }
04817 }
04818 return copy;
04819 }
04820
04821 #ifndef NDEBUG
04822 static VALUE
04823 d_lite_fill(VALUE self)
04824 {
04825 get_d1(self);
04826
04827 if (simple_dat_p(dat)) {
04828 get_s_jd(dat);
04829 get_s_civil(dat);
04830 }
04831 else {
04832 get_c_jd(dat);
04833 get_c_civil(dat);
04834 get_c_df(dat);
04835 get_c_time(dat);
04836 }
04837 return self;
04838 }
04839 #endif
04840
04841
04842
04843
04844
04845
04846
04847
04848
04849
04850
04851
04852
04853 static VALUE
04854 d_lite_ajd(VALUE self)
04855 {
04856 get_d1(self);
04857 return m_ajd(dat);
04858 }
04859
04860
04861
04862
04863
04864
04865
04866
04867
04868
04869
04870
04871
04872 static VALUE
04873 d_lite_amjd(VALUE self)
04874 {
04875 get_d1(self);
04876 return m_amjd(dat);
04877 }
04878
04879
04880
04881
04882
04883
04884
04885
04886
04887
04888
04889
04890
04891 static VALUE
04892 d_lite_jd(VALUE self)
04893 {
04894 get_d1(self);
04895 return m_real_local_jd(dat);
04896 }
04897
04898
04899
04900
04901
04902
04903
04904
04905
04906
04907
04908
04909
04910 static VALUE
04911 d_lite_mjd(VALUE self)
04912 {
04913 get_d1(self);
04914 return f_sub(m_real_local_jd(dat), INT2FIX(2400001));
04915 }
04916
04917
04918
04919
04920
04921
04922
04923
04924
04925
04926
04927
04928 static VALUE
04929 d_lite_ld(VALUE self)
04930 {
04931 get_d1(self);
04932 return f_sub(m_real_local_jd(dat), INT2FIX(2299160));
04933 }
04934
04935
04936
04937
04938
04939
04940
04941
04942
04943
04944
04945
04946 static VALUE
04947 d_lite_year(VALUE self)
04948 {
04949 get_d1(self);
04950 return m_real_year(dat);
04951 }
04952
04953
04954
04955
04956
04957
04958
04959
04960
04961
04962
04963 static VALUE
04964 d_lite_yday(VALUE self)
04965 {
04966 get_d1(self);
04967 return INT2FIX(m_yday(dat));
04968 }
04969
04970
04971
04972
04973
04974
04975
04976
04977
04978
04979
04980
04981 static VALUE
04982 d_lite_mon(VALUE self)
04983 {
04984 get_d1(self);
04985 return INT2FIX(m_mon(dat));
04986 }
04987
04988
04989
04990
04991
04992
04993
04994
04995
04996
04997
04998
04999 static VALUE
05000 d_lite_mday(VALUE self)
05001 {
05002 get_d1(self);
05003 return INT2FIX(m_mday(dat));
05004 }
05005
05006
05007
05008
05009
05010
05011
05012
05013
05014
05015
05016 static VALUE
05017 d_lite_day_fraction(VALUE self)
05018 {
05019 get_d1(self);
05020 if (simple_dat_p(dat))
05021 return INT2FIX(0);
05022 return m_fr(dat);
05023 }
05024
05025
05026
05027
05028
05029
05030
05031
05032
05033
05034
05035
05036 static VALUE
05037 d_lite_cwyear(VALUE self)
05038 {
05039 get_d1(self);
05040 return m_real_cwyear(dat);
05041 }
05042
05043
05044
05045
05046
05047
05048
05049
05050
05051
05052
05053 static VALUE
05054 d_lite_cweek(VALUE self)
05055 {
05056 get_d1(self);
05057 return INT2FIX(m_cweek(dat));
05058 }
05059
05060
05061
05062
05063
05064
05065
05066
05067
05068
05069
05070 static VALUE
05071 d_lite_cwday(VALUE self)
05072 {
05073 get_d1(self);
05074 return INT2FIX(m_cwday(dat));
05075 }
05076
05077 #ifndef NDEBUG
05078 static VALUE
05079 d_lite_wnum0(VALUE self)
05080 {
05081 get_d1(self);
05082 return INT2FIX(m_wnum0(dat));
05083 }
05084
05085 static VALUE
05086 d_lite_wnum1(VALUE self)
05087 {
05088 get_d1(self);
05089 return INT2FIX(m_wnum1(dat));
05090 }
05091 #endif
05092
05093
05094
05095
05096
05097
05098
05099
05100
05101
05102
05103 static VALUE
05104 d_lite_wday(VALUE self)
05105 {
05106 get_d1(self);
05107 return INT2FIX(m_wday(dat));
05108 }
05109
05110
05111
05112
05113
05114
05115
05116 static VALUE
05117 d_lite_sunday_p(VALUE self)
05118 {
05119 get_d1(self);
05120 return f_boolcast(m_wday(dat) == 0);
05121 }
05122
05123
05124
05125
05126
05127
05128
05129 static VALUE
05130 d_lite_monday_p(VALUE self)
05131 {
05132 get_d1(self);
05133 return f_boolcast(m_wday(dat) == 1);
05134 }
05135
05136
05137
05138
05139
05140
05141
05142 static VALUE
05143 d_lite_tuesday_p(VALUE self)
05144 {
05145 get_d1(self);
05146 return f_boolcast(m_wday(dat) == 2);
05147 }
05148
05149
05150
05151
05152
05153
05154
05155 static VALUE
05156 d_lite_wednesday_p(VALUE self)
05157 {
05158 get_d1(self);
05159 return f_boolcast(m_wday(dat) == 3);
05160 }
05161
05162
05163
05164
05165
05166
05167
05168 static VALUE
05169 d_lite_thursday_p(VALUE self)
05170 {
05171 get_d1(self);
05172 return f_boolcast(m_wday(dat) == 4);
05173 }
05174
05175
05176
05177
05178
05179
05180
05181 static VALUE
05182 d_lite_friday_p(VALUE self)
05183 {
05184 get_d1(self);
05185 return f_boolcast(m_wday(dat) == 5);
05186 }
05187
05188
05189
05190
05191
05192
05193
05194 static VALUE
05195 d_lite_saturday_p(VALUE self)
05196 {
05197 get_d1(self);
05198 return f_boolcast(m_wday(dat) == 6);
05199 }
05200
05201 #ifndef NDEBUG
05202 static VALUE
05203 d_lite_nth_kday_p(VALUE self, VALUE n, VALUE k)
05204 {
05205 int rjd, ns;
05206
05207 get_d1(self);
05208
05209 if (NUM2INT(k) != m_wday(dat))
05210 return Qfalse;
05211
05212 c_nth_kday_to_jd(m_year(dat), m_mon(dat),
05213 NUM2INT(n), NUM2INT(k), m_virtual_sg(dat),
05214 &rjd, &ns);
05215 if (m_local_jd(dat) != rjd)
05216 return Qfalse;
05217 return Qtrue;
05218 }
05219 #endif
05220
05221
05222
05223
05224
05225
05226
05227
05228
05229
05230
05231 static VALUE
05232 d_lite_hour(VALUE self)
05233 {
05234 get_d1(self);
05235 return INT2FIX(m_hour(dat));
05236 }
05237
05238
05239
05240
05241
05242
05243
05244
05245
05246
05247
05248
05249 static VALUE
05250 d_lite_min(VALUE self)
05251 {
05252 get_d1(self);
05253 return INT2FIX(m_min(dat));
05254 }
05255
05256
05257
05258
05259
05260
05261
05262
05263
05264
05265
05266
05267 static VALUE
05268 d_lite_sec(VALUE self)
05269 {
05270 get_d1(self);
05271 return INT2FIX(m_sec(dat));
05272 }
05273
05274
05275
05276
05277
05278
05279
05280
05281
05282
05283
05284
05285 static VALUE
05286 d_lite_sec_fraction(VALUE self)
05287 {
05288 get_d1(self);
05289 return m_sf_in_sec(dat);
05290 }
05291
05292
05293
05294
05295
05296
05297
05298
05299
05300
05301
05302 static VALUE
05303 d_lite_offset(VALUE self)
05304 {
05305 get_d1(self);
05306 return m_of_in_day(dat);
05307 }
05308
05309
05310
05311
05312
05313
05314
05315
05316
05317
05318
05319 static VALUE
05320 d_lite_zone(VALUE self)
05321 {
05322 get_d1(self);
05323 return m_zone(dat);
05324 }
05325
05326
05327
05328
05329
05330
05331
05332
05333
05334
05335
05336
05337 static VALUE
05338 d_lite_julian_p(VALUE self)
05339 {
05340 get_d1(self);
05341 return f_boolcast(m_julian_p(dat));
05342 }
05343
05344
05345
05346
05347
05348
05349
05350
05351
05352
05353
05354
05355 static VALUE
05356 d_lite_gregorian_p(VALUE self)
05357 {
05358 get_d1(self);
05359 return f_boolcast(m_gregorian_p(dat));
05360 }
05361
05362
05363
05364
05365
05366
05367
05368
05369
05370
05371
05372
05373 static VALUE
05374 d_lite_leap_p(VALUE self)
05375 {
05376 int rjd, ns, ry, rm, rd;
05377
05378 get_d1(self);
05379 if (m_gregorian_p(dat))
05380 return f_boolcast(c_gregorian_leap_p(m_year(dat)));
05381
05382 c_civil_to_jd(m_year(dat), 3, 1, m_virtual_sg(dat),
05383 &rjd, &ns);
05384 c_jd_to_civil(rjd - 1, m_virtual_sg(dat), &ry, &rm, &rd);
05385 return f_boolcast(rd == 29);
05386 }
05387
05388
05389
05390
05391
05392
05393
05394
05395
05396
05397
05398
05399 static VALUE
05400 d_lite_start(VALUE self)
05401 {
05402 get_d1(self);
05403 return DBL2NUM(m_sg(dat));
05404 }
05405
05406 static void
05407 clear_civil(union DateData *x)
05408 {
05409 if (simple_dat_p(x)) {
05410 x->s.year = 0;
05411 #ifndef USE_PACK
05412 x->s.mon = 0;
05413 x->s.mday = 0;
05414 #else
05415 x->s.pc = 0;
05416 #endif
05417 x->s.flags &= ~HAVE_CIVIL;
05418 }
05419 else {
05420 x->c.year = 0;
05421 #ifndef USE_PACK
05422 x->c.mon = 0;
05423 x->c.mday = 0;
05424 x->c.hour = 0;
05425 x->c.min = 0;
05426 x->c.sec = 0;
05427 #else
05428 x->c.pc = 0;
05429 #endif
05430 x->c.flags &= ~(HAVE_CIVIL | HAVE_TIME);
05431 }
05432 }
05433
05434 static void
05435 set_sg(union DateData *x, double sg)
05436 {
05437 if (simple_dat_p(x)) {
05438 get_s_jd(x);
05439 clear_civil(x);
05440 x->s.sg = (sg_cast)sg;
05441 } else {
05442 get_c_jd(x);
05443 get_c_df(x);
05444 clear_civil(x);
05445 x->c.sg = (sg_cast)sg;
05446 }
05447 }
05448
05449 static VALUE
05450 dup_obj_with_new_start(VALUE obj, double sg)
05451 {
05452 volatile VALUE dup = dup_obj(obj);
05453 {
05454 get_d1(dup);
05455 set_sg(dat, sg);
05456 }
05457 return dup;
05458 }
05459
05460
05461
05462
05463
05464
05465
05466
05467
05468
05469
05470
05471 static VALUE
05472 d_lite_new_start(int argc, VALUE *argv, VALUE self)
05473 {
05474 VALUE vsg;
05475 double sg;
05476
05477 rb_scan_args(argc, argv, "01", &vsg);
05478
05479 sg = DEFAULT_SG;
05480 if (argc >= 1)
05481 val2sg(vsg, sg);
05482
05483 return dup_obj_with_new_start(self, sg);
05484 }
05485
05486
05487
05488
05489
05490
05491
05492 static VALUE
05493 d_lite_italy(VALUE self)
05494 {
05495 return dup_obj_with_new_start(self, ITALY);
05496 }
05497
05498
05499
05500
05501
05502
05503
05504 static VALUE
05505 d_lite_england(VALUE self)
05506 {
05507 return dup_obj_with_new_start(self, ENGLAND);
05508 }
05509
05510
05511
05512
05513
05514
05515
05516 static VALUE
05517 d_lite_julian(VALUE self)
05518 {
05519 return dup_obj_with_new_start(self, JULIAN);
05520 }
05521
05522
05523
05524
05525
05526
05527
05528 static VALUE
05529 d_lite_gregorian(VALUE self)
05530 {
05531 return dup_obj_with_new_start(self, GREGORIAN);
05532 }
05533
05534 static void
05535 set_of(union DateData *x, int of)
05536 {
05537 assert(complex_dat_p(x));
05538 get_c_jd(x);
05539 get_c_df(x);
05540 clear_civil(x);
05541 x->c.of = of;
05542 }
05543
05544 static VALUE
05545 dup_obj_with_new_offset(VALUE obj, int of)
05546 {
05547 volatile VALUE dup = dup_obj_as_complex(obj);
05548 {
05549 get_d1(dup);
05550 set_of(dat, of);
05551 }
05552 return dup;
05553 }
05554
05555
05556
05557
05558
05559
05560
05561
05562
05563
05564
05565
05566
05567 static VALUE
05568 d_lite_new_offset(int argc, VALUE *argv, VALUE self)
05569 {
05570 VALUE vof;
05571 int rof;
05572
05573 rb_scan_args(argc, argv, "01", &vof);
05574
05575 rof = 0;
05576 if (argc >= 1)
05577 val2off(vof, rof);
05578
05579 return dup_obj_with_new_offset(self, rof);
05580 }
05581
05582
05583
05584
05585
05586
05587
05588
05589
05590
05591
05592
05593
05594
05595
05596
05597
05598
05599
05600 static VALUE
05601 d_lite_plus(VALUE self, VALUE other)
05602 {
05603 get_d1(self);
05604
05605 switch (TYPE(other)) {
05606 case T_FIXNUM:
05607 {
05608 VALUE nth;
05609 long t;
05610 int jd;
05611
05612 nth = m_nth(dat);
05613 t = FIX2LONG(other);
05614 if (DIV(t, CM_PERIOD)) {
05615 nth = f_add(nth, INT2FIX(DIV(t, CM_PERIOD)));
05616 t = MOD(t, CM_PERIOD);
05617 }
05618
05619 if (!t)
05620 jd = m_jd(dat);
05621 else {
05622 jd = m_jd(dat) + (int)t;
05623 canonicalize_jd(nth, jd);
05624 }
05625
05626 if (simple_dat_p(dat))
05627 return d_simple_new_internal(rb_obj_class(self),
05628 nth, jd,
05629 dat->s.sg,
05630 0, 0, 0,
05631 (dat->s.flags | HAVE_JD) &
05632 ~HAVE_CIVIL);
05633 else
05634 return d_complex_new_internal(rb_obj_class(self),
05635 nth, jd,
05636 dat->c.df, dat->c.sf,
05637 dat->c.of, dat->c.sg,
05638 0, 0, 0,
05639 #ifndef USE_PACK
05640 dat->c.hour,
05641 dat->c.min,
05642 dat->c.sec,
05643 #else
05644 EX_HOUR(dat->c.pc),
05645 EX_MIN(dat->c.pc),
05646 EX_SEC(dat->c.pc),
05647 #endif
05648 (dat->c.flags | HAVE_JD) &
05649 ~HAVE_CIVIL);
05650 }
05651 break;
05652 case T_BIGNUM:
05653 {
05654 VALUE nth;
05655 int jd, s;
05656
05657 if (f_positive_p(other))
05658 s = +1;
05659 else {
05660 s = -1;
05661 other = f_negate(other);
05662 }
05663
05664 nth = f_idiv(other, INT2FIX(CM_PERIOD));
05665 jd = FIX2INT(f_mod(other, INT2FIX(CM_PERIOD)));
05666
05667 if (s < 0) {
05668 nth = f_negate(nth);
05669 jd = -jd;
05670 }
05671
05672 if (!jd)
05673 jd = m_jd(dat);
05674 else {
05675 jd = m_jd(dat) + jd;
05676 canonicalize_jd(nth, jd);
05677 }
05678
05679 if (f_zero_p(nth))
05680 nth = m_nth(dat);
05681 else
05682 nth = f_add(m_nth(dat), nth);
05683
05684 if (simple_dat_p(dat))
05685 return d_simple_new_internal(rb_obj_class(self),
05686 nth, jd,
05687 dat->s.sg,
05688 0, 0, 0,
05689 (dat->s.flags | HAVE_JD) &
05690 ~HAVE_CIVIL);
05691 else
05692 return d_complex_new_internal(rb_obj_class(self),
05693 nth, jd,
05694 dat->c.df, dat->c.sf,
05695 dat->c.of, dat->c.sg,
05696 0, 0, 0,
05697 #ifndef USE_PACK
05698 dat->c.hour,
05699 dat->c.min,
05700 dat->c.sec,
05701 #else
05702 EX_HOUR(dat->c.pc),
05703 EX_MIN(dat->c.pc),
05704 EX_SEC(dat->c.pc),
05705 #endif
05706 (dat->c.flags | HAVE_JD) &
05707 ~HAVE_CIVIL);
05708 }
05709 break;
05710 case T_FLOAT:
05711 {
05712 double jd, o, tmp;
05713 int s, df;
05714 VALUE nth, sf;
05715
05716 o = RFLOAT_VALUE(other);
05717
05718 if (o > 0)
05719 s = +1;
05720 else {
05721 s = -1;
05722 o = -o;
05723 }
05724
05725 o = modf(o, &tmp);
05726
05727 if (!floor(tmp / CM_PERIOD)) {
05728 nth = INT2FIX(0);
05729 jd = (int)tmp;
05730 }
05731 else {
05732 double i, f;
05733
05734 f = modf(tmp / CM_PERIOD, &i);
05735 nth = f_floor(DBL2NUM(i));
05736 jd = (int)(f * CM_PERIOD);
05737 }
05738
05739 o *= DAY_IN_SECONDS;
05740 o = modf(o, &tmp);
05741 df = (int)tmp;
05742 o *= SECOND_IN_NANOSECONDS;
05743 sf = INT2FIX((int)round(o));
05744
05745 if (s < 0) {
05746 jd = -jd;
05747 df = -df;
05748 sf = f_negate(sf);
05749 }
05750
05751 if (f_zero_p(sf))
05752 sf = m_sf(dat);
05753 else {
05754 sf = f_add(m_sf(dat), sf);
05755 if (f_lt_p(sf, INT2FIX(0))) {
05756 df -= 1;
05757 sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS));
05758 }
05759 else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) {
05760 df += 1;
05761 sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS));
05762 }
05763 }
05764
05765 if (!df)
05766 df = m_df(dat);
05767 else {
05768 df = m_df(dat) + df;
05769 if (df < 0) {
05770 jd -= 1;
05771 df += DAY_IN_SECONDS;
05772 }
05773 else if (df >= DAY_IN_SECONDS) {
05774 jd += 1;
05775 df -= DAY_IN_SECONDS;
05776 }
05777 }
05778
05779 if (!jd)
05780 jd = m_jd(dat);
05781 else {
05782 jd = m_jd(dat) + jd;
05783 canonicalize_jd(nth, jd);
05784 }
05785
05786 if (f_zero_p(nth))
05787 nth = m_nth(dat);
05788 else
05789 nth = f_add(m_nth(dat), nth);
05790
05791 if (!df && f_zero_p(sf) && !m_of(dat))
05792 return d_simple_new_internal(rb_obj_class(self),
05793 nth, (int)jd,
05794 m_sg(dat),
05795 0, 0, 0,
05796 (dat->s.flags | HAVE_JD) &
05797 ~(HAVE_CIVIL | HAVE_TIME |
05798 COMPLEX_DAT));
05799 else
05800 return d_complex_new_internal(rb_obj_class(self),
05801 nth, (int)jd,
05802 df, sf,
05803 m_of(dat), m_sg(dat),
05804 0, 0, 0,
05805 0, 0, 0,
05806 (dat->c.flags |
05807 HAVE_JD | HAVE_DF) &
05808 ~(HAVE_CIVIL | HAVE_TIME));
05809 }
05810 break;
05811 default:
05812 if (!k_numeric_p(other))
05813 rb_raise(rb_eTypeError, "expected numeric");
05814 other = f_to_r(other);
05815 #ifdef CANONICALIZATION_FOR_MATHN
05816 if (!k_rational_p(other))
05817 return d_lite_plus(self, other);
05818 #endif
05819
05820 case T_RATIONAL:
05821 {
05822 VALUE nth, sf, t;
05823 int jd, df, s;
05824
05825 if (wholenum_p(other))
05826 return d_lite_plus(self, RRATIONAL(other)->num);
05827
05828 if (f_positive_p(other))
05829 s = +1;
05830 else {
05831 s = -1;
05832 other = f_negate(other);
05833 }
05834
05835 nth = f_idiv(other, INT2FIX(CM_PERIOD));
05836 t = f_mod(other, INT2FIX(CM_PERIOD));
05837
05838 jd = FIX2INT(f_idiv(t, INT2FIX(1)));
05839 t = f_mod(t, INT2FIX(1));
05840
05841 t = f_mul(t, INT2FIX(DAY_IN_SECONDS));
05842 df = FIX2INT(f_idiv(t, INT2FIX(1)));
05843 t = f_mod(t, INT2FIX(1));
05844
05845 sf = f_mul(t, INT2FIX(SECOND_IN_NANOSECONDS));
05846
05847 if (s < 0) {
05848 nth = f_negate(nth);
05849 jd = -jd;
05850 df = -df;
05851 sf = f_negate(sf);
05852 }
05853
05854 if (f_zero_p(sf))
05855 sf = m_sf(dat);
05856 else {
05857 sf = f_add(m_sf(dat), sf);
05858 if (f_lt_p(sf, INT2FIX(0))) {
05859 df -= 1;
05860 sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS));
05861 }
05862 else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) {
05863 df += 1;
05864 sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS));
05865 }
05866 }
05867
05868 if (!df)
05869 df = m_df(dat);
05870 else {
05871 df = m_df(dat) + df;
05872 if (df < 0) {
05873 jd -= 1;
05874 df += DAY_IN_SECONDS;
05875 }
05876 else if (df >= DAY_IN_SECONDS) {
05877 jd += 1;
05878 df -= DAY_IN_SECONDS;
05879 }
05880 }
05881
05882 if (!jd)
05883 jd = m_jd(dat);
05884 else {
05885 jd = m_jd(dat) + jd;
05886 canonicalize_jd(nth, jd);
05887 }
05888
05889 if (f_zero_p(nth))
05890 nth = m_nth(dat);
05891 else
05892 nth = f_add(m_nth(dat), nth);
05893
05894 if (!df && f_zero_p(sf) && !m_of(dat))
05895 return d_simple_new_internal(rb_obj_class(self),
05896 nth, jd,
05897 m_sg(dat),
05898 0, 0, 0,
05899 (dat->s.flags | HAVE_JD) &
05900 ~(HAVE_CIVIL | HAVE_TIME |
05901 COMPLEX_DAT));
05902 else
05903 return d_complex_new_internal(rb_obj_class(self),
05904 nth, jd,
05905 df, sf,
05906 m_of(dat), m_sg(dat),
05907 0, 0, 0,
05908 0, 0, 0,
05909 (dat->c.flags |
05910 HAVE_JD | HAVE_DF) &
05911 ~(HAVE_CIVIL | HAVE_TIME));
05912 }
05913 break;
05914 }
05915 }
05916
05917 static VALUE
05918 minus_dd(VALUE self, VALUE other)
05919 {
05920 get_d2(self, other);
05921
05922 {
05923 int d, df;
05924 VALUE n, sf, r;
05925
05926 n = f_sub(m_nth(adat), m_nth(bdat));
05927 d = m_jd(adat) - m_jd(bdat);
05928 df = m_df(adat) - m_df(bdat);
05929 sf = f_sub(m_sf(adat), m_sf(bdat));
05930 canonicalize_jd(n, d);
05931
05932 if (df < 0) {
05933 d -= 1;
05934 df += DAY_IN_SECONDS;
05935 }
05936 else if (df >= DAY_IN_SECONDS) {
05937 d += 1;
05938 df -= DAY_IN_SECONDS;
05939 }
05940
05941 if (f_lt_p(sf, INT2FIX(0))) {
05942 df -= 1;
05943 sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS));
05944 }
05945 else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) {
05946 df += 1;
05947 sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS));
05948 }
05949
05950 if (f_zero_p(n))
05951 r = INT2FIX(0);
05952 else
05953 r = f_mul(n, INT2FIX(CM_PERIOD));
05954
05955 if (d)
05956 r = f_add(r, rb_rational_new1(INT2FIX(d)));
05957 if (df)
05958 r = f_add(r, isec_to_day(df));
05959 if (f_nonzero_p(sf))
05960 r = f_add(r, ns_to_day(sf));
05961
05962 if (TYPE(r) == T_RATIONAL)
05963 return r;
05964 return rb_rational_new1(r);
05965 }
05966 }
05967
05968
05969
05970
05971
05972
05973
05974
05975
05976
05977
05978
05979
05980
05981
05982
05983
05984
05985
05986
05987 static VALUE
05988 d_lite_minus(VALUE self, VALUE other)
05989 {
05990 if (k_date_p(other))
05991 return minus_dd(self, other);
05992
05993 switch (TYPE(other)) {
05994 case T_FIXNUM:
05995 return d_lite_plus(self, LONG2NUM(-FIX2LONG(other)));
05996 case T_FLOAT:
05997 return d_lite_plus(self, DBL2NUM(-RFLOAT_VALUE(other)));
05998 default:
05999 if (!k_numeric_p(other))
06000 rb_raise(rb_eTypeError, "expected numeric");
06001
06002 case T_BIGNUM:
06003 case T_RATIONAL:
06004 return d_lite_plus(self, f_negate(other));
06005 }
06006 }
06007
06008
06009
06010
06011
06012
06013
06014 static VALUE
06015 d_lite_next_day(int argc, VALUE *argv, VALUE self)
06016 {
06017 VALUE n;
06018
06019 rb_scan_args(argc, argv, "01", &n);
06020 if (argc < 1)
06021 n = INT2FIX(1);
06022 return d_lite_plus(self, n);
06023 }
06024
06025
06026
06027
06028
06029
06030
06031 static VALUE
06032 d_lite_prev_day(int argc, VALUE *argv, VALUE self)
06033 {
06034 VALUE n;
06035
06036 rb_scan_args(argc, argv, "01", &n);
06037 if (argc < 1)
06038 n = INT2FIX(1);
06039 return d_lite_minus(self, n);
06040 }
06041
06042
06043
06044
06045
06046
06047
06048 static VALUE
06049 d_lite_next(VALUE self)
06050 {
06051 return d_lite_next_day(0, (VALUE *)NULL, self);
06052 }
06053
06054
06055
06056
06057
06058
06059
06060
06061
06062
06063
06064
06065
06066
06067 static VALUE
06068 d_lite_rshift(VALUE self, VALUE other)
06069 {
06070 VALUE t, y, nth, rjd2;
06071 int m, d, rjd;
06072 double sg;
06073
06074 get_d1(self);
06075 t = f_add3(f_mul(m_real_year(dat), INT2FIX(12)),
06076 INT2FIX(m_mon(dat) - 1),
06077 other);
06078 if (FIXNUM_P(t)) {
06079 long it = FIX2LONG(t);
06080 y = LONG2NUM(DIV(it, 12));
06081 it = MOD(it, 12);
06082 m = (int)it + 1;
06083 }
06084 else {
06085 y = f_idiv(t, INT2FIX(12));
06086 t = f_mod(t, INT2FIX(12));
06087 m = FIX2INT(t) + 1;
06088 }
06089 d = m_mday(dat);
06090 sg = m_sg(dat);
06091
06092 while (1) {
06093 int ry, rm, rd, ns;
06094
06095 if (valid_civil_p(y, m, d, sg,
06096 &nth, &ry,
06097 &rm, &rd, &rjd, &ns))
06098 break;
06099 if (--d < 1)
06100 rb_raise(rb_eArgError, "invalid date");
06101 }
06102 encode_jd(nth, rjd, &rjd2);
06103 return d_lite_plus(self, f_sub(rjd2, m_real_local_jd(dat)));
06104 }
06105
06106
06107
06108
06109
06110
06111
06112
06113
06114
06115
06116
06117
06118
06119 static VALUE
06120 d_lite_lshift(VALUE self, VALUE other)
06121 {
06122 return d_lite_rshift(self, f_negate(other));
06123 }
06124
06125
06126
06127
06128
06129
06130
06131 static VALUE
06132 d_lite_next_month(int argc, VALUE *argv, VALUE self)
06133 {
06134 VALUE n;
06135
06136 rb_scan_args(argc, argv, "01", &n);
06137 if (argc < 1)
06138 n = INT2FIX(1);
06139 return d_lite_rshift(self, n);
06140 }
06141
06142
06143
06144
06145
06146
06147
06148 static VALUE
06149 d_lite_prev_month(int argc, VALUE *argv, VALUE self)
06150 {
06151 VALUE n;
06152
06153 rb_scan_args(argc, argv, "01", &n);
06154 if (argc < 1)
06155 n = INT2FIX(1);
06156 return d_lite_lshift(self, n);
06157 }
06158
06159
06160
06161
06162
06163
06164
06165 static VALUE
06166 d_lite_next_year(int argc, VALUE *argv, VALUE self)
06167 {
06168 VALUE n;
06169
06170 rb_scan_args(argc, argv, "01", &n);
06171 if (argc < 1)
06172 n = INT2FIX(1);
06173 return d_lite_rshift(self, f_mul(n, INT2FIX(12)));
06174 }
06175
06176
06177
06178
06179
06180
06181
06182 static VALUE
06183 d_lite_prev_year(int argc, VALUE *argv, VALUE self)
06184 {
06185 VALUE n;
06186
06187 rb_scan_args(argc, argv, "01", &n);
06188 if (argc < 1)
06189 n = INT2FIX(1);
06190 return d_lite_lshift(self, f_mul(n, INT2FIX(12)));
06191 }
06192
06193 static VALUE d_lite_cmp(VALUE, VALUE);
06194
06195
06196
06197
06198
06199
06200
06201
06202
06203
06204
06205
06206
06207
06208 static VALUE
06209 d_lite_step(int argc, VALUE *argv, VALUE self)
06210 {
06211 VALUE limit, step, date;
06212
06213 rb_scan_args(argc, argv, "11", &limit, &step);
06214
06215 if (argc < 2)
06216 step = INT2FIX(1);
06217
06218 #if 0
06219 if (f_zero_p(step))
06220 rb_raise(rb_eArgError, "step can't be 0");
06221 #endif
06222
06223 RETURN_ENUMERATOR(self, argc, argv);
06224
06225 date = self;
06226 switch (FIX2INT(f_cmp(step, INT2FIX(0)))) {
06227 case -1:
06228 while (FIX2INT(d_lite_cmp(date, limit)) >= 0) {
06229 rb_yield(date);
06230 date = d_lite_plus(date, step);
06231 }
06232 break;
06233 case 0:
06234 while (1)
06235 rb_yield(date);
06236 break;
06237 case 1:
06238 while (FIX2INT(d_lite_cmp(date, limit)) <= 0) {
06239 rb_yield(date);
06240 date = d_lite_plus(date, step);
06241 }
06242 break;
06243 default:
06244 abort();
06245 }
06246 return self;
06247 }
06248
06249
06250
06251
06252
06253
06254
06255
06256 static VALUE
06257 d_lite_upto(VALUE self, VALUE max)
06258 {
06259 VALUE date;
06260
06261 RETURN_ENUMERATOR(self, 1, &max);
06262
06263 date = self;
06264 while (FIX2INT(d_lite_cmp(date, max)) <= 0) {
06265 rb_yield(date);
06266 date = d_lite_plus(date, INT2FIX(1));
06267 }
06268 return self;
06269 }
06270
06271
06272
06273
06274
06275
06276
06277
06278 static VALUE
06279 d_lite_downto(VALUE self, VALUE min)
06280 {
06281 VALUE date;
06282
06283 RETURN_ENUMERATOR(self, 1, &min);
06284
06285 date = self;
06286 while (FIX2INT(d_lite_cmp(date, min)) >= 0) {
06287 rb_yield(date);
06288 date = d_lite_plus(date, INT2FIX(-1));
06289 }
06290 return self;
06291 }
06292
06293 static VALUE
06294 cmp_gen(VALUE self, VALUE other)
06295 {
06296 get_d1(self);
06297
06298 if (k_numeric_p(other))
06299 return f_cmp(m_ajd(dat), other);
06300 else if (k_date_p(other))
06301 return f_cmp(m_ajd(dat), f_ajd(other));
06302 return rb_num_coerce_cmp(self, other, rb_intern("<=>"));
06303 }
06304
06305 static VALUE
06306 cmp_dd(VALUE self, VALUE other)
06307 {
06308 get_d2(self, other);
06309
06310 {
06311 VALUE a_nth, b_nth,
06312 a_sf, b_sf;
06313 int a_jd, b_jd,
06314 a_df, b_df;
06315
06316 m_canonicalize_jd(adat);
06317 m_canonicalize_jd(bdat);
06318 a_nth = m_nth(adat);
06319 b_nth = m_nth(bdat);
06320 if (f_eqeq_p(a_nth, b_nth)) {
06321 a_jd = m_jd(adat);
06322 b_jd = m_jd(bdat);
06323 if (a_jd == b_jd) {
06324 a_df = m_df(adat);
06325 b_df = m_df(bdat);
06326 if (a_df == b_df) {
06327 a_sf = m_sf(adat);
06328 b_sf = m_sf(bdat);
06329 if (f_eqeq_p(a_sf, b_sf)) {
06330 return INT2FIX(0);
06331 }
06332 else if (f_lt_p(a_sf, b_sf)) {
06333 return INT2FIX(-1);
06334 }
06335 else {
06336 return INT2FIX(1);
06337 }
06338 }
06339 else if (a_df < b_df) {
06340 return INT2FIX(-1);
06341 }
06342 else {
06343 return INT2FIX(1);
06344 }
06345 }
06346 else if (a_jd < b_jd) {
06347 return INT2FIX(-1);
06348 }
06349 else {
06350 return INT2FIX(1);
06351 }
06352 }
06353 else if (f_lt_p(a_nth, b_nth)) {
06354 return INT2FIX(-1);
06355 }
06356 else {
06357 return INT2FIX(1);
06358 }
06359 }
06360 }
06361
06362
06363
06364
06365
06366
06367
06368
06369
06370
06371
06372
06373
06374
06375
06376
06377
06378
06379
06380 static VALUE
06381 d_lite_cmp(VALUE self, VALUE other)
06382 {
06383 if (!k_date_p(other))
06384 return cmp_gen(self, other);
06385
06386 {
06387 get_d2(self, other);
06388
06389 if (!(simple_dat_p(adat) && simple_dat_p(bdat) &&
06390 m_gregorian_p(adat) == m_gregorian_p(bdat)))
06391 return cmp_dd(self, other);
06392
06393 if (have_jd_p(adat) &&
06394 have_jd_p(bdat)) {
06395 VALUE a_nth, b_nth;
06396 int a_jd, b_jd;
06397
06398 m_canonicalize_jd(adat);
06399 m_canonicalize_jd(bdat);
06400 a_nth = m_nth(adat);
06401 b_nth = m_nth(bdat);
06402 if (f_eqeq_p(a_nth, b_nth)) {
06403 a_jd = m_jd(adat);
06404 b_jd = m_jd(bdat);
06405 if (a_jd == b_jd) {
06406 return INT2FIX(0);
06407 }
06408 else if (a_jd < b_jd) {
06409 return INT2FIX(-1);
06410 }
06411 else {
06412 return INT2FIX(1);
06413 }
06414 }
06415 else if (a_nth < b_nth) {
06416 return INT2FIX(-1);
06417 }
06418 else {
06419 return INT2FIX(1);
06420 }
06421 }
06422 else {
06423 #ifndef USE_PACK
06424 VALUE a_nth, b_nth;
06425 int a_year, b_year,
06426 a_mon, b_mon,
06427 a_mday, b_mday;
06428 #else
06429 VALUE a_nth, b_nth;
06430 int a_year, b_year,
06431 a_pd, b_pd;
06432 #endif
06433
06434 m_canonicalize_jd(adat);
06435 m_canonicalize_jd(bdat);
06436 a_nth = m_nth(adat);
06437 b_nth = m_nth(bdat);
06438 if (f_eqeq_p(a_nth, b_nth)) {
06439 a_year = m_year(adat);
06440 b_year = m_year(bdat);
06441 if (a_year == b_year) {
06442 #ifndef USE_PACK
06443 a_mon = m_mon(adat);
06444 b_mon = m_mon(bdat);
06445 if (a_mon == b_mon) {
06446 a_mday = m_mday(adat);
06447 b_mday = m_mday(bdat);
06448 if (a_mday == b_mday) {
06449 return INT2FIX(0);
06450 }
06451 else if (a_mday < b_mday) {
06452 return INT2FIX(-1);
06453 }
06454 else {
06455 return INT2FIX(1);
06456 }
06457 }
06458 else if (a_mon < b_mon) {
06459 return INT2FIX(-1);
06460 }
06461 else {
06462 return INT2FIX(1);
06463 }
06464 #else
06465 a_pd = m_pc(adat);
06466 b_pd = m_pc(bdat);
06467 if (a_pd == b_pd) {
06468 return INT2FIX(0);
06469 }
06470 else if (a_pd < b_pd) {
06471 return INT2FIX(-1);
06472 }
06473 else {
06474 return INT2FIX(1);
06475 }
06476 #endif
06477 }
06478 else if (a_year < b_year) {
06479 return INT2FIX(-1);
06480 }
06481 else {
06482 return INT2FIX(1);
06483 }
06484 }
06485 else if (f_lt_p(a_nth, b_nth)) {
06486 return INT2FIX(-1);
06487 }
06488 else {
06489 return INT2FIX(1);
06490 }
06491 }
06492 }
06493 }
06494
06495 static VALUE
06496 equal_gen(VALUE self, VALUE other)
06497 {
06498 get_d1(self);
06499
06500 if (k_numeric_p(other))
06501 return f_eqeq_p(m_real_local_jd(dat), other);
06502 else if (k_date_p(other))
06503 return f_eqeq_p(m_real_local_jd(dat), f_jd(other));
06504 return rb_num_coerce_cmp(self, other, rb_intern("=="));
06505 }
06506
06507
06508
06509
06510
06511
06512
06513
06514
06515
06516
06517
06518
06519
06520
06521
06522
06523
06524
06525
06526 static VALUE
06527 d_lite_equal(VALUE self, VALUE other)
06528 {
06529 if (!k_date_p(other))
06530 return equal_gen(self, other);
06531
06532 {
06533 get_d2(self, other);
06534
06535 if (!(m_gregorian_p(adat) == m_gregorian_p(bdat)))
06536 return equal_gen(self, other);
06537
06538 if (have_jd_p(adat) &&
06539 have_jd_p(bdat)) {
06540 VALUE a_nth, b_nth;
06541 int a_jd, b_jd;
06542
06543 m_canonicalize_jd(adat);
06544 m_canonicalize_jd(bdat);
06545 a_nth = m_nth(adat);
06546 b_nth = m_nth(bdat);
06547 a_jd = m_local_jd(adat);
06548 b_jd = m_local_jd(bdat);
06549 if (f_eqeq_p(a_nth, b_nth) &&
06550 a_jd == b_jd)
06551 return Qtrue;
06552 return Qfalse;
06553 }
06554 else {
06555 #ifndef USE_PACK
06556 VALUE a_nth, b_nth;
06557 int a_year, b_year,
06558 a_mon, b_mon,
06559 a_mday, b_mday;
06560 #else
06561 VALUE a_nth, b_nth;
06562 int a_year, b_year,
06563 a_pd, b_pd;
06564 #endif
06565
06566 m_canonicalize_jd(adat);
06567 m_canonicalize_jd(bdat);
06568 a_nth = m_nth(adat);
06569 b_nth = m_nth(bdat);
06570 if (f_eqeq_p(a_nth, b_nth)) {
06571 a_year = m_year(adat);
06572 b_year = m_year(bdat);
06573 if (a_year == b_year) {
06574 #ifndef USE_PACK
06575 a_mon = m_mon(adat);
06576 b_mon = m_mon(bdat);
06577 if (a_mon == b_mon) {
06578 a_mday = m_mday(adat);
06579 b_mday = m_mday(bdat);
06580 if (a_mday == b_mday)
06581 return Qtrue;
06582 }
06583 #else
06584
06585 a_pd = (m_pc(adat) >> MDAY_SHIFT);
06586 b_pd = (m_pc(bdat) >> MDAY_SHIFT);
06587 if (a_pd == b_pd) {
06588 return Qtrue;
06589 }
06590 #endif
06591 }
06592 }
06593 return Qfalse;
06594 }
06595 }
06596 }
06597
06598
06599 static VALUE
06600 d_lite_eql_p(VALUE self, VALUE other)
06601 {
06602 if (!k_date_p(other))
06603 return Qfalse;
06604 return f_zero_p(d_lite_cmp(self, other));
06605 }
06606
06607
06608 static VALUE
06609 d_lite_hash(VALUE self)
06610 {
06611 st_index_t v, h[4];
06612
06613 get_d1(self);
06614 h[0] = m_nth(dat);
06615 h[1] = m_jd(dat);
06616 h[2] = m_df(dat);
06617 h[3] = m_sf(dat);
06618 v = rb_memhash(h, sizeof(h));
06619 return LONG2FIX(v);
06620 }
06621
06622 #include "date_tmx.h"
06623 static void set_tmx(VALUE, struct tmx *);
06624 static VALUE strftimev(const char *, VALUE,
06625 void (*)(VALUE, struct tmx *));
06626
06627
06628
06629
06630
06631
06632
06633
06634
06635
06636
06637
06638 static VALUE
06639 d_lite_to_s(VALUE self)
06640 {
06641 return strftimev("%Y-%m-%d", self, set_tmx);
06642 }
06643
06644 #ifndef NDEBUG
06645 static VALUE
06646 mk_inspect_flags(union DateData *x)
06647 {
06648 return rb_enc_sprintf(rb_usascii_encoding(),
06649 "%c%c%c%c%c",
06650 (x->flags & COMPLEX_DAT) ? 'C' : 'S',
06651 (x->flags & HAVE_JD) ? 'j' : '-',
06652 (x->flags & HAVE_DF) ? 'd' : '-',
06653 (x->flags & HAVE_CIVIL) ? 'c' : '-',
06654 (x->flags & HAVE_TIME) ? 't' : '-');
06655 }
06656
06657 static VALUE
06658 mk_inspect_raw(union DateData *x, const char *klass)
06659 {
06660 if (simple_dat_p(x)) {
06661 VALUE nth, flags;
06662
06663 RB_GC_GUARD(nth) = f_inspect(x->s.nth);
06664 RB_GC_GUARD(flags) = mk_inspect_flags(x);
06665
06666 return rb_enc_sprintf(rb_usascii_encoding(),
06667 "#<%s: "
06668 "(%sth,%dj),+0s,%.0fj; "
06669 "%dy%dm%dd; %s>",
06670 klass ? klass : "?",
06671 RSTRING_PTR(nth), x->s.jd, x->s.sg,
06672 #ifndef USE_PACK
06673 x->s.year, x->s.mon, x->s.mday,
06674 #else
06675 x->s.year,
06676 EX_MON(x->s.pc), EX_MDAY(x->s.pc),
06677 #endif
06678 RSTRING_PTR(flags));
06679 }
06680 else {
06681 VALUE nth, sf, flags;
06682
06683 RB_GC_GUARD(nth) = f_inspect(x->c.nth);
06684 RB_GC_GUARD(sf) = f_inspect(x->c.sf);
06685 RB_GC_GUARD(flags) = mk_inspect_flags(x);
06686
06687 return rb_enc_sprintf(rb_usascii_encoding(),
06688 "#<%s: "
06689 "(%sth,%dj,%ds,%sn),%+ds,%.0fj; "
06690 "%dy%dm%dd %dh%dm%ds; %s>",
06691 klass ? klass : "?",
06692 RSTRING_PTR(nth), x->c.jd, x->c.df,
06693 RSTRING_PTR(sf),
06694 x->c.of, x->c.sg,
06695 #ifndef USE_PACK
06696 x->c.year, x->c.mon, x->c.mday,
06697 x->c.hour, x->c.min, x->c.sec,
06698 #else
06699 x->c.year,
06700 EX_MON(x->c.pc), EX_MDAY(x->c.pc),
06701 EX_HOUR(x->c.pc), EX_MIN(x->c.pc),
06702 EX_SEC(x->c.pc),
06703 #endif
06704 RSTRING_PTR(flags));
06705 }
06706 }
06707
06708 static VALUE
06709 d_lite_inspect_raw(VALUE self)
06710 {
06711 get_d1(self);
06712 return mk_inspect_raw(dat, rb_obj_classname(self));
06713 }
06714 #endif
06715
06716 static VALUE
06717 mk_inspect(union DateData *x, const char *klass, const char *to_s)
06718 {
06719 VALUE jd, sf;
06720
06721 RB_GC_GUARD(jd) = f_inspect(m_real_jd(x));
06722 RB_GC_GUARD(sf) = f_inspect(m_sf(x));
06723
06724 return rb_enc_sprintf(rb_usascii_encoding(),
06725 "#<%s: %s ((%sj,%ds,%sn),%+ds,%.0fj)>",
06726 klass ? klass : "?",
06727 to_s ? to_s : "?",
06728 RSTRING_PTR(jd), m_df(x), RSTRING_PTR(sf),
06729 m_of(x), m_sg(x));
06730 }
06731
06732
06733
06734
06735
06736
06737
06738
06739
06740
06741
06742
06743
06744
06745
06746 static VALUE
06747 d_lite_inspect(VALUE self)
06748 {
06749 get_d1(self);
06750 {
06751 VALUE to_s;
06752
06753 RB_GC_GUARD(to_s) = f_to_s(self);
06754 return mk_inspect(dat, rb_obj_classname(self), RSTRING_PTR(to_s));
06755 }
06756 }
06757
06758 #include <errno.h>
06759 #include "date_tmx.h"
06760
06761 size_t date_strftime(char *s, size_t maxsize, const char *format,
06762 const struct tmx *tmx);
06763
06764 #define SMALLBUF 100
06765 static size_t
06766 date_strftime_alloc(char **buf, const char *format,
06767 struct tmx *tmx)
06768 {
06769 size_t size, len, flen;
06770
06771 (*buf)[0] = '\0';
06772 flen = strlen(format);
06773 if (flen == 0) {
06774 return 0;
06775 }
06776 errno = 0;
06777 len = date_strftime(*buf, SMALLBUF, format, tmx);
06778 if (len != 0 || (**buf == '\0' && errno != ERANGE)) return len;
06779 for (size=1024; ; size*=2) {
06780 *buf = xmalloc(size);
06781 (*buf)[0] = '\0';
06782 len = date_strftime(*buf, size, format, tmx);
06783
06784
06785
06786
06787
06788
06789
06790 if (len > 0) break;
06791 xfree(*buf);
06792 if (size >= 1024 * flen) {
06793 rb_sys_fail(format);
06794 break;
06795 }
06796 }
06797 return len;
06798 }
06799
06800 static VALUE
06801 tmx_m_secs(union DateData *x)
06802 {
06803 VALUE s;
06804 int df;
06805
06806 s = day_to_sec(f_sub(m_real_jd(x),
06807 UNIX_EPOCH_IN_CJD));
06808 if (simple_dat_p(x))
06809 return s;
06810 df = m_df(x);
06811 if (df)
06812 s = f_add(s, INT2FIX(df));
06813 return s;
06814 }
06815
06816 #define MILLISECOND_IN_NANOSECONDS 1000000
06817
06818 static VALUE
06819 tmx_m_msecs(union DateData *x)
06820 {
06821 VALUE s, sf;
06822
06823 s = sec_to_ms(tmx_m_secs(x));
06824 if (simple_dat_p(x))
06825 return s;
06826 sf = m_sf(x);
06827 if (f_nonzero_p(sf))
06828 s = f_add(s, f_div(sf, INT2FIX(MILLISECOND_IN_NANOSECONDS)));
06829 return s;
06830 }
06831
06832 static VALUE
06833 tmx_m_of(union DateData *x)
06834 {
06835 return INT2FIX(m_of(x));
06836 }
06837
06838 static char *
06839 tmx_m_zone(union DateData *x)
06840 {
06841 return RSTRING_PTR(m_zone(x));
06842 }
06843
06844 static struct tmx_funcs tmx_funcs = {
06845 (VALUE (*)(void *))m_real_year,
06846 (int (*)(void *))m_yday,
06847 (int (*)(void *))m_mon,
06848 (int (*)(void *))m_mday,
06849 (VALUE (*)(void *))m_real_cwyear,
06850 (int (*)(void *))m_cweek,
06851 (int (*)(void *))m_cwday,
06852 (int (*)(void *))m_wnum0,
06853 (int (*)(void *))m_wnum1,
06854 (int (*)(void *))m_wday,
06855 (int (*)(void *))m_hour,
06856 (int (*)(void *))m_min,
06857 (int (*)(void *))m_sec,
06858 (VALUE (*)(void *))m_sf_in_sec,
06859 (VALUE (*)(void *))tmx_m_secs,
06860 (VALUE (*)(void *))tmx_m_msecs,
06861 (VALUE (*)(void *))tmx_m_of,
06862 (char *(*)(void *))tmx_m_zone
06863 };
06864
06865 static void
06866 set_tmx(VALUE self, struct tmx *tmx)
06867 {
06868 get_d1(self);
06869 tmx->dat = (void *)dat;
06870 tmx->funcs = &tmx_funcs;
06871 }
06872
06873 static VALUE
06874 date_strftime_internal(int argc, VALUE *argv, VALUE self,
06875 const char *default_fmt,
06876 void (*func)(VALUE, struct tmx *))
06877 {
06878 VALUE vfmt;
06879 const char *fmt;
06880 long len;
06881 char buffer[SMALLBUF], *buf = buffer;
06882 struct tmx tmx;
06883 VALUE str;
06884
06885 rb_scan_args(argc, argv, "01", &vfmt);
06886
06887 if (argc < 1)
06888 vfmt = rb_usascii_str_new2(default_fmt);
06889 else {
06890 StringValue(vfmt);
06891 if (!rb_enc_str_asciicompat_p(vfmt)) {
06892 rb_raise(rb_eArgError,
06893 "format should have ASCII compatible encoding");
06894 }
06895 }
06896 fmt = RSTRING_PTR(vfmt);
06897 len = RSTRING_LEN(vfmt);
06898 (*func)(self, &tmx);
06899 if (memchr(fmt, '\0', len)) {
06900
06901 const char *p = fmt, *pe = fmt + len;
06902
06903 str = rb_str_new(0, 0);
06904 while (p < pe) {
06905 len = date_strftime_alloc(&buf, p, &tmx);
06906 rb_str_cat(str, buf, len);
06907 p += strlen(p);
06908 if (buf != buffer) {
06909 xfree(buf);
06910 buf = buffer;
06911 }
06912 for (fmt = p; p < pe && !*p; ++p);
06913 if (p > fmt) rb_str_cat(str, fmt, p - fmt);
06914 }
06915 rb_enc_copy(str, vfmt);
06916 OBJ_INFECT(str, vfmt);
06917 return str;
06918 }
06919 else
06920 len = date_strftime_alloc(&buf, fmt, &tmx);
06921
06922 str = rb_str_new(buf, len);
06923 if (buf != buffer) xfree(buf);
06924 rb_enc_copy(str, vfmt);
06925 OBJ_INFECT(str, vfmt);
06926 return str;
06927 }
06928
06929
06930
06931
06932
06933
06934
06935
06936
06937
06938
06939
06940
06941
06942
06943
06944
06945
06946
06947
06948
06949
06950
06951
06952
06953
06954
06955
06956
06957
06958
06959
06960
06961
06962
06963
06964
06965
06966
06967
06968
06969
06970
06971
06972
06973
06974
06975
06976
06977
06978
06979
06980
06981
06982
06983
06984
06985
06986
06987
06988
06989
06990
06991
06992
06993
06994
06995
06996
06997
06998
06999
07000
07001
07002
07003
07004
07005
07006
07007
07008
07009
07010
07011
07012
07013
07014
07015
07016
07017
07018
07019
07020
07021
07022
07023
07024
07025
07026
07027
07028
07029
07030
07031
07032
07033
07034
07035
07036
07037
07038
07039
07040
07041
07042
07043
07044
07045
07046
07047
07048
07049
07050
07051
07052
07053
07054
07055
07056
07057
07058
07059
07060
07061
07062
07063
07064
07065
07066
07067
07068
07069
07070
07071
07072
07073
07074
07075
07076
07077
07078
07079
07080
07081
07082
07083
07084
07085
07086
07087
07088
07089
07090
07091
07092
07093
07094
07095
07096
07097
07098
07099
07100
07101
07102
07103
07104
07105
07106 static VALUE
07107 d_lite_strftime(int argc, VALUE *argv, VALUE self)
07108 {
07109 return date_strftime_internal(argc, argv, self,
07110 "%Y-%m-%d", set_tmx);
07111 }
07112
07113 static VALUE
07114 strftimev(const char *fmt, VALUE self,
07115 void (*func)(VALUE, struct tmx *))
07116 {
07117 char buffer[SMALLBUF], *buf = buffer;
07118 struct tmx tmx;
07119 long len;
07120 VALUE str;
07121
07122 (*func)(self, &tmx);
07123 len = date_strftime_alloc(&buf, fmt, &tmx);
07124 str = rb_usascii_str_new(buf, len);
07125 if (buf != buffer) xfree(buf);
07126 return str;
07127 }
07128
07129
07130
07131
07132
07133
07134
07135
07136
07137
07138
07139 static VALUE
07140 d_lite_asctime(VALUE self)
07141 {
07142 return strftimev("%a %b %e %H:%M:%S %Y", self, set_tmx);
07143 }
07144
07145
07146
07147
07148
07149
07150
07151
07152 static VALUE
07153 d_lite_iso8601(VALUE self)
07154 {
07155 return strftimev("%Y-%m-%d", self, set_tmx);
07156 }
07157
07158
07159
07160
07161
07162
07163
07164 static VALUE
07165 d_lite_rfc3339(VALUE self)
07166 {
07167 return strftimev("%Y-%m-%dT%H:%M:%S%:z", self, set_tmx);
07168 }
07169
07170
07171
07172
07173
07174
07175
07176
07177 static VALUE
07178 d_lite_rfc2822(VALUE self)
07179 {
07180 return strftimev("%a, %-d %b %Y %T %z", self, set_tmx);
07181 }
07182
07183
07184
07185
07186
07187
07188
07189
07190 static VALUE
07191 d_lite_httpdate(VALUE self)
07192 {
07193 volatile VALUE dup = dup_obj_with_new_offset(self, 0);
07194 return strftimev("%a, %d %b %Y %T GMT", dup, set_tmx);
07195 }
07196
07197 static VALUE
07198 jisx0301_date(VALUE jd, VALUE y)
07199 {
07200 VALUE a[2];
07201
07202 if (f_lt_p(jd, INT2FIX(2405160)))
07203 return rb_usascii_str_new2("%Y-%m-%d");
07204 if (f_lt_p(jd, INT2FIX(2419614))) {
07205 a[0] = rb_usascii_str_new2("M%02d" ".%%m.%%d");
07206 a[1] = f_sub(y, INT2FIX(1867));
07207 }
07208 else if (f_lt_p(jd, INT2FIX(2424875))) {
07209 a[0] = rb_usascii_str_new2("T%02d" ".%%m.%%d");
07210 a[1] = f_sub(y, INT2FIX(1911));
07211 }
07212 else if (f_lt_p(jd, INT2FIX(2447535))) {
07213 a[0] = rb_usascii_str_new2("S%02d" ".%%m.%%d");
07214 a[1] = f_sub(y, INT2FIX(1925));
07215 }
07216 else {
07217 a[0] = rb_usascii_str_new2("H%02d" ".%%m.%%d");
07218 a[1] = f_sub(y, INT2FIX(1988));
07219 }
07220 return rb_f_sprintf(2, a);
07221 }
07222
07223
07224
07225
07226
07227
07228
07229
07230
07231
07232
07233 static VALUE
07234 d_lite_jisx0301(VALUE self)
07235 {
07236 VALUE s;
07237
07238 get_d1(self);
07239 s = jisx0301_date(m_real_local_jd(dat),
07240 m_real_year(dat));
07241 return strftimev(RSTRING_PTR(s), self, set_tmx);
07242 }
07243
07244 #ifndef NDEBUG
07245 static VALUE
07246 d_lite_marshal_dump_old(VALUE self)
07247 {
07248 VALUE a;
07249
07250 get_d1(self);
07251
07252 a = rb_ary_new3(3,
07253 m_ajd(dat),
07254 m_of_in_day(dat),
07255 DBL2NUM(m_sg(dat)));
07256
07257 if (FL_TEST(self, FL_EXIVAR)) {
07258 rb_copy_generic_ivar(a, self);
07259 FL_SET(a, FL_EXIVAR);
07260 }
07261
07262 return a;
07263 }
07264 #endif
07265
07266
07267 static VALUE
07268 d_lite_marshal_dump(VALUE self)
07269 {
07270 VALUE a;
07271
07272 get_d1(self);
07273
07274 a = rb_ary_new3(6,
07275 m_nth(dat),
07276 INT2FIX(m_jd(dat)),
07277 INT2FIX(m_df(dat)),
07278 m_sf(dat),
07279 INT2FIX(m_of(dat)),
07280 DBL2NUM(m_sg(dat)));
07281
07282 if (FL_TEST(self, FL_EXIVAR)) {
07283 rb_copy_generic_ivar(a, self);
07284 FL_SET(a, FL_EXIVAR);
07285 }
07286
07287 return a;
07288 }
07289
07290
07291 static VALUE
07292 d_lite_marshal_load(VALUE self, VALUE a)
07293 {
07294 get_d1(self);
07295
07296 if (TYPE(a) != T_ARRAY)
07297 rb_raise(rb_eTypeError, "expected an array");
07298
07299 switch (RARRAY_LEN(a)) {
07300 case 3:
07301 {
07302 VALUE ajd, of, sg, nth, sf;
07303 int jd, df, rof;
07304 double rsg;
07305
07306 ajd = RARRAY_PTR(a)[0];
07307 of = RARRAY_PTR(a)[1];
07308 sg = RARRAY_PTR(a)[2];
07309
07310 old_to_new(ajd, of, sg,
07311 &nth, &jd, &df, &sf, &rof, &rsg);
07312
07313 if (!df && f_zero_p(sf) && !rof) {
07314 set_to_simple(&dat->s, nth, jd, rsg, 0, 0, 0, HAVE_JD);
07315 } else {
07316 if (!complex_dat_p(dat))
07317 rb_raise(rb_eArgError,
07318 "cannot load complex into simple");
07319
07320 set_to_complex(&dat->c, nth, jd, df, sf, rof, rsg,
07321 0, 0, 0, 0, 0, 0,
07322 HAVE_JD | HAVE_DF | COMPLEX_DAT);
07323 }
07324 }
07325 break;
07326 case 6:
07327 {
07328 VALUE nth, sf;
07329 int jd, df, of;
07330 double sg;
07331
07332 nth = RARRAY_PTR(a)[0];
07333 jd = NUM2INT(RARRAY_PTR(a)[1]);
07334 df = NUM2INT(RARRAY_PTR(a)[2]);
07335 sf = RARRAY_PTR(a)[3];
07336 of = NUM2INT(RARRAY_PTR(a)[4]);
07337 sg = NUM2DBL(RARRAY_PTR(a)[5]);
07338 if (!df && f_zero_p(sf) && !of) {
07339 set_to_simple(&dat->s, nth, jd, sg, 0, 0, 0, HAVE_JD);
07340 } else {
07341 if (!complex_dat_p(dat))
07342 rb_raise(rb_eArgError,
07343 "cannot load complex into simple");
07344
07345 set_to_complex(&dat->c, nth, jd, df, sf, of, sg,
07346 0, 0, 0, 0, 0, 0,
07347 HAVE_JD | HAVE_DF | COMPLEX_DAT);
07348 }
07349 }
07350 break;
07351 default:
07352 rb_raise(rb_eTypeError, "invalid size");
07353 break;
07354 }
07355
07356 if (FL_TEST(a, FL_EXIVAR)) {
07357 rb_copy_generic_ivar(self, a);
07358 FL_SET(self, FL_EXIVAR);
07359 }
07360
07361 return self;
07362 }
07363
07364
07365
07366
07367
07368
07369
07370
07371
07372
07373
07374
07375
07376
07377
07378
07379
07380
07381 static VALUE
07382 datetime_s_jd(int argc, VALUE *argv, VALUE klass)
07383 {
07384 VALUE vjd, vh, vmin, vs, vof, vsg, jd, fr, fr2, ret;
07385 int h, min, s, rof;
07386 double sg;
07387
07388 rb_scan_args(argc, argv, "06", &vjd, &vh, &vmin, &vs, &vof, &vsg);
07389
07390 jd = INT2FIX(0);
07391
07392 h = min = s = 0;
07393 fr2 = INT2FIX(0);
07394 rof = 0;
07395 sg = DEFAULT_SG;
07396
07397 switch (argc) {
07398 case 6:
07399 val2sg(vsg, sg);
07400 case 5:
07401 val2off(vof, rof);
07402 case 4:
07403 num2int_with_frac(s, positive_inf);
07404 case 3:
07405 num2int_with_frac(min, 3);
07406 case 2:
07407 num2int_with_frac(h, 2);
07408 case 1:
07409 num2num_with_frac(jd, 1);
07410 }
07411
07412 {
07413 VALUE nth;
07414 int rh, rmin, rs, rjd, rjd2;
07415
07416 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
07417 rb_raise(rb_eArgError, "invalid date");
07418 canon24oc();
07419
07420 decode_jd(jd, &nth, &rjd);
07421 rjd2 = jd_local_to_utc(rjd,
07422 time_to_df(rh, rmin, rs),
07423 rof);
07424
07425 ret = d_complex_new_internal(klass,
07426 nth, rjd2,
07427 0, INT2FIX(0),
07428 rof, sg,
07429 0, 0, 0,
07430 rh, rmin, rs,
07431 HAVE_JD | HAVE_TIME);
07432 }
07433 add_frac();
07434 return ret;
07435 }
07436
07437
07438
07439
07440
07441
07442
07443
07444
07445
07446
07447
07448
07449
07450
07451 static VALUE
07452 datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
07453 {
07454 VALUE vy, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
07455 int d, h, min, s, rof;
07456 double sg;
07457
07458 rb_scan_args(argc, argv, "07", &vy, &vd, &vh, &vmin, &vs, &vof, &vsg);
07459
07460 y = INT2FIX(-4712);
07461 d = 1;
07462
07463 h = min = s = 0;
07464 fr2 = INT2FIX(0);
07465 rof = 0;
07466 sg = DEFAULT_SG;
07467
07468 switch (argc) {
07469 case 7:
07470 val2sg(vsg, sg);
07471 case 6:
07472 val2off(vof, rof);
07473 case 5:
07474 num2int_with_frac(s, positive_inf);
07475 case 4:
07476 num2int_with_frac(min, 4);
07477 case 3:
07478 num2int_with_frac(h, 3);
07479 case 2:
07480 num2int_with_frac(d, 2);
07481 case 1:
07482 y = vy;
07483 }
07484
07485 {
07486 VALUE nth;
07487 int ry, rd, rh, rmin, rs, rjd, rjd2, ns;
07488
07489 if (!valid_ordinal_p(y, d, sg,
07490 &nth, &ry,
07491 &rd, &rjd,
07492 &ns))
07493 rb_raise(rb_eArgError, "invalid date");
07494 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
07495 rb_raise(rb_eArgError, "invalid date");
07496 canon24oc();
07497
07498 rjd2 = jd_local_to_utc(rjd,
07499 time_to_df(rh, rmin, rs),
07500 rof);
07501
07502 ret = d_complex_new_internal(klass,
07503 nth, rjd2,
07504 0, INT2FIX(0),
07505 rof, sg,
07506 0, 0, 0,
07507 rh, rmin, rs,
07508 HAVE_JD | HAVE_TIME);
07509 }
07510 add_frac();
07511 return ret;
07512 }
07513
07514
07515
07516
07517
07518
07519
07520
07521
07522
07523
07524
07525
07526
07527
07528
07529 static VALUE
07530 datetime_s_civil(int argc, VALUE *argv, VALUE klass)
07531 {
07532 VALUE vy, vm, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
07533 int m, d, h, min, s, rof;
07534 double sg;
07535
07536 rb_scan_args(argc, argv, "08", &vy, &vm, &vd, &vh, &vmin, &vs, &vof, &vsg);
07537
07538 y = INT2FIX(-4712);
07539 m = 1;
07540 d = 1;
07541
07542 h = min = s = 0;
07543 fr2 = INT2FIX(0);
07544 rof = 0;
07545 sg = DEFAULT_SG;
07546
07547 switch (argc) {
07548 case 8:
07549 val2sg(vsg, sg);
07550 case 7:
07551 val2off(vof, rof);
07552 case 6:
07553 num2int_with_frac(s, positive_inf);
07554 case 5:
07555 num2int_with_frac(min, 5);
07556 case 4:
07557 num2int_with_frac(h, 4);
07558 case 3:
07559 num2int_with_frac(d, 3);
07560 case 2:
07561 m = NUM2INT(vm);
07562 case 1:
07563 y = vy;
07564 }
07565
07566 if (guess_style(y, sg) < 0) {
07567 VALUE nth;
07568 int ry, rm, rd, rh, rmin, rs;
07569
07570 if (!valid_gregorian_p(y, m, d,
07571 &nth, &ry,
07572 &rm, &rd))
07573 rb_raise(rb_eArgError, "invalid date");
07574 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
07575 rb_raise(rb_eArgError, "invalid date");
07576 canon24oc();
07577
07578 ret = d_complex_new_internal(klass,
07579 nth, 0,
07580 0, INT2FIX(0),
07581 rof, sg,
07582 ry, rm, rd,
07583 rh, rmin, rs,
07584 HAVE_CIVIL | HAVE_TIME);
07585 }
07586 else {
07587 VALUE nth;
07588 int ry, rm, rd, rh, rmin, rs, rjd, rjd2, ns;
07589
07590 if (!valid_civil_p(y, m, d, sg,
07591 &nth, &ry,
07592 &rm, &rd, &rjd,
07593 &ns))
07594 rb_raise(rb_eArgError, "invalid date");
07595 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
07596 rb_raise(rb_eArgError, "invalid date");
07597 canon24oc();
07598
07599 rjd2 = jd_local_to_utc(rjd,
07600 time_to_df(rh, rmin, rs),
07601 rof);
07602
07603 ret = d_complex_new_internal(klass,
07604 nth, rjd2,
07605 0, INT2FIX(0),
07606 rof, sg,
07607 ry, rm, rd,
07608 rh, rmin, rs,
07609 HAVE_JD | HAVE_CIVIL | HAVE_TIME);
07610 }
07611 add_frac();
07612 return ret;
07613 }
07614
07615
07616
07617
07618
07619
07620
07621
07622
07623
07624
07625
07626
07627
07628 static VALUE
07629 datetime_s_commercial(int argc, VALUE *argv, VALUE klass)
07630 {
07631 VALUE vy, vw, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
07632 int w, d, h, min, s, rof;
07633 double sg;
07634
07635 rb_scan_args(argc, argv, "08", &vy, &vw, &vd, &vh, &vmin, &vs, &vof, &vsg);
07636
07637 y = INT2FIX(-4712);
07638 w = 1;
07639 d = 1;
07640
07641 h = min = s = 0;
07642 fr2 = INT2FIX(0);
07643 rof = 0;
07644 sg = DEFAULT_SG;
07645
07646 switch (argc) {
07647 case 8:
07648 val2sg(vsg, sg);
07649 case 7:
07650 val2off(vof, rof);
07651 case 6:
07652 num2int_with_frac(s, positive_inf);
07653 case 5:
07654 num2int_with_frac(min, 5);
07655 case 4:
07656 num2int_with_frac(h, 4);
07657 case 3:
07658 num2int_with_frac(d, 3);
07659 case 2:
07660 w = NUM2INT(vw);
07661 case 1:
07662 y = vy;
07663 }
07664
07665 {
07666 VALUE nth;
07667 int ry, rw, rd, rh, rmin, rs, rjd, rjd2, ns;
07668
07669 if (!valid_commercial_p(y, w, d, sg,
07670 &nth, &ry,
07671 &rw, &rd, &rjd,
07672 &ns))
07673 rb_raise(rb_eArgError, "invalid date");
07674 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
07675 rb_raise(rb_eArgError, "invalid date");
07676 canon24oc();
07677
07678 rjd2 = jd_local_to_utc(rjd,
07679 time_to_df(rh, rmin, rs),
07680 rof);
07681
07682 ret = d_complex_new_internal(klass,
07683 nth, rjd2,
07684 0, INT2FIX(0),
07685 rof, sg,
07686 0, 0, 0,
07687 rh, rmin, rs,
07688 HAVE_JD | HAVE_TIME);
07689 }
07690 add_frac();
07691 return ret;
07692 }
07693
07694 #ifndef NDEBUG
07695 static VALUE
07696 datetime_s_weeknum(int argc, VALUE *argv, VALUE klass)
07697 {
07698 VALUE vy, vw, vd, vf, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
07699 int w, d, f, h, min, s, rof;
07700 double sg;
07701
07702 rb_scan_args(argc, argv, "09", &vy, &vw, &vd, &vf,
07703 &vh, &vmin, &vs, &vof, &vsg);
07704
07705 y = INT2FIX(-4712);
07706 w = 0;
07707 d = 1;
07708 f = 0;
07709
07710 h = min = s = 0;
07711 fr2 = INT2FIX(0);
07712 rof = 0;
07713 sg = DEFAULT_SG;
07714
07715 switch (argc) {
07716 case 9:
07717 val2sg(vsg, sg);
07718 case 8:
07719 val2off(vof, rof);
07720 case 7:
07721 num2int_with_frac(s, positive_inf);
07722 case 6:
07723 num2int_with_frac(min, 6);
07724 case 5:
07725 num2int_with_frac(h, 5);
07726 case 4:
07727 f = NUM2INT(vf);
07728 case 3:
07729 num2int_with_frac(d, 4);
07730 case 2:
07731 w = NUM2INT(vw);
07732 case 1:
07733 y = vy;
07734 }
07735
07736 {
07737 VALUE nth;
07738 int ry, rw, rd, rh, rmin, rs, rjd, rjd2, ns;
07739
07740 if (!valid_weeknum_p(y, w, d, f, sg,
07741 &nth, &ry,
07742 &rw, &rd, &rjd,
07743 &ns))
07744 rb_raise(rb_eArgError, "invalid date");
07745 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
07746 rb_raise(rb_eArgError, "invalid date");
07747 canon24oc();
07748
07749 rjd2 = jd_local_to_utc(rjd,
07750 time_to_df(rh, rmin, rs),
07751 rof);
07752 ret = d_complex_new_internal(klass,
07753 nth, rjd2,
07754 0, INT2FIX(0),
07755 rof, sg,
07756 0, 0, 0,
07757 rh, rmin, rs,
07758 HAVE_JD | HAVE_TIME);
07759 }
07760 add_frac();
07761 return ret;
07762 }
07763
07764 static VALUE
07765 datetime_s_nth_kday(int argc, VALUE *argv, VALUE klass)
07766 {
07767 VALUE vy, vm, vn, vk, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
07768 int m, n, k, h, min, s, rof;
07769 double sg;
07770
07771 rb_scan_args(argc, argv, "09", &vy, &vm, &vn, &vk,
07772 &vh, &vmin, &vs, &vof, &vsg);
07773
07774 y = INT2FIX(-4712);
07775 m = 1;
07776 n = 1;
07777 k = 1;
07778
07779 h = min = s = 0;
07780 fr2 = INT2FIX(0);
07781 rof = 0;
07782 sg = DEFAULT_SG;
07783
07784 switch (argc) {
07785 case 9:
07786 val2sg(vsg, sg);
07787 case 8:
07788 val2off(vof, rof);
07789 case 7:
07790 num2int_with_frac(s, positive_inf);
07791 case 6:
07792 num2int_with_frac(min, 6);
07793 case 5:
07794 num2int_with_frac(h, 5);
07795 case 4:
07796 num2int_with_frac(k, 4);
07797 case 3:
07798 n = NUM2INT(vn);
07799 case 2:
07800 m = NUM2INT(vm);
07801 case 1:
07802 y = vy;
07803 }
07804
07805 {
07806 VALUE nth;
07807 int ry, rm, rn, rk, rh, rmin, rs, rjd, rjd2, ns;
07808
07809 if (!valid_nth_kday_p(y, m, n, k, sg,
07810 &nth, &ry,
07811 &rm, &rn, &rk, &rjd,
07812 &ns))
07813 rb_raise(rb_eArgError, "invalid date");
07814 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
07815 rb_raise(rb_eArgError, "invalid date");
07816 canon24oc();
07817
07818 rjd2 = jd_local_to_utc(rjd,
07819 time_to_df(rh, rmin, rs),
07820 rof);
07821 ret = d_complex_new_internal(klass,
07822 nth, rjd2,
07823 0, INT2FIX(0),
07824 rof, sg,
07825 0, 0, 0,
07826 rh, rmin, rs,
07827 HAVE_JD | HAVE_TIME);
07828 }
07829 add_frac();
07830 return ret;
07831 }
07832 #endif
07833
07834
07835
07836
07837
07838
07839
07840
07841
07842
07843
07844 static VALUE
07845 datetime_s_now(int argc, VALUE *argv, VALUE klass)
07846 {
07847 VALUE vsg, nth, ret;
07848 double sg;
07849 #ifdef HAVE_CLOCK_GETTIME
07850 struct timespec ts;
07851 #else
07852 struct timeval tv;
07853 #endif
07854 time_t sec;
07855 struct tm tm;
07856 long sf, of;
07857 int y, ry, m, d, h, min, s;
07858
07859 rb_scan_args(argc, argv, "01", &vsg);
07860
07861 if (argc < 1)
07862 sg = DEFAULT_SG;
07863 else
07864 sg = NUM2DBL(vsg);
07865
07866 #ifdef HAVE_CLOCK_GETTIME
07867 if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
07868 rb_sys_fail("clock_gettime");
07869 sec = ts.tv_sec;
07870 #else
07871 if (gettimeofday(&tv, NULL) == -1)
07872 rb_sys_fail("gettimeofday");
07873 sec = tv.tv_sec;
07874 #endif
07875 tzset();
07876 if (!localtime_r(&sec, &tm))
07877 rb_sys_fail("localtime");
07878
07879 y = tm.tm_year + 1900;
07880 m = tm.tm_mon + 1;
07881 d = tm.tm_mday;
07882 h = tm.tm_hour;
07883 min = tm.tm_min;
07884 s = tm.tm_sec;
07885 if (s == 60)
07886 s = 59;
07887 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
07888 of = tm.tm_gmtoff;
07889 #elif defined(HAVE_VAR_TIMEZONE)
07890 #ifdef HAVE_VAR_ALTZONE
07891 of = (long)-((tm.tm_isdst > 0) ? altzone : timezone);
07892 #else
07893 of = (long)-timezone;
07894 if (tm.tm_isdst) {
07895 time_t sec2;
07896
07897 tm.tm_isdst = 0;
07898 sec2 = mktime(&tm);
07899 of += (long)difftime(sec2, sec);
07900 }
07901 #endif
07902 #elif defined(HAVE_TIMEGM)
07903 {
07904 time_t sec2;
07905
07906 sec2 = timegm(&tm);
07907 of = (long)difftime(sec2, sec);
07908 }
07909 #else
07910 {
07911 struct tm tm2;
07912 time_t sec2;
07913
07914 if (!gmtime_r(&sec, &tm2))
07915 rb_sys_fail("gmtime");
07916 tm2.tm_isdst = tm.tm_isdst;
07917 sec2 = mktime(&tm2);
07918 of = (long)difftime(sec, sec2);
07919 }
07920 #endif
07921 #ifdef HAVE_CLOCK_GETTIME
07922 sf = ts.tv_nsec;
07923 #else
07924 sf = tv.tv_usec * 1000;
07925 #endif
07926
07927 if (of < -DAY_IN_SECONDS || of > DAY_IN_SECONDS) {
07928 of = 0;
07929 rb_warning("invalid offset is ignored");
07930 }
07931
07932 decode_year(INT2FIX(y), -1, &nth, &ry);
07933
07934 ret = d_complex_new_internal(klass,
07935 nth, 0,
07936 0, LONG2NUM(sf),
07937 (int)of, GREGORIAN,
07938 ry, m, d,
07939 h, min, s,
07940 HAVE_CIVIL | HAVE_TIME);
07941 {
07942 get_d1(ret);
07943 set_sg(dat, sg);
07944 }
07945 return ret;
07946 }
07947
07948 static VALUE
07949 dt_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
07950 {
07951 VALUE jd, sf, t;
07952 int df, of;
07953
07954 if (!c_valid_start_p(NUM2DBL(sg))) {
07955 sg = INT2FIX(DEFAULT_SG);
07956 rb_warning("invalid start is ignored");
07957 }
07958
07959 if (NIL_P(hash))
07960 rb_raise(rb_eArgError, "invalid date");
07961
07962 if (NIL_P(ref_hash("jd")) &&
07963 NIL_P(ref_hash("yday")) &&
07964 !NIL_P(ref_hash("year")) &&
07965 !NIL_P(ref_hash("mon")) &&
07966 !NIL_P(ref_hash("mday"))) {
07967 jd = rt__valid_civil_p(ref_hash("year"),
07968 ref_hash("mon"),
07969 ref_hash("mday"), sg);
07970
07971 if (NIL_P(ref_hash("hour")))
07972 set_hash("hour", INT2FIX(0));
07973 if (NIL_P(ref_hash("min")))
07974 set_hash("min", INT2FIX(0));
07975 if (NIL_P(ref_hash("sec")))
07976 set_hash("sec", INT2FIX(0));
07977 else if (f_gt_p(ref_hash("sec"), INT2FIX(59)))
07978 set_hash("sec", INT2FIX(59));
07979 }
07980 else {
07981 hash = rt_rewrite_frags(hash);
07982 hash = rt_complete_frags(klass, hash);
07983 jd = rt__valid_date_frags_p(hash, sg);
07984 }
07985
07986 if (NIL_P(jd))
07987 rb_raise(rb_eArgError, "invalid date");
07988
07989 {
07990 int rh, rmin, rs;
07991
07992 if (!c_valid_time_p(NUM2INT(ref_hash("hour")),
07993 NUM2INT(ref_hash("min")),
07994 NUM2INT(ref_hash("sec")),
07995 &rh, &rmin, &rs))
07996 rb_raise(rb_eArgError, "invalid date");
07997
07998 df = time_to_df(rh, rmin, rs);
07999 }
08000
08001 t = ref_hash("sec_fraction");
08002 if (NIL_P(t))
08003 sf = INT2FIX(0);
08004 else
08005 sf = sec_to_ns(t);
08006
08007 t = ref_hash("offset");
08008 if (NIL_P(t))
08009 of = 0;
08010 else {
08011 of = NUM2INT(t);
08012 if (of < -DAY_IN_SECONDS || of > DAY_IN_SECONDS) {
08013 of = 0;
08014 rb_warning("invalid offset is ignored");
08015 }
08016 }
08017 {
08018 VALUE nth;
08019 int rjd, rjd2;
08020
08021 decode_jd(jd, &nth, &rjd);
08022 rjd2 = jd_local_to_utc(rjd, df, of);
08023 df = df_local_to_utc(df, of);
08024
08025 return d_complex_new_internal(klass,
08026 nth, rjd2,
08027 df, sf,
08028 of, NUM2DBL(sg),
08029 0, 0, 0,
08030 0, 0, 0,
08031 HAVE_JD | HAVE_DF);
08032 }
08033 }
08034
08035
08036
08037
08038
08039
08040
08041
08042
08043
08044 static VALUE
08045 datetime_s__strptime(int argc, VALUE *argv, VALUE klass)
08046 {
08047 return date_s__strptime_internal(argc, argv, klass, "%FT%T%z");
08048 }
08049
08050
08051
08052
08053
08054
08055
08056
08057
08058
08059
08060
08061
08062
08063
08064
08065
08066
08067
08068
08069
08070
08071
08072
08073
08074
08075
08076
08077
08078 static VALUE
08079 datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
08080 {
08081 VALUE str, fmt, sg;
08082
08083 rb_scan_args(argc, argv, "03", &str, &fmt, &sg);
08084
08085 switch (argc) {
08086 case 0:
08087 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
08088 case 1:
08089 fmt = rb_str_new2("%FT%T%z");
08090 case 2:
08091 sg = INT2FIX(DEFAULT_SG);
08092 }
08093
08094 {
08095 VALUE argv2[2], hash;
08096
08097 argv2[0] = str;
08098 argv2[1] = fmt;
08099 hash = date_s__strptime(2, argv2, klass);
08100 return dt_new_by_frags(klass, hash, sg);
08101 }
08102 }
08103
08104
08105
08106
08107
08108
08109
08110
08111
08112
08113
08114
08115
08116
08117
08118
08119
08120
08121
08122
08123 static VALUE
08124 datetime_s_parse(int argc, VALUE *argv, VALUE klass)
08125 {
08126 VALUE str, comp, sg;
08127
08128 rb_scan_args(argc, argv, "03", &str, &comp, &sg);
08129
08130 switch (argc) {
08131 case 0:
08132 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
08133 case 1:
08134 comp = Qtrue;
08135 case 2:
08136 sg = INT2FIX(DEFAULT_SG);
08137 }
08138
08139 {
08140 VALUE argv2[2], hash;
08141
08142 argv2[0] = str;
08143 argv2[1] = comp;
08144 hash = date_s__parse(2, argv2, klass);
08145 return dt_new_by_frags(klass, hash, sg);
08146 }
08147 }
08148
08149
08150
08151
08152
08153
08154
08155
08156
08157
08158
08159
08160
08161
08162
08163
08164
08165 static VALUE
08166 datetime_s_iso8601(int argc, VALUE *argv, VALUE klass)
08167 {
08168 VALUE str, sg;
08169
08170 rb_scan_args(argc, argv, "02", &str, &sg);
08171
08172 switch (argc) {
08173 case 0:
08174 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
08175 case 1:
08176 sg = INT2FIX(DEFAULT_SG);
08177 }
08178
08179 {
08180 VALUE hash = date_s__iso8601(klass, str);
08181 return dt_new_by_frags(klass, hash, sg);
08182 }
08183 }
08184
08185
08186
08187
08188
08189
08190
08191
08192
08193
08194
08195
08196
08197 static VALUE
08198 datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass)
08199 {
08200 VALUE str, sg;
08201
08202 rb_scan_args(argc, argv, "02", &str, &sg);
08203
08204 switch (argc) {
08205 case 0:
08206 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
08207 case 1:
08208 sg = INT2FIX(DEFAULT_SG);
08209 }
08210
08211 {
08212 VALUE hash = date_s__rfc3339(klass, str);
08213 return dt_new_by_frags(klass, hash, sg);
08214 }
08215 }
08216
08217
08218
08219
08220
08221
08222
08223
08224
08225
08226
08227
08228
08229 static VALUE
08230 datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass)
08231 {
08232 VALUE str, sg;
08233
08234 rb_scan_args(argc, argv, "02", &str, &sg);
08235
08236 switch (argc) {
08237 case 0:
08238 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
08239 case 1:
08240 sg = INT2FIX(DEFAULT_SG);
08241 }
08242
08243 {
08244 VALUE hash = date_s__xmlschema(klass, str);
08245 return dt_new_by_frags(klass, hash, sg);
08246 }
08247 }
08248
08249
08250
08251
08252
08253
08254
08255
08256
08257
08258
08259
08260
08261
08262 static VALUE
08263 datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
08264 {
08265 VALUE str, sg;
08266
08267 rb_scan_args(argc, argv, "02", &str, &sg);
08268
08269 switch (argc) {
08270 case 0:
08271 str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000");
08272 case 1:
08273 sg = INT2FIX(DEFAULT_SG);
08274 }
08275
08276 {
08277 VALUE hash = date_s__rfc2822(klass, str);
08278 return dt_new_by_frags(klass, hash, sg);
08279 }
08280 }
08281
08282
08283
08284
08285
08286
08287
08288
08289
08290
08291
08292
08293
08294 static VALUE
08295 datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
08296 {
08297 VALUE str, sg;
08298
08299 rb_scan_args(argc, argv, "02", &str, &sg);
08300
08301 switch (argc) {
08302 case 0:
08303 str = rb_str_new2("Mon, 01 Jan -4712 00:00:00 GMT");
08304 case 1:
08305 sg = INT2FIX(DEFAULT_SG);
08306 }
08307
08308 {
08309 VALUE hash = date_s__httpdate(klass, str);
08310 return dt_new_by_frags(klass, hash, sg);
08311 }
08312 }
08313
08314
08315
08316
08317
08318
08319
08320
08321
08322
08323
08324
08325
08326 static VALUE
08327 datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass)
08328 {
08329 VALUE str, sg;
08330
08331 rb_scan_args(argc, argv, "02", &str, &sg);
08332
08333 switch (argc) {
08334 case 0:
08335 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
08336 case 1:
08337 sg = INT2FIX(DEFAULT_SG);
08338 }
08339
08340 {
08341 VALUE hash = date_s__jisx0301(klass, str);
08342 return dt_new_by_frags(klass, hash, sg);
08343 }
08344 }
08345
08346
08347
08348
08349
08350
08351
08352
08353
08354
08355
08356
08357
08358 static VALUE
08359 dt_lite_to_s(VALUE self)
08360 {
08361 return strftimev("%Y-%m-%dT%H:%M:%S%:z", self, set_tmx);
08362 }
08363
08364
08365
08366
08367
08368
08369
08370
08371
08372
08373
08374
08375
08376
08377
08378
08379
08380
08381
08382
08383
08384
08385
08386
08387
08388
08389
08390
08391
08392
08393
08394
08395
08396
08397
08398
08399
08400
08401
08402
08403
08404
08405
08406
08407
08408
08409
08410
08411
08412
08413
08414
08415
08416
08417
08418
08419
08420
08421
08422
08423
08424
08425
08426
08427
08428
08429
08430
08431
08432
08433
08434
08435
08436
08437
08438
08439
08440
08441
08442
08443
08444
08445
08446
08447
08448
08449
08450
08451
08452
08453
08454
08455
08456
08457
08458
08459
08460
08461
08462
08463
08464
08465
08466
08467
08468
08469
08470
08471
08472
08473
08474
08475
08476
08477
08478
08479
08480
08481
08482
08483
08484
08485
08486
08487
08488
08489
08490
08491
08492
08493
08494
08495
08496
08497
08498
08499
08500
08501
08502
08503
08504
08505
08506
08507
08508
08509
08510
08511
08512
08513
08514
08515
08516
08517
08518
08519
08520
08521
08522
08523
08524
08525
08526
08527
08528
08529
08530
08531
08532
08533
08534
08535
08536
08537
08538
08539
08540
08541 static VALUE
08542 dt_lite_strftime(int argc, VALUE *argv, VALUE self)
08543 {
08544 return date_strftime_internal(argc, argv, self,
08545 "%Y-%m-%dT%H:%M:%S%:z", set_tmx);
08546 }
08547
08548 static VALUE
08549 iso8601_timediv(VALUE self, VALUE n)
08550 {
08551 VALUE fmt;
08552
08553 fmt = rb_usascii_str_new2("T%H:%M:%S");
08554 if (f_gt_p(n, INT2FIX(0))) {
08555 VALUE argv[3];
08556
08557 get_d1(self);
08558
08559 argv[0] = rb_usascii_str_new2(".%0*d");
08560 argv[1] = n;
08561 argv[2] = f_round(f_quo(m_sf_in_sec(dat),
08562 f_quo(INT2FIX(1),
08563 f_expt(INT2FIX(10), n))));
08564 rb_str_append(fmt, rb_f_sprintf(3, argv));
08565 }
08566 rb_str_append(fmt, rb_usascii_str_new2("%:z"));
08567 return strftimev(RSTRING_PTR(fmt), self, set_tmx);
08568 }
08569
08570
08571
08572
08573
08574
08575
08576
08577
08578
08579
08580
08581
08582
08583 static VALUE
08584 dt_lite_iso8601(int argc, VALUE *argv, VALUE self)
08585 {
08586 VALUE n;
08587
08588 rb_scan_args(argc, argv, "01", &n);
08589
08590 if (argc < 1)
08591 n = INT2FIX(0);
08592
08593 return f_add(strftimev("%Y-%m-%d", self, set_tmx),
08594 iso8601_timediv(self, n));
08595 }
08596
08597
08598
08599
08600
08601
08602
08603
08604
08605
08606
08607
08608
08609 static VALUE
08610 dt_lite_rfc3339(int argc, VALUE *argv, VALUE self)
08611 {
08612 return dt_lite_iso8601(argc, argv, self);
08613 }
08614
08615
08616
08617
08618
08619
08620
08621
08622
08623
08624
08625
08626
08627 static VALUE
08628 dt_lite_jisx0301(int argc, VALUE *argv, VALUE self)
08629 {
08630 VALUE n, s;
08631
08632 rb_scan_args(argc, argv, "01", &n);
08633
08634 if (argc < 1)
08635 n = INT2FIX(0);
08636
08637 {
08638 get_d1(self);
08639 s = jisx0301_date(m_real_local_jd(dat),
08640 m_real_year(dat));
08641 return rb_str_append(strftimev(RSTRING_PTR(s), self, set_tmx),
08642 iso8601_timediv(self, n));
08643 }
08644 }
08645
08646
08647
08648 #define f_getlocal(x) rb_funcall(x, rb_intern("getlocal"), 0)
08649 #define f_subsec(x) rb_funcall(x, rb_intern("subsec"), 0)
08650 #define f_utc_offset(x) rb_funcall(x, rb_intern("utc_offset"), 0)
08651 #define f_local3(x,y,m,d) rb_funcall(x, rb_intern("local"), 3, y, m, d)
08652 #define f_utc6(x,y,m,d,h,min,s) rb_funcall(x, rb_intern("utc"), 6,\
08653 y, m, d, h, min, s)
08654
08655
08656
08657
08658
08659
08660
08661 static VALUE
08662 time_to_time(VALUE self)
08663 {
08664 return rb_funcall(self, rb_intern("getlocal"), 0);
08665 }
08666
08667
08668
08669
08670
08671
08672
08673 static VALUE
08674 time_to_date(VALUE self)
08675 {
08676 VALUE y, nth, ret;
08677 int ry, m, d;
08678
08679 y = f_year(self);
08680 m = FIX2INT(f_mon(self));
08681 d = FIX2INT(f_mday(self));
08682
08683 decode_year(y, -1, &nth, &ry);
08684
08685 ret = d_simple_new_internal(cDate,
08686 nth, 0,
08687 GREGORIAN,
08688 ry, m, d,
08689 HAVE_CIVIL);
08690 {
08691 get_d1(ret);
08692 set_sg(dat, DEFAULT_SG);
08693 }
08694 return ret;
08695 }
08696
08697
08698
08699
08700
08701
08702
08703 static VALUE
08704 time_to_datetime(VALUE self)
08705 {
08706 VALUE y, sf, nth, ret;
08707 int ry, m, d, h, min, s, of;
08708
08709 y = f_year(self);
08710 m = FIX2INT(f_mon(self));
08711 d = FIX2INT(f_mday(self));
08712
08713 h = FIX2INT(f_hour(self));
08714 min = FIX2INT(f_min(self));
08715 s = FIX2INT(f_sec(self));
08716 if (s == 60)
08717 s = 59;
08718
08719 sf = sec_to_ns(f_subsec(self));
08720 of = FIX2INT(f_utc_offset(self));
08721
08722 decode_year(y, -1, &nth, &ry);
08723
08724 ret = d_complex_new_internal(cDateTime,
08725 nth, 0,
08726 0, sf,
08727 of, DEFAULT_SG,
08728 ry, m, d,
08729 h, min, s,
08730 HAVE_CIVIL | HAVE_TIME);
08731 {
08732 get_d1(ret);
08733 set_sg(dat, DEFAULT_SG);
08734 }
08735 return ret;
08736 }
08737
08738
08739
08740
08741
08742
08743
08744 static VALUE
08745 date_to_time(VALUE self)
08746 {
08747 get_d1(self);
08748
08749 return f_local3(rb_cTime,
08750 m_real_year(dat),
08751 INT2FIX(m_mon(dat)),
08752 INT2FIX(m_mday(dat)));
08753 }
08754
08755
08756
08757
08758
08759
08760
08761 static VALUE
08762 date_to_date(VALUE self)
08763 {
08764 return self;
08765 }
08766
08767
08768
08769
08770
08771
08772
08773 static VALUE
08774 date_to_datetime(VALUE self)
08775 {
08776 get_d1a(self);
08777
08778 if (simple_dat_p(adat)) {
08779 VALUE new = d_lite_s_alloc_simple(cDateTime);
08780 {
08781 get_d1b(new);
08782 bdat->s = adat->s;
08783 return new;
08784 }
08785 }
08786 else {
08787 VALUE new = d_lite_s_alloc_complex(cDateTime);
08788 {
08789 get_d1b(new);
08790 bdat->c = adat->c;
08791 bdat->c.df = 0;
08792 bdat->c.sf = INT2FIX(0);
08793 #ifndef USE_PACK
08794 bdat->c.hour = 0;
08795 bdat->c.min = 0;
08796 bdat->c.sec = 0;
08797 #else
08798 bdat->c.pc = PACK5(EX_MON(adat->c.pc), EX_MDAY(adat->c.pc),
08799 0, 0, 0);
08800 bdat->c.flags |= HAVE_DF | HAVE_TIME;
08801 #endif
08802 return new;
08803 }
08804 }
08805 }
08806
08807
08808
08809
08810
08811
08812
08813 static VALUE
08814 datetime_to_time(VALUE self)
08815 {
08816 volatile VALUE dup = dup_obj_with_new_offset(self, 0);
08817 {
08818 VALUE t;
08819
08820 get_d1(dup);
08821
08822 t = f_utc6(rb_cTime,
08823 m_real_year(dat),
08824 INT2FIX(m_mon(dat)),
08825 INT2FIX(m_mday(dat)),
08826 INT2FIX(m_hour(dat)),
08827 INT2FIX(m_min(dat)),
08828 f_add(INT2FIX(m_sec(dat)),
08829 m_sf_in_sec(dat)));
08830 return f_getlocal(t);
08831 }
08832 }
08833
08834
08835
08836
08837
08838
08839
08840 static VALUE
08841 datetime_to_date(VALUE self)
08842 {
08843 get_d1a(self);
08844
08845 if (simple_dat_p(adat)) {
08846 VALUE new = d_lite_s_alloc_simple(cDate);
08847 {
08848 get_d1b(new);
08849 bdat->s = adat->s;
08850 bdat->s.jd = m_local_jd(adat);
08851 return new;
08852 }
08853 }
08854 else {
08855 VALUE new = d_lite_s_alloc_simple(cDate);
08856 {
08857 get_d1b(new);
08858 copy_complex_to_simple(&bdat->s, &adat->c)
08859 bdat->s.jd = m_local_jd(adat);
08860 bdat->s.flags &= ~(HAVE_DF | HAVE_TIME | COMPLEX_DAT);
08861 return new;
08862 }
08863 }
08864 }
08865
08866
08867
08868
08869
08870
08871
08872 static VALUE
08873 datetime_to_datetime(VALUE self)
08874 {
08875 return self;
08876 }
08877
08878 #ifndef NDEBUG
08879
08880
08881 #define MIN_YEAR -4713
08882 #define MAX_YEAR 1000000
08883 #define MIN_JD -327
08884 #define MAX_JD 366963925
08885
08886 static int
08887 test_civil(int from, int to, double sg)
08888 {
08889 int j;
08890
08891 fprintf(stderr, "test_civil: %d...%d (%d) - %.0f\n",
08892 from, to, to - from, sg);
08893 for (j = from; j <= to; j++) {
08894 int y, m, d, rj, ns;
08895
08896 c_jd_to_civil(j, sg, &y, &m, &d);
08897 c_civil_to_jd(y, m, d, sg, &rj, &ns);
08898 if (j != rj) {
08899 fprintf(stderr, "%d != %d\n", j, rj);
08900 return 0;
08901 }
08902 }
08903 return 1;
08904 }
08905
08906 static VALUE
08907 date_s_test_civil(VALUE klass)
08908 {
08909 if (!test_civil(MIN_JD, MIN_JD + 366, GREGORIAN))
08910 return Qfalse;
08911 if (!test_civil(2305814, 2598007, GREGORIAN))
08912 return Qfalse;
08913 if (!test_civil(MAX_JD - 366, MAX_JD, GREGORIAN))
08914 return Qfalse;
08915
08916 if (!test_civil(MIN_JD, MIN_JD + 366, ITALY))
08917 return Qfalse;
08918 if (!test_civil(2305814, 2598007, ITALY))
08919 return Qfalse;
08920 if (!test_civil(MAX_JD - 366, MAX_JD, ITALY))
08921 return Qfalse;
08922
08923 return Qtrue;
08924 }
08925
08926 static int
08927 test_ordinal(int from, int to, double sg)
08928 {
08929 int j;
08930
08931 fprintf(stderr, "test_ordinal: %d...%d (%d) - %.0f\n",
08932 from, to, to - from, sg);
08933 for (j = from; j <= to; j++) {
08934 int y, d, rj, ns;
08935
08936 c_jd_to_ordinal(j, sg, &y, &d);
08937 c_ordinal_to_jd(y, d, sg, &rj, &ns);
08938 if (j != rj) {
08939 fprintf(stderr, "%d != %d\n", j, rj);
08940 return 0;
08941 }
08942 }
08943 return 1;
08944 }
08945
08946 static VALUE
08947 date_s_test_ordinal(VALUE klass)
08948 {
08949 if (!test_ordinal(MIN_JD, MIN_JD + 366, GREGORIAN))
08950 return Qfalse;
08951 if (!test_ordinal(2305814, 2598007, GREGORIAN))
08952 return Qfalse;
08953 if (!test_ordinal(MAX_JD - 366, MAX_JD, GREGORIAN))
08954 return Qfalse;
08955
08956 if (!test_ordinal(MIN_JD, MIN_JD + 366, ITALY))
08957 return Qfalse;
08958 if (!test_ordinal(2305814, 2598007, ITALY))
08959 return Qfalse;
08960 if (!test_ordinal(MAX_JD - 366, MAX_JD, ITALY))
08961 return Qfalse;
08962
08963 return Qtrue;
08964 }
08965
08966 static int
08967 test_commercial(int from, int to, double sg)
08968 {
08969 int j;
08970
08971 fprintf(stderr, "test_commercial: %d...%d (%d) - %.0f\n",
08972 from, to, to - from, sg);
08973 for (j = from; j <= to; j++) {
08974 int y, w, d, rj, ns;
08975
08976 c_jd_to_commercial(j, sg, &y, &w, &d);
08977 c_commercial_to_jd(y, w, d, sg, &rj, &ns);
08978 if (j != rj) {
08979 fprintf(stderr, "%d != %d\n", j, rj);
08980 return 0;
08981 }
08982 }
08983 return 1;
08984 }
08985
08986 static VALUE
08987 date_s_test_commercial(VALUE klass)
08988 {
08989 if (!test_commercial(MIN_JD, MIN_JD + 366, GREGORIAN))
08990 return Qfalse;
08991 if (!test_commercial(2305814, 2598007, GREGORIAN))
08992 return Qfalse;
08993 if (!test_commercial(MAX_JD - 366, MAX_JD, GREGORIAN))
08994 return Qfalse;
08995
08996 if (!test_commercial(MIN_JD, MIN_JD + 366, ITALY))
08997 return Qfalse;
08998 if (!test_commercial(2305814, 2598007, ITALY))
08999 return Qfalse;
09000 if (!test_commercial(MAX_JD - 366, MAX_JD, ITALY))
09001 return Qfalse;
09002
09003 return Qtrue;
09004 }
09005
09006 static int
09007 test_weeknum(int from, int to, int f, double sg)
09008 {
09009 int j;
09010
09011 fprintf(stderr, "test_weeknum: %d...%d (%d) - %.0f\n",
09012 from, to, to - from, sg);
09013 for (j = from; j <= to; j++) {
09014 int y, w, d, rj, ns;
09015
09016 c_jd_to_weeknum(j, f, sg, &y, &w, &d);
09017 c_weeknum_to_jd(y, w, d, f, sg, &rj, &ns);
09018 if (j != rj) {
09019 fprintf(stderr, "%d != %d\n", j, rj);
09020 return 0;
09021 }
09022 }
09023 return 1;
09024 }
09025
09026 static VALUE
09027 date_s_test_weeknum(VALUE klass)
09028 {
09029 int f;
09030
09031 for (f = 0; f <= 1; f++) {
09032 if (!test_weeknum(MIN_JD, MIN_JD + 366, f, GREGORIAN))
09033 return Qfalse;
09034 if (!test_weeknum(2305814, 2598007, f, GREGORIAN))
09035 return Qfalse;
09036 if (!test_weeknum(MAX_JD - 366, MAX_JD, f, GREGORIAN))
09037 return Qfalse;
09038
09039 if (!test_weeknum(MIN_JD, MIN_JD + 366, f, ITALY))
09040 return Qfalse;
09041 if (!test_weeknum(2305814, 2598007, f, ITALY))
09042 return Qfalse;
09043 if (!test_weeknum(MAX_JD - 366, MAX_JD, f, ITALY))
09044 return Qfalse;
09045 }
09046
09047 return Qtrue;
09048 }
09049
09050 static int
09051 test_nth_kday(int from, int to, double sg)
09052 {
09053 int j;
09054
09055 fprintf(stderr, "test_nth_kday: %d...%d (%d) - %.0f\n",
09056 from, to, to - from, sg);
09057 for (j = from; j <= to; j++) {
09058 int y, m, n, k, rj, ns;
09059
09060 c_jd_to_nth_kday(j, sg, &y, &m, &n, &k);
09061 c_nth_kday_to_jd(y, m, n, k, sg, &rj, &ns);
09062 if (j != rj) {
09063 fprintf(stderr, "%d != %d\n", j, rj);
09064 return 0;
09065 }
09066 }
09067 return 1;
09068 }
09069
09070 static VALUE
09071 date_s_test_nth_kday(VALUE klass)
09072 {
09073 if (!test_nth_kday(MIN_JD, MIN_JD + 366, GREGORIAN))
09074 return Qfalse;
09075 if (!test_nth_kday(2305814, 2598007, GREGORIAN))
09076 return Qfalse;
09077 if (!test_nth_kday(MAX_JD - 366, MAX_JD, GREGORIAN))
09078 return Qfalse;
09079
09080 if (!test_nth_kday(MIN_JD, MIN_JD + 366, ITALY))
09081 return Qfalse;
09082 if (!test_nth_kday(2305814, 2598007, ITALY))
09083 return Qfalse;
09084 if (!test_nth_kday(MAX_JD - 366, MAX_JD, ITALY))
09085 return Qfalse;
09086
09087 return Qtrue;
09088 }
09089
09090 static int
09091 test_unit_v2v(VALUE i,
09092 VALUE (* conv1)(VALUE),
09093 VALUE (* conv2)(VALUE))
09094 {
09095 VALUE c, o;
09096 c = (*conv1)(i);
09097 o = (*conv2)(c);
09098 return f_eqeq_p(o, i);
09099 }
09100
09101 static int
09102 test_unit_v2v_iter2(VALUE (* conv1)(VALUE),
09103 VALUE (* conv2)(VALUE))
09104 {
09105 if (!test_unit_v2v(INT2FIX(0), conv1, conv2))
09106 return 0;
09107 if (!test_unit_v2v(INT2FIX(1), conv1, conv2))
09108 return 0;
09109 if (!test_unit_v2v(INT2FIX(2), conv1, conv2))
09110 return 0;
09111 if (!test_unit_v2v(INT2FIX(3), conv1, conv2))
09112 return 0;
09113 if (!test_unit_v2v(INT2FIX(11), conv1, conv2))
09114 return 0;
09115 if (!test_unit_v2v(INT2FIX(65535), conv1, conv2))
09116 return 0;
09117 if (!test_unit_v2v(INT2FIX(1073741823), conv1, conv2))
09118 return 0;
09119 if (!test_unit_v2v(INT2NUM(1073741824), conv1, conv2))
09120 return 0;
09121 if (!test_unit_v2v(rb_rational_new2(INT2FIX(0), INT2FIX(1)), conv1, conv2))
09122 return 0;
09123 if (!test_unit_v2v(rb_rational_new2(INT2FIX(1), INT2FIX(1)), conv1, conv2))
09124 return 0;
09125 if (!test_unit_v2v(rb_rational_new2(INT2FIX(1), INT2FIX(2)), conv1, conv2))
09126 return 0;
09127 if (!test_unit_v2v(rb_rational_new2(INT2FIX(2), INT2FIX(3)), conv1, conv2))
09128 return 0;
09129 return 1;
09130 }
09131
09132 static int
09133 test_unit_v2v_iter(VALUE (* conv1)(VALUE),
09134 VALUE (* conv2)(VALUE))
09135 {
09136 if (!test_unit_v2v_iter2(conv1, conv2))
09137 return 0;
09138 if (!test_unit_v2v_iter2(conv2, conv1))
09139 return 0;
09140 return 1;
09141 }
09142
09143 static VALUE
09144 date_s_test_unit_conv(VALUE klass)
09145 {
09146 if (!test_unit_v2v_iter(sec_to_day, day_to_sec))
09147 return Qfalse;
09148 if (!test_unit_v2v_iter(ms_to_sec, sec_to_ms))
09149 return Qfalse;
09150 if (!test_unit_v2v_iter(ns_to_day, day_to_ns))
09151 return Qfalse;
09152 if (!test_unit_v2v_iter(ns_to_sec, sec_to_ns))
09153 return Qfalse;
09154 return Qtrue;
09155 }
09156
09157 static VALUE
09158 date_s_test_all(VALUE klass)
09159 {
09160 if (date_s_test_civil(klass) == Qfalse)
09161 return Qfalse;
09162 if (date_s_test_ordinal(klass) == Qfalse)
09163 return Qfalse;
09164 if (date_s_test_commercial(klass) == Qfalse)
09165 return Qfalse;
09166 if (date_s_test_weeknum(klass) == Qfalse)
09167 return Qfalse;
09168 if (date_s_test_nth_kday(klass) == Qfalse)
09169 return Qfalse;
09170 if (date_s_test_unit_conv(klass) == Qfalse)
09171 return Qfalse;
09172 return Qtrue;
09173 }
09174 #endif
09175
09176 static const char *monthnames[] = {
09177 NULL,
09178 "January", "February", "March",
09179 "April", "May", "June",
09180 "July", "August", "September",
09181 "October", "November", "December"
09182 };
09183
09184 static const char *abbr_monthnames[] = {
09185 NULL,
09186 "Jan", "Feb", "Mar", "Apr",
09187 "May", "Jun", "Jul", "Aug",
09188 "Sep", "Oct", "Nov", "Dec"
09189 };
09190
09191 static const char *daynames[] = {
09192 "Sunday", "Monday", "Tuesday", "Wednesday",
09193 "Thursday", "Friday", "Saturday"
09194 };
09195
09196 static const char *abbr_daynames[] = {
09197 "Sun", "Mon", "Tue", "Wed",
09198 "Thu", "Fri", "Sat"
09199 };
09200
09201 static VALUE
09202 mk_ary_of_str(long len, const char *a[])
09203 {
09204 VALUE o;
09205 long i;
09206
09207 o = rb_ary_new2(len);
09208 for (i = 0; i < len; i++) {
09209 VALUE e;
09210
09211 if (!a[i])
09212 e = Qnil;
09213 else {
09214 e = rb_usascii_str_new2(a[i]);
09215 rb_obj_freeze(e);
09216 }
09217 rb_ary_push(o, e);
09218 }
09219 rb_obj_freeze(o);
09220 return o;
09221 }
09222
09223 void
09224 Init_date_core(void)
09225 {
09226 #undef rb_intern
09227 #define rb_intern(str) rb_intern_const(str)
09228
09229 assert(fprintf(stderr, "assert() is now active\n"));
09230
09231 id_cmp = rb_intern("<=>");
09232 id_le_p = rb_intern("<=");
09233 id_ge_p = rb_intern(">=");
09234 id_eqeq_p = rb_intern("==");
09235
09236 half_days_in_day = rb_rational_new2(INT2FIX(1), INT2FIX(2));
09237
09238 #if (LONG_MAX / DAY_IN_SECONDS) > SECOND_IN_NANOSECONDS
09239 day_in_nanoseconds = LONG2NUM((long)DAY_IN_SECONDS *
09240 SECOND_IN_NANOSECONDS);
09241 #elif defined HAVE_LONG_LONG
09242 day_in_nanoseconds = LL2NUM((LONG_LONG)DAY_IN_SECONDS *
09243 SECOND_IN_NANOSECONDS);
09244 #else
09245 day_in_nanoseconds = f_mul(INT2FIX(DAY_IN_SECONDS),
09246 INT2FIX(SECOND_IN_NANOSECONDS));
09247 #endif
09248
09249 rb_gc_register_mark_object(half_days_in_day);
09250 rb_gc_register_mark_object(day_in_nanoseconds);
09251
09252 positive_inf = +INFINITY;
09253 negative_inf = -INFINITY;
09254
09255
09256
09257
09258
09259
09260
09261
09262
09263
09264
09265
09266
09267
09268
09269
09270
09271
09272
09273
09274
09275
09276
09277
09278
09279
09280
09281
09282
09283
09284
09285
09286
09287
09288
09289
09290
09291
09292
09293
09294
09295
09296
09297
09298
09299
09300
09301
09302
09303
09304
09305
09306
09307
09308
09309
09310
09311
09312
09313
09314
09315
09316
09317
09318
09319
09320
09321
09322
09323
09324
09325
09326
09327
09328
09329
09330
09331
09332
09333
09334
09335
09336
09337
09338
09339
09340
09341
09342
09343
09344
09345
09346
09347
09348
09349
09350
09351
09352
09353
09354
09355
09356
09357
09358
09359
09360
09361
09362
09363
09364
09365
09366
09367
09368
09369
09370
09371
09372
09373
09374
09375
09376
09377
09378
09379
09380
09381
09382
09383
09384
09385
09386
09387
09388
09389
09390
09391
09392
09393
09394
09395
09396
09397
09398
09399
09400
09401
09402
09403
09404
09405
09406
09407
09408
09409
09410
09411
09412
09413
09414
09415
09416
09417
09418
09419
09420
09421
09422
09423
09424
09425
09426
09427
09428
09429
09430
09431
09432
09433
09434
09435
09436
09437
09438
09439
09440
09441
09442
09443
09444
09445
09446
09447
09448
09449
09450
09451
09452
09453
09454
09455 cDate = rb_define_class("Date", rb_cObject);
09456
09457 rb_include_module(cDate, rb_mComparable);
09458
09459
09460
09461
09462 rb_define_const(cDate, "MONTHNAMES", mk_ary_of_str(13, monthnames));
09463
09464
09465
09466
09467 rb_define_const(cDate, "ABBR_MONTHNAMES",
09468 mk_ary_of_str(13, abbr_monthnames));
09469
09470
09471
09472
09473 rb_define_const(cDate, "DAYNAMES", mk_ary_of_str(7, daynames));
09474
09475
09476
09477
09478 rb_define_const(cDate, "ABBR_DAYNAMES", mk_ary_of_str(7, abbr_daynames));
09479
09480
09481
09482
09483 rb_define_const(cDate, "ITALY", INT2FIX(ITALY));
09484
09485
09486
09487
09488 rb_define_const(cDate, "ENGLAND", INT2FIX(ENGLAND));
09489
09490
09491
09492
09493 rb_define_const(cDate, "JULIAN", DBL2NUM(JULIAN));
09494
09495
09496
09497
09498 rb_define_const(cDate, "GREGORIAN", DBL2NUM(GREGORIAN));
09499
09500 rb_define_alloc_func(cDate, d_lite_s_alloc);
09501
09502 #ifndef NDEBUG
09503 #define de_define_private_method rb_define_private_method
09504 de_define_private_method(CLASS_OF(cDate), "_valid_jd?",
09505 date_s__valid_jd_p, -1);
09506 de_define_private_method(CLASS_OF(cDate), "_valid_ordinal?",
09507 date_s__valid_ordinal_p, -1);
09508 de_define_private_method(CLASS_OF(cDate), "_valid_civil?",
09509 date_s__valid_civil_p, -1);
09510 de_define_private_method(CLASS_OF(cDate), "_valid_date?",
09511 date_s__valid_civil_p, -1);
09512 de_define_private_method(CLASS_OF(cDate), "_valid_commercial?",
09513 date_s__valid_commercial_p, -1);
09514 de_define_private_method(CLASS_OF(cDate), "_valid_weeknum?",
09515 date_s__valid_weeknum_p, -1);
09516 de_define_private_method(CLASS_OF(cDate), "_valid_nth_kday?",
09517 date_s__valid_nth_kday_p, -1);
09518 #endif
09519
09520 rb_define_singleton_method(cDate, "valid_jd?", date_s_valid_jd_p, -1);
09521 rb_define_singleton_method(cDate, "valid_ordinal?",
09522 date_s_valid_ordinal_p, -1);
09523 rb_define_singleton_method(cDate, "valid_civil?", date_s_valid_civil_p, -1);
09524 rb_define_singleton_method(cDate, "valid_date?", date_s_valid_civil_p, -1);
09525 rb_define_singleton_method(cDate, "valid_commercial?",
09526 date_s_valid_commercial_p, -1);
09527
09528 #ifndef NDEBUG
09529 de_define_private_method(CLASS_OF(cDate), "valid_weeknum?",
09530 date_s_valid_weeknum_p, -1);
09531 de_define_private_method(CLASS_OF(cDate), "valid_nth_kday?",
09532 date_s_valid_nth_kday_p, -1);
09533 de_define_private_method(CLASS_OF(cDate), "zone_to_diff",
09534 date_s_zone_to_diff, 1);
09535 #endif
09536
09537 rb_define_singleton_method(cDate, "julian_leap?", date_s_julian_leap_p, 1);
09538 rb_define_singleton_method(cDate, "gregorian_leap?",
09539 date_s_gregorian_leap_p, 1);
09540 rb_define_singleton_method(cDate, "leap?",
09541 date_s_gregorian_leap_p, 1);
09542
09543 #ifndef NDEBUG
09544 #define de_define_singleton_method rb_define_singleton_method
09545 #define de_define_alias rb_define_alias
09546 de_define_singleton_method(cDate, "new!", date_s_new_bang, -1);
09547 de_define_alias(rb_singleton_class(cDate), "new_l!", "new");
09548 #endif
09549
09550 rb_define_singleton_method(cDate, "jd", date_s_jd, -1);
09551 rb_define_singleton_method(cDate, "ordinal", date_s_ordinal, -1);
09552 rb_define_singleton_method(cDate, "civil", date_s_civil, -1);
09553 rb_define_singleton_method(cDate, "new", date_s_civil, -1);
09554 rb_define_singleton_method(cDate, "commercial", date_s_commercial, -1);
09555
09556 #ifndef NDEBUG
09557 de_define_singleton_method(cDate, "weeknum", date_s_weeknum, -1);
09558 de_define_singleton_method(cDate, "nth_kday", date_s_nth_kday, -1);
09559 #endif
09560
09561 rb_define_singleton_method(cDate, "today", date_s_today, -1);
09562 rb_define_singleton_method(cDate, "_strptime", date_s__strptime, -1);
09563 rb_define_singleton_method(cDate, "strptime", date_s_strptime, -1);
09564 rb_define_singleton_method(cDate, "_parse", date_s__parse, -1);
09565 rb_define_singleton_method(cDate, "parse", date_s_parse, -1);
09566 rb_define_singleton_method(cDate, "_iso8601", date_s__iso8601, 1);
09567 rb_define_singleton_method(cDate, "iso8601", date_s_iso8601, -1);
09568 rb_define_singleton_method(cDate, "_rfc3339", date_s__rfc3339, 1);
09569 rb_define_singleton_method(cDate, "rfc3339", date_s_rfc3339, -1);
09570 rb_define_singleton_method(cDate, "_xmlschema", date_s__xmlschema, 1);
09571 rb_define_singleton_method(cDate, "xmlschema", date_s_xmlschema, -1);
09572 rb_define_singleton_method(cDate, "_rfc2822", date_s__rfc2822, 1);
09573 rb_define_singleton_method(cDate, "_rfc822", date_s__rfc2822, 1);
09574 rb_define_singleton_method(cDate, "rfc2822", date_s_rfc2822, -1);
09575 rb_define_singleton_method(cDate, "rfc822", date_s_rfc2822, -1);
09576 rb_define_singleton_method(cDate, "_httpdate", date_s__httpdate, 1);
09577 rb_define_singleton_method(cDate, "httpdate", date_s_httpdate, -1);
09578 rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, 1);
09579 rb_define_singleton_method(cDate, "jisx0301", date_s_jisx0301, -1);
09580
09581 #ifndef NDEBUG
09582 #define de_define_method rb_define_method
09583 de_define_method(cDate, "initialize", d_lite_initialize, -1);
09584 #endif
09585 rb_define_method(cDate, "initialize_copy", d_lite_initialize_copy, 1);
09586
09587 #ifndef NDEBUG
09588 de_define_method(cDate, "fill", d_lite_fill, 0);
09589 #endif
09590
09591 rb_define_method(cDate, "ajd", d_lite_ajd, 0);
09592 rb_define_method(cDate, "amjd", d_lite_amjd, 0);
09593 rb_define_method(cDate, "jd", d_lite_jd, 0);
09594 rb_define_method(cDate, "mjd", d_lite_mjd, 0);
09595 rb_define_method(cDate, "ld", d_lite_ld, 0);
09596
09597 rb_define_method(cDate, "year", d_lite_year, 0);
09598 rb_define_method(cDate, "yday", d_lite_yday, 0);
09599 rb_define_method(cDate, "mon", d_lite_mon, 0);
09600 rb_define_method(cDate, "month", d_lite_mon, 0);
09601 rb_define_method(cDate, "mday", d_lite_mday, 0);
09602 rb_define_method(cDate, "day", d_lite_mday, 0);
09603 rb_define_method(cDate, "day_fraction", d_lite_day_fraction, 0);
09604
09605 rb_define_method(cDate, "cwyear", d_lite_cwyear, 0);
09606 rb_define_method(cDate, "cweek", d_lite_cweek, 0);
09607 rb_define_method(cDate, "cwday", d_lite_cwday, 0);
09608
09609 #ifndef NDEBUG
09610 de_define_private_method(cDate, "wnum0", d_lite_wnum0, 0);
09611 de_define_private_method(cDate, "wnum1", d_lite_wnum1, 0);
09612 #endif
09613
09614 rb_define_method(cDate, "wday", d_lite_wday, 0);
09615
09616 rb_define_method(cDate, "sunday?", d_lite_sunday_p, 0);
09617 rb_define_method(cDate, "monday?", d_lite_monday_p, 0);
09618 rb_define_method(cDate, "tuesday?", d_lite_tuesday_p, 0);
09619 rb_define_method(cDate, "wednesday?", d_lite_wednesday_p, 0);
09620 rb_define_method(cDate, "thursday?", d_lite_thursday_p, 0);
09621 rb_define_method(cDate, "friday?", d_lite_friday_p, 0);
09622 rb_define_method(cDate, "saturday?", d_lite_saturday_p, 0);
09623
09624 #ifndef NDEBUG
09625 de_define_method(cDate, "nth_kday?", d_lite_nth_kday_p, 2);
09626 #endif
09627
09628 rb_define_private_method(cDate, "hour", d_lite_hour, 0);
09629 rb_define_private_method(cDate, "min", d_lite_min, 0);
09630 rb_define_private_method(cDate, "minute", d_lite_min, 0);
09631 rb_define_private_method(cDate, "sec", d_lite_sec, 0);
09632 rb_define_private_method(cDate, "second", d_lite_sec, 0);
09633 rb_define_private_method(cDate, "sec_fraction", d_lite_sec_fraction, 0);
09634 rb_define_private_method(cDate, "second_fraction", d_lite_sec_fraction, 0);
09635 rb_define_private_method(cDate, "offset", d_lite_offset, 0);
09636 rb_define_private_method(cDate, "zone", d_lite_zone, 0);
09637
09638 rb_define_method(cDate, "julian?", d_lite_julian_p, 0);
09639 rb_define_method(cDate, "gregorian?", d_lite_gregorian_p, 0);
09640 rb_define_method(cDate, "leap?", d_lite_leap_p, 0);
09641
09642 rb_define_method(cDate, "start", d_lite_start, 0);
09643 rb_define_method(cDate, "new_start", d_lite_new_start, -1);
09644 rb_define_method(cDate, "italy", d_lite_italy, 0);
09645 rb_define_method(cDate, "england", d_lite_england, 0);
09646 rb_define_method(cDate, "julian", d_lite_julian, 0);
09647 rb_define_method(cDate, "gregorian", d_lite_gregorian, 0);
09648
09649 rb_define_private_method(cDate, "new_offset", d_lite_new_offset, -1);
09650
09651 rb_define_method(cDate, "+", d_lite_plus, 1);
09652 rb_define_method(cDate, "-", d_lite_minus, 1);
09653
09654 rb_define_method(cDate, "next_day", d_lite_next_day, -1);
09655 rb_define_method(cDate, "prev_day", d_lite_prev_day, -1);
09656 rb_define_method(cDate, "next", d_lite_next, 0);
09657 rb_define_method(cDate, "succ", d_lite_next, 0);
09658
09659 rb_define_method(cDate, ">>", d_lite_rshift, 1);
09660 rb_define_method(cDate, "<<", d_lite_lshift, 1);
09661
09662 rb_define_method(cDate, "next_month", d_lite_next_month, -1);
09663 rb_define_method(cDate, "prev_month", d_lite_prev_month, -1);
09664 rb_define_method(cDate, "next_year", d_lite_next_year, -1);
09665 rb_define_method(cDate, "prev_year", d_lite_prev_year, -1);
09666
09667 rb_define_method(cDate, "step", d_lite_step, -1);
09668 rb_define_method(cDate, "upto", d_lite_upto, 1);
09669 rb_define_method(cDate, "downto", d_lite_downto, 1);
09670
09671 rb_define_method(cDate, "<=>", d_lite_cmp, 1);
09672 rb_define_method(cDate, "===", d_lite_equal, 1);
09673 rb_define_method(cDate, "eql?", d_lite_eql_p, 1);
09674 rb_define_method(cDate, "hash", d_lite_hash, 0);
09675
09676 rb_define_method(cDate, "to_s", d_lite_to_s, 0);
09677 #ifndef NDEBUG
09678 de_define_method(cDate, "inspect_raw", d_lite_inspect_raw, 0);
09679 #endif
09680 rb_define_method(cDate, "inspect", d_lite_inspect, 0);
09681
09682 rb_define_method(cDate, "strftime", d_lite_strftime, -1);
09683
09684 rb_define_method(cDate, "asctime", d_lite_asctime, 0);
09685 rb_define_method(cDate, "ctime", d_lite_asctime, 0);
09686 rb_define_method(cDate, "iso8601", d_lite_iso8601, 0);
09687 rb_define_method(cDate, "xmlschema", d_lite_iso8601, 0);
09688 rb_define_method(cDate, "rfc3339", d_lite_rfc3339, 0);
09689 rb_define_method(cDate, "rfc2822", d_lite_rfc2822, 0);
09690 rb_define_method(cDate, "rfc822", d_lite_rfc2822, 0);
09691 rb_define_method(cDate, "httpdate", d_lite_httpdate, 0);
09692 rb_define_method(cDate, "jisx0301", d_lite_jisx0301, 0);
09693
09694 #ifndef NDEBUG
09695 de_define_method(cDate, "marshal_dump_old", d_lite_marshal_dump_old, 0);
09696 #endif
09697 rb_define_method(cDate, "marshal_dump", d_lite_marshal_dump, 0);
09698 rb_define_method(cDate, "marshal_load", d_lite_marshal_load, 1);
09699
09700
09701
09702 cDateTime = rb_define_class("DateTime", cDate);
09703
09704 rb_define_singleton_method(cDateTime, "jd", datetime_s_jd, -1);
09705 rb_define_singleton_method(cDateTime, "ordinal", datetime_s_ordinal, -1);
09706 rb_define_singleton_method(cDateTime, "civil", datetime_s_civil, -1);
09707 rb_define_singleton_method(cDateTime, "new", datetime_s_civil, -1);
09708 rb_define_singleton_method(cDateTime, "commercial",
09709 datetime_s_commercial, -1);
09710
09711 #ifndef NDEBUG
09712 de_define_singleton_method(cDateTime, "weeknum",
09713 datetime_s_weeknum, -1);
09714 de_define_singleton_method(cDateTime, "nth_kday",
09715 datetime_s_nth_kday, -1);
09716 #endif
09717
09718 rb_undef_method(CLASS_OF(cDateTime), "today");
09719
09720 rb_define_singleton_method(cDateTime, "now", datetime_s_now, -1);
09721 rb_define_singleton_method(cDateTime, "_strptime",
09722 datetime_s__strptime, -1);
09723 rb_define_singleton_method(cDateTime, "strptime",
09724 datetime_s_strptime, -1);
09725 rb_define_singleton_method(cDateTime, "parse",
09726 datetime_s_parse, -1);
09727 rb_define_singleton_method(cDateTime, "iso8601",
09728 datetime_s_iso8601, -1);
09729 rb_define_singleton_method(cDateTime, "rfc3339",
09730 datetime_s_rfc3339, -1);
09731 rb_define_singleton_method(cDateTime, "xmlschema",
09732 datetime_s_xmlschema, -1);
09733 rb_define_singleton_method(cDateTime, "rfc2822",
09734 datetime_s_rfc2822, -1);
09735 rb_define_singleton_method(cDateTime, "rfc822",
09736 datetime_s_rfc2822, -1);
09737 rb_define_singleton_method(cDateTime, "httpdate",
09738 datetime_s_httpdate, -1);
09739 rb_define_singleton_method(cDateTime, "jisx0301",
09740 datetime_s_jisx0301, -1);
09741
09742 #define f_public(m,s) rb_funcall(m, rb_intern("public"), 1,\
09743 ID2SYM(rb_intern(s)))
09744
09745 f_public(cDateTime, "hour");
09746 f_public(cDateTime, "min");
09747 f_public(cDateTime, "minute");
09748 f_public(cDateTime, "sec");
09749 f_public(cDateTime, "second");
09750 f_public(cDateTime, "sec_fraction");
09751 f_public(cDateTime, "second_fraction");
09752 f_public(cDateTime, "offset");
09753 f_public(cDateTime, "zone");
09754 f_public(cDateTime, "new_offset");
09755
09756 rb_define_method(cDateTime, "to_s", dt_lite_to_s, 0);
09757
09758 rb_define_method(cDateTime, "strftime", dt_lite_strftime, -1);
09759
09760 rb_define_method(cDateTime, "iso8601", dt_lite_iso8601, -1);
09761 rb_define_method(cDateTime, "xmlschema", dt_lite_iso8601, -1);
09762 rb_define_method(cDateTime, "rfc3339", dt_lite_rfc3339, -1);
09763 rb_define_method(cDateTime, "jisx0301", dt_lite_jisx0301, -1);
09764
09765
09766
09767 rb_define_method(rb_cTime, "to_time", time_to_time, 0);
09768 rb_define_method(rb_cTime, "to_date", time_to_date, 0);
09769 rb_define_method(rb_cTime, "to_datetime", time_to_datetime, 0);
09770
09771 rb_define_method(cDate, "to_time", date_to_time, 0);
09772 rb_define_method(cDate, "to_date", date_to_date, 0);
09773 rb_define_method(cDate, "to_datetime", date_to_datetime, 0);
09774
09775 rb_define_method(cDateTime, "to_time", datetime_to_time, 0);
09776 rb_define_method(cDateTime, "to_date", datetime_to_date, 0);
09777 rb_define_method(cDateTime, "to_datetime", datetime_to_datetime, 0);
09778
09779 #ifndef NDEBUG
09780
09781
09782 de_define_singleton_method(cDate, "test_civil", date_s_test_civil, 0);
09783 de_define_singleton_method(cDate, "test_ordinal", date_s_test_ordinal, 0);
09784 de_define_singleton_method(cDate, "test_commercial",
09785 date_s_test_commercial, 0);
09786 de_define_singleton_method(cDate, "test_weeknum", date_s_test_weeknum, 0);
09787 de_define_singleton_method(cDate, "test_nth_kday", date_s_test_nth_kday, 0);
09788 de_define_singleton_method(cDate, "test_unit_conv",
09789 date_s_test_unit_conv, 0);
09790 de_define_singleton_method(cDate, "test_all", date_s_test_all, 0);
09791 #endif
09792 }
09793
09794
09795
09796
09797
09798
09799