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