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