diff options
author | tadf <tadf@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2011-05-31 13:28:48 +0000 |
---|---|---|
committer | tadf <tadf@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2011-05-31 13:28:48 +0000 |
commit | 899d2c14b055e180308396b5ef36397c0737f6f7 (patch) | |
tree | 09310a78d95c8acd0652f3be4c84359870f8d875 /ext/date | |
parent | 3b3cf8753de031cdd109c5a7bd18ca6d18f95e01 (diff) |
* ext/date/date_core.c: use simple/complex mode instead of light/right mode.
* test/date/*.rb: followed the above changes.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@31862 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/date')
-rw-r--r-- | ext/date/date_core.c | 8897 | ||||
-rw-r--r-- | ext/date/date_parse.c | 2 |
2 files changed, 3515 insertions, 5384 deletions
diff --git a/ext/date/date_core.c b/ext/date/date_core.c index 4faedc86b7..bff8029cbe 100644 --- a/ext/date/date_core.c +++ b/ext/date/date_core.c @@ -10,179 +10,136 @@ #define NDEBUG #include <assert.h> -/* #define FORCE_RIGHT */ - #ifdef RUBY_EXTCONF_H #include RUBY_EXTCONF_H #endif -#define LIGHT_MODE (1 << 0) -#define HAVE_JD (1 << 1) -#define HAVE_DF (1 << 2) -#define HAVE_CIVIL (1 << 3) -#define HAVE_TIME (1 << 4) -#define DATETIME_OBJ (1 << 7) +#define USE_DPK + +static ID id_cmp, id_le_p, id_ge_p, id_eqeq_p; +static VALUE cDate, cDateTime; +static VALUE half_days_in_day, unix_epoch_in_ajd, day_in_nanoseconds; +static double positive_inf, negative_inf; + +#define HAVE_JD (1 << 0) +#define HAVE_DF (1 << 1) +#define HAVE_CIVIL (1 << 2) +#define HAVE_TIME (1 << 3) +#define COMPLEX_DAT (1 << 7) -#define light_mode_p(x) ((x)->flags & LIGHT_MODE) #define have_jd_p(x) ((x)->flags & HAVE_JD) #define have_df_p(x) ((x)->flags & HAVE_DF) #define have_civil_p(x) ((x)->flags & HAVE_CIVIL) #define have_time_p(x) ((x)->flags & HAVE_TIME) -#define datetime_obj_p(x) ((x)->flags & DATETIME_OBJ) -#define date_obj_p(x) (!datetime_obj_p(x)) - -#define MIN_YEAR -4713 -#define MAX_YEAR 1000000 -#define MIN_JD -327 -#define MAX_JD 366963925 - -#define LIGHTABLE_JD(j) (j >= MIN_JD && j <= MAX_JD) -#define LIGHTABLE_YEAR(y) (y >= MIN_YEAR && y <= MAX_YEAR) -#define LIGHTABLE_CWYEAR(y) LIGHTABLE_YEAR(y) +#define complex_dat_p(x) ((x)->flags & COMPLEX_DAT) +#define simple_dat_p(x) (!complex_dat_p(x)) #define ITALY 2299161 #define ENGLAND 2361222 -#define JULIAN (NUM2DBL(rb_const_get(rb_cFloat, rb_intern("INFINITY")))) -#define GREGORIAN (-NUM2DBL(rb_const_get(rb_cFloat, rb_intern("INFINITY")))) +#define JULIAN positive_inf +#define GREGORIAN negative_inf +#define DEFAULT_SG ITALY + +#define UNIX_EPOCH_IN_AJD unix_epoch_in_ajd /* 1970-01-01 */ +#define UNIX_EPOCH_IN_CJD INT2FIX(2440588) #define MINUTE_IN_SECONDS 60 #define HOUR_IN_SECONDS 3600 #define DAY_IN_SECONDS 86400 #define SECOND_IN_NANOSECONDS 1000000000 -/* copied from time.c */ -#define NDIV(x,y) (-(-((x)+1)/(y))-1) -#define NMOD(x,y) ((y)-(-((x)+1)%(y))-1) -#define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d)) -#define MOD(n,d) ((n)<0 ? NMOD((n),(d)) : (n)%(d)) +#define JC_PERIOD0 1461 /* 365.25 * 4 */ +#define GC_PERIOD0 146097 /* 365.2425 * 400 */ +#define CM_PERIOD0 71149239 /* (lcm 7 1461 146097) */ +#define CM_PERIOD (0xfffffff / CM_PERIOD0 * CM_PERIOD0) +#define CM_PERIOD_JCY (CM_PERIOD / JC_PERIOD0 * 4) +#define CM_PERIOD_GCY (CM_PERIOD / GC_PERIOD0 * 400) + +#ifdef USE_PACK +#define SEC_WIDTH 6 +#define MIN_WIDTH 6 +#define HOUR_WIDTH 5 +#define MDAY_WIDTH 5 +#define MON_WIDTH 4 + +#define SEC_SHIFT 0 +#define MIN_SHIFT SEC_WIDTH +#define HOUR_SHIFT (MIN_WIDTH + SEC_WIDTH) +#define MDAY_SHIFT (HOUR_WIDTH + MIN_WIDTH + SEC_WIDTH) +#define MON_SHIFT (MDAY_WIDTH + HOUR_WIDTH + MIN_WIDTH + SEC_WIDTH) + +#define PK_MASK(x) ((1 << (x)) - 1) + +#define EX_SEC(x) (((x) >> SEC_SHIFT) & PK_MASK(SEC_WIDTH)) +#define EX_MIN(x) (((x) >> MIN_SHIFT) & PK_MASK(MIN_WIDTH)) +#define EX_HOUR(x) (((x) >> HOUR_SHIFT) & PK_MASK(HOUR_WIDTH)) +#define EX_MDAY(x) (((x) >> MDAY_SHIFT) & PK_MASK(MDAY_WIDTH)) +#define EX_MON(x) (((x) >> MON_SHIFT) & PK_MASK(MON_WIDTH)) + +#define PACK5(m,d,h,min,s) \ + (((m) << MON_SHIFT) | ((d) << MDAY_SHIFT) |\ + ((h) << HOUR_SHIFT) | ((min) << MIN_SHIFT) | ((s) << SEC_SHIFT)) + +#define PACK2(m,d) \ + (((m) << MON_SHIFT) | ((d) << MDAY_SHIFT)) +#endif -union DateData +struct SimpleDateData { unsigned flags; - struct { - unsigned flags; - VALUE ajd; - VALUE of; - VALUE sg; - VALUE cache; - } r; - struct { - unsigned flags; - long jd; /* as utc */ - double sg; - /* decoded as utc=local */ - int year; - int mon; - int mday; - } l; + VALUE nth; /* not always canonicalized */ + int jd; /* as utc */ + double sg; /* -oo, 2299161..2451910 or +oo */ + /* decoded as utc=local */ + int year; /* truncated */ +#ifndef USE_PACK + int mon; + int mday; +#else + /* packed civil */ + unsigned pd; +#endif }; -union DateTimeData +struct ComplexDateData { unsigned flags; - struct { - unsigned flags; - VALUE ajd; - VALUE of; - VALUE sg; - VALUE cache; - } r; - struct { - unsigned flags; - long jd; /* as utc */ - int df; /* as utc, in secs */ - long sf; /* in nano secs */ - int of; /* in secs */ - double sg; - /* decoded as local */ - int year; - int mon; - int mday; - int hour; - int min; - int sec; - } l; + VALUE nth; /* not always canonicalized */ + int jd; /* as utc */ + int df; /* as utc, in secs */ + VALUE sf; /* in nano secs */ + int of; /* in secs */ + double sg; /* -oo, 2299161..2451910 or +oo */ + /* decoded as local */ + int year; /* truncated */ +#ifndef USE_PACK + int mon; + int mday; + int hour; + int min; + int sec; +#else + /* packed civil */ + unsigned pd; +#endif +}; + +union DateData { + unsigned flags; + struct SimpleDateData s; + struct ComplexDateData c; }; #define get_d1(x)\ union DateData *dat;\ - Data_Get_Struct(x, union DateData, dat);\ - assert(date_obj_p(dat)) + Data_Get_Struct(x, union DateData, dat); #define get_d2(x,y)\ union DateData *adat, *bdat;\ Data_Get_Struct(x, union DateData, adat);\ - Data_Get_Struct(y, union DateData, bdat);\ - assert(date_obj_p(adat));\ - assert(date_obj_p(bdat)) + Data_Get_Struct(y, union DateData, bdat); -#define get_d1_dt1(x,y)\ - union DateData *adat;\ - union DateTimeData *bdat;\ - Data_Get_Struct(x, union DateData, adat);\ - Data_Get_Struct(y, union DateTimeData, bdat)\ - assert(date_obj_p(adat));\ - assert(datetime_obj_p(bdat)) - -#define get_dt1(x)\ - union DateTimeData *dat;\ - Data_Get_Struct(x, union DateTimeData, dat);\ - assert(datetime_obj_p(dat)) - -#define get_dt2(x,y)\ - union DateTimeData *adat, *bdat;\ - Data_Get_Struct(x, union DateTimeData, adat);\ - Data_Get_Struct(y, union DateTimeData, bdat);\ - assert(datetime_obj_p(adat));\ - assert(datetime_obj_p(bdat)) - -#define get_dt1_d1(x,y)\ - union DateTimeData *adat;\ - union DateData *bdat;\ - Data_Get_Struct(x, union DateTimeData, adat);\ - Data_Get_Struct(y, union DateData, bdat);\ - assert(datetime_obj_p(adat));\ - assert(date_obj_p(bdat)) - -#define get_dt2_cast(x,y)\ - union DateData *atmp, *btmp;\ - union DateTimeData abuf, bbuf, *adat, *bdat;\ - if (k_datetime_p(x))\ - Data_Get_Struct(x, union DateTimeData, adat);\ - else {\ - Data_Get_Struct(x, union DateData, atmp);\ - abuf.l.jd = atmp->l.jd;\ - abuf.l.df = 0;\ - abuf.l.sf = 0;\ - abuf.l.of = 0;\ - abuf.l.sg = atmp->l.sg;\ - abuf.l.year = atmp->l.year;\ - abuf.l.mon = atmp->l.mon;\ - abuf.l.mday = atmp->l.mday;\ - abuf.l.hour = 0;\ - abuf.l.min = 0;\ - abuf.l.sec = 0;\ - abuf.flags = HAVE_DF | HAVE_TIME | DATETIME_OBJ | atmp->l.flags;\ - adat = &abuf;\ - }\ - if (k_datetime_p(y))\ - Data_Get_Struct(y, union DateTimeData, bdat);\ - else {\ - Data_Get_Struct(y, union DateData, btmp);\ - bbuf.l.jd = btmp->l.jd;\ - bbuf.l.df = 0;\ - bbuf.l.sf = 0;\ - bbuf.l.of = 0;\ - bbuf.l.sg = btmp->l.sg;\ - bbuf.l.year = btmp->l.year;\ - bbuf.l.mon = btmp->l.mon;\ - bbuf.l.mday = btmp->l.mday;\ - bbuf.l.hour = 0;\ - bbuf.l.min = 0;\ - bbuf.l.sec = 0;\ - bbuf.flags = HAVE_DF | HAVE_TIME | DATETIME_OBJ | btmp->l.flags;\ - bdat = &bbuf;\ - } +#define f_boolcast(x) ((x) ? Qtrue : Qfalse) #define f_abs(x) rb_funcall(x, rb_intern("abs"), 0) #define f_negate(x) rb_funcall(x, rb_intern("-@"), 0) @@ -190,6 +147,7 @@ union DateTimeData #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) #define f_idiv(x,y) rb_funcall(x, rb_intern("div"), 1, y) #define f_mod(x,y) rb_funcall(x, '%', 1, y) #define f_remainder(x,y) rb_funcall(x, rb_intern("remainder"), 1, y) @@ -199,646 +157,170 @@ union DateTimeData #define f_truncate(x) rb_funcall(x, rb_intern("truncate"), 0) #define f_round(x) rb_funcall(x, rb_intern("round"), 0) +#define f_to_r(x) rb_funcall(x, rb_intern("to_r"), 0) +#define f_to_s(x) rb_funcall(x, rb_intern("to_s"), 0) +#define f_inspect(x) rb_funcall(x, rb_intern("inspect"), 0) + #define f_add3(x,y,z) f_add(f_add(x, y), z) #define f_sub3(x,y,z) f_sub(f_sub(x, y), z) -#define f_cmp(x,y) rb_funcall(x, rb_intern("<=>"), 1, y) -#define f_lt_p(x,y) rb_funcall(x, '<', 1, y) -#define f_gt_p(x,y) rb_funcall(x, '>', 1, y) -#define f_le_p(x,y) rb_funcall(x, rb_intern("<="), 1, y) -#define f_ge_p(x,y) rb_funcall(x, rb_intern(">="), 1, y) - -#define f_eqeq_p(x,y) rb_funcall(x, rb_intern("=="), 1, y) -#define f_equal_p(x,y) rb_funcall(x, rb_intern("==="), 1, y) -#define f_zero_p(x) rb_funcall(x, rb_intern("zero?"), 0) -#define f_negative_p(x) f_lt_p(x, INT2FIX(0)) -#define f_positive_p(x) (!f_negative_p(x)) - -#define f_compact(x) rb_funcall(x, rb_intern("compact"), 0) - -#define f_ajd(x) rb_funcall(x, rb_intern("ajd"), 0) -#define f_jd(x) rb_funcall(x, rb_intern("jd"), 0) -#define f_year(x) rb_funcall(x, rb_intern("year"), 0) -#define f_mon(x) rb_funcall(x, rb_intern("mon"), 0) -#define f_mday(x) rb_funcall(x, rb_intern("mday"), 0) -#define f_wday(x) rb_funcall(x, rb_intern("wday"), 0) -#define f_hour(x) rb_funcall(x, rb_intern("hour"), 0) -#define f_min(x) rb_funcall(x, rb_intern("min"), 0) -#define f_sec(x) rb_funcall(x, rb_intern("sec"), 0) -#define f_start(x) rb_funcall(x, rb_intern("start"), 0) - -static VALUE cDate, cDateTime; -static VALUE rzero, rhalf, day_in_nanoseconds; - -/* right base */ - -#define HALF_DAYS_IN_DAY rb_rational_new2(INT2FIX(1), INT2FIX(2)) -#define HOURS_IN_DAY rb_rational_new2(INT2FIX(1), INT2FIX(24)) -#define MINUTES_IN_DAY rb_rational_new2(INT2FIX(1), INT2FIX(1440)) -#define SECONDS_IN_DAY rb_rational_new2(INT2FIX(1), INT2FIX(86400)) -#define MILLISECONDS_IN_DAY\ - rb_rational_new2(INT2FIX(1), f_mul(INT2FIX(86400), INT2FIX(1000))) -#define NANOSECONDS_IN_DAY\ - rb_rational_new2(INT2FIX(1), f_mul(INT2FIX(86400), INT2FIX(1000000000))) -#define MILLISECONDS_IN_SECOND rb_rational_new2(INT2FIX(1), INT2FIX(1000)) -#define NANOSECONDS_IN_SECOND rb_rational_new2(INT2FIX(1), INT2FIX(1000000000)) - -#define MJD_EPOCH_IN_AJD\ - rb_rational_new2(INT2FIX(4800001), INT2FIX(2)) /* 1858-11-17 */ -#define UNIX_EPOCH_IN_AJD\ - rb_rational_new2(INT2FIX(4881175), INT2FIX(2)) /* 1970-01-01 */ -#define MJD_EPOCH_IN_CJD INT2FIX(2400001) -#define UNIX_EPOCH_IN_CJD INT2FIX(2440588) -#define LD_EPOCH_IN_CJD INT2FIX(2299160) - -static VALUE rt__valid_civil_p(VALUE, VALUE, VALUE, VALUE); - -static VALUE -rt_find_fdoy(VALUE y, VALUE sg) -{ - int d; - - for (d = 1; d < 31; d++) { - VALUE j = rt__valid_civil_p(y, INT2FIX(1), INT2FIX(d), sg); - if (!NIL_P(j)) - return j; - } - return Qnil; -} - -static VALUE -rt_find_ldoy(VALUE y, VALUE sg) -{ - int i; - - for (i = 0; i < 30; i++) { - VALUE j = rt__valid_civil_p(y, INT2FIX(12), INT2FIX(31 - i), sg); - if (!NIL_P(j)) - return j; - } - return Qnil; -} - -#ifndef NDEBUG -static VALUE -rt_find_fdom(VALUE y, VALUE m, VALUE sg) -{ - int d; - - for (d = 1; d < 31; d++) { - VALUE j = rt__valid_civil_p(y, m, INT2FIX(d), sg); - if (!NIL_P(j)) - return j; - } - return Qnil; -} -#endif - -static VALUE -rt_find_ldom(VALUE y, VALUE m, VALUE sg) -{ - int i; - - for (i = 0; i < 30; i++) { - VALUE j = rt__valid_civil_p(y, m, INT2FIX(31 - i), sg); - if (!NIL_P(j)) - return j; - } - return Qnil; -} - -static VALUE -rt_ordinal_to_jd(VALUE y, VALUE d, VALUE sg) -{ - return f_sub(f_add(rt_find_fdoy(y, sg), d), INT2FIX(1)); -} - -static VALUE rt_jd_to_civil(VALUE jd, VALUE sg); - -static VALUE -rt_jd_to_ordinal(VALUE jd, VALUE sg) -{ - VALUE a, y, j, doy; - - a = rt_jd_to_civil(jd, sg); - y = RARRAY_PTR(a)[0]; - j = rt_find_fdoy(y, sg); - doy = f_add(f_sub(jd, j), INT2FIX(1)); - return rb_assoc_new(y, doy); -} - -static VALUE -rt_civil_to_jd(VALUE y, VALUE m, VALUE d, VALUE sg) -{ - VALUE a, b, jd; - - if (f_le_p(m, INT2FIX(2))) { - y = f_sub(y, INT2FIX(1)); - m = f_add(m, INT2FIX(12)); - } - a = f_floor(f_div(y, DBL2NUM(100.0))); - b = f_add(f_sub(INT2FIX(2), a), f_floor(f_div(a, DBL2NUM(4.0)))); - jd = f_add3(f_floor(f_mul(DBL2NUM(365.25), f_add(y, INT2FIX(4716)))), - f_floor(f_mul(DBL2NUM(30.6001), f_add(m, INT2FIX(1)))), - f_sub(f_add(d, b), INT2FIX(1524))); - if (f_lt_p(jd, sg)) - jd = f_sub(jd, b); - return jd; -} - -static VALUE -rt_jd_to_civil(VALUE jd, VALUE sg) -{ - VALUE a, x, b, c, d, e, dom, m, y; - - if (f_lt_p(jd, sg)) - a = jd; - else { - x = f_floor(f_div(f_sub(jd, DBL2NUM(1867216.25)), DBL2NUM(36524.25))); - a = f_sub(f_add3(jd, INT2FIX(1), x), f_floor(f_div(x, DBL2NUM(4.0)))); - } - b = f_add(a, INT2FIX(1524)); - c = f_floor(f_div(f_sub(b, DBL2NUM(122.1)), DBL2NUM(365.25))); - d = f_floor(f_mul(DBL2NUM(365.25), c)); - e = f_floor(f_div(f_sub(b, d), DBL2NUM(30.6001))); - dom = f_sub3(b, d, f_floor(f_mul(DBL2NUM(30.6001), e))); - if (f_le_p(e, INT2FIX(13))) { - m = f_sub(e, INT2FIX(1)); - y = f_sub(c, INT2FIX(4716)); - } - else { - m = f_sub(e, INT2FIX(13)); - y = f_sub(c, INT2FIX(4715)); - } - return rb_ary_new3(3, y, m, dom); -} - -static VALUE -rt_commercial_to_jd(VALUE y, VALUE w, VALUE d, VALUE sg) -{ - VALUE j; - - j = f_add(rt_find_fdoy(y, sg), INT2FIX(3)); - return f_add3(f_sub(j, f_mod(j, INT2FIX(7))), - f_mul(INT2FIX(7), f_sub(w, INT2FIX(1))), - f_sub(d, INT2FIX(1))); -} - -static VALUE -rt_jd_to_commercial(VALUE jd, VALUE sg) +inline static VALUE +f_cmp(VALUE x, VALUE y) { - VALUE t, a, j, y, w, d; - - t = rt_jd_to_civil(f_sub(jd, INT2FIX(3)), sg); - a = RARRAY_PTR(t)[0]; - j = rt_commercial_to_jd(f_add(a, INT2FIX(1)), INT2FIX(1), INT2FIX(1), sg); - if (f_ge_p(jd, j)) - y = f_add(a, INT2FIX(1)); - else { - j = rt_commercial_to_jd(a, INT2FIX(1), INT2FIX(1), sg); - y = a; + if (FIXNUM_P(x) && FIXNUM_P(y)) { + long c = FIX2LONG(x) - FIX2LONG(y); + if (c > 0) + c = 1; + else if (c < 0) + c = -1; + return INT2FIX(c); } - w = f_add(INT2FIX(1), f_idiv(f_sub(jd, j), INT2FIX(7))); - d = f_mod(f_add(jd, INT2FIX(1)), INT2FIX(7)); - if (f_zero_p(d)) - d = INT2FIX(7); - return rb_ary_new3(3, y, w, d); -} - -static VALUE -rt_weeknum_to_jd(VALUE y, VALUE w, VALUE d, VALUE f, VALUE sg) -{ - VALUE a; - - a = f_add(rt_find_fdoy(y, sg), INT2FIX(6)); - return f_add3(f_sub3(a, - f_mod(f_add(f_sub(a, f), INT2FIX(1)), INT2FIX(7)), - INT2FIX(7)), - f_mul(INT2FIX(7), w), - d); -} - -static VALUE -rt_jd_to_weeknum(VALUE jd, VALUE f, VALUE sg) -{ - VALUE t, y, d, a, w; - - t = rt_jd_to_civil(jd, sg); - y = RARRAY_PTR(t)[0]; - d = RARRAY_PTR(t)[2]; - a = f_add(rt_find_fdoy(y, sg), INT2FIX(6)); - t = f_add(f_sub(jd, - f_sub(a, f_mod(f_add(f_sub(a, f), INT2FIX(1)), - INT2FIX(7)))), - INT2FIX(7)); - w = f_idiv(t, INT2FIX(7)); - d = f_mod(t, INT2FIX(7)); - return rb_ary_new3(3, y, w, d); -} - -#ifndef NDEBUG -static VALUE -rt_nth_kday_to_jd(VALUE y, VALUE m, VALUE n, VALUE k, VALUE sg) -{ - VALUE j; - - if (f_gt_p(n, INT2FIX(0))) - j = f_sub(rt_find_fdom(y, m, sg), INT2FIX(1)); - else - j = f_add(rt_find_ldom(y, m, sg), INT2FIX(7)); - return f_add(f_sub(j, - f_mod(f_add(f_sub(j, k), INT2FIX(1)), INT2FIX(7))), - f_mul(INT2FIX(7), n)); -} - -static VALUE rt_jd_to_wday(VALUE); - -static VALUE -rt_jd_to_nth_kday(VALUE jd, VALUE sg) -{ - VALUE t, y, m, n, k, j; - - t = rt_jd_to_civil(jd, sg); - y = RARRAY_PTR(t)[0]; - m = RARRAY_PTR(t)[1]; - j = rt_find_fdom(y, m, sg); - n = f_add(f_idiv(f_sub(jd, j), INT2FIX(7)), INT2FIX(1)); - k = rt_jd_to_wday(jd); - return rb_ary_new3(4, y, m, n, k); -} -#endif - -static VALUE -rt_ajd_to_jd(VALUE ajd, VALUE of) -{ - VALUE t, jd, fr; - - t = f_add3(ajd, of, HALF_DAYS_IN_DAY); - jd = f_idiv(t, INT2FIX(1)); - fr = f_mod(t, INT2FIX(1)); - return rb_assoc_new(jd, fr); -} - -static VALUE -rt_jd_to_ajd(VALUE jd, VALUE fr, VALUE of) -{ - return f_sub3(f_add(jd, fr), of, HALF_DAYS_IN_DAY); -} - -#ifndef NDEBUG -static VALUE -rt_day_fraction_to_time(VALUE fr) -{ - VALUE h, min, s, ss; - - ss = f_idiv(fr, SECONDS_IN_DAY); - fr = f_mod(fr, SECONDS_IN_DAY); - - h = f_idiv(ss, INT2FIX(HOUR_IN_SECONDS)); - ss = f_mod(ss, INT2FIX(HOUR_IN_SECONDS)); - - min = f_idiv(ss, INT2FIX(MINUTE_IN_SECONDS)); - s = f_mod(ss, INT2FIX(MINUTE_IN_SECONDS)); - - return rb_ary_new3(4, h, min, s, f_mul(fr, INT2FIX(DAY_IN_SECONDS))); -} -#endif - -static VALUE -rt_day_fraction_to_time_wo_sf(VALUE fr) -{ - VALUE h, min, s, ss; - - ss = f_idiv(fr, SECONDS_IN_DAY); - - h = f_idiv(ss, INT2FIX(HOUR_IN_SECONDS)); - ss = f_mod(ss, INT2FIX(HOUR_IN_SECONDS)); - - min = f_idiv(ss, INT2FIX(MINUTE_IN_SECONDS)); - s = f_mod(ss, INT2FIX(MINUTE_IN_SECONDS)); - - return rb_ary_new3(3, h, min, s); -} - -static VALUE -rt_time_to_day_fraction(VALUE h, VALUE min, VALUE s) -{ - return rb_Rational(f_add3(f_mul(h, INT2FIX(HOUR_IN_SECONDS)), - f_mul(min, INT2FIX(MINUTE_IN_SECONDS)), - s), - INT2FIX(DAY_IN_SECONDS)); -} - -#ifndef NDEBUG -static VALUE -rt_amjd_to_ajd(VALUE amjd) -{ - return f_add(amjd, MJD_EPOCH_IN_AJD); -} -#endif - -static VALUE -rt_ajd_to_amjd(VALUE ajd) -{ - return f_sub(ajd, MJD_EPOCH_IN_AJD); + return rb_funcall(x, id_cmp, 1, y); } -#ifndef NDEBUG -static VALUE -rt_mjd_to_jd(VALUE mjd) +inline static VALUE +f_lt_p(VALUE x, VALUE y) { - return f_add(mjd, MJD_EPOCH_IN_CJD); + if (FIXNUM_P(x) && FIXNUM_P(y)) + return f_boolcast(FIX2LONG(x) < FIX2LONG(y)); + return rb_funcall(x, '<', 1, y); } -#endif -static VALUE -rt_jd_to_mjd(VALUE jd) +inline static VALUE +f_gt_p(VALUE x, VALUE y) { - return f_sub(jd, MJD_EPOCH_IN_CJD); + if (FIXNUM_P(x) && FIXNUM_P(y)) + return f_boolcast(FIX2LONG(x) > FIX2LONG(y)); + return rb_funcall(x, '>', 1, y); } -#ifndef NDEBUG -static VALUE -rt_ld_to_jd(VALUE ld) +inline static VALUE +f_le_p(VALUE x, VALUE y) { - return f_add(ld, LD_EPOCH_IN_CJD); + if (FIXNUM_P(x) && FIXNUM_P(y)) + return f_boolcast(FIX2LONG(x) <= FIX2LONG(y)); + return rb_funcall(x, id_le_p, 1, y); } -#endif -static VALUE -rt_jd_to_ld(VALUE jd) +inline static VALUE +f_ge_p(VALUE x, VALUE y) { - return f_sub(jd, LD_EPOCH_IN_CJD); + if (FIXNUM_P(x) && FIXNUM_P(y)) + return f_boolcast(FIX2LONG(x) >= FIX2LONG(y)); + return rb_funcall(x, rb_intern(">="), 1, y); } -static VALUE -rt_jd_to_wday(VALUE jd) +inline static VALUE +f_eqeq_p(VALUE x, VALUE y) { - return f_mod(f_add(jd, INT2FIX(1)), INT2FIX(7)); + if (FIXNUM_P(x) && FIXNUM_P(y)) + return f_boolcast(FIX2LONG(x) == FIX2LONG(y)); + return rb_funcall(x, rb_intern("=="), 1, y); } -static VALUE -rt__valid_jd_p(VALUE jd, VALUE sg) -{ - return jd; -} +#define f_equal_p(x,y) rb_funcall(x, rb_intern("==="), 1, y) -static VALUE -rt__valid_ordinal_p(VALUE y, VALUE d, VALUE sg) +inline static VALUE +f_zero_p(VALUE x) { - VALUE jd, t, ny, nd; - - if (f_negative_p(d)) { - VALUE j; + switch (TYPE(x)) { + case T_FIXNUM: + return f_boolcast(FIX2LONG(x) == 0); + case T_BIGNUM: + return Qfalse; + case T_RATIONAL: + { + VALUE num = RRATIONAL(x)->num; - j = rt_find_ldoy(y, sg); - if (NIL_P(j)) - return Qnil; - t = rt_jd_to_ordinal(f_add3(j, d, INT2FIX(1)), sg); - ny = RARRAY_PTR(t)[0]; - nd = RARRAY_PTR(t)[1]; - if (!f_eqeq_p(ny, y)) - return Qnil; - d = nd; + return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 0); + } } - jd = rt_ordinal_to_jd(y, d, sg); - t = rt_jd_to_ordinal(jd, sg); - ny = RARRAY_PTR(t)[0]; - nd = RARRAY_PTR(t)[1]; - if (!f_eqeq_p(y, ny)) - return Qnil; - if (!f_eqeq_p(d, nd)) - return Qnil; - return jd; + return rb_funcall(x, id_eqeq_p, 1, INT2FIX(0)); } -static VALUE -rt__valid_civil_p(VALUE y, VALUE m, VALUE d, VALUE sg) -{ - VALUE t, ny, nm, nd, jd; +#define f_nonzero_p(x) (!f_zero_p(x)) - if (f_negative_p(m)) - m = f_add(m, INT2FIX(13)); - if (f_negative_p(d)) { - VALUE j; - - j = rt_find_ldom(y, m, sg); - if (NIL_P(j)) - return Qnil; - t = rt_jd_to_civil(f_add3(j, d, INT2FIX(1)), sg); - ny = RARRAY_PTR(t)[0]; - nm = RARRAY_PTR(t)[1]; - nd = RARRAY_PTR(t)[2]; - if (!f_eqeq_p(ny, y)) - return Qnil; - if (!f_eqeq_p(nm, m)) - return Qnil; - d = nd; - } - jd = rt_civil_to_jd(y, m, d, sg); - t = rt_jd_to_civil(jd, sg); - ny = RARRAY_PTR(t)[0]; - nm = RARRAY_PTR(t)[1]; - nd = RARRAY_PTR(t)[2]; - if (!f_eqeq_p(y, ny)) - return Qnil; - if (!f_eqeq_p(m, nm)) - return Qnil; - if (!f_eqeq_p(d, nd)) - return Qnil; - return jd; -} - -static VALUE -rt__valid_commercial_p(VALUE y, VALUE w, VALUE d, VALUE sg) -{ - VALUE t, ny, nw, nd, jd; - - if (f_negative_p(d)) - d = f_add(d, INT2FIX(8)); - if (f_negative_p(w)) { - VALUE j; - - j = rt_commercial_to_jd(f_add(y, INT2FIX(1)), - INT2FIX(1), INT2FIX(1), sg); - t = rt_jd_to_commercial(f_add(j, f_mul(w, INT2FIX(7))), sg); - ny = RARRAY_PTR(t)[0]; - nw = RARRAY_PTR(t)[1]; - if (!f_eqeq_p(ny, y)) - return Qnil; - w = nw; - } - jd = rt_commercial_to_jd(y, w, d, sg); - t = rt_jd_to_commercial(jd, sg); - ny = RARRAY_PTR(t)[0]; - nw = RARRAY_PTR(t)[1]; - nd = RARRAY_PTR(t)[2]; - if (!f_eqeq_p(ny, y)) - return Qnil; - if (!f_eqeq_p(nw, w)) - return Qnil; - if (!f_eqeq_p(nd, d)) - return Qnil; - return jd; -} - -static VALUE -rt__valid_weeknum_p(VALUE y, VALUE w, VALUE d, VALUE f, VALUE sg) +inline static VALUE +f_negative_p(VALUE x) { - VALUE t, ny, nw, nd, jd; - - if (f_negative_p(d)) - d = f_add(d, INT2FIX(7)); - if (f_negative_p(w)) { - VALUE j; - - j = rt_weeknum_to_jd(f_add(y, INT2FIX(1)), - INT2FIX(1), f, f, sg); - t = rt_jd_to_weeknum(f_add(j, f_mul(w, INT2FIX(7))), f, sg); - ny = RARRAY_PTR(t)[0]; - nw = RARRAY_PTR(t)[1]; - if (!f_eqeq_p(ny, y)) - return Qnil; - w = nw; - } - jd = rt_weeknum_to_jd(y, w, d, f, sg); - t = rt_jd_to_weeknum(jd, f, sg); - ny = RARRAY_PTR(t)[0]; - nw = RARRAY_PTR(t)[1]; - nd = RARRAY_PTR(t)[2]; - if (!f_eqeq_p(ny, y)) - return Qnil; - if (!f_eqeq_p(nw, w)) - return Qnil; - if (!f_eqeq_p(nd, d)) - return Qnil; - return jd; + if (FIXNUM_P(x)) + return f_boolcast(FIX2LONG(x) < 0); + return rb_funcall(x, '<', 1, INT2FIX(0)); } -#ifndef NDEBUG -static VALUE -rt__valid_nth_kday_p(VALUE y, VALUE m, VALUE n, VALUE k, VALUE sg) -{ - VALUE t, ny, nm, nn, nk, jd; - - if (f_negative_p(k)) - k = f_add(k, INT2FIX(7)); - if (f_negative_p(n)) { - VALUE j; +#define f_positive_p(x) (!f_negative_p(x)) - t = f_add(f_mul(y, INT2FIX(12)), m); - ny = f_idiv(t, INT2FIX(12)); - nm = f_mod(t, INT2FIX(12)); - nm = f_floor(f_add(nm, INT2FIX(1))); +#define f_ajd(x) rb_funcall(x, rb_intern("ajd"), 0) +#define f_jd(x) rb_funcall(x, rb_intern("jd"), 0) +#define f_year(x) rb_funcall(x, rb_intern("year"), 0) +#define f_mon(x) rb_funcall(x, rb_intern("mon"), 0) +#define f_mday(x) rb_funcall(x, rb_intern("mday"), 0) +#define f_wday(x) rb_funcall(x, rb_intern("wday"), 0) +#define f_hour(x) rb_funcall(x, rb_intern("hour"), 0) +#define f_min(x) rb_funcall(x, rb_intern("min"), 0) +#define f_sec(x) rb_funcall(x, rb_intern("sec"), 0) - j = rt_nth_kday_to_jd(ny, nm, INT2FIX(1), k, sg); - t = rt_jd_to_nth_kday(f_add(j, f_mul(n, INT2FIX(7))), sg); - ny = RARRAY_PTR(t)[0]; - nm = RARRAY_PTR(t)[1]; - nn = RARRAY_PTR(t)[2]; - if (!f_eqeq_p(ny, y)) - return Qnil; - if (!f_eqeq_p(nm, m)) - return Qnil; - n = nn; - } - jd = rt_nth_kday_to_jd(y, m, n, k, sg); - t = rt_jd_to_nth_kday(jd, sg); - ny = RARRAY_PTR(t)[0]; - nm = RARRAY_PTR(t)[1]; - nn = RARRAY_PTR(t)[2]; - nk = RARRAY_PTR(t)[3]; - if (!f_eqeq_p(ny, y)) - return Qnil; - if (!f_eqeq_p(nm, m)) - return Qnil; - if (!f_eqeq_p(nn, n)) - return Qnil; - if (!f_eqeq_p(nk, k)) - return Qnil; - return jd; -} -#endif +#define f_compact(x) rb_funcall(x, rb_intern("compact"), 0) -static VALUE -rt__valid_time_p(VALUE h, VALUE min, VALUE s) -{ - if (f_negative_p(h)) - h = f_add(h, INT2FIX(24)); - if (f_negative_p(min)) - min = f_add(min, INT2FIX(MINUTE_IN_SECONDS)); - if (f_negative_p(s)) - s = f_add(s, INT2FIX(MINUTE_IN_SECONDS)); - if (f_eqeq_p(h, INT2FIX(24))) { - if (!f_eqeq_p(min, INT2FIX(0))) - return Qnil; - if (!f_eqeq_p(s, INT2FIX(0))) - return Qnil; - } - else { - if (f_lt_p(h, INT2FIX(0)) || f_ge_p(h, INT2FIX(24))) - return Qnil; - if (f_lt_p(min, INT2FIX(0)) || f_ge_p(min, INT2FIX(60))) - return Qnil; - if (f_lt_p(s, INT2FIX(0)) || f_ge_p(s, INT2FIX(60))) - return Qnil; - } - return rt_time_to_day_fraction(h, min, s); -} +/* copied from time.c */ +#define NDIV(x,y) (-(-((x)+1)/(y))-1) +#define NMOD(x,y) ((y)-(-((x)+1)%(y))-1) +#define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d)) +#define MOD(n,d) ((n)<0 ? NMOD((n),(d)) : (n)%(d)) /* light base */ -static int valid_civil_p(int y, int m, int d, double sg, - int *rm, int *rd, long *rjd, int *ns); +static int c_valid_civil_p(int, int, int, double, + int *, int *, int *, int *); static int -find_fdoy(int y, double sg, long *rjd, int *ns) +c_find_fdoy(int y, double sg, int *rjd, int *ns) { int d, rm, rd; for (d = 1; d < 31; d++) - if (valid_civil_p(y, 1, d, sg, &rm, &rd, rjd, ns)) + if (c_valid_civil_p(y, 1, d, sg, &rm, &rd, rjd, ns)) return 1; return 0; } static int -find_ldoy(int y, double sg, long *rjd, int *ns) +c_find_ldoy(int y, double sg, int *rjd, int *ns) { int i, rm, rd; for (i = 0; i < 30; i++) - if (valid_civil_p(y, 12, 31 - i, sg, &rm, &rd, rjd, ns)) + if (c_valid_civil_p(y, 12, 31 - i, sg, &rm, &rd, rjd, ns)) return 1; return 0; } #ifndef NDEBUG static int -find_fdom(int y, int m, double sg, long *rjd, int *ns) +c_find_fdom(int y, int m, double sg, int *rjd, int *ns) { int d, rm, rd; for (d = 1; d < 31; d++) - if (valid_civil_p(y, m, d, sg, &rm, &rd, rjd, ns)) + if (c_valid_civil_p(y, m, d, sg, &rm, &rd, rjd, ns)) return 1; return 0; } #endif static int -find_ldom(int y, int m, double sg, long *rjd, int *ns) +c_find_ldom(int y, int m, double sg, int *rjd, int *ns) { int i, rm, rd; for (i = 0; i < 30; i++) - if (valid_civil_p(y, m, 31 - i, sg, &rm, &rd, rjd, ns)) + if (c_valid_civil_p(y, m, 31 - i, sg, &rm, &rd, rjd, ns)) return 1; return 0; } static void -civil_to_jd(int y, int m, int d, double sg, long *rjd, int *ns) +c_civil_to_jd(int y, int m, int d, double sg, int *rjd, int *ns) { double a, b, jd; @@ -858,11 +340,11 @@ civil_to_jd(int y, int m, int d, double sg, long *rjd, int *ns) else *ns = 1; - *rjd = (long)jd; + *rjd = (int)jd; } static void -jd_to_civil(long jd, double sg, int *ry, int *rm, int *rdom) +c_jd_to_civil(int jd, double sg, int *ry, int *rm, int *rdom) { double x, a, b, c, d, e, y, m, dom; @@ -892,33 +374,31 @@ jd_to_civil(long jd, double sg, int *ry, int *rm, int *rdom) } static void -ordinal_to_jd(int y, int d, double sg, long *rjd, int *ns) +c_ordinal_to_jd(int y, int d, double sg, int *rjd, int *ns) { int ns2; - find_fdoy(y, sg, rjd, &ns2); + c_find_fdoy(y, sg, rjd, &ns2); *rjd += d - 1; *ns = (*rjd < sg) ? 0 : 1; } static void -jd_to_ordinal(long jd, double sg, int *ry, int *rd) +c_jd_to_ordinal(int jd, double sg, int *ry, int *rd) { - int rm2, rd2, ns; - long rjd; + int rm2, rd2, rjd, ns; - jd_to_civil(jd, sg, ry, &rm2, &rd2); - find_fdoy(*ry, sg, &rjd, &ns); - *rd = (int)(jd - rjd) + 1; + c_jd_to_civil(jd, sg, ry, &rm2, &rd2); + c_find_fdoy(*ry, sg, &rjd, &ns); + *rd = (jd - rjd) + 1; } static void -commercial_to_jd(int y, int w, int d, double sg, long *rjd, int *ns) +c_commercial_to_jd(int y, int w, int d, double sg, int *rjd, int *ns) { - long rjd2; - int ns2; + int rjd2, ns2; - find_fdoy(y, sg, &rjd2, &ns2); + c_find_fdoy(y, sg, &rjd2, &ns2); rjd2 += 3; *rjd = (rjd2 - MOD((rjd2 - 1) + 1, 7)) + @@ -928,48 +408,43 @@ commercial_to_jd(int y, int w, int d, double sg, long *rjd, int *ns) } static void -jd_to_commercial(long jd, double sg, int *ry, int *rw, int *rd) +c_jd_to_commercial(int jd, double sg, int *ry, int *rw, int *rd) { - int ry2, rm2, rd2, a, ns2; - long rjd2; + int ry2, rm2, rd2, a, rjd2, ns2; - jd_to_civil(jd - 3, sg, &ry2, &rm2, &rd2); + c_jd_to_civil(jd - 3, sg, &ry2, &rm2, &rd2); a = ry2; - commercial_to_jd(a + 1, 1, 1, sg, &rjd2, &ns2); + c_commercial_to_jd(a + 1, 1, 1, sg, &rjd2, &ns2); if (jd >= rjd2) *ry = a + 1; else { - commercial_to_jd(a, 1, 1, sg, &rjd2, &ns2); + c_commercial_to_jd(a, 1, 1, sg, &rjd2, &ns2); *ry = a; } - *rw = 1 + (int)DIV(jd - rjd2, 7); - *rd = (int)MOD(jd + 1, 7); + *rw = 1 + DIV(jd - rjd2, 7); + *rd = MOD(jd + 1, 7); if (*rd == 0) *rd = 7; } -#ifndef NDEBUG static void -weeknum_to_jd(int y, int w, int d, int f, double sg, long *rjd, int *ns) +c_weeknum_to_jd(int y, int w, int d, int f, double sg, int *rjd, int *ns) { - long rjd2; - int ns2; + int rjd2, ns2; - find_fdoy(y, sg, &rjd2, &ns2); + c_find_fdoy(y, sg, &rjd2, &ns2); rjd2 += 6; *rjd = (rjd2 - MOD(((rjd2 - f) + 1), 7) - 7) + 7 * w + d; *ns = (*rjd < sg) ? 0 : 1; } -#endif static void -jd_to_weeknum(long jd, int f, double sg, int *ry, int *rw, int *rd) +c_jd_to_weeknum(int jd, int f, double sg, int *ry, int *rw, int *rd) { - int rm, rd2, ns; - long rjd, j; + int rm, rd2, rjd, ns, j; - jd_to_civil(jd, sg, ry, &rm, &rd2); - find_fdoy(*ry, sg, &rjd, &ns); + c_jd_to_civil(jd, sg, ry, &rm, &rd2); + c_find_fdoy(*ry, sg, &rjd, &ns); rjd += 6; j = jd - (rjd - MOD((rjd - f) + 1, 7)) + 7; *rw = (int)DIV(j, 7); @@ -978,17 +453,16 @@ jd_to_weeknum(long jd, int f, double sg, int *ry, int *rw, int *rd) #ifndef NDEBUG static void -nth_kday_to_jd(int y, int m, int n, int k, double sg, long *rjd, int *ns) +c_nth_kday_to_jd(int y, int m, int n, int k, double sg, int *rjd, int *ns) { - long rjd2; - int ns2; + int rjd2, ns2; if (n > 0) { - find_fdom(y, m, sg, &rjd2, &ns2); + c_find_fdom(y, m, sg, &rjd2, &ns2); rjd2 -= 1; } else { - find_ldom(y, m, sg, &rjd2, &ns2); + c_find_ldom(y, m, sg, &rjd2, &ns2); rjd2 += 7; } *rjd = (rjd2 - MOD((rjd2 - k) + 1, 7)) + 7 * n; @@ -996,41 +470,43 @@ nth_kday_to_jd(int y, int m, int n, int k, double sg, long *rjd, int *ns) } #endif -#ifndef NDEBUG -inline static int jd_to_wday(long jd); +inline static int +c_jd_to_wday(int jd) +{ + return MOD(jd + 1, 7); +} +#ifndef NDEBUG static void -jd_to_nth_kday(long jd, double sg, int *ry, int *rm, int *rn, int *rk) +c_jd_to_nth_kday(int jd, double sg, int *ry, int *rm, int *rn, int *rk) { - int rd, ns2; - long rjd; + int rd, rjd, ns2; - jd_to_civil(jd, sg, ry, rm, &rd); - find_fdom(*ry, *rm, sg, &rjd, &ns2); - *rn = (int)DIV(jd - rjd, 7) + 1; - *rk = jd_to_wday(jd); + c_jd_to_civil(jd, sg, ry, rm, &rd); + c_find_fdom(*ry, *rm, sg, &rjd, &ns2); + *rn = DIV(jd - rjd, 7) + 1; + *rk = c_jd_to_wday(jd); } #endif static int -valid_ordinal_p(int y, int d, double sg, - int *rd, long *rjd, int *ns) +c_valid_ordinal_p(int y, int d, double sg, + int *rd, int *rjd, int *ns) { int ry2, rd2; if (d < 0) { - long rjd2; - int ns2; + int rjd2, ns2; - if (!find_ldoy(y, sg, &rjd2, &ns2)) + if (!c_find_ldoy(y, sg, &rjd2, &ns2)) return 0; - jd_to_ordinal(rjd2 + d + 1, sg, &ry2, &rd2); + c_jd_to_ordinal(rjd2 + d + 1, sg, &ry2, &rd2); if (ry2 != y) return 0; d = rd2; } - ordinal_to_jd(y, d, sg, rjd, ns); - jd_to_ordinal(*rjd, sg, &ry2, &rd2); + c_ordinal_to_jd(y, d, sg, rjd, ns); + c_jd_to_ordinal(*rjd, sg, &ry2, &rd2); if (ry2 != y || rd2 != d) return 0; return 1; @@ -1042,25 +518,25 @@ static const int monthtab[2][13] = { }; inline static int -leap_p(int y) +c_leap_p(int y) { return (MOD(y, 4) == 0 && y % 100 != 0) || (MOD(y, 400) == 0); } static int -last_day_of_month(int y, int m) +c_last_day_of_month(int y, int m) { - return monthtab[leap_p(y) ? 1 : 0][m]; + return monthtab[c_leap_p(y) ? 1 : 0][m]; } static int -valid_gregorian_p(int y, int m, int d, int *rm, int *rd) +c_valid_gregorian_p(int y, int m, int d, int *rm, int *rd) { int last; if (m < 0) m += 13; - last = last_day_of_month(y, m); + last = c_last_day_of_month(y, m); if (d < 0) d = last + d + 1; @@ -1072,101 +548,100 @@ valid_gregorian_p(int y, int m, int d, int *rm, int *rd) } static int -valid_civil_p(int y, int m, int d, double sg, - int *rm, int *rd, long *rjd, int *ns) +c_valid_civil_p(int y, int m, int d, double sg, + int *rm, int *rd, int *rjd, int *ns) { int ry; if (m < 0) m += 13; if (d < 0) { - if (!find_ldom(y, m, sg, rjd, ns)) + if (!c_find_ldom(y, m, sg, rjd, ns)) return 0; - jd_to_civil(*rjd + d + 1, sg, &ry, rm, rd); + c_jd_to_civil(*rjd + d + 1, sg, &ry, rm, rd); if (ry != y || *rm != m) return 0; d = *rd; } - civil_to_jd(y, m, d, sg, rjd, ns); - jd_to_civil(*rjd, sg, &ry, rm, rd); + c_civil_to_jd(y, m, d, sg, rjd, ns); + c_jd_to_civil(*rjd, sg, &ry, rm, rd); if (ry != y || *rm != m || *rd != d) return 0; return 1; } static int -valid_commercial_p(int y, int w, int d, double sg, - int *rw, int *rd, long *rjd, int *ns) +c_valid_commercial_p(int y, int w, int d, double sg, + int *rw, int *rd, int *rjd, int *ns) { int ns2, ry2, rw2, rd2; if (d < 0) d += 8; if (w < 0) { - long rjd2; + int rjd2; - commercial_to_jd(y + 1, 1, 1, sg, &rjd2, &ns2); - jd_to_commercial(rjd2 + w * 7, sg, &ry2, &rw2, &rd2); + c_commercial_to_jd(y + 1, 1, 1, sg, &rjd2, &ns2); + c_jd_to_commercial(rjd2 + w * 7, sg, &ry2, &rw2, &rd2); if (ry2 != y) return 0; w = rw2; } - commercial_to_jd(y, w, d, sg, rjd, ns); - jd_to_commercial(*rjd, sg, &ry2, rw, rd); + c_commercial_to_jd(y, w, d, sg, rjd, ns); + c_jd_to_commercial(*rjd, sg, &ry2, rw, rd); if (y != ry2 || w != *rw || d != *rd) return 0; return 1; } -#ifndef NDEBUG static int -valid_weeknum_p(int y, int w, int d, int f, double sg, - int *rw, int *rd, long *rjd, int *ns) +c_valid_weeknum_p(int y, int w, int d, int f, double sg, + int *rw, int *rd, int *rjd, int *ns) { int ns2, ry2, rw2, rd2; if (d < 0) d += 7; if (w < 0) { - long rjd2; + int rjd2; - weeknum_to_jd(y + 1, 1, f, f, sg, &rjd2, &ns2); - jd_to_weeknum(rjd2 + w * 7, f, sg, &ry2, &rw2, &rd2); + c_weeknum_to_jd(y + 1, 1, f, f, sg, &rjd2, &ns2); + c_jd_to_weeknum(rjd2 + w * 7, f, sg, &ry2, &rw2, &rd2); if (ry2 != y) return 0; w = rw2; } - weeknum_to_jd(y, w, d, f, sg, rjd, ns); - jd_to_weeknum(*rjd, f, sg, &ry2, rw, rd); + c_weeknum_to_jd(y, w, d, f, sg, rjd, ns); + c_jd_to_weeknum(*rjd, f, sg, &ry2, rw, rd); if (y != ry2 || w != *rw || d != *rd) return 0; return 1; } +#ifndef NDEBUG static int -valid_nth_kday_p(int y, int m, int n, int k, double sg, - int *rm, int *rn, int *rk, long *rjd, int *ns) +c_valid_nth_kday_p(int y, int m, int n, int k, double sg, + int *rm, int *rn, int *rk, int *rjd, int *ns) { int ns2, ry2, rm2, rn2, rk2; if (k < 0) k += 7; if (n < 0) { - long rjd2; - int t, ny, nm; + int t, ny, nm, rjd2; t = y * 12 + m; ny = DIV(t, 12); nm = MOD(t, 12) + 1; - nth_kday_to_jd(ny, nm, 1, k, sg, &rjd2, &ns2); - jd_to_nth_kday(rjd2 + n * 7, sg, &ry2, &rm2, &rn2, &rk2); + c_nth_kday_to_jd(ny, nm, 1, k, sg, &rjd2, &ns2); + c_jd_to_nth_kday(rjd2 + n * 7, sg, &ry2, &rm2, &rn2, &rk2); if (ry2 != y || rm2 != m) return 0; n = rn2; } - nth_kday_to_jd(y, m, n, k, sg, rjd, ns); - jd_to_nth_kday(*rjd, sg, &ry2, rm, rn, rk); + c_nth_kday_to_jd(y, m, n, k, sg, rjd, ns); + c_jd_to_nth_kday(*rjd, sg, &ry2, rm, rn, rk); if (y != ry2 || m != *rm || n != *rn || k != *rk) return 0; return 1; @@ -1174,7 +649,7 @@ valid_nth_kday_p(int y, int m, int n, int k, double sg, #endif static int -valid_time_p(int h, int min, int s, int *rh, int *rmin, int *rs) +c_valid_time_p(int h, int min, int s, int *rh, int *rmin, int *rs) { if (h < 0) h += 24; @@ -1191,6 +666,18 @@ valid_time_p(int h, int min, int s, int *rh, int *rmin, int *rs) (h == 24 && (min > 0 || s > 0))); } +static int +c_valid_start_p(double sg) +{ + if (!isinf(sg)) { + if (sg < ITALY) + return 0; + if (sg > 2451910) + return 0; + } + return 1; +} + inline static int df_local_to_utc(int df, int of) { @@ -1213,8 +700,8 @@ df_utc_to_local(int df, int of) return df; } -inline static long -jd_local_to_utc(long jd, int df, int of) +inline static int +jd_local_to_utc(int jd, int df, int of) { df -= of; if (df < 0) @@ -1224,8 +711,8 @@ jd_local_to_utc(long jd, int df, int of) return jd; } -inline static long -jd_utc_to_local(long jd, int df, int of) +inline static int +jd_utc_to_local(int jd, int df, int of) { df += of; if (df < 0) @@ -1241,184 +728,770 @@ time_to_df(int h, int min, int s) return h * HOUR_IN_SECONDS + min * MINUTE_IN_SECONDS + s; } -inline static int -jd_to_wday(long jd) +static VALUE +sec_to_day(VALUE s) { - return (int)MOD(jd + 1, 7); + return f_quo(s, INT2FIX(DAY_IN_SECONDS)); } -VALUE date_zone_to_diff(VALUE); +static VALUE +isec_to_day(int s) +{ + return sec_to_day(INT2FIX(s)); +} -static int -daydiff_to_sec(VALUE vof, int *rof) +static VALUE +ns_to_day(VALUE n) { - switch (TYPE(vof)) { - case T_FIXNUM: - { - int n; + return f_quo(n, day_in_nanoseconds); +} - n = FIX2INT(vof); - if (n != -1 && n != 0 && n != 1) - return 0; - *rof = n * DAY_IN_SECONDS; - return 1; - } - case T_FLOAT: - { - double n; +static VALUE +ns_to_sec(VALUE n) +{ + return f_quo(n, INT2FIX(SECOND_IN_NANOSECONDS)); +} - n = NUM2DBL(vof); - if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS) - return 0; - *rof = round(n * DAY_IN_SECONDS); - return 1; - } - case T_RATIONAL: - { - VALUE vs = f_mul(vof, INT2FIX(DAY_IN_SECONDS)); - VALUE vn = RRATIONAL(vs)->num; - VALUE vd = RRATIONAL(vs)->den; - int n, d; +#ifndef NDEBUG +static VALUE +ins_to_day(int n) +{ + return ns_to_day(INT2FIX(n)); +} +#endif - if (!FIXNUM_P(vn) || !FIXNUM_P(vd)) - return 0; - n = FIX2INT(vn); - d = FIX2INT(vd); - if (d != 1) - return 0; - if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS) - return 0; - *rof = n; - return 1; - } - case T_STRING: - { - VALUE vs = date_zone_to_diff(vof); - int n; +static VALUE +day_to_sec(VALUE d) +{ + return f_mul(d, INT2FIX(DAY_IN_SECONDS)); +} - if (!FIXNUM_P(vs)) - return 0; - n = FIX2INT(vs); - if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS) - return 0; - *rof = n; - return 1; - } - } - return 0; +#ifndef NDEBUG +static VALUE +day_to_ns(VALUE d) +{ + return f_mul(d, day_in_nanoseconds); +} +#endif + +static VALUE +sec_to_ns(VALUE s) +{ + return f_mul(s, INT2FIX(SECOND_IN_NANOSECONDS)); +} + +static VALUE +div_day(VALUE d, VALUE *f) +{ + if (f) + *f = f_mod(d, INT2FIX(1)); + return f_floor(d); +} + +static VALUE +div_df(VALUE d, VALUE *f) +{ + VALUE s = day_to_sec(d); + + if (f) + *f = f_mod(s, INT2FIX(1)); + return f_floor(s); +} + +#ifndef NDEBUG +static VALUE +div_sf(VALUE s, VALUE *f) +{ + VALUE n = sec_to_ns(s); + + if (f) + *f = f_mod(n, INT2FIX(1)); + return f_floor(n); +} +#endif + +static void +decode_day(VALUE d, VALUE *jd, VALUE *df, VALUE *sf) +{ + VALUE f; + + *jd = div_day(d, &f); + *df = div_df(f, &f); + *sf = sec_to_ns(f); +} + +inline static double +s_sg(union DateData *x) +{ + if (isinf(x->s.sg)) + return x->s.sg; + if (f_zero_p(x->s.nth)) + return x->s.sg; + else if (f_negative_p(x->s.nth)) + return positive_inf; + return negative_inf; +} + +inline static double +c_sg(union DateData *x) +{ + if (isinf(x->c.sg)) + return x->c.sg; + if (f_zero_p(x->c.nth)) + return x->c.sg; + else if (f_negative_p(x->c.nth)) + return positive_inf; + return negative_inf; } inline static void -get_d_jd(union DateData *x) +get_s_jd(union DateData *x) { + assert(simple_dat_p(x)); if (!have_jd_p(x)) { - long jd; - int ns; + int jd, ns; assert(have_civil_p(x)); - - civil_to_jd(x->l.year, x->l.mon, x->l.mday, x->l.sg, &jd, &ns); - x->l.jd = jd; - x->l.flags |= HAVE_JD; +#ifndef USE_PACK + c_civil_to_jd(x->s.year, x->s.mon, x->s.mday, s_sg(x), &jd, &ns); +#else + c_civil_to_jd(x->s.year, EX_MON(x->s.pd), EX_MDAY(x->s.pd), + s_sg(x), &jd, &ns); +#endif + x->s.jd = jd; + x->s.flags |= HAVE_JD; } } inline static void -get_d_civil(union DateData *x) +get_s_civil(union DateData *x) { + assert(simple_dat_p(x)); if (!have_civil_p(x)) { int y, m, d; assert(have_jd_p(x)); - - jd_to_civil(x->l.jd, x->l.sg, &y, &m, &d); - x->l.year = y; - x->l.mon = m; - x->l.mday = d; - x->l.flags |= HAVE_CIVIL; + c_jd_to_civil(x->s.jd, s_sg(x), &y, &m, &d); + x->s.year = y; +#ifndef USE_PACK + x->s.mon = m; + x->s.mday = d; +#else + x->s.pd = PACK2(m, d); +#endif + x->s.flags |= HAVE_CIVIL; } } inline static void -get_dt_df(union DateTimeData *x) +get_c_df(union DateData *x) { + assert(complex_dat_p(x)); if (!have_df_p(x)) { assert(have_time_p(x)); - - x->l.df = df_local_to_utc(time_to_df(x->l.hour, x->l.min, x->l.sec), - x->l.of); - x->l.flags |= HAVE_DF; +#ifndef USE_PACK + x->c.df = df_local_to_utc(time_to_df(x->c.hour, x->c.min, x->c.sec), + x->c.of); +#else + x->c.df = df_local_to_utc(time_to_df(EX_HOUR(x->c.pd), + EX_MIN(x->c.pd), + EX_SEC(x->c.pd)), + x->c.of); +#endif + x->c.flags |= HAVE_DF; } } inline static void -get_dt_time(union DateTimeData *x) +get_c_time(union DateData *x) { - int r; - + assert(complex_dat_p(x)); if (!have_time_p(x)) { +#ifndef USE_PACK + int r; assert(have_df_p(x)); + r = df_utc_to_local(x->c.df, x->c.of); + x->c.hour = r / HOUR_IN_SECONDS; + r %= HOUR_IN_SECONDS; + x->c.min = r / MINUTE_IN_SECONDS; + x->c.sec = r % MINUTE_IN_SECONDS; + x->c.flags |= HAVE_TIME; +#else + int r, m, d, h, min, s; - r = df_utc_to_local(x->l.df, x->l.of); - x->l.hour = r / HOUR_IN_SECONDS; + assert(have_df_p(x)); + r = df_utc_to_local(x->c.df, x->c.of); + m = EX_MON(x->c.pd); + d = EX_MDAY(x->c.pd); + h = r / HOUR_IN_SECONDS; r %= HOUR_IN_SECONDS; - x->l.min = r / MINUTE_IN_SECONDS; - x->l.sec = r % MINUTE_IN_SECONDS; - x->l.flags |= HAVE_TIME; + min = r / MINUTE_IN_SECONDS; + s = r % MINUTE_IN_SECONDS; + x->c.pd = PACK5(m, d, h, min, s); + x->c.flags |= HAVE_TIME; +#endif } } inline static void -get_dt_jd(union DateTimeData *x) +get_c_jd(union DateData *x) { + assert(complex_dat_p(x)); if (!have_jd_p(x)) { - long jd; - int ns; + int jd, ns; assert(have_civil_p(x)); +#ifndef USE_PACK + c_civil_to_jd(x->c.year, x->c.mon, x->c.mday, c_sg(x), &jd, &ns); +#else + c_civil_to_jd(x->c.year, EX_MON(x->c.pd), EX_MDAY(x->c.pd), + c_sg(x), &jd, &ns); +#endif - civil_to_jd(x->l.year, x->l.mon, x->l.mday, x->l.sg, &jd, &ns); - - get_dt_time(x); - x->l.jd = jd_local_to_utc(jd, - time_to_df(x->l.hour, x->l.min, x->l.sec), - x->l.of); - x->l.flags |= HAVE_JD; + get_c_time(x); +#ifndef USE_PACK + x->c.jd = jd_local_to_utc(jd, + time_to_df(x->c.hour, x->c.min, x->c.sec), + x->c.of); +#else + x->c.jd = jd_local_to_utc(jd, + time_to_df(EX_HOUR(x->c.pd), + EX_MIN(x->c.pd), + EX_SEC(x->c.pd)), + x->c.of); +#endif + x->c.flags |= HAVE_JD; } } inline static void -get_dt_civil(union DateTimeData *x) +get_c_civil(union DateData *x) { + assert(complex_dat_p(x)); if (!have_civil_p(x)) { - long jd; - int y, m, d; +#ifndef USE_PACK + int jd, y, m, d; +#else + int jd, y, m, d, h, min, s; +#endif assert(have_jd_p(x)); - - get_dt_df(x); - jd = jd_utc_to_local(x->l.jd, x->l.df, x->l.of); - jd_to_civil(jd, x->l.sg, &y, &m, &d); - x->l.year = y; - x->l.mon = m; - x->l.mday = d; - x->l.flags |= HAVE_CIVIL; + get_c_df(x); + jd = jd_utc_to_local(x->c.jd, x->c.df, x->c.of); + c_jd_to_civil(jd, c_sg(x), &y, &m, &d); + x->c.year = y; +#ifndef USE_PACK + x->c.mon = m; + x->c.mday = d; +#else + h = EX_HOUR(x->c.pd); + min = EX_MIN(x->c.pd); + s = EX_SEC(x->c.pd); + x->c.pd = PACK5(m, d, h, min, s); +#endif + x->c.flags |= HAVE_CIVIL; } } -inline static long -local_jd(union DateTimeData *x) +inline static int +local_jd(union DateData *x) { + assert(complex_dat_p(x)); assert(have_jd_p(x)); assert(have_df_p(x)); - return jd_utc_to_local(x->l.jd, x->l.df, x->l.of); + return jd_utc_to_local(x->c.jd, x->c.df, x->c.of); } inline static int -local_df(union DateTimeData *x) +local_df(union DateData *x) { + assert(complex_dat_p(x)); assert(have_df_p(x)); - return df_utc_to_local(x->l.df, x->l.of); + return df_utc_to_local(x->c.df, x->c.of); +} + +static void +decode_year(VALUE y, double style, + VALUE *nth, int *ry) +{ + int period; + VALUE t; + + period = (style < 0) ? + CM_PERIOD_GCY : + CM_PERIOD_JCY; + t = f_add(y, INT2FIX(4712)); /* shift */ + *nth = f_idiv(t, INT2FIX(period)); + if (f_nonzero_p(*nth)) + t = f_mod(t, INT2FIX(period)); + *ry = FIX2INT(t) - 4712; /* unshift */ +} + +static void +encode_year(VALUE nth, int y, double style, + VALUE *ry) +{ + int period; + VALUE t; + + period = (style < 0) ? + CM_PERIOD_GCY : + CM_PERIOD_JCY; + if (f_zero_p(nth)) + *ry = INT2FIX(y); + else { + t = f_mul(INT2FIX(period), nth); + t = f_add(t, INT2FIX(y)); + *ry = t; + } +} + +static void +decode_jd(VALUE jd, VALUE *nth, int *rjd) +{ + *nth = f_idiv(jd, INT2FIX(CM_PERIOD)); + if (f_zero_p(*nth)) { + *rjd = FIX2INT(jd); + return; + } + *rjd = FIX2INT(f_mod(jd, INT2FIX(CM_PERIOD))); +} + +static void +encode_jd(VALUE nth, int jd, VALUE *rjd) +{ + if (f_zero_p(nth)) { + *rjd = INT2FIX(jd); + return; + } + *rjd = f_add(f_mul(INT2FIX(CM_PERIOD), nth), INT2FIX(jd)); +} + +static double +style_p(VALUE y, double sg) +{ + double style = 0; + + if (isinf(sg)) + style = (sg < 0) ? negative_inf : positive_inf; + else if (!FIXNUM_P(y)) + style = (f_positive_p(y)) ? negative_inf : positive_inf; + else { + if (f_lt_p(y, INT2FIX(1582))) + style = positive_inf; + else if (f_gt_p(y, INT2FIX(2001))) + style = negative_inf; + } + return style; +} + +static VALUE +m_nth(union DateData *x) +{ + if (simple_dat_p(x)) { + return x->s.nth; + } + else { + get_c_civil(x); + return x->c.nth; + } +} + +static int +m_jd(union DateData *x) +{ + if (simple_dat_p(x)) { + get_s_jd(x); + return x->s.jd; + } + else { + get_c_jd(x); + return x->c.jd; + } +} + +static VALUE +m_real_jd(union DateData *x) +{ + VALUE nth, rjd; + int jd; + + nth = m_nth(x); + jd = m_jd(x); + + encode_jd(nth, jd, &rjd); + return rjd; +} + +static int +m_local_jd(union DateData *x) +{ + if (simple_dat_p(x)) { + get_s_jd(x); + return x->s.jd; + } + else { + get_c_jd(x); + get_c_df(x); + return local_jd(x); + } +} + +static VALUE +m_real_local_jd(union DateData *x) +{ + VALUE nth, rjd; + int jd; + + nth = m_nth(x); + jd = m_local_jd(x); + + encode_jd(nth, jd, &rjd); + return rjd; +} + +static int +m_df(union DateData *x) +{ + if (simple_dat_p(x)) + return 0; + else { + get_c_df(x); + return x->c.df; + } +} + +#ifndef NDEBUG +static VALUE +m_df_in_day(union DateData *x) +{ + return isec_to_day(m_df(x)); +} +#endif + +static int +m_local_df(union DateData *x) +{ + if (simple_dat_p(x)) + return 0; + else { + get_c_df(x); + return local_df(x); + } +} + +#ifndef NDEBUG +static VALUE +m_local_df_in_day(union DateData *x) +{ + return isec_to_day(m_local_df(x)); +} +#endif + +static VALUE +m_sf(union DateData *x) +{ + if (simple_dat_p(x)) + return INT2FIX(0); + else + return x->c.sf; +} + +#ifndef NDEBUG +static VALUE +m_sf_in_day(union DateData *x) +{ + return ns_to_day(m_sf(x)); +} +#endif + +static VALUE +m_sf_in_sec(union DateData *x) +{ + return ns_to_sec(m_sf(x)); +} + +static VALUE +m_fr(union DateData *x) +{ + if (simple_dat_p(x)) + return INT2FIX(0); + else { + int df; + VALUE sf, fr; + + df = m_local_df(x); + sf = m_sf(x); + fr = isec_to_day(df); + if (f_nonzero_p(sf)) + fr = f_add(fr, ns_to_day(sf)); + return fr; + } +} + +static VALUE +m_ajd(union DateData *x) +{ + VALUE r, sf; + int df; + + r = f_sub(m_real_jd(x), half_days_in_day); + if (simple_dat_p(x)) + return r; + + df = m_df(x); + if (df) + r = f_add(r, isec_to_day(df)); + + sf = m_sf(x); + if (f_nonzero_p(sf)) + r = f_add(r, ns_to_day(sf)); + + return r; +} + +static int +m_of(union DateData *x) +{ + if (simple_dat_p(x)) + return 0; + else { + get_c_jd(x); + return x->c.of; + } +} + +static VALUE +m_of_in_day(union DateData *x) +{ + return isec_to_day(m_of(x)); +} + +static double +m_sg(union DateData *x) +{ + if (simple_dat_p(x)) + return x->s.sg; + else { + get_c_jd(x); + return x->c.sg; + } +} + +static int +m_julian_p(union DateData *x) +{ + int jd; + double sg; + + if (simple_dat_p(x)) { + jd = x->s.jd; + sg = s_sg(x); + } + else { + jd = x->c.jd; + sg = c_sg(x); + } + if (isinf(sg)) + return sg == positive_inf; + return jd < sg; +} + +static int +m_gregorian_p(union DateData *x) +{ + return !m_julian_p(x); +} + +static int +m_year(union DateData *x) +{ + if (simple_dat_p(x)) { + get_s_civil(x); + return x->s.year; + } + else { + get_c_civil(x); + return x->c.year; + } +} + +static VALUE +m_real_year(union DateData *x) +{ + VALUE nth, ry; + int year; + + nth = m_nth(x); + year = m_year(x); + + encode_year(nth, year, + m_gregorian_p(x) ? -1 : +1, + &ry); + return ry; +} + + +#ifdef USE_PACK +static int +m_pd(union DateData *x) +{ + if (simple_dat_p(x)) { + get_s_civil(x); + return x->s.pd; + } + else { + get_c_civil(x); + return x->c.pd; + } +} +#endif + +static int +m_mon(union DateData *x) +{ + if (simple_dat_p(x)) { + get_s_civil(x); +#ifndef USE_PACK + return x->s.mon; +#else + return EX_MON(x->s.pd); +#endif + } + else { + get_c_civil(x); +#ifndef USE_PACK + return x->c.mon; +#else + return EX_MON(x->c.pd); +#endif + } +} + +static int +m_mday(union DateData *x) +{ + if (simple_dat_p(x)) { + get_s_civil(x); +#ifndef USE_PACK + return x->s.mday; +#else + return EX_MDAY(x->s.pd); +#endif + } + else { + get_c_civil(x); +#ifndef USE_PACK + return x->c.mday; +#else + return EX_MDAY(x->c.pd); +#endif + } +} + +static int +m_hour(union DateData *x) +{ + if (simple_dat_p(x)) + return 0; + else { + get_c_time(x); +#ifndef USE_PACK + return x->c.hour; +#else + return EX_HOUR(x->c.pd); +#endif + } +} + +static const int yeartab[2][13] = { + { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }, + { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 } +}; + +static int +c_gregorian_to_yday(int y, int m, int d) +{ + return yeartab[c_leap_p(y) ? 1 : 0][m] + d; +} + +static void c_jd_to_ordinal(int, double, int *, int *); + +static int +m_yday(union DateData *x) +{ + double sg; + int jd, ry, rd; + + sg = m_sg(x); + jd = m_local_jd(x); + if ((isinf(sg) && sg < 0) || + (jd - sg) > 366) + return c_gregorian_to_yday(m_year(x), m_mon(x), m_mday(x)); + c_jd_to_ordinal(jd, sg, &ry, &rd); + return rd; +} + +static int +m_min(union DateData *x) +{ + if (simple_dat_p(x)) + return 0; + else { + get_c_time(x); +#ifndef USE_PACK + return x->c.min; +#else + return EX_MIN(x->c.pd); +#endif + } +} + +static int +m_sec(union DateData *x) +{ + if (simple_dat_p(x)) + return 0; + else { + get_c_time(x); +#ifndef USE_PACK + return x->c.sec; +#else + return EX_SEC(x->c.pd); +#endif + } +} + +static int +m_wday(union DateData *x) +{ + return c_jd_to_wday(m_local_jd(x)); +} + +#define decode_offset(of,s,h,m)\ +{\ + int a;\ + s = (of < 0) ? '-' : '+';\ + a = (of < 0) ? -of : of;\ + h = a / HOUR_IN_SECONDS;\ + m = a % HOUR_IN_SECONDS / MINUTE_IN_SECONDS;\ +} + +static VALUE +of2str(int of) +{ + int s, h, m; + + decode_offset(of, s, h, m); + return rb_enc_sprintf(rb_usascii_encoding(), "%c%02d:%02d", s, h, m); +} + +static VALUE +m_zone(union DateData *x) +{ + if (simple_dat_p(x)) + return rb_usascii_str_new2("+00:00"); + return of2str(m_of(x)); } inline static VALUE @@ -1445,19 +1518,401 @@ k_numeric_p(VALUE x) return f_kind_of_p(x, rb_cNumeric); } +#ifndef NDEBUG +static void +civil_to_jd(VALUE y, int m, int d, double sg, + VALUE *nth, int *ry, + int *rjd, + int *ns) +{ + double style = style_p(y, sg); + + if (style == 0) { + int jd; + + c_civil_to_jd(FIX2INT(y), m, d, sg, &jd, ns); + decode_jd(INT2FIX(jd), nth, rjd); + if (f_zero_p(*nth)) + *ry = FIX2INT(y); + else { + VALUE nth2; + decode_year(y, ns ? -1 : +1, &nth2, ry); + } + } + else { + decode_year(y, style, nth, ry); + c_civil_to_jd(*ry, m, d, style, rjd, ns); + } +} + +static void +jd_to_civil(VALUE jd, double sg, + VALUE *nth, int *rjd, + int *ry, int *rm, int *rd) +{ + decode_jd(jd, nth, rjd); + c_jd_to_civil(*rjd, sg, ry, rm, rd); +} + +static void +ordinal_to_jd(VALUE y, int d, double sg, + VALUE *nth, int *ry, + int *rjd, + int *ns) +{ + double style = style_p(y, sg); + + if (style == 0) { + int jd; + + c_ordinal_to_jd(FIX2INT(y), d, sg, &jd, ns); + decode_jd(INT2FIX(jd), nth, rjd); + if (f_zero_p(*nth)) + *ry = FIX2INT(y); + else { + VALUE nth2; + decode_year(y, ns ? -1 : +1, &nth2, ry); + } + } + else { + decode_year(y, style, nth, ry); + c_ordinal_to_jd(*ry, d, style, rjd, ns); + } +} + +static void +jd_to_ordinal(VALUE jd, double sg, + VALUE *nth, int *rjd, + int *ry, int *rd) +{ + decode_jd(jd, nth, rjd); + c_jd_to_ordinal(*rjd, sg, ry, rd); +} + +static void +commercial_to_jd(VALUE y, int w, int d, double sg, + VALUE *nth, int *ry, + int *rjd, + int *ns) +{ + double style = style_p(y, sg); + + if (style == 0) { + int jd; + + c_commercial_to_jd(FIX2INT(y), w, d, sg, &jd, ns); + decode_jd(INT2FIX(jd), nth, rjd); + if (f_zero_p(*nth)) + *ry = FIX2INT(y); + else { + VALUE nth2; + decode_year(y, ns ? -1 : +1, &nth2, ry); + } + } + else { + decode_year(y, style, nth, ry); + c_commercial_to_jd(*ry, w, d, style, rjd, ns); + } +} + +static void +jd_to_commercial(VALUE jd, double sg, + VALUE *nth, int *rjd, + int *ry, int *rw, int *rd) +{ + decode_jd(jd, nth, rjd); + c_jd_to_commercial(*rjd, sg, ry, rw, rd); +} + +static void +weeknum_to_jd(VALUE y, int w, int d, int f, double sg, + VALUE *nth, int *ry, + int *rjd, + int *ns) +{ + double style = style_p(y, sg); + + if (style == 0) { + int jd; + + c_weeknum_to_jd(FIX2INT(y), w, d, f, sg, &jd, ns); + decode_jd(INT2FIX(jd), nth, rjd); + if (f_zero_p(*nth)) + *ry = FIX2INT(y); + else { + VALUE nth2; + decode_year(y, ns ? -1 : +1, &nth2, ry); + } + } + else { + decode_year(y, style, nth, ry); + c_weeknum_to_jd(*ry, w, d, f, style, rjd, ns); + } +} + +static void +jd_to_weeknum(VALUE jd, int f, double sg, + VALUE *nth, int *rjd, + int *ry, int *rw, int *rd) +{ + decode_jd(jd, nth, rjd); + c_jd_to_weeknum(*rjd, f, sg, ry, rw, rd); +} + +static void +nth_kday_to_jd(VALUE y, int m, int n, int k, double sg, + VALUE *nth, int *ry, + int *rjd, + int *ns) +{ + double style = style_p(y, sg); + + if (style == 0) { + int jd; + + c_nth_kday_to_jd(FIX2INT(y), m, n, k, sg, &jd, ns); + decode_jd(INT2FIX(jd), nth, rjd); + if (f_zero_p(*nth)) + *ry = FIX2INT(y); + else { + VALUE nth2; + decode_year(y, ns ? -1 : +1, &nth2, ry); + } + } + else { + decode_year(y, style, nth, ry); + c_nth_kday_to_jd(*ry, m, n, k, style, rjd, ns); + } +} + +static void +jd_to_nth_kday(VALUE jd, double sg, + VALUE *nth, int *rjd, + int *ry, int *rm, int *rn, int *rk) +{ + decode_jd(jd, nth, rjd); + c_jd_to_nth_kday(*rjd, sg, ry, rm, rn, rk); +} +#endif + +static int +valid_ordinal_p(VALUE y, int d, double sg, + VALUE *nth, int *ry, + int *rd, int *rjd, + int *ns) +{ + double style = style_p(y, sg); + int r; + + if (style == 0) { + int jd; + + r = c_valid_ordinal_p(FIX2INT(y), d, sg, rd, &jd, ns); + decode_jd(INT2FIX(jd), nth, rjd); + if (f_zero_p(*nth)) + *ry = FIX2INT(y); + else { + VALUE nth2; + decode_year(y, ns ? -1 : +1, &nth2, ry); + } + } + else { + decode_year(y, style, nth, ry); + r = c_valid_ordinal_p(*ry, d, style, rd, rjd, ns); + } + return r; +} + +static int +valid_gregorian_p(VALUE y, int m, int d, + VALUE *nth, int *ry, + int *rm, int *rd) +{ + decode_year(y, -1, nth, ry); + return c_valid_gregorian_p(*ry, m, d, rm, rd); +} + +static int +valid_civil_p(VALUE y, int m, int d, double sg, + VALUE *nth, int *ry, + int *rm, int *rd, int *rjd, + int *ns) +{ + double style = style_p(y, sg); + int r; + + if (style == 0) { + int jd; + + r = c_valid_civil_p(FIX2INT(y), m, d, sg, rm, rd, &jd, ns); + decode_jd(INT2FIX(jd), nth, rjd); + if (f_zero_p(*nth)) + *ry = FIX2INT(y); + else { + VALUE nth2; + decode_year(y, ns ? -1 : +1, &nth2, ry); + } + } + else { + decode_year(y, style, nth, ry); + r = c_valid_civil_p(*ry, m, d, style, rm, rd, rjd, ns); + } + return r; +} + +static int +valid_commercial_p(VALUE y, int w, int d, double sg, + VALUE *nth, int *ry, + int *rw, int *rd, int *rjd, + int *ns) +{ + double style = style_p(y, sg); + int r; + + if (style == 0) { + int jd; + + r = c_valid_commercial_p(FIX2INT(y), w, d, sg, rw, rd, &jd, ns); + decode_jd(INT2FIX(jd), nth, rjd); + if (f_zero_p(*nth)) + *ry = FIX2INT(y); + else { + VALUE nth2; + decode_year(y, ns ? -1 : +1, &nth2, ry); + } + } + else { + decode_year(y, style, nth, ry); + r = c_valid_commercial_p(*ry, w, d, style, rw, rd, rjd, ns); + } + return r; +} + +static int +valid_weeknum_p(VALUE y, int w, int d, int f, double sg, + VALUE *nth, int *ry, + int *rw, int *rd, int *rjd, + int *ns) +{ + double style = style_p(y, sg); + int r; + + if (style == 0) { + int jd; + + r = c_valid_weeknum_p(FIX2INT(y), w, d, f, sg, rw, rd, &jd, ns); + decode_jd(INT2FIX(jd), nth, rjd); + if (f_zero_p(*nth)) + *ry = FIX2INT(y); + else { + VALUE nth2; + decode_year(y, ns ? -1 : +1, &nth2, ry); + } + } + else { + decode_year(y, style, nth, ry); + r = c_valid_weeknum_p(*ry, w, d, f, style, rw, rd, rjd, ns); + } + return r; +} + +#ifndef NDEBUG +static int +valid_nth_kday_p(VALUE y, int m, int n, int k, double sg, + VALUE *nth, int *ry, + int *rm, int *rn, int *rk, int *rjd, + int *ns) +{ + double style = style_p(y, sg); + int r; + + if (style == 0) { + int jd; + + r = c_valid_nth_kday_p(FIX2INT(y), m, n, k, sg, rm, rn, rk, &jd, ns); + decode_jd(INT2FIX(jd), nth, rjd); + if (f_zero_p(*nth)) + *ry = FIX2INT(y); + else { + VALUE nth2; + decode_year(y, ns ? -1 : +1, &nth2, ry); + } + } + else { + decode_year(y, style, nth, ry); + r = c_valid_nth_kday_p(*ry, m, n, k, style, rm, rn, rk, rjd, ns); + } + return r; +} +#endif + /* date light */ -static VALUE -rtv__valid_jd_p(int argc, VALUE *argv) +VALUE date_zone_to_diff(VALUE); + +static int +offset_to_sec(VALUE vof, int *rof) { - assert(argc == 2); - return rt__valid_jd_p(argv[0], argv[1]); + switch (TYPE(vof)) { + case T_FIXNUM: + { + long n; + + n = FIX2LONG(vof); + if (n != -1 && n != 0 && n != 1) + return 0; + *rof = (int)n * DAY_IN_SECONDS; + return 1; + } + case T_FLOAT: + { + double n; + + n = NUM2DBL(vof); + if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS) + return 0; + *rof = round(n * DAY_IN_SECONDS); + return 1; + } + case T_RATIONAL: + { + VALUE vs = day_to_sec(vof); + VALUE vn = RRATIONAL(vs)->num; + VALUE vd = RRATIONAL(vs)->den; + long n, d; + + if (!FIXNUM_P(vn) || !FIXNUM_P(vd)) + return 0; + n = FIX2LONG(vn); + d = FIX2LONG(vd); + if (d != 1) + return 0; + if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS) + return 0; + *rof = n; + return 1; + } + case T_STRING: + { + VALUE vs = date_zone_to_diff(vof); + long n; + + if (!FIXNUM_P(vs)) + return 0; + n = FIX2LONG(vs); + if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS) + return 0; + *rof = n; + return 1; + } + } + return 0; } static VALUE -valid_jd_sub(int argc, VALUE *argv, VALUE klass) +valid_jd_sub(int argc, VALUE *argv, VALUE klass, int need_jd) { - return rtv__valid_jd_p(argc, argv); + return argv[0]; } #ifndef NDEBUG @@ -1475,7 +1930,7 @@ date_s__valid_jd_p(int argc, VALUE *argv, VALUE klass) else argv[1] = vsg; - return valid_jd_sub(2, argv2, klass); + return valid_jd_sub(2, argv2, klass, 1); } #endif @@ -1496,57 +1951,57 @@ date_s_valid_jd_p(int argc, VALUE *argv, VALUE klass) argv2[0] = vjd; if (argc < 2) - argv[1] = INT2FIX(ITALY); + argv[1] = INT2FIX(DEFAULT_SG); else argv[1] = vsg; - if (NIL_P(valid_jd_sub(2, argv2, klass))) + if (NIL_P(valid_jd_sub(2, argv2, klass, 0))) return Qfalse; return Qtrue; } -static VALUE -rtv__valid_civil_p(int argc, VALUE *argv) -{ - assert(argc == 4); - return rt__valid_civil_p(argv[0], argv[1], argv[2], argv[3]); +#define valid_sg(sg) \ +{\ + if (!c_valid_start_p(sg)) {\ + sg = 0;\ + rb_warning("invalid start is ignored");\ + }\ } static VALUE valid_civil_sub(int argc, VALUE *argv, VALUE klass, int need_jd) { - int y, m, d, rm, rd; + VALUE nth, y; + int m, d, ry, rm, rd; double sg; -#ifdef FORCE_RIGHT - return rtv__valid_civil_p(argc, argv); -#endif - - if (!(FIXNUM_P(argv[0]) && - FIXNUM_P(argv[1]) && - FIXNUM_P(argv[2]))) - return rtv__valid_civil_p(argc, argv); - - y = NUM2INT(argv[0]); - if (!LIGHTABLE_YEAR(y)) - return rtv__valid_civil_p(argc, argv); - + y = argv[0]; m = NUM2INT(argv[1]); d = NUM2INT(argv[2]); sg = NUM2DBL(argv[3]); + valid_sg(sg); + if (!need_jd && isinf(sg) && sg < 0) { - if (!valid_gregorian_p(y, m, d, &rm, &rd)) + if (!valid_gregorian_p(y, m, d, + &nth, &ry, + &rm, &rd)) return Qnil; return INT2FIX(0); /* dummy */ } else { - long jd; - int ns; + int rjd, ns; + VALUE rjd2; - if (!valid_civil_p(y, m, d, sg, &rm, &rd, &jd, &ns)) + if (!valid_civil_p(y, m, d, sg, + &nth, &ry, + &rm, &rd, &rjd, + &ns)) return Qnil; - return LONG2NUM(jd); + if (!need_jd) + return INT2FIX(0); /* dummy */ + encode_jd(nth, rjd, &rjd2); + return rjd2; } } @@ -1599,7 +2054,7 @@ date_s_valid_civil_p(int argc, VALUE *argv, VALUE klass) argv2[1] = vm; argv2[2] = vd; if (argc < 4) - argv2[3] = INT2FIX(ITALY); + argv2[3] = INT2FIX(DEFAULT_SG); else argv2[3] = vsg; @@ -1609,40 +2064,31 @@ date_s_valid_civil_p(int argc, VALUE *argv, VALUE klass) } static VALUE -rtv__valid_ordinal_p(int argc, VALUE *argv) +valid_ordinal_sub(int argc, VALUE *argv, VALUE klass, int need_jd) { - assert(argc == 3); - return rt__valid_ordinal_p(argv[0], argv[1], argv[2]); -} - -static VALUE -valid_ordinal_sub(int argc, VALUE *argv, VALUE klass) -{ - int y, d, rd; + VALUE nth, y; + int d, ry, rd; double sg; -#ifdef FORCE_RIGHT - return rtv__valid_ordinal_p(argc, argv); -#endif - - if (!(FIXNUM_P(argv[0]) && - FIXNUM_P(argv[1]))) - return rtv__valid_ordinal_p(argc, argv); - - y = NUM2INT(argv[0]); - if (!LIGHTABLE_YEAR(y)) - return rtv__valid_ordinal_p(argc, argv); - + y = argv[0]; d = NUM2INT(argv[1]); sg = NUM2DBL(argv[2]); + valid_sg(sg); + { - long jd; - int ns; + int rjd, ns; + VALUE rjd2; - if (!valid_ordinal_p(y, d, sg, &rd, &jd, &ns)) + if (!valid_ordinal_p(y, d, sg, + &nth, &ry, + &rd, &rjd, + &ns)) return Qnil; - return LONG2NUM(jd); + if (!need_jd) + return INT2FIX(0); /* dummy */ + encode_jd(nth, rjd, &rjd2); + return rjd2; } } @@ -1662,7 +2108,7 @@ date_s__valid_ordinal_p(int argc, VALUE *argv, VALUE klass) else argv2[2] = vsg; - return valid_ordinal_sub(3, argv2, klass); + return valid_ordinal_sub(3, argv2, klass, 1); } #endif @@ -1694,52 +2140,42 @@ date_s_valid_ordinal_p(int argc, VALUE *argv, VALUE klass) argv2[0] = vy; argv2[1] = vd; if (argc < 3) - argv2[2] = INT2FIX(ITALY); + argv2[2] = INT2FIX(DEFAULT_SG); else argv2[2] = vsg; - if (NIL_P(valid_ordinal_sub(3, argv2, klass))) + if (NIL_P(valid_ordinal_sub(3, argv2, klass, 0))) return Qfalse; return Qtrue; } static VALUE -rtv__valid_commercial_p(int argc, VALUE *argv) +valid_commercial_sub(int argc, VALUE *argv, VALUE klass, int need_jd) { - assert(argc == 4); - return rt__valid_commercial_p(argv[0], argv[1], argv[2], argv[3]); -} - -static VALUE -valid_commercial_sub(int argc, VALUE *argv, VALUE klass) -{ - int y, w, d, rw, rd; + VALUE nth, y; + int w, d, ry, rw, rd; double sg; -#ifdef FORCE_RIGHT - return rtv__valid_commercial_p(argc, argv); -#endif - - if (!(FIXNUM_P(argv[0]) && - FIXNUM_P(argv[1]) && - FIXNUM_P(argv[2]))) - return rtv__valid_commercial_p(argc, argv); - - y = NUM2INT(argv[0]); - if (!LIGHTABLE_CWYEAR(y)) - return rtv__valid_commercial_p(argc, argv); - + y = argv[0]; w = NUM2INT(argv[1]); d = NUM2INT(argv[2]); sg = NUM2DBL(argv[3]); + valid_sg(sg); + { - long jd; - int ns; + int rjd, ns; + VALUE rjd2; - if (!valid_commercial_p(y, w, d, sg, &rw, &rd, &jd, &ns)) + if (!valid_commercial_p(y, w, d, sg, + &nth, &ry, + &rw, &rd, &rjd, + &ns)) return Qnil; - return LONG2NUM(jd); + if (!need_jd) + return INT2FIX(0); /* dummy */ + encode_jd(nth, rjd, &rjd2); + return rjd2; } } @@ -1760,7 +2196,7 @@ date_s__valid_commercial_p(int argc, VALUE *argv, VALUE klass) else argv2[3] = vsg; - return valid_commercial_sub(4, argv2, klass); + return valid_commercial_sub(4, argv2, klass, 1); } #endif @@ -1795,55 +2231,44 @@ date_s_valid_commercial_p(int argc, VALUE *argv, VALUE klass) argv2[1] = vw; argv2[2] = vd; if (argc < 4) - argv2[3] = INT2FIX(ITALY); + argv2[3] = INT2FIX(DEFAULT_SG); else argv2[3] = vsg; - if (NIL_P(valid_commercial_sub(4, argv2, klass))) + if (NIL_P(valid_commercial_sub(4, argv2, klass, 0))) return Qfalse; return Qtrue; } #ifndef NDEBUG static VALUE -rtv__valid_weeknum_p(int argc, VALUE *argv) +valid_weeknum_sub(int argc, VALUE *argv, VALUE klass, int need_jd) { - assert(argc == 5); - return rt__valid_weeknum_p(argv[0], argv[1], argv[2], argv[3], argv[4]); -} - -static VALUE -valid_weeknum_sub(int argc, VALUE *argv, VALUE klass) -{ - int y, w, d, f, rw, rd; + VALUE nth, y; + int w, d, f, ry, rw, rd; double sg; -#ifdef FORCE_RIGHT - return rtv__valid_weeknum_p(argc, argv); -#endif - - if (!(FIXNUM_P(argv[0]) && - FIXNUM_P(argv[1]) && - FIXNUM_P(argv[2]) && - FIXNUM_P(argv[3]))) - return rtv__valid_weeknum_p(argc, argv); - - y = NUM2INT(argv[0]); - if (!LIGHTABLE_YEAR(y)) - return rtv__valid_weeknum_p(argc, argv); - + y = argv[0]; w = NUM2INT(argv[1]); d = NUM2INT(argv[2]); f = NUM2INT(argv[3]); sg = NUM2DBL(argv[4]); + valid_sg(sg); + { - long jd; - int ns; + int rjd, ns; + VALUE rjd2; - if (!valid_weeknum_p(y, w, d, f, sg, &rw, &rd, &jd, &ns)) + if (!valid_weeknum_p(y, w, d, f, sg, + &nth, &ry, + &rw, &rd, &rjd, + &ns)) return Qnil; - return LONG2NUM(jd); + if (!need_jd) + return INT2FIX(0); /* dummy */ + encode_jd(nth, rjd, &rjd2); + return rjd2; } } @@ -1864,7 +2289,7 @@ date_s__valid_weeknum_p(int argc, VALUE *argv, VALUE klass) else argv2[4] = vsg; - return valid_weeknum_sub(5, argv2, klass); + return valid_weeknum_sub(5, argv2, klass, 1); } static VALUE @@ -1880,53 +2305,41 @@ date_s_valid_weeknum_p(int argc, VALUE *argv, VALUE klass) argv2[2] = vd; argv2[3] = vf; if (argc < 5) - argv2[4] = INT2FIX(ITALY); + argv2[4] = INT2FIX(DEFAULT_SG); else argv2[4] = vsg; - if (NIL_P(valid_weeknum_sub(5, argv2, klass))) + if (NIL_P(valid_weeknum_sub(5, argv2, klass, 0))) return Qfalse; return Qtrue; } static VALUE -rtv__valid_nth_kday_p(int argc, VALUE *argv) +valid_nth_kday_sub(int argc, VALUE *argv, VALUE klass, int need_jd) { - assert(argc == 5); - return rt__valid_nth_kday_p(argv[0], argv[1], argv[2], argv[3], argv[4]); -} -static VALUE -valid_nth_kday_sub(int argc, VALUE *argv, VALUE klass) -{ - int y, m, n, k, rm, rn, rk; + VALUE nth, y; + int m, n, k, ry, rm, rn, rk; double sg; -#ifdef FORCE_RIGHT - return rtv__valid_nth_kday_p(argc, argv); -#endif - - if (!(FIXNUM_P(argv[0]) && - FIXNUM_P(argv[1]) && - FIXNUM_P(argv[2]) && - FIXNUM_P(argv[3]))) - return rtv__valid_nth_kday_p(argc, argv); - - y = NUM2INT(argv[0]); - if (!LIGHTABLE_YEAR(y)) - return rtv__valid_nth_kday_p(argc, argv); - + y = argv[0]; m = NUM2INT(argv[1]); n = NUM2INT(argv[2]); k = NUM2INT(argv[3]); sg = NUM2DBL(argv[4]); { - long jd; - int ns; + int rjd, ns; + VALUE rjd2; - if (!valid_nth_kday_p(y, m, n, k, sg, &rm, &rn, &rk, &jd, &ns)) + if (!valid_nth_kday_p(y, m, n, k, sg, + &nth, &ry, + &rm, &rn, &rk, &rjd, + &ns)) return Qnil; - return LONG2NUM(jd); + if (!need_jd) + return INT2FIX(0); /* dummy */ + encode_jd(nth, rjd, &rjd2); + return rjd2; } } @@ -1947,7 +2360,7 @@ date_s__valid_nth_kday_p(int argc, VALUE *argv, VALUE klass) else argv2[4] = vsg; - return valid_nth_kday_sub(5, argv2, klass); + return valid_nth_kday_sub(5, argv2, klass, 1); } static VALUE @@ -1963,11 +2376,11 @@ date_s_valid_nth_kday_p(int argc, VALUE *argv, VALUE klass) argv2[2] = vn; argv2[3] = vk; if (argc < 5) - argv2[4] = INT2FIX(ITALY); + argv2[4] = INT2FIX(DEFAULT_SG); else argv2[4] = vsg; - if (NIL_P(valid_nth_kday_sub(5, argv2, klass))) + if (NIL_P(valid_nth_kday_sub(5, argv2, klass, 0))) return Qfalse; return Qtrue; } @@ -2004,153 +2417,189 @@ static VALUE date_s_gregorian_leap_p(VALUE klass, VALUE y) { if (f_zero_p(f_mod(y, INT2FIX(4))) && - !f_zero_p(f_mod(y, INT2FIX(100))) || + f_nonzero_p(f_mod(y, INT2FIX(100))) || f_zero_p(f_mod(y, INT2FIX(400)))) return Qtrue; return Qfalse; } static void -d_right_gc_mark(union DateData *dat) +d_simple_gc_mark(struct SimpleDateData *dat) { - assert(!light_mode_p(dat)); - rb_gc_mark(dat->r.ajd); - rb_gc_mark(dat->r.of); - rb_gc_mark(dat->r.sg); - rb_gc_mark(dat->r.cache); + rb_gc_mark(dat->nth); } -#define d_lite_gc_mark 0 - inline static VALUE -d_right_new_internal(VALUE klass, VALUE ajd, VALUE of, VALUE sg, - unsigned flags) +d_simple_new_internal(VALUE klass, + VALUE nth, int jd, + double sg, + int y, int m, int d, + unsigned flags) { - union DateData *dat; + struct SimpleDateData *dat; VALUE obj; - obj = Data_Make_Struct(klass, union DateData, - d_right_gc_mark, -1, dat); + obj = Data_Make_Struct(klass, struct SimpleDateData, + d_simple_gc_mark, -1, dat); + + dat->nth = nth; + dat->jd = jd; + dat->sg = sg; + dat->year = y; +#ifndef USE_PACK + dat->mon = m; + dat->mday = d; +#else + dat->pd = PACK2(m, d); +#endif + dat->flags = flags; - dat->r.ajd = ajd; - dat->r.of = of; - dat->r.sg = sg; - dat->r.cache = rb_hash_new(); - dat->r.flags = flags; + assert(have_jd_p(dat) || have_civil_p(dat)); return obj; } -inline static VALUE -d_lite_new_internal(VALUE klass, long jd, double sg, - int y, int m, int d, unsigned flags) +static void +d_complex_gc_mark(struct ComplexDateData *dat) { - union DateData *dat; + rb_gc_mark(dat->nth); + rb_gc_mark(dat->sf); +} + +inline static VALUE +d_complex_new_internal(VALUE klass, + VALUE nth, int jd, + int df, VALUE sf, + int of, double sg, + int y, int m, int d, + int h, int min, int s, + unsigned flags) +{ + struct ComplexDateData *dat; VALUE obj; - obj = Data_Make_Struct(klass, union DateData, - d_lite_gc_mark, -1, dat); + obj = Data_Make_Struct(klass, struct ComplexDateData, + d_complex_gc_mark, -1, dat); + + dat->nth = nth; + dat->jd = jd; + dat->df = df; + dat->sf = sf; + dat->of = of; + dat->sg = sg; + dat->year = y; +#ifndef USE_PACK + dat->mon = m; + dat->mday = d; + dat->hour = h; + dat->min = min; + dat->sec = s; +#else + dat->pd = PACK5(m, d, h, min, s); +#endif + dat->flags = flags | COMPLEX_DAT; - dat->l.jd = jd; - dat->l.sg = sg; - dat->l.year = y; - dat->l.mon = m; - dat->l.mday = d; - dat->l.flags = flags | LIGHT_MODE; + assert(have_jd_p(dat) || have_civil_p(dat)); + assert(have_df_p(dat) || have_time_p(dat)); return obj; } -static VALUE -d_lite_new_internal_wo_civil(VALUE klass, long jd, double sg, - unsigned flags) +static void +d_date_gc_mark(union DateData *dat) { - return d_lite_new_internal(klass, jd, sg, 0, 0, 0, flags); + if (simple_dat_p(dat)) + rb_gc_mark(dat->s.nth); + else { + rb_gc_mark(dat->c.nth); + rb_gc_mark(dat->c.sf); + } } -static VALUE -d_lite_s_alloc(VALUE klass) +inline static VALUE +d_date_new_internal(VALUE klass, + VALUE nth, int jd, + double sg, + int y, int m, int d, + unsigned flags) { - return d_lite_new_internal_wo_civil(klass, 0, 0, 0); -} + union DateData *dat; + VALUE obj; -static VALUE -d_right_new(VALUE klass, VALUE ajd, VALUE of, VALUE sg) -{ - return d_right_new_internal(klass, ajd, of, sg, 0); -} + obj = Data_Make_Struct(klass, union DateData, + d_date_gc_mark, -1, dat); + + dat->s.nth = nth; + dat->s.jd = jd; + dat->s.sg = sg; + dat->s.year = y; +#ifndef USE_PACK + dat->s.mon = m; + dat->s.mday = d; +#else + dat->s.pd = PACK2(m, d); +#endif + dat->s.flags = flags; -static VALUE -d_lite_new(VALUE klass, VALUE jd, VALUE sg) -{ - return d_lite_new_internal_wo_civil(klass, - NUM2LONG(jd), - NUM2DBL(sg), - HAVE_JD); + assert(have_jd_p(dat) || have_civil_p(dat)); + + return obj; } static VALUE -d_switch_new(VALUE klass, VALUE ajd, VALUE of, VALUE sg) +d_lite_s_alloc(VALUE klass) { - VALUE t, jd, df; - - t = rt_ajd_to_jd(ajd, INT2FIX(0)); /* as utc */ - jd = RARRAY_PTR(t)[0]; - df = RARRAY_PTR(t)[1]; - -#ifdef FORCE_RIGHT - if (1) -#else - if (!FIXNUM_P(jd) || - f_lt_p(jd, sg) || !f_zero_p(df) || !f_zero_p(of) || - !LIGHTABLE_JD(NUM2LONG(jd))) -#endif - return d_right_new(klass, ajd, of, sg); - else - return d_lite_new(klass, jd, sg); + return d_date_new_internal(klass, + INT2FIX(0), 0, + DEFAULT_SG, + 0, 0, 0, + HAVE_JD); } -#ifndef NDEBUG -static VALUE -d_right_new_m(int argc, VALUE *argv, VALUE klass) +static void +old_to_new(VALUE ajd, VALUE of, VALUE sg, + VALUE *rnth, int *rjd, int *rdf, VALUE *rsf, + int *rof, double *rsg, + unsigned *flags) { - VALUE ajd, of, sg; + VALUE jd, df, sf, of2, t; - rb_scan_args(argc, argv, "03", &ajd, &of, &sg); + decode_day(f_add(ajd, half_days_in_day), + &jd, &df, &sf); + t = day_to_sec(of); + of2 = f_round(t); - switch (argc) { - case 0: - ajd = INT2FIX(0); - case 1: - of = INT2FIX(0); - case 2: - sg = INT2FIX(ITALY); - } + if (!f_eqeq_p(of2, t)) + rb_warning("fraction of offset is ignored"); - return d_right_new(klass, ajd, of, sg); -} + decode_jd(jd, rnth, rjd); -static VALUE -d_lite_new_m(int argc, VALUE *argv, VALUE klass) -{ - VALUE jd, sg; + *rdf = NUM2INT(df); + *rsf = sf; + *rof = NUM2INT(of2); + *rsg = NUM2DBL(sg); - rb_scan_args(argc, argv, "02", &jd, &sg); + if (*rof < -1 || *rof > 1) { + *rof = 0; + rb_warning("invalid offset is ignored"); + } - switch (argc) { - case 0: - jd = INT2FIX(0); - case 1: - sg = INT2FIX(ITALY); + if (!c_valid_start_p(*rsg)) { + *rsg = DEFAULT_SG; + rb_warning("invalid start is ignored"); } - return d_lite_new(klass, jd, sg); + *flags = HAVE_JD | HAVE_DF | COMPLEX_DAT; } +#ifndef NDEBUG static VALUE -d_switch_new_m(int argc, VALUE *argv, VALUE klass) +date_s_new_bang(int argc, VALUE *argv, VALUE klass) { - VALUE ajd, of, sg; + VALUE ajd, of, sg, nth, sf; + int jd, df, rof; + double rsg; + unsigned flags; rb_scan_args(argc, argv, "03", &ajd, &of, &sg); @@ -2160,83 +2609,148 @@ d_switch_new_m(int argc, VALUE *argv, VALUE klass) case 1: of = INT2FIX(0); case 2: - sg = INT2FIX(ITALY); + sg = INT2FIX(DEFAULT_SG); } - return d_switch_new(klass, ajd, of, sg); + old_to_new(ajd, of, sg, + &nth, &jd, &df, &sf, &rof, &rsg, &flags); + + return d_complex_new_internal(klass, + nth, jd, + df, sf, + rof, rsg, + 0, 0, 0, + 0, 0, 0, + flags); } #endif -static VALUE -d_right_new_jd(VALUE klass, VALUE jd, VALUE sg) +inline static int +integer_p(VALUE x) { - return d_right_new(klass, - rt_jd_to_ajd(jd, INT2FIX(0), INT2FIX(0)), - INT2FIX(0), - sg); + if (FIXNUM_P(x)) + return 1; + switch (TYPE(x)) { + case T_BIGNUM: + return 1; + case T_FLOAT: + { + double d = NUM2DBL(x); + if (round(d) == d) + return 1; + } + case T_RATIONAL: + { + if (RRATIONAL(x)->den == 1) + return 1; + } + } + return 0; } -#ifndef NDEBUG -static VALUE -d_lite_new_jd(VALUE klass, VALUE jd, VALUE sg) +inline static VALUE +d_trunc(VALUE d, VALUE *fr) { - return d_lite_new(klass, jd, sg); -} -#endif + VALUE rd; -static VALUE -d_switch_new_jd(VALUE klass, VALUE jd, VALUE sg) -{ - return d_switch_new(klass, - rt_jd_to_ajd(jd, INT2FIX(0), INT2FIX(0)), - INT2FIX(0), - sg); + if (integer_p(d)) { + rd = d; + *fr = INT2FIX(0); + } else { + rd = f_idiv(d, INT2FIX(1)); + *fr = f_mod(d, INT2FIX(1)); + } + return rd; } -#ifndef NDEBUG -static VALUE -date_s_new_r_bang(int argc, VALUE *argv, VALUE klass) -{ - return d_right_new_m(argc, argv, klass); -} +#define jd_trunc d_trunc +#define k_trunc d_trunc -static VALUE -date_s_new_l_bang(int argc, VALUE *argv, VALUE klass) +inline static VALUE +h_trunc(VALUE h, VALUE *fr) { - return d_lite_new_m(argc, argv, klass); + VALUE rh; + + if (integer_p(h)) { + rh = h; + *fr = INT2FIX(0); + } else { + rh = f_idiv(h, INT2FIX(1)); + *fr = f_mod(h, INT2FIX(1)); + *fr = f_quo(*fr, INT2FIX(24)); + } + return rh; } -static VALUE -date_s_new_bang(int argc, VALUE *argv, VALUE klass) +inline static VALUE +min_trunc(VALUE min, VALUE *fr) { - return d_switch_new_m(argc, argv, klass); -} -#endif + VALUE rmin; -#define c_cforwardv(m) rt_date_s_##m(argc, argv, klass) + if (integer_p(min)) { + rmin = min; + *fr = INT2FIX(0); + } else { + rmin = f_idiv(min, INT2FIX(1)); + *fr = f_mod(min, INT2FIX(1)); + *fr = f_quo(*fr, INT2FIX(1440)); + } + return rmin; +} -static VALUE -rt_date_s_jd(int argc, VALUE *argv, VALUE klass) +inline static VALUE +s_trunc(VALUE s, VALUE *fr) { - VALUE jd, sg; + VALUE rs; - rb_scan_args(argc, argv, "02", &jd, &sg); - - switch (argc) { - case 0: - jd = INT2FIX(0); - case 1: - sg = INT2FIX(ITALY); + if (integer_p(s)) { + rs = s; + *fr = INT2FIX(0); + } else { + rs = f_idiv(s, INT2FIX(1)); + *fr = f_mod(s, INT2FIX(1)); + *fr = f_quo(*fr, INT2FIX(86400)); } + return rs; +} - jd = rt__valid_jd_p(jd, sg); +#define num2num_with_frac(s,n) \ +{\ + s = s##_trunc(v##s, &fr);\ + if (f_nonzero_p(fr)) {\ + if (argc > n)\ + rb_raise(rb_eArgError, "invalid fraction");\ + fr2 = fr;\ + }\ +} - if (NIL_P(jd)) - rb_raise(rb_eArgError, "invalid date"); +#define num2int_with_frac(s,n) \ +{\ + s = NUM2INT(s##_trunc(v##s, &fr));\ + if (f_nonzero_p(fr)) {\ + if (argc > n)\ + rb_raise(rb_eArgError, "invalid fraction");\ + fr2 = fr;\ + }\ +} - return d_right_new_jd(klass, jd, sg); +#define add_frac() \ +{\ + if (f_nonzero_p(fr2))\ + ret = d_lite_plus(ret, fr2);\ } +#define val2sg(vsg,dsg) \ +{\ + dsg = NUM2DBL(vsg);\ + if (!c_valid_start_p(dsg)) {\ + dsg = DEFAULT_SG;\ + rb_warning("invalid start is ignored");\ + }\ +} + +static VALUE d_lite_plus(VALUE, VALUE); + /* * call-seq: * Date.jd([jd=0[, start=Date::ITALY]]) @@ -2249,59 +2763,36 @@ rt_date_s_jd(int argc, VALUE *argv, VALUE klass) static VALUE date_s_jd(int argc, VALUE *argv, VALUE klass) { - VALUE vjd, vsg; - long jd; + VALUE vjd, vsg, jd, fr, fr2, ret; double sg; -#ifdef FORCE_RIGHT - return c_cforwardv(jd); -#endif - rb_scan_args(argc, argv, "02", &vjd, &vsg); - if (!FIXNUM_P(vjd)) - return c_cforwardv(jd); - - jd = 0; - sg = ITALY; + jd = INT2FIX(0); + fr2 = INT2FIX(0); + sg = DEFAULT_SG; switch (argc) { case 2: - sg = NUM2DBL(vsg); + val2sg(vsg, sg); case 1: - jd = NUM2LONG(vjd); - if (!LIGHTABLE_JD(jd)) - return c_cforwardv(jd); + num2num_with_frac(jd, positive_inf); } - if (jd < sg) - return c_cforwardv(jd); - - return d_lite_new_internal_wo_civil(klass, jd, sg, HAVE_JD); -} - -static VALUE -rt_date_s_ordinal(int argc, VALUE *argv, VALUE klass) -{ - VALUE y, d, sg, jd; + { + VALUE nth; + int rjd; - rb_scan_args(argc, argv, "03", &y, &d, &sg); + decode_jd(jd, &nth, &rjd); - switch (argc) { - case 0: - y = INT2FIX(-4712); - case 1: - d = INT2FIX(1); - case 2: - sg = INT2FIX(ITALY); + ret = d_simple_new_internal(klass, + nth, rjd, + sg, + 0, 0, 0, + HAVE_JD); } - - jd = rt__valid_ordinal_p(y, d, sg); - - if (NIL_P(jd)) - rb_raise(rb_eArgError, "invalid date"); - - return d_right_new_jd(klass, jd, sg); + add_frac(); + return ret; } /* @@ -2322,74 +2813,44 @@ rt_date_s_ordinal(int argc, VALUE *argv, VALUE klass) static VALUE date_s_ordinal(int argc, VALUE *argv, VALUE klass) { - VALUE vy, vd, vsg; - int y, d, rd; + VALUE vy, vd, vsg, y, fr, fr2, ret; + int d; double sg; -#ifdef FORCE_RIGHT - return c_cforwardv(ordinal); -#endif - rb_scan_args(argc, argv, "03", &vy, &vd, &vsg); - if (!((NIL_P(vy) || FIXNUM_P(vy)) && - (NIL_P(vd) || FIXNUM_P(vd)))) - return c_cforwardv(ordinal); - - y = -4712; + y = INT2FIX(-4712); d = 1; - sg = ITALY; + fr2 = INT2FIX(0); + sg = DEFAULT_SG; switch (argc) { case 3: - sg = NUM2DBL(vsg); + val2sg(vsg, sg); case 2: - d = NUM2INT(vd); + num2int_with_frac(d, positive_inf); case 1: - y = NUM2INT(vy); - if (!LIGHTABLE_YEAR(y)) - return c_cforwardv(ordinal); + y = vy; } { - long jd; - int ns; + VALUE nth; + int ry, rd, rjd, ns; - if (!valid_ordinal_p(y, d, sg, &rd, &jd, &ns)) + if (!valid_ordinal_p(y, d, sg, + &nth, &ry, + &rd, &rjd, + &ns)) rb_raise(rb_eArgError, "invalid date"); - if (!LIGHTABLE_JD(jd) || !ns) - return c_cforwardv(ordinal); - - return d_lite_new_internal_wo_civil(klass, jd, sg, - HAVE_JD); + ret = d_simple_new_internal(klass, + nth, rjd, + sg, + 0, 0, 0, + HAVE_JD); } -} - -static VALUE -rt_date_s_civil(int argc, VALUE *argv, VALUE klass) -{ - VALUE y, m, d, sg, jd; - - rb_scan_args(argc, argv, "04", &y, &m, &d, &sg); - - switch (argc) { - case 0: - y = INT2FIX(-4712); - case 1: - m = INT2FIX(1); - case 2: - d = INT2FIX(1); - case 3: - sg = INT2FIX(ITALY); - } - - jd = rt__valid_civil_p(y, m, d, sg); - - if (NIL_P(jd)) - rb_raise(rb_eArgError, "invalid date"); - - return d_right_new_jd(klass, jd, sg); + add_frac(); + return ret; } /* @@ -2414,85 +2875,62 @@ rt_date_s_civil(int argc, VALUE *argv, VALUE klass) static VALUE date_s_civil(int argc, VALUE *argv, VALUE klass) { - VALUE vy, vm, vd, vsg; - int y, m, d, rm, rd; + VALUE vy, vm, vd, vsg, y, fr, fr2, ret; + int m, d; double sg; -#ifdef FORCE_RIGHT - return c_cforwardv(civil); -#endif - rb_scan_args(argc, argv, "04", &vy, &vm, &vd, &vsg); - if (!((NIL_P(vy) || FIXNUM_P(vy)) && - (NIL_P(vm) || FIXNUM_P(vm)) && - (NIL_P(vd) || FIXNUM_P(vd)))) - return c_cforwardv(civil); - - y = -4712; + y = INT2FIX(-4712); m = 1; d = 1; - sg = ITALY; + fr2 = INT2FIX(0); + sg = DEFAULT_SG; switch (argc) { case 4: - sg = NUM2DBL(vsg); + val2sg(vsg, sg); case 3: - d = NUM2INT(vd); + num2int_with_frac(d, positive_inf); case 2: m = NUM2INT(vm); case 1: - y = NUM2INT(vy); - if (!LIGHTABLE_YEAR(y)) - return c_cforwardv(civil); + y = vy; } if (isinf(sg) && sg < 0) { - if (!valid_gregorian_p(y, m, d, &rm, &rd)) + VALUE nth; + int ry, rm, rd; + + if (!valid_gregorian_p(y, m, d, + &nth, &ry, + &rm, &rd)) rb_raise(rb_eArgError, "invalid date"); - return d_lite_new_internal(klass, 0, sg, y, rm, rd, - HAVE_CIVIL); + ret = d_simple_new_internal(klass, + nth, 0, + sg, + ry, rm, rd, + HAVE_CIVIL); } else { - long jd; - int ns; + VALUE nth; + int ry, rm, rd, rjd, ns; - if (!valid_civil_p(y, m, d, sg, &rm, &rd, &jd, &ns)) + if (!valid_civil_p(y, m, d, sg, + &nth, &ry, + &rm, &rd, &rjd, + &ns)) rb_raise(rb_eArgError, "invalid date"); - if (!LIGHTABLE_JD(jd) || !ns) - return c_cforwardv(civil); - - return d_lite_new_internal(klass, jd, sg, y, rm, rd, - HAVE_JD | HAVE_CIVIL); - } -} - -static VALUE -rt_date_s_commercial(int argc, VALUE *argv, VALUE klass) -{ - VALUE y, w, d, sg, jd; - - rb_scan_args(argc, argv, "04", &y, &w, &d, &sg); - - switch (argc) { - case 0: - y = INT2FIX(-4712); - case 1: - w = INT2FIX(1); - case 2: - d = INT2FIX(1); - case 3: - sg = INT2FIX(ITALY); + ret = d_simple_new_internal(klass, + nth, rjd, + sg, + ry, rm, rd, + HAVE_JD | HAVE_CIVIL); } - - jd = rt__valid_commercial_p(y, w, d, sg); - - if (NIL_P(jd)) - rb_raise(rb_eArgError, "invalid date"); - - return d_right_new_jd(klass, jd, sg); + add_frac(); + return ret; } /* @@ -2518,219 +2956,146 @@ rt_date_s_commercial(int argc, VALUE *argv, VALUE klass) static VALUE date_s_commercial(int argc, VALUE *argv, VALUE klass) { - VALUE vy, vw, vd, vsg; - int y, w, d, rw, rd; + VALUE vy, vw, vd, vsg, y, fr, fr2, ret; + int w, d; double sg; -#ifdef FORCE_RIGHT - return c_cforwardv(commercial); -#endif - rb_scan_args(argc, argv, "04", &vy, &vw, &vd, &vsg); - if (!((NIL_P(vy) || FIXNUM_P(vy)) && - (NIL_P(vw) || FIXNUM_P(vw)) && - (NIL_P(vd) || FIXNUM_P(vd)))) - return c_cforwardv(commercial); - - y = -4712; + y = INT2FIX(-4712); w = 1; d = 1; - sg = ITALY; + fr2 = INT2FIX(0); + sg = DEFAULT_SG; switch (argc) { case 4: - sg = NUM2DBL(vsg); + val2sg(vsg, sg); case 3: - d = NUM2INT(vd); + num2int_with_frac(d, positive_inf); case 2: w = NUM2INT(vw); case 1: - y = NUM2INT(vy); - if (!LIGHTABLE_CWYEAR(y)) - return c_cforwardv(commercial); + y = vy; } { - long jd; - int ns; + VALUE nth; + int ry, rw, rd, rjd, ns; - if (!valid_commercial_p(y, w, d, sg, &rw, &rd, &jd, &ns)) + if (!valid_commercial_p(y, w, d, sg, + &nth, &ry, + &rw, &rd, &rjd, + &ns)) rb_raise(rb_eArgError, "invalid date"); - if (!LIGHTABLE_JD(jd) || !ns) - return c_cforwardv(commercial); - - return d_lite_new_internal_wo_civil(klass, jd, sg, - HAVE_JD); + ret = d_simple_new_internal(klass, + nth, rjd, + sg, + 0, 0, 0, + HAVE_JD); } + add_frac(); + return ret; } #ifndef NDEBUG static VALUE -rt_date_s_weeknum(int argc, VALUE *argv, VALUE klass) -{ - VALUE y, w, d, f, sg, jd; - - rb_scan_args(argc, argv, "05", &y, &w, &d, &f, &sg); - - switch (argc) { - case 0: - y = INT2FIX(-4712); - case 1: - w = INT2FIX(0); - case 2: - d = INT2FIX(1); - case 3: - f = INT2FIX(0); - case 4: - sg = INT2FIX(ITALY); - } - - jd = rt__valid_weeknum_p(y, w, d, f, sg); - - if (NIL_P(jd)) - rb_raise(rb_eArgError, "invalid date"); - - return d_right_new_jd(klass, jd, sg); -} - -static VALUE date_s_weeknum(int argc, VALUE *argv, VALUE klass) { - VALUE vy, vw, vd, vf, vsg; - int y, w, d, f, rw, rd; + VALUE vy, vw, vd, vf, vsg, y, fr, fr2, ret; + int w, d, f; double sg; -#ifdef FORCE_RIGHT - return c_cforwardv(weeknum); -#endif - rb_scan_args(argc, argv, "05", &vy, &vw, &vd, &vf, &vsg); - if (!((NIL_P(vy) || FIXNUM_P(vy)) && - (NIL_P(vw) || FIXNUM_P(vw)) && - (NIL_P(vd) || FIXNUM_P(vd)) && - (NIL_P(vf) || FIXNUM_P(vf)))) - return c_cforwardv(weeknum); - - y = -4712; + y = INT2FIX(-4712); w = 0; d = 1; f = 0; - sg = ITALY; + fr2 = INT2FIX(0); + sg = DEFAULT_SG; switch (argc) { case 5: - sg = NUM2DBL(vsg); + val2sg(vsg, sg); case 4: f = NUM2INT(vf); case 3: - d = NUM2INT(vd); + num2int_with_frac(d, positive_inf); case 2: w = NUM2INT(vw); case 1: - y = NUM2INT(vy); - if (!LIGHTABLE_YEAR(y)) - return c_cforwardv(weeknum); + y = vy; } { - long jd; - int ns; + VALUE nth; + int ry, rw, rd, rjd, ns; - if (!valid_weeknum_p(y, w, d, f, sg, &rw, &rd, &jd, &ns)) + if (!valid_weeknum_p(y, w, d, f, sg, + &nth, &ry, + &rw, &rd, &rjd, + &ns)) rb_raise(rb_eArgError, "invalid date"); - if (!LIGHTABLE_JD(jd) || !ns) - return c_cforwardv(weeknum); - - return d_lite_new_internal_wo_civil(klass, jd, sg, - HAVE_JD); - } -} - -static VALUE -rt_date_s_nth_kday(int argc, VALUE *argv, VALUE klass) -{ - VALUE y, m, n, k, sg, jd; - - rb_scan_args(argc, argv, "05", &y, &m, &n, &k, &sg); - - switch (argc) { - case 0: - y = INT2FIX(-4712); - case 1: - m = INT2FIX(1); - case 2: - n = INT2FIX(1); - case 3: - k = INT2FIX(1); - case 4: - sg = INT2FIX(ITALY); + ret = d_simple_new_internal(klass, + nth, rjd, + sg, + 0, 0, 0, + HAVE_JD); } - - jd = rt__valid_nth_kday_p(y, m, n, k, sg); - - if (NIL_P(jd)) - rb_raise(rb_eArgError, "invalid date"); - - return d_right_new_jd(klass, jd, sg); + add_frac(); + return ret; } static VALUE date_s_nth_kday(int argc, VALUE *argv, VALUE klass) { - VALUE vy, vm, vn, vk, vsg; - int y, m, n, k, rm, rn, rk; + VALUE vy, vm, vn, vk, vsg, y, fr, fr2, ret; + int m, n, k; double sg; -#ifdef FORCE_RIGHT - return c_cforwardv(nth_kday); -#endif - rb_scan_args(argc, argv, "05", &vy, &vm, &vn, &vk, &vsg); - if (!((NIL_P(vy) || FIXNUM_P(vy)) && - (NIL_P(vm) || FIXNUM_P(vm)) && - (NIL_P(vn) || FIXNUM_P(vn)) && - (NIL_P(vk) || FIXNUM_P(vk)))) - return c_cforwardv(nth_kday); - - y = -4712; + y = INT2FIX(-4712); m = 1; n = 1; k = 1; - sg = ITALY; + fr2 = INT2FIX(0); + sg = DEFAULT_SG; switch (argc) { case 5: - sg = NUM2DBL(vsg); + val2sg(vsg, sg); case 4: - k = NUM2INT(vk); + num2int_with_frac(k, positive_inf); case 3: n = NUM2INT(vn); case 2: m = NUM2INT(vm); case 1: - y = NUM2INT(vy); - if (!LIGHTABLE_YEAR(y)) - return c_cforwardv(nth_kday); + y = vy; } { - long jd; - int ns; + VALUE nth; + int ry, rm, rn, rk, rjd, ns; - if (!valid_nth_kday_p(y, m, n, k, sg, &rm, &rn, &rk, &jd, &ns)) + if (!valid_nth_kday_p(y, m, n, k, sg, + &nth, &ry, + &rm, &rn, &rk, &rjd, + &ns)) rb_raise(rb_eArgError, "invalid date"); - if (!LIGHTABLE_JD(jd) || !ns) - return c_cforwardv(nth_kday); - - return d_lite_new_internal_wo_civil(klass, jd, sg, - HAVE_JD); + ret = d_simple_new_internal(klass, + nth, rjd, + sg, + 0, 0, 0, + HAVE_JD); } + add_frac(); + return ret; } #endif @@ -2745,6 +3110,8 @@ localtime_r(const time_t *t, struct tm *tm) } #endif +static void set_sg(union DateData *, double); + /* * call-seq: * Date.today([start=Date::ITALY]) @@ -2756,19 +3123,18 @@ localtime_r(const time_t *t, struct tm *tm) static VALUE date_s_today(int argc, VALUE *argv, VALUE klass) { - VALUE vsg; + VALUE vsg, nth, ret; double sg; time_t t; struct tm tm; - int y; - int m, d; + int y, ry, m, d; rb_scan_args(argc, argv, "01", &vsg); if (argc < 1) - sg = ITALY; + sg = DEFAULT_SG; else - sg = NUM2DBL(vsg); + val2sg(vsg, sg); if (time(&t) == -1) rb_sys_fail("time"); @@ -2778,33 +3144,18 @@ date_s_today(int argc, VALUE *argv, VALUE klass) m = tm.tm_mon + 1; d = tm.tm_mday; -#ifdef FORCE_RIGHT - goto right; -#endif - - if (!LIGHTABLE_YEAR(y)) - goto right; - - if (isinf(sg) && sg < 0) - return d_lite_new_internal(klass, 0, sg, y, m, d, - HAVE_CIVIL); - else { - long jd; - int ns; + decode_year(INT2FIX(y), -1, &nth, &ry); - civil_to_jd(y, m, d, sg, &jd, &ns); - - return d_lite_new_internal(klass, jd, sg, y, m, d, - HAVE_JD | HAVE_CIVIL); - } - right: + ret = d_simple_new_internal(klass, + nth, 0, + GREGORIAN, + ry, m, d, + HAVE_CIVIL); { - VALUE jd, ajd; - - jd = rt_civil_to_jd(INT2FIX(y), INT2FIX(m), INT2FIX(d), DBL2NUM(sg)); - ajd = rt_jd_to_ajd(jd, INT2FIX(0), INT2FIX(0)); - return d_right_new(klass, ajd, INT2FIX(0), DBL2NUM(sg)); + get_d1(ret); + set_sg(dat, sg); } + return ret; } #define set_hash0(k,v) rb_hash_aset(hash, k, v) @@ -2859,6 +3210,8 @@ fv_values_at(VALUE h, VALUE a) RARRAY_LENINT(a), RARRAY_PTR(a)); } +static VALUE d_lite_wday(VALUE); + static VALUE rt_complete_frags(VALUE klass, VALUE hash) { @@ -3040,7 +3393,9 @@ rt_complete_frags(VALUE klass, VALUE hash) set_hash("cwday", INT2FIX(1)); } else if (k == sym("wday")) { - set_hash("jd", f_jd(f_add(f_sub(d, f_wday(d)), ref_hash("wday")))); + set_hash("jd", f_jd(f_add(f_sub(d, + d_lite_wday(d)), + ref_hash("wday")))); } else if (k == sym("wnum0")) { int i; @@ -3097,7 +3452,8 @@ rt_complete_frags(VALUE klass, VALUE hash) #define f_values_at1(o,k1) rb_funcall(o, rb_intern("values_at"), 1, k1) #define f_values_at2(o,k1,k2) rb_funcall(o, rb_intern("values_at"), 2, k1, k2) -#define f_values_at3(o,k1,k2,k3) rb_funcall(o, rb_intern("values_at"), 3, k1, k2, k3) +#define f_values_at3(o,k1,k2,k3) rb_funcall(o, rb_intern("values_at"), 3,\ + k1, k2, k3) static VALUE f_all_p(VALUE a) @@ -3111,6 +3467,72 @@ f_all_p(VALUE a) } static VALUE +rt__valid_jd_p(VALUE jd, VALUE sg) +{ + return jd; +} + +static VALUE +rt__valid_ordinal_p(VALUE y, VALUE d, VALUE sg) +{ + VALUE nth, rjd2; + int ry, rd, rjd, ns; + + if (!valid_ordinal_p(y, NUM2INT(d), NUM2DBL(sg), + &nth, &ry, + &rd, &rjd, + &ns)) + return Qnil; + encode_jd(nth, rjd, &rjd2); + return rjd2; +} + +static VALUE +rt__valid_civil_p(VALUE y, VALUE m, VALUE d, VALUE sg) +{ + VALUE nth, rjd2; + int ry, rm, rd, rjd, ns; + + if (!valid_civil_p(y, NUM2INT(m), NUM2INT(d), NUM2DBL(sg), + &nth, &ry, + &rm, &rd, &rjd, + &ns)) + return Qnil; + encode_jd(nth, rjd, &rjd2); + return rjd2; +} + +static VALUE +rt__valid_commercial_p(VALUE y, VALUE w, VALUE d, VALUE sg) +{ + VALUE nth, rjd2; + int ry, rw, rd, rjd, ns; + + if (!valid_commercial_p(y, NUM2INT(w), NUM2INT(d), NUM2DBL(sg), + &nth, &ry, + &rw, &rd, &rjd, + &ns)) + return Qnil; + encode_jd(nth, rjd, &rjd2); + return rjd2; +} + +static VALUE +rt__valid_weeknum_p(VALUE y, VALUE w, VALUE d, VALUE f, VALUE sg) +{ + VALUE nth, rjd2; + int ry, rw, rd, rjd, ns; + + if (!valid_weeknum_p(y, NUM2INT(w), NUM2INT(d), NUM2INT(f), NUM2DBL(sg), + &nth, &ry, + &rw, &rd, &rjd, + &ns)) + return Qnil; + encode_jd(nth, rjd, &rjd2); + return rjd2; +} + +static VALUE rt__valid_date_frags_p(VALUE hash, VALUE sg) { VALUE a; @@ -3190,27 +3612,33 @@ rt__valid_date_frags_p(VALUE hash, VALUE sg) } static VALUE -rt__valid_time_frags_p(VALUE hash) -{ - VALUE a; - - a = f_values_at3(hash, sym("hour"), sym("min"), sym("sec")); - return rt__valid_time_p(RARRAY_PTR(a)[0], - RARRAY_PTR(a)[1], - RARRAY_PTR(a)[2]); -} - -static VALUE -d_switch_new_by_frags(VALUE klass, VALUE hash, VALUE sg) +d_new_by_frags(VALUE klass, VALUE hash, VALUE sg) { VALUE jd; + if (!c_valid_start_p(NUM2DBL(sg))) { + sg = INT2FIX(DEFAULT_SG); + rb_warning("invalid start is ignored"); + } + hash = rt_rewrite_frags(hash); hash = rt_complete_frags(klass, hash); + jd = rt__valid_date_frags_p(hash, sg); if (NIL_P(jd)) rb_raise(rb_eArgError, "invalid date"); - return d_switch_new_jd(klass, jd, sg); + { + VALUE nth; + int rjd; + + decode_jd(jd, &nth, &rjd); + + return d_simple_new_internal(klass, + nth, rjd, + NUM2DBL(sg), + 0, 0, 0, + HAVE_JD); + } } VALUE @@ -3312,7 +3740,7 @@ date_s_strptime(int argc, VALUE *argv, VALUE klass) case 1: fmt = rb_str_new2("%F"); case 2: - sg = INT2FIX(ITALY); + sg = INT2FIX(DEFAULT_SG); } { @@ -3321,7 +3749,7 @@ date_s_strptime(int argc, VALUE *argv, VALUE klass) argv2[0] = str; argv2[1] = fmt; hash = date_s__strptime(2, argv2, klass); - return d_switch_new_by_frags(klass, hash, sg); + return d_new_by_frags(klass, hash, sg); } } @@ -3400,7 +3828,7 @@ date_s_parse(int argc, VALUE *argv, VALUE klass) case 1: comp = Qtrue; case 2: - sg = INT2FIX(ITALY); + sg = INT2FIX(DEFAULT_SG); } { @@ -3409,7 +3837,7 @@ date_s_parse(int argc, VALUE *argv, VALUE klass) argv2[0] = str; argv2[1] = comp; hash = date_s__parse(2, argv2, klass); - return d_switch_new_by_frags(klass, hash, sg); + return d_new_by_frags(klass, hash, sg); } } @@ -3450,12 +3878,12 @@ date_s_iso8601(int argc, VALUE *argv, VALUE klass) case 0: str = rb_str_new2("-4712-01-01"); case 1: - sg = INT2FIX(ITALY); + sg = INT2FIX(DEFAULT_SG); } { VALUE hash = date_s__iso8601(klass, str); - return d_switch_new_by_frags(klass, hash, sg); + return d_new_by_frags(klass, hash, sg); } } @@ -3489,12 +3917,12 @@ date_s_rfc3339(int argc, VALUE *argv, VALUE klass) case 0: str = rb_str_new2("-4712-01-01T00:00:00+00:00"); case 1: - sg = INT2FIX(ITALY); + sg = INT2FIX(DEFAULT_SG); } { VALUE hash = date_s__rfc3339(klass, str); - return d_switch_new_by_frags(klass, hash, sg); + return d_new_by_frags(klass, hash, sg); } } @@ -3528,12 +3956,12 @@ date_s_xmlschema(int argc, VALUE *argv, VALUE klass) case 0: str = rb_str_new2("-4712-01-01"); case 1: - sg = INT2FIX(ITALY); + sg = INT2FIX(DEFAULT_SG); } { VALUE hash = date_s__xmlschema(klass, str); - return d_switch_new_by_frags(klass, hash, sg); + return d_new_by_frags(klass, hash, sg); } } @@ -3569,12 +3997,12 @@ date_s_rfc2822(int argc, VALUE *argv, VALUE klass) case 0: str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000"); case 1: - sg = INT2FIX(ITALY); + sg = INT2FIX(DEFAULT_SG); } { VALUE hash = date_s__rfc2822(klass, str); - return d_switch_new_by_frags(klass, hash, sg); + return d_new_by_frags(klass, hash, sg); } } @@ -3608,12 +4036,12 @@ date_s_httpdate(int argc, VALUE *argv, VALUE klass) case 0: str = rb_str_new2("Mon, 01 Jan -4712 00:00:00 GMT"); case 1: - sg = INT2FIX(ITALY); + sg = INT2FIX(DEFAULT_SG); } { VALUE hash = date_s__httpdate(klass, str); - return d_switch_new_by_frags(klass, hash, sg); + return d_new_by_frags(klass, hash, sg); } } @@ -3647,43 +4075,184 @@ date_s_jisx0301(int argc, VALUE *argv, VALUE klass) case 0: str = rb_str_new2("-4712-01-01"); case 1: - sg = INT2FIX(ITALY); + sg = INT2FIX(DEFAULT_SG); } { VALUE hash = date_s__jisx0301(klass, str); - return d_switch_new_by_frags(klass, hash, sg); + return d_new_by_frags(klass, hash, sg); } } -/* - * call-seq: - * d.ajd - * - * Get the date as an Astronomical Julian Day Number. - */ +#ifndef NDEBUG static VALUE -d_lite_ajd(VALUE self) +d_lite_fill(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return dat->r.ajd; - { - get_d_jd(dat); - return f_sub(INT2FIX(dat->l.jd), rhalf); + + if (simple_dat_p(dat)) { + get_s_jd(dat); + get_s_civil(dat); + } + else { + get_c_jd(dat); + get_c_civil(dat); + get_c_df(dat); + get_c_time(dat); } + return self; } +#endif -#define c_iforward0(m) d_right_##m(self) -#define c_iforwardv(m) d_right_##m(argc, argv, self) -#define c_iforwardop(m) d_right_##m(self, other) +static VALUE +copy_obj(VALUE self) +{ + get_d1(self); + + if (simple_dat_p(dat)) + return d_simple_new_internal(CLASS_OF(self), + dat->s.nth, + dat->s.jd, + dat->s.sg, + dat->s.year, +#ifndef USE_PACK + dat->s.mon, + dat->s.mday, +#else + EX_MON(dat->s.pd), + EX_MDAY(dat->s.pd), +#endif + dat->s.flags); + else + return d_complex_new_internal(CLASS_OF(self), + dat->c.nth, + dat->c.jd, + dat->c.df, + dat->c.sf, + dat->c.of, + dat->c.sg, + dat->c.year, +#ifndef USE_PACK + dat->c.mon, + dat->c.mday, + dat->c.hour, + dat->c.min, + dat->c.sec, +#else + EX_MON(dat->c.pd), + EX_MDAY(dat->c.pd), + EX_HOUR(dat->c.pd), + EX_MIN(dat->c.pd), + EX_SEC(dat->c.pd), +#endif + dat->c.flags); +} static VALUE -d_right_amjd(VALUE self) +copy_obj_as_complex(VALUE self) { get_d1(self); - assert(!light_mode_p(dat)); - return rt_ajd_to_amjd(dat->r.ajd); + + if (simple_dat_p(dat)) + return d_complex_new_internal(CLASS_OF(self), + dat->s.nth, + dat->s.jd, + 0, + INT2FIX(0), + 0, + dat->s.sg, + dat->s.year, +#ifndef USE_PACK + dat->s.mon, + dat->s.mday, +#else + EX_MON(dat->s.pd), + EX_MDAY(dat->s.pd), +#endif + 0, + 0, + 0, + dat->s.flags | HAVE_DF); + else + return d_complex_new_internal(CLASS_OF(self), + dat->c.nth, + dat->c.jd, + dat->c.df, + dat->c.sf, + dat->c.of, + dat->c.sg, + dat->c.year, +#ifndef USE_PACK + dat->c.mon, + dat->c.mday, + dat->c.hour, + dat->c.min, + dat->c.sec, +#else + EX_MON(dat->c.pd), + EX_MDAY(dat->c.pd), + EX_HOUR(dat->c.pd), + EX_MIN(dat->c.pd), + EX_SEC(dat->c.pd), +#endif + dat->c.flags); +} + +/* :nodoc: */ +static VALUE +d_lite_initialize_copy(VALUE copy, VALUE date) +{ + if (copy == date) + return copy; + { + get_d2(copy, date); + if (simple_dat_p(bdat)) { + adat->s.nth = bdat->s.nth; + adat->s.jd = bdat->s.jd; + adat->s.sg = bdat->s.sg; + adat->s.year = bdat->s.year; +#ifndef USE_PACK + adat->s.mon = bdat->s.mon; + adat->s.mday = bdat->s.mday; +#else + adat->s.pd = bdat->s.pd; +#endif + adat->s.flags = bdat->s.flags; + } + else { + adat->c.nth = bdat->c.nth; + adat->c.jd = bdat->c.jd; + adat->c.df = bdat->c.df; + adat->c.sf = bdat->c.sf; + adat->c.of = bdat->c.of; + adat->c.sg = bdat->c.sg; + adat->c.year = bdat->c.year; +#ifndef USE_PACK + adat->c.mon = bdat->c.mon; + adat->c.mday = bdat->c.mday; + adat->c.hour = bdat->c.hour; + adat->c.min = bdat->c.min; + adat->c.sec = bdat->c.sec; +#else + adat->c.pd = bdat->c.pd; +#endif + adat->c.flags = bdat->c.flags | COMPLEX_DAT; + } + } + return copy; +} + +/* + * call-seq: + * d.ajd + * + * Get the date as an Astronomical Julian Day Number. + */ +static VALUE +d_lite_ajd(VALUE self) +{ + get_d1(self); + return m_ajd(dat); } /* @@ -3695,13 +4264,24 @@ d_right_amjd(VALUE self) static VALUE d_lite_amjd(VALUE self) { + VALUE r, sf; + int df; + get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(amjd); - { - get_d_jd(dat); - return rb_rational_new1(LONG2NUM(dat->l.jd - 2400001L)); - } + + r = rb_rational_new1(f_sub(m_real_jd(dat), INT2FIX(2400001))); + + if (simple_dat_p(dat)) + return r; + + df = m_df(dat); + if (df) + r = f_add(r, isec_to_day(df)); + + sf = m_sf(dat); + if (f_nonzero_p(sf)) + r = f_add(r, ns_to_day(sf)); + return r; } #define return_once(k, expr)\ @@ -3717,20 +4297,6 @@ d_lite_amjd(VALUE self) return val;\ } -static VALUE -d_right_daynum(VALUE self) -{ - get_d1(self); - assert(!light_mode_p(dat)); - return_once(daynum, rt_ajd_to_jd(dat->r.ajd, dat->r.of)); -} - -static VALUE -d_right_jd(VALUE self) -{ - return RARRAY_PTR(c_iforward0(daynum))[0]; -} - /* * call-seq: * d.jd @@ -3741,20 +4307,7 @@ static VALUE d_lite_jd(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(jd); - { - get_d_jd(dat); - return INT2FIX(dat->l.jd); - } -} - -static VALUE -d_right_mjd(VALUE self) -{ - get_d1(self); - assert(!light_mode_p(dat)); - return rt_jd_to_mjd(d_right_jd(self)); + return m_real_local_jd(dat); } /* @@ -3767,20 +4320,7 @@ static VALUE d_lite_mjd(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(mjd); - { - get_d_jd(dat); - return LONG2NUM(dat->l.jd - 2400001L); - } -} - -static VALUE -d_right_ld(VALUE self) -{ - get_d1(self); - assert(!light_mode_p(dat)); - return rt_jd_to_ld(d_right_jd(self)); + return f_sub(m_real_local_jd(dat), INT2FIX(2400001)); } /* @@ -3793,26 +4333,7 @@ static VALUE d_lite_ld(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(ld); - { - get_d_jd(dat); - return LONG2NUM(dat->l.jd - 2299160L); - } -} - -static VALUE -d_right_civil(VALUE self) -{ - get_d1(self); - assert(!light_mode_p(dat)); - return_once(civil, rt_jd_to_civil(d_right_jd(self), dat->r.sg)); -} - -static VALUE -d_right_year(VALUE self) -{ - return RARRAY_PTR(c_iforward0(civil))[0]; + return f_sub(m_real_local_jd(dat), INT2FIX(2299160)); } /* @@ -3825,37 +4346,7 @@ static VALUE d_lite_year(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(year); - { - get_d_civil(dat); - return INT2FIX(dat->l.year); - } -} - -static VALUE -d_right_ordinal(VALUE self) -{ - get_d1(self); - assert(!light_mode_p(dat)); - return_once(ordinal, rt_jd_to_ordinal(d_right_jd(self), dat->r.sg)); -} - -static VALUE -d_right_yday(VALUE self) -{ - return RARRAY_PTR(c_iforward0(ordinal))[1]; -} - -static const int yeartab[2][13] = { - { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }, - { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 } -}; - -static int -civil_to_yday(int y, int m, int d) -{ - return yeartab[leap_p(y) ? 1 : 0][m] + d; + return m_real_year(dat); } /* @@ -3870,18 +4361,7 @@ static VALUE d_lite_yday(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(yday); - { - get_d_civil(dat); - return INT2FIX(civil_to_yday(dat->l.year, dat->l.mon, dat->l.mday)); - } -} - -static VALUE -d_right_mon(VALUE self) -{ - return RARRAY_PTR(c_iforward0(civil))[1]; + return INT2FIX(m_yday(dat)); } /* @@ -3897,18 +4377,7 @@ static VALUE d_lite_mon(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(mon); - { - get_d_civil(dat); - return INT2FIX(dat->l.mon); - } -} - -static VALUE -d_right_mday(VALUE self) -{ - return RARRAY_PTR(c_iforward0(civil))[2]; + return INT2FIX(m_mon(dat)); } /* @@ -3922,18 +4391,7 @@ static VALUE d_lite_mday(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(mday); - { - get_d_civil(dat); - return INT2FIX(dat->l.mday); - } -} - -static VALUE -d_right_day_fraction(VALUE self) -{ - return RARRAY_PTR(c_iforward0(daynum))[1]; + return INT2FIX(m_mday(dat)); } /* @@ -3946,24 +4404,9 @@ static VALUE d_lite_day_fraction(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(day_fraction); - return INT2FIX(0); -} - -static VALUE -d_right_weeknum0(VALUE self) -{ - get_d1(self); - assert(!light_mode_p(dat)); - return_once(weeknum0, rt_jd_to_weeknum(d_right_jd(self), - INT2FIX(0), dat->r.sg)); -} - -static VALUE -d_right_wnum0(VALUE self) -{ - return RARRAY_PTR(c_iforward0(weeknum0))[1]; + if (simple_dat_p(dat)) + return INT2FIX(0); + return m_fr(dat); } static VALUE @@ -3972,28 +4415,9 @@ d_lite_wnum0(VALUE self) int ry, rw, rd; get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(wnum0); - { - get_d_jd(dat); - jd_to_weeknum(dat->l.jd, 0, dat->l.sg, &ry, &rw, &rd); - return INT2FIX(rw); - } -} - -static VALUE -d_right_weeknum1(VALUE self) -{ - get_d1(self); - assert(!light_mode_p(dat)); - return_once(weeknum1, rt_jd_to_weeknum(d_right_jd(self), - INT2FIX(1), dat->r.sg)); -} - -static VALUE -d_right_wnum1(VALUE self) -{ - return RARRAY_PTR(c_iforward0(weeknum1))[1]; + c_jd_to_weeknum(m_local_jd(dat), 0, m_sg(dat), + &ry, &rw, &rd); + return INT2FIX(rw); } static VALUE @@ -4002,52 +4426,9 @@ d_lite_wnum1(VALUE self) int ry, rw, rd; get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(wnum1); - { - get_d_jd(dat); - jd_to_weeknum(dat->l.jd, 1, dat->l.sg, &ry, &rw, &rd); - return INT2FIX(rw); - } -} - -#ifndef NDEBUG -static VALUE -d_right_time(VALUE self) -{ - get_d1(self); - assert(!light_mode_p(dat)); - return_once(time, rt_day_fraction_to_time(d_right_day_fraction(self))); -} -#endif - -static VALUE -d_right_time_wo_sf(VALUE self) -{ - get_d1(self); - assert(!light_mode_p(dat)); - return_once(time_wo_sf, - rt_day_fraction_to_time_wo_sf(d_right_day_fraction(self))); -} - -static VALUE -d_right_time_sf(VALUE self) -{ - get_d1(self); - assert(!light_mode_p(dat)); - return_once(time_sf, f_mul(f_mod(d_right_day_fraction(self), - SECONDS_IN_DAY), - INT2FIX(DAY_IN_SECONDS))); -} - -static VALUE -d_right_hour(VALUE self) -{ -#if 0 - return RARRAY_PTR(c_iforward0(time))[0]; -#else - return RARRAY_PTR(c_iforward0(time_wo_sf))[0]; -#endif + c_jd_to_weeknum(m_local_jd(dat), 1, m_sg(dat), + &ry, &rw, &rd); + return INT2FIX(rw); } /* @@ -4060,19 +4441,7 @@ static VALUE d_lite_hour(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(hour); - return INT2FIX(0); -} - -static VALUE -d_right_min(VALUE self) -{ -#if 0 - return RARRAY_PTR(c_iforward0(time))[1]; -#else - return RARRAY_PTR(c_iforward0(time_wo_sf))[1]; -#endif + return INT2FIX(m_hour(dat)); } /* @@ -4086,19 +4455,7 @@ static VALUE d_lite_min(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(min); - return INT2FIX(0); -} - -static VALUE -d_right_sec(VALUE self) -{ -#if 0 - return RARRAY_PTR(c_iforward0(time))[2]; -#else - return RARRAY_PTR(c_iforward0(time_wo_sf))[2]; -#endif + return INT2FIX(m_min(dat)); } /* @@ -4112,19 +4469,7 @@ static VALUE d_lite_sec(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(sec); - return INT2FIX(0); -} - -static VALUE -d_right_sec_fraction(VALUE self) -{ -#if 0 - return RARRAY_PTR(c_iforward0(time))[3]; -#else - return c_iforward0(time_sf); -#endif + return INT2FIX(m_sec(dat)); } /* @@ -4138,9 +4483,7 @@ static VALUE d_lite_sec_fraction(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(sec_fraction); - return INT2FIX(0); + return m_sf_in_sec(dat); } /* @@ -4153,39 +4496,7 @@ static VALUE d_lite_offset(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return dat->r.of; - return INT2FIX(0); -} - -static VALUE -d_right_zone(VALUE self) -{ - get_d1(self); - assert(!light_mode_p(dat)); - { - int sign; - VALUE hh, mm, ss, fr; - - if (f_negative_p(dat->r.of)) { - sign = '-'; - fr = f_abs(dat->r.of); - } - else { - sign = '+'; - fr = dat->r.of; - } - ss = f_div(fr, SECONDS_IN_DAY); - - hh = f_idiv(ss, INT2FIX(HOUR_IN_SECONDS)); - ss = f_mod(ss, INT2FIX(HOUR_IN_SECONDS)); - - mm = f_idiv(ss, INT2FIX(MINUTE_IN_SECONDS)); - - return rb_enc_sprintf(rb_usascii_encoding(), - "%c%02d:%02d", - sign, NUM2INT(hh), NUM2INT(mm)); - } + return m_of_in_day(dat); } /* @@ -4198,23 +4509,7 @@ static VALUE d_lite_zone(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(zone); - return rb_usascii_str_new2("+00:00"); -} - -static VALUE -d_right_commercial(VALUE self) -{ - get_d1(self); - assert(!light_mode_p(dat)); - return_once(commercial, rt_jd_to_commercial(d_right_jd(self), dat->r.sg)); -} - -static VALUE -d_right_cwyear(VALUE self) -{ - return RARRAY_PTR(c_iforward0(commercial))[0]; + return m_zone(dat); } /* @@ -4228,21 +4523,13 @@ static VALUE d_lite_cwyear(VALUE self) { int ry, rw, rd; + VALUE ry2; get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(cwyear); - { - get_d_jd(dat); - jd_to_commercial(dat->l.jd, dat->l.sg, &ry, &rw, &rd); - return INT2FIX(ry); - } -} - -static VALUE -d_right_cweek(VALUE self) -{ - return RARRAY_PTR(c_iforward0(commercial))[1]; + c_jd_to_commercial(m_local_jd(dat), m_sg(dat), + &ry, &rw, &rd); + encode_year(m_nth(dat), ry, +1, &ry2); + return ry2; } /* @@ -4257,19 +4544,9 @@ d_lite_cweek(VALUE self) int ry, rw, rd; get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(cweek); - { - get_d_jd(dat); - jd_to_commercial(dat->l.jd, dat->l.sg, &ry, &rw, &rd); - return INT2FIX(rw); - } -} - -static VALUE -d_right_cwday(VALUE self) -{ - return RARRAY_PTR(c_iforward0(commercial))[2]; + c_jd_to_commercial(m_local_jd(dat), m_sg(dat), + &ry, &rw, &rd); + return INT2FIX(rw); } /* @@ -4285,21 +4562,10 @@ d_lite_cwday(VALUE self) int w; get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(cwday); - { - get_d_jd(dat); - w = jd_to_wday(dat->l.jd); - if (w == 0) - w = 7; - return INT2FIX(w); - } -} - -static VALUE -d_right_wday(VALUE self) -{ - return rt_jd_to_wday(d_right_jd(self)); + w = m_wday(dat); + if (w == 0) + w = 7; + return INT2FIX(w); } /* @@ -4313,12 +4579,7 @@ static VALUE d_lite_wday(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(wday); - { - get_d_jd(dat); - return INT2FIX(jd_to_wday(dat->l.jd)); - } + return INT2FIX(m_wday(dat)); } /* @@ -4330,7 +4591,8 @@ d_lite_wday(VALUE self) static VALUE d_lite_sunday_p(VALUE self) { - return f_eqeq_p(d_lite_wday(self), INT2FIX(0)); + get_d1(self); + return f_boolcast(m_wday(dat) == 0); } /* @@ -4342,7 +4604,8 @@ d_lite_sunday_p(VALUE self) static VALUE d_lite_monday_p(VALUE self) { - return f_eqeq_p(d_lite_wday(self), INT2FIX(1)); + get_d1(self); + return f_boolcast(m_wday(dat) == 1); } /* @@ -4354,7 +4617,8 @@ d_lite_monday_p(VALUE self) static VALUE d_lite_tuesday_p(VALUE self) { - return f_eqeq_p(d_lite_wday(self), INT2FIX(2)); + get_d1(self); + return f_boolcast(m_wday(dat) == 2); } /* @@ -4366,7 +4630,8 @@ d_lite_tuesday_p(VALUE self) static VALUE d_lite_wednesday_p(VALUE self) { - return f_eqeq_p(d_lite_wday(self), INT2FIX(3)); + get_d1(self); + return f_boolcast(m_wday(dat) == 3); } /* @@ -4378,7 +4643,8 @@ d_lite_wednesday_p(VALUE self) static VALUE d_lite_thursday_p(VALUE self) { - return f_eqeq_p(d_lite_wday(self), INT2FIX(4)); + get_d1(self); + return f_boolcast(m_wday(dat) == 4); } /* @@ -4390,7 +4656,8 @@ d_lite_thursday_p(VALUE self) static VALUE d_lite_friday_p(VALUE self) { - return f_eqeq_p(d_lite_wday(self), INT2FIX(5)); + get_d1(self); + return f_boolcast(m_wday(dat) == 5); } /* @@ -4402,30 +4669,29 @@ d_lite_friday_p(VALUE self) static VALUE d_lite_saturday_p(VALUE self) { - return f_eqeq_p(d_lite_wday(self), INT2FIX(6)); + get_d1(self); + return f_boolcast(m_wday(dat) == 6); } #ifndef NDEBUG static VALUE generic_nth_kday_p(VALUE self, VALUE n, VALUE k) { - if (f_eqeq_p(k, f_wday(self)) && - f_equal_p(f_jd(self), rt_nth_kday_to_jd(f_year(self), - f_mon(self), - n, k, - f_start(self)))) - return Qtrue; - return Qfalse; -} -#endif + int rjd, ns; -static VALUE -d_right_julian_p(VALUE self) -{ get_d1(self); - assert(!light_mode_p(dat)); - return f_lt_p(d_right_jd(self), dat->r.sg); + + if (NUM2INT(k) != m_wday(dat)) + return Qfalse; + + c_nth_kday_to_jd(m_year(dat), m_mon(dat), + NUM2INT(n), NUM2INT(k), m_sg(dat), + &rjd, &ns); + if (m_local_jd(dat) != rjd) + return Qfalse; + return Qtrue; } +#endif /* * call-seq: @@ -4437,17 +4703,7 @@ static VALUE d_lite_julian_p(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(julian_p); - return Qfalse; -} - -static VALUE -d_right_gregorian_p(VALUE self) -{ - get_d1(self); - assert(!light_mode_p(dat)); - return d_right_julian_p(self) ? Qfalse : Qtrue; + return f_boolcast(m_julian_p(dat)); } /* @@ -4460,33 +4716,10 @@ static VALUE d_lite_gregorian_p(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(gregorian_p); - return Qtrue; + return f_boolcast(m_gregorian_p(dat)); } -static VALUE -d_right_fix_style(VALUE self) -{ - if (d_right_julian_p(self)) - return DBL2NUM(JULIAN); - return DBL2NUM(GREGORIAN); -} - -static VALUE -d_right_leap_p(VALUE self) -{ - VALUE style, a; - - style = d_right_fix_style(self); - a = rt_jd_to_civil(f_sub(rt_civil_to_jd(d_right_year(self), - INT2FIX(3), INT2FIX(1), style), - INT2FIX(1)), - style); - if (f_eqeq_p(RARRAY_PTR(a)[2], INT2FIX(29))) - return Qtrue; - return Qfalse; -} +#define fix_style(dat) (m_julian_p(dat) ? JULIAN : GREGORIAN) /* * call-seq: @@ -4497,13 +4730,18 @@ d_right_leap_p(VALUE self) static VALUE d_lite_leap_p(VALUE self) { + double sg; + int rjd, ns, ry, rm, rd; + get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(leap_p); - { - get_d_civil(dat); - return leap_p(dat->l.year) ? Qtrue : Qfalse; - } + sg = m_sg(dat); + if (isinf(sg) && sg < 0) + return f_boolcast(c_leap_p(m_year(dat))); + + c_civil_to_jd(m_year(dat), 3, 1, fix_style(dat), + &rjd, &ns); + c_jd_to_civil(rjd - 1, fix_style(dat), &ry, &rm, &rd); + return f_boolcast(rd == 29); } /* @@ -4516,19 +4754,61 @@ static VALUE d_lite_start(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return dat->r.sg; - return DBL2NUM(dat->l.sg); + return DBL2NUM(m_sg(dat)); +} + +static void +clear_civil(union DateData *x) +{ + if (simple_dat_p(x)) { + x->s.year = 0; +#ifndef USE_PACK + x->s.mon = 0; + x->s.mday = 0; +#else + x->s.pd = 0; +#endif + x->s.flags &= ~HAVE_CIVIL; + } + else { + x->c.year = 0; +#ifndef USE_PACK + x->c.mon = 0; + x->c.mday = 0; + x->c.hour = 0; + x->c.min = 0; + x->c.sec = 0; +#else + x->c.pd = 0; +#endif + x->c.flags &= ~(HAVE_CIVIL | HAVE_TIME); + } +} + +static void +set_sg(union DateData *x, double sg) +{ + if (simple_dat_p(x)) { + get_s_jd(x); + clear_civil(x); + x->s.sg = sg; + } else { + get_c_jd(x); + get_c_df(x); + clear_civil(x); + x->c.sg = sg; + } } static VALUE -d_right_new_start(int argc, VALUE *argv, VALUE self) +copy_obj_with_new_start(VALUE obj, double sg) { - get_d1(self); - return d_right_new(CLASS_OF(self), - d_lite_ajd(self), - d_lite_offset(self), - (argc >= 1) ? argv[0] : INT2FIX(ITALY)); + VALUE copy = copy_obj(obj); + { + get_d1(copy); + set_sg(dat, sg); + } + return copy; } /* @@ -4543,28 +4823,13 @@ d_lite_new_start(int argc, VALUE *argv, VALUE self) VALUE vsg; double sg; - get_d1(self); - - if (!light_mode_p(dat)) - return c_iforwardv(new_start); - rb_scan_args(argc, argv, "01", &vsg); - sg = ITALY; + sg = DEFAULT_SG; if (argc >= 1) - sg = NUM2DBL(vsg); + val2sg(vsg, sg); - { - get_d_jd(dat); - - if (dat->l.jd < sg) - return c_iforwardv(new_start); - - return d_lite_new_internal_wo_civil(CLASS_OF(self), - dat->l.jd, - sg, - HAVE_JD); - } + return copy_obj_with_new_start(self, sg); } /* @@ -4577,9 +4842,7 @@ d_lite_new_start(int argc, VALUE *argv, VALUE self) static VALUE d_lite_italy(VALUE self) { - VALUE argv[1]; - argv[0] = INT2FIX(ITALY); - return d_lite_new_start(1, argv, self); + return copy_obj_with_new_start(self, ITALY); } /* @@ -4592,9 +4855,7 @@ d_lite_italy(VALUE self) static VALUE d_lite_england(VALUE self) { - VALUE argv[1]; - argv[0] = INT2FIX(ENGLAND); - return d_lite_new_start(1, argv, self); + return copy_obj_with_new_start(self, ENGLAND); } /* @@ -4607,9 +4868,7 @@ d_lite_england(VALUE self) static VALUE d_lite_julian(VALUE self) { - VALUE argv[1]; - argv[0] = DBL2NUM(JULIAN); - return d_lite_new_start(1, argv, self); + return copy_obj_with_new_start(self, JULIAN); } /* @@ -4622,36 +4881,36 @@ d_lite_julian(VALUE self) static VALUE d_lite_gregorian(VALUE self) { - VALUE argv[1]; - argv[0] = DBL2NUM(GREGORIAN); - return d_lite_new_start(1, argv, self); + return copy_obj_with_new_start(self, GREGORIAN); } -static VALUE -sof2nof(VALUE of) +static void +set_of(union DateData *x, int of) { - if (TYPE(of) == T_STRING) { - VALUE n = date_zone_to_diff(of); - if (NIL_P(n)) - of = INT2FIX(0); - else - of = rb_rational_new2(n, INT2FIX(DAY_IN_SECONDS)); - } - else if (TYPE(of) == T_FLOAT) { - of = rb_rational_new2(f_truncate(f_mul(of, INT2FIX(DAY_IN_SECONDS))), - INT2FIX(DAY_IN_SECONDS)); - } - return of; + assert(complex_dat_p(x)); + get_c_jd(x); + get_c_df(x); + clear_civil(x); + x->c.of = of; } static VALUE -d_right_new_offset(int argc, VALUE *argv, VALUE self) +copy_obj_with_new_offset(VALUE obj, int of) { - get_d1(self); - return d_right_new(CLASS_OF(self), - d_lite_ajd(self), - (argc >= 1) ? sof2nof(argv[0]) : INT2FIX(0), - d_lite_start(self)); + VALUE copy = copy_obj_as_complex(obj); + { + get_d1(copy); + set_of(dat, of); + } + return copy; +} + +#define val2off(vof,iof) \ +{\ + if (!offset_to_sec(vof, &iof)) {\ + iof = 0;\ + rb_warning("invalid offset is ignored");\ + }\ } /* @@ -4666,45 +4925,13 @@ d_lite_new_offset(int argc, VALUE *argv, VALUE self) VALUE vof; int rof; - get_d1(self); - - if (!light_mode_p(dat)) - return c_iforwardv(new_offset); - rb_scan_args(argc, argv, "01", &vof); - if (NIL_P(vof)) - rof = 0; - else { - vof = sof2nof(vof); - if (!daydiff_to_sec(vof, &rof) || rof != 0) - return c_iforwardv(new_offset); - } - - { - get_d_jd(dat); - - return d_lite_new_internal_wo_civil(CLASS_OF(self), - dat->l.jd, - dat->l.sg, - HAVE_JD); - } -} + rof = 0; + if (argc >= 1) + val2off(vof, rof); -static VALUE -d_right_plus(VALUE self, VALUE other) -{ - if (k_numeric_p(other)) { - get_d1(self); - if (TYPE(other) == T_FLOAT) - other = rb_rational_new2(f_round(f_mul(other, day_in_nanoseconds)), - day_in_nanoseconds); - return d_right_new(CLASS_OF(self), - f_add(d_lite_ajd(self), other), - d_lite_offset(self), - d_lite_start(self)); - } - rb_raise(rb_eTypeError, "expected numeric"); + return copy_obj_with_new_offset(self, rof); } /* @@ -4726,79 +4953,305 @@ d_lite_plus(VALUE self, VALUE other) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforwardop(plus); - switch (TYPE(other)) { case T_FIXNUM: { - long jd; + VALUE nth; + long t; + int jd; + + nth = m_nth(dat); + t = FIX2LONG(other); + if (DIV(t, CM_PERIOD)) { + nth = f_add(nth, INT2FIX(DIV(t, CM_PERIOD))); + t = MOD(t, CM_PERIOD); + } + jd = m_jd(dat) + (int)t; - get_d_jd(dat); + if (jd < 0) { + nth = f_sub(nth, INT2FIX(1)); + jd += CM_PERIOD; + } + else if (jd >= CM_PERIOD) { + nth = f_add(nth, INT2FIX(1)); + jd -= CM_PERIOD; + } - jd = dat->l.jd + FIX2LONG(other); + if (simple_dat_p(dat)) + return d_simple_new_internal(CLASS_OF(self), + nth, jd, + m_sg(dat), + 0, 0, 0, + (dat->s.flags | HAVE_JD) & + ~HAVE_CIVIL); + else + return d_complex_new_internal(CLASS_OF(self), + nth, jd, + m_df(dat), m_sf(dat), + m_of(dat), m_sg(dat), + 0, 0, 0, + m_hour(dat), + m_min(dat), + m_sec(dat), + (dat->c.flags | HAVE_JD) & + ~HAVE_CIVIL); + } + break; + case T_BIGNUM: + { + VALUE nth; + int jd, s; - if (LIGHTABLE_JD(jd) && jd >= dat->l.sg) - return d_lite_new_internal(CLASS_OF(self), - jd, dat->l.sg, - 0, 0, 0, - (dat->l.flags | HAVE_JD) & - ~HAVE_CIVIL); + if (f_positive_p(other)) + s = +1; + else { + s = -1; + other = f_negate(other); + } + + nth = f_idiv(other, INT2FIX(CM_PERIOD)); + jd = FIX2INT(f_mod(other, INT2FIX(CM_PERIOD))); + + if (s < 0) { + nth = f_negate(nth); + jd = -jd; + } + + jd = m_jd(dat) + jd; + if (jd < 0) { + nth = f_sub(nth, INT2FIX(1)); + jd += CM_PERIOD; + } + else if (jd >= CM_PERIOD) { + nth = f_add(nth, INT2FIX(1)); + jd -= CM_PERIOD; + } + nth = f_add(m_nth(dat), nth); + + if (simple_dat_p(dat)) + return d_simple_new_internal(CLASS_OF(self), + nth, jd, + m_sg(dat), + 0, 0, 0, + (dat->s.flags | HAVE_JD) & + ~HAVE_CIVIL); + else + return d_complex_new_internal(CLASS_OF(self), + nth, jd, + m_df(dat), m_sf(dat), + m_of(dat), m_sg(dat), + 0, 0, 0, + m_hour(dat), + m_min(dat), + m_sec(dat), + (dat->c.flags | HAVE_JD) & + ~HAVE_CIVIL); } break; case T_FLOAT: { - double d = NUM2DBL(other); - long l = round(d); - if (l == d && LIGHTABLE_JD(l)) - return d_lite_plus(self, INT2FIX(l)); + double jd, o, tmp; + int s, df; + VALUE nth, sf; + + o = NUM2DBL(other); + + if (o > 0) + s = +1; + else { + s = -1; + o = -o; + } + + o = modf(o, &tmp); + + if (!floor(tmp / CM_PERIOD)) { + nth = INT2FIX(0); + jd = (int)tmp; + } + else { + double i, f; + + f = modf(tmp / CM_PERIOD, &i); + nth = f_floor(DBL2NUM(i)); + jd = (int)(f * CM_PERIOD); + } + + o *= DAY_IN_SECONDS; + o = modf(o, &tmp); + df = (int)tmp; + o *= SECOND_IN_NANOSECONDS; + sf = INT2FIX((int)round(o)); + + if (s < 0) { + jd = -jd; + df = -df; + sf = f_negate(sf); + } + + sf = f_add(m_sf(dat), sf); + if (f_lt_p(sf, INT2FIX(0))) { + df -= 1; + sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS)); + } + else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) { + df += 1; + sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS)); + } + + df = m_df(dat) + df; + if (df < 0) { + jd -= 1; + df += DAY_IN_SECONDS; + } + else if (df >= DAY_IN_SECONDS) { + jd += 1; + df -= DAY_IN_SECONDS; + } + + jd = m_jd(dat) + jd; + if (jd < 0) { + nth = f_sub(nth, INT2FIX(1)); + jd += CM_PERIOD; + } + else if (jd >= CM_PERIOD) { + nth = f_add(nth, INT2FIX(1)); + jd -= CM_PERIOD; + } + nth = f_add(m_nth(dat), nth); + + if (!df && f_zero_p(sf) && !m_of(dat)) + return d_simple_new_internal(CLASS_OF(self), + nth, jd, + m_sg(dat), + 0, 0, 0, + (dat->s.flags | HAVE_JD) & + ~(HAVE_CIVIL | HAVE_TIME | + COMPLEX_DAT)); + else + return d_complex_new_internal(CLASS_OF(self), + nth, jd, + df, sf, + m_of(dat), m_sg(dat), + 0, 0, 0, + 0, 0, 0, + (dat->c.flags | + HAVE_JD | HAVE_DF) & + ~(HAVE_CIVIL | HAVE_TIME)); } break; - } - return c_iforwardop(plus); -} + default: + if (!k_numeric_p(other)) + rb_raise(rb_eTypeError, "expected numeric"); + other = f_to_r(other); + case T_RATIONAL: + { + VALUE nth, sf, t; + int jd, df, s; -static VALUE -d_right_minus(VALUE self, VALUE other) -{ - if (k_numeric_p(other)) { - get_d1(self); - if (TYPE(other) == T_FLOAT) - other = rb_rational_new2(f_round(f_mul(other, day_in_nanoseconds)), - day_in_nanoseconds); - return d_right_new(CLASS_OF(self), - f_sub(d_lite_ajd(self), other), - d_lite_offset(self), - d_lite_start(self)); + if (f_positive_p(other)) + s = +1; + else { + s = -1; + other = f_negate(other); + } + nth = f_idiv(other, INT2FIX(CM_PERIOD)); + t = f_mod(other, INT2FIX(CM_PERIOD)); + + jd = FIX2INT(f_idiv(t, INT2FIX(1))); + t = f_mod(t, INT2FIX(1)); + + t = f_mul(t, INT2FIX(DAY_IN_SECONDS)); + df = FIX2INT(f_idiv(t, INT2FIX(1))); + t = f_mod(t, INT2FIX(1)); + + sf = f_mul(t, INT2FIX(SECOND_IN_NANOSECONDS)); + + if (s < 0) { + nth = f_negate(nth); + jd = -jd; + df = -df; + sf = f_negate(sf); + } + + sf = f_add(m_sf(dat), sf); + if (f_lt_p(sf, INT2FIX(0))) { + df -= 1; + sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS)); + } + else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) { + df += 1; + sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS)); + } + + df = m_df(dat) + df; + if (df < 0) { + jd -= 1; + df += DAY_IN_SECONDS; + } + else if (df >= DAY_IN_SECONDS) { + jd += 1; + df -= DAY_IN_SECONDS; + } + + jd = m_jd(dat) + jd; + if (jd < 0) { + nth = f_sub(nth, INT2FIX(1)); + jd += CM_PERIOD; + } + else if (jd >= CM_PERIOD) { + nth = f_add(nth, INT2FIX(1)); + jd -= CM_PERIOD; + } + nth = f_add(m_nth(dat), nth); + + if (!df && f_zero_p(sf) && !m_of(dat)) + return d_simple_new_internal(CLASS_OF(self), + nth, jd, + m_sg(dat), + 0, 0, 0, + (dat->s.flags | HAVE_JD) & + ~(HAVE_CIVIL | HAVE_TIME | + COMPLEX_DAT)); + else + return d_complex_new_internal(CLASS_OF(self), + nth, jd, + df, sf, + m_of(dat), m_sg(dat), + 0, 0, 0, + 0, 0, 0, + (dat->c.flags | + HAVE_JD | HAVE_DF) & + ~(HAVE_CIVIL | HAVE_TIME)); + } + break; } - else if (k_date_p(other)) { - return f_sub(d_lite_ajd(self), f_ajd(other)); - } - rb_raise(rb_eTypeError, "expected numeric"); } -static VALUE dt_right_minus(VALUE, VALUE); - static VALUE minus_dd(VALUE self, VALUE other) { - get_dt2_cast(self, other); + get_d2(self, other); - if (light_mode_p(adat) && - light_mode_p(bdat)) { - long d, sf; - int df; - VALUE r; + { + int d, df; + VALUE n, sf, r; - get_dt_jd(adat); - get_dt_jd(bdat); - get_dt_df(adat); - get_dt_df(bdat); + n = f_sub(m_nth(adat), m_nth(bdat)); + d = m_jd(adat) - m_jd(bdat); + df = m_df(adat) - m_df(bdat); + sf = f_sub(m_sf(adat), m_sf(bdat)); + + if (d < 0) { + n = f_sub(n, INT2FIX(1)); + d += CM_PERIOD; + } + else if (d >= CM_PERIOD) { + n = f_add(n, INT2FIX(1)); + d -= CM_PERIOD; + } - d = adat->l.jd - bdat->l.jd; - df = adat->l.df - bdat->l.df; - sf = adat->l.sf - bdat->l.sf; if (df < 0) { d -= 1; df += DAY_IN_SECONDS; @@ -4807,25 +5260,32 @@ minus_dd(VALUE self, VALUE other) d += 1; df -= DAY_IN_SECONDS; } - if (sf < 0) { + + if (f_lt_p(sf, INT2FIX(0))) { df -= 1; - sf += SECOND_IN_NANOSECONDS; + sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS)); } - else if (sf >= SECOND_IN_NANOSECONDS) { + else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) { df += 1; - sf -= SECOND_IN_NANOSECONDS; + sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS)); } - r = rb_rational_new1(LONG2NUM(d)); + + if (f_zero_p(n)) + r = INT2FIX(0); + else + r = f_mul(n, INT2FIX(CM_PERIOD)); + + if (d) + r = f_add(r, rb_rational_new1(INT2FIX(d))); if (df) - r = f_add(r, rb_rational_new2(INT2FIX(df), - INT2FIX(DAY_IN_SECONDS))); - if (sf) - r = f_add(r, rb_rational_new2(LONG2NUM(sf), day_in_nanoseconds)); - return r; + r = f_add(r, isec_to_day(df)); + if (f_nonzero_p(sf)) + r = f_add(r, ns_to_day(sf)); + + if (TYPE(r) == T_RATIONAL) + return r; + return rb_rational_new1(r); } - if (!k_datetime_p(self)) - return d_right_minus(self, other); - return dt_right_minus(self, other); } /* @@ -4844,32 +5304,19 @@ minus_dd(VALUE self, VALUE other) static VALUE d_lite_minus(VALUE self, VALUE other) { - if (k_datetime_p(other)) + if (k_date_p(other)) return minus_dd(self, other); - assert(!k_datetime_p(other)); - if (k_date_p(other)) { - get_d2(self, other); - - if (light_mode_p(adat) && - light_mode_p(bdat)) { - long d; - - get_d_jd(adat); - get_d_jd(bdat); - - d = adat->l.jd - bdat->l.jd; - return rb_rational_new1(LONG2NUM(d)); - } - } - switch (TYPE(other)) { case T_FIXNUM: return d_lite_plus(self, LONG2NUM(-FIX2LONG(other))); case T_FLOAT: return d_lite_plus(self, DBL2NUM(-NUM2DBL(other))); + default: + if (!k_numeric_p(other)) + rb_raise(rb_eTypeError, "expected numeric"); + return d_lite_plus(self, f_negate(other)); } - return c_iforwardop(minus); } /* @@ -4932,23 +5379,32 @@ d_lite_next(VALUE self) static VALUE d_lite_rshift(VALUE self, VALUE other) { - VALUE t, y, m, d, sg, j; + VALUE t, y, nth, rjd2; + int m, d, rjd; + double sg; - t = f_add3(f_mul(d_lite_year(self), INT2FIX(12)), - f_sub(d_lite_mon(self), INT2FIX(1)), + get_d1(self); + t = f_add3(f_mul(m_real_year(dat), INT2FIX(12)), + f_sub(INT2FIX(m_mon(dat)), INT2FIX(1)), other); y = f_idiv(t, INT2FIX(12)); - m = f_mod(t, INT2FIX(12)); - m = f_add(m, INT2FIX(1)); - d = d_lite_mday(self); - sg = d_lite_start(self); - - while (NIL_P(j = rt__valid_civil_p(y, m, d, sg))) { - d = f_sub(d, INT2FIX(1)); - if (f_lt_p(d, INT2FIX(1))) + t = f_mod(t, INT2FIX(12)); + m = FIX2INT(f_add(t, INT2FIX(1))); + d = m_mday(dat); + sg = m_sg(dat); + + while (1) { + int ry, rm, rd, ns; + + if (valid_civil_p(y, m, d, sg, + &nth, &ry, + &rm, &rd, &rjd, &ns)) + break; + if (--d < 1) rb_raise(rb_eArgError, "invalid date"); } - return f_add(self, f_sub(j, d_lite_jd(self))); + encode_jd(nth, rjd, &rjd2); + return f_add(self, f_sub(rjd2, m_real_local_jd(dat))); } /* @@ -5134,61 +5590,70 @@ generic_downto(VALUE self, VALUE min) } static VALUE -d_right_cmp(VALUE self, VALUE other) +cmp_gen(VALUE self, VALUE other) { - if (k_numeric_p(other)) { - get_d1(self); - return f_cmp(d_lite_ajd(self), other); - } - else if (k_date_p(other)) { - return f_cmp(d_lite_ajd(self), f_ajd(other)); - } + get_d1(self); + + if (k_numeric_p(other)) + return f_cmp(m_ajd(dat), other); + else if (k_date_p(other)) + return f_cmp(m_ajd(dat), f_ajd(other)); return rb_num_coerce_cmp(self, other, rb_intern("<=>")); } -static VALUE dt_right_cmp(VALUE, VALUE); - static VALUE cmp_dd(VALUE self, VALUE other) { - get_dt2_cast(self, other); - - if (light_mode_p(adat) && - light_mode_p(bdat)) { - get_dt_jd(adat); - get_dt_jd(bdat); - get_dt_df(adat); - get_dt_df(bdat); + get_d2(self, other); - if (adat->l.jd == bdat->l.jd) { - if (adat->l.df == bdat->l.df) { - if (adat->l.sf == bdat->l.sf) { - return INT2FIX(0); + { + VALUE a_nth, b_nth, + a_sf, b_sf; + int a_jd, b_jd, + a_df, b_df; + + a_nth = m_nth(adat); + b_nth = m_nth(bdat); + if (f_eqeq_p(a_nth, b_nth)) { + a_jd = m_jd(adat); + b_jd = m_jd(bdat); + if (a_jd == b_jd) { + a_df = m_df(adat); + b_df = m_df(bdat); + if (a_df == b_df) { + a_sf = m_sf(adat); + b_sf = m_sf(bdat); + if (f_eqeq_p(a_sf, b_sf)) { + return INT2FIX(0); + } + else if (f_lt_p(a_sf, b_sf)) { + return INT2FIX(-1); + } + else { + return INT2FIX(1); + } } - else if (adat->l.sf < bdat->l.sf) { + else if (a_df < b_df) { return INT2FIX(-1); } else { return INT2FIX(1); } } - else if (adat->l.df < bdat->l.df) { + else if (a_jd < b_jd) { return INT2FIX(-1); } else { return INT2FIX(1); } } - else if (adat->l.jd < bdat->l.jd) { + else if (f_lt_p(a_nth, b_nth)) { return INT2FIX(-1); } else { return INT2FIX(1); } } - if (!k_datetime_p(self)) - return d_right_cmp(self, other); - return dt_right_cmp(self, other); } /* @@ -5210,92 +5675,124 @@ cmp_dd(VALUE self, VALUE other) static VALUE d_lite_cmp(VALUE self, VALUE other) { - if (k_datetime_p(other)) - return cmp_dd(self, other); + if (!k_date_p(other)) + return cmp_gen(self, other); - assert(!k_datetime_p(other)); - if (k_date_p(other)) { + { get_d2(self, other); - if (light_mode_p(adat) && - light_mode_p(bdat)) { - if (have_jd_p(adat) && - have_jd_p(bdat)) { - if (adat->l.jd == bdat->l.jd) + if (!(simple_dat_p(adat) && simple_dat_p(bdat) && + m_gregorian_p(adat) == m_gregorian_p(bdat))) + return cmp_dd(self, other); + + if (have_jd_p(adat) && + have_jd_p(bdat)) { + VALUE a_nth, b_nth; + int a_jd, b_jd; + + a_nth = m_nth(adat); + b_nth = m_nth(bdat); + if (f_eqeq_p(a_nth, b_nth)) { + a_jd = m_jd(adat); + b_jd = m_jd(bdat); + if (a_jd == b_jd) { return INT2FIX(0); - if (adat->l.jd < bdat->l.jd) + } + else if (a_jd < b_jd) { return INT2FIX(-1); - return INT2FIX(1); + } + else { + return INT2FIX(1); + } + } + else if (a_nth < b_nth) { + return INT2FIX(-1); } else { - get_d_civil(adat); - get_d_civil(bdat); + return INT2FIX(1); + } + } + else { +#ifndef USE_PACK + VALUE a_nth, b_nth; + int a_year, b_year, + a_mon, b_mon, + a_mday, b_mday; +#else + VALUE a_nth, b_nth; + int a_year, b_year, + a_pd, b_pd; +#endif - if (adat->l.year == bdat->l.year) { - if (adat->l.mon == bdat->l.mon) { - if (adat->l.mday == bdat->l.mday) { + a_nth = m_nth(adat); + b_nth = m_nth(bdat); + if (f_eqeq_p(a_nth, b_nth)) { + a_year = m_year(adat); + b_year = m_year(bdat); + if (a_year == b_year) { +#ifndef USE_PACK + a_mon = m_mon(adat); + b_mon = m_mon(bdat); + if (a_mon == b_mon) { + a_mday = m_mday(adat); + b_mday = m_mday(bdat); + if (a_mday == b_mday) { return INT2FIX(0); } - else if (adat->l.mday < bdat->l.mday) { + else if (a_mday < b_mday) { return INT2FIX(-1); } else { return INT2FIX(1); } } - else if (adat->l.mon < bdat->l.mon) { + else if (a_mon < b_mon) { + return INT2FIX(-1); + } + else { + return INT2FIX(1); + } +#else + a_pd = m_pd(adat); + b_pd = m_pd(bdat); + if (a_pd == b_pd) { + return INT2FIX(0); + } + else if (a_pd < b_pd) { return INT2FIX(-1); } else { return INT2FIX(1); } +#endif } - else if (adat->l.year < bdat->l.year) { + else if (a_year < b_year) { return INT2FIX(-1); } else { return INT2FIX(1); } } + else if (f_lt_p(a_nth, b_nth)) { + return INT2FIX(-1); + } + else { + return INT2FIX(1); + } } } - return c_iforwardop(cmp); } static VALUE -d_right_equal(VALUE self, VALUE other) +equal_gen(VALUE self, VALUE other) { - if (k_numeric_p(other)) { - get_d1(self); - return f_eqeq_p(d_lite_jd(self), other); - } - else if (k_date_p(other)) { - return f_eqeq_p(d_lite_jd(self), f_jd(other)); - } - return rb_num_coerce_cmp(self, other, rb_intern("==")); -} - -static VALUE dt_right_equal(VALUE, VALUE); - -static VALUE -equal_dd(VALUE self, VALUE other) -{ - get_dt2_cast(self, other); - - if (light_mode_p(adat) && - light_mode_p(bdat)) { - get_dt_jd(adat); - get_dt_jd(bdat); - get_dt_df(adat); - get_dt_df(bdat); + get_d1(self); - if (local_jd(adat) == local_jd(bdat)) - return Qtrue; - return Qfalse; - } - if (!k_datetime_p(self)) - return d_right_equal(self, other); - return dt_right_equal(self, other); + if (k_numeric_p(other)) + return f_eqeq_p(m_real_local_jd(dat), other); + else if (k_date_p(other)) + return f_eqeq_p(m_real_local_jd(dat), f_jd(other)); + return rb_num_coerce_cmp(self, other, rb_intern("==")); } /* @@ -5312,63 +5809,69 @@ equal_dd(VALUE self, VALUE other) static VALUE d_lite_equal(VALUE self, VALUE other) { - if (k_datetime_p(other)) - return equal_dd(self, other); + if (!k_date_p(other)) + return equal_gen(self, other); - assert(!k_datetime_p(other)); - if (k_date_p(other)) { + { get_d2(self, other); - if (light_mode_p(adat) && - light_mode_p(bdat)) { - if (have_jd_p(adat) && - have_jd_p(bdat)) { - if (adat->l.jd == bdat->l.jd) - return Qtrue; - return Qfalse; - } - else { - get_d_civil(adat); - get_d_civil(bdat); + if (!(m_gregorian_p(adat) == m_gregorian_p(bdat))) + return equal_gen(self, other); + + if (have_jd_p(adat) && + have_jd_p(bdat)) { + VALUE a_nth, b_nth; + int a_jd, b_jd; + + a_nth = m_nth(adat); + b_nth = m_nth(bdat); + a_jd = m_local_jd(adat); + b_jd = m_local_jd(bdat); + if (f_eqeq_p(a_nth, b_nth) && + a_jd == b_jd) + return Qtrue; + return Qfalse; + } + else { +#ifndef USE_PACK + VALUE a_nth, b_nth; + int a_year, b_year, + a_mon, b_mon, + a_mday, b_mday; +#else + VALUE a_nth, b_nth; + int a_year, b_year, + a_pd, b_pd; +#endif - if (adat->l.year == bdat->l.year) - if (adat->l.mon == bdat->l.mon) - if (adat->l.mday == bdat->l.mday) + a_nth = m_nth(adat); + b_nth = m_nth(bdat); + if (f_eqeq_p(a_nth, b_nth)) { + a_year = m_year(adat); + b_year = m_year(bdat); + if (a_year == b_year) { +#ifndef USE_PACK + a_mon = m_mon(adat); + b_mon = m_mon(bdat); + if (a_mon == b_mon) { + a_mday = m_mday(adat); + b_mday = m_mday(bdat); + if (a_mday == b_mday) return Qtrue; - return Qfalse; + } +#else + /* mon and mday only */ + a_pd = (m_pd(adat) >> MDAY_SHIFT); + b_pd = (m_pd(bdat) >> MDAY_SHIFT); + if (a_pd == b_pd) { + return Qtrue; + } +#endif + } } + return Qfalse; } } - return c_iforwardop(equal); -} - -static VALUE -d_right_eql_p(VALUE self, VALUE other) -{ - if (k_date_p(other) && f_eqeq_p(self, other)) - return Qtrue; - return Qfalse; -} - -static VALUE -eql_p_dd(VALUE self, VALUE other) -{ - get_dt2_cast(self, other); - - if (light_mode_p(adat) && - light_mode_p(bdat)) { - get_dt_jd(adat); - get_dt_jd(bdat); - get_dt_df(adat); - get_dt_df(bdat); - - if (adat->l.jd == bdat->l.jd) - if (adat->l.df == bdat->l.df) - if (adat->l.sf == bdat->l.sf) - return Qtrue; - return Qfalse; - } - return c_iforwardop(eql_p); } /* @@ -5382,42 +5885,9 @@ eql_p_dd(VALUE self, VALUE other) static VALUE d_lite_eql_p(VALUE self, VALUE other) { - if (k_datetime_p(other)) - return eql_p_dd(self, other); - - assert(!k_datetime_p(other)); - if (k_date_p(other)) { - get_d2(self, other); - - if (light_mode_p(adat) && - light_mode_p(bdat)) { - if (have_jd_p(adat) && - have_jd_p(bdat)) { - if (adat->l.jd == bdat->l.jd) - return Qtrue; - return Qfalse; - } - else { - get_d_civil(adat); - get_d_civil(bdat); - - if (adat->l.year == bdat->l.year) - if (adat->l.mon == bdat->l.mon) - if (adat->l.mday == bdat->l.mday) - return Qtrue; - return Qfalse; - } - } - } - return c_iforwardop(eql_p); -} - -static VALUE -d_right_hash(VALUE self) -{ - get_d1(self); - assert(!light_mode_p(dat)); - return rb_hash(dat->r.ajd); + if (!k_date_p(other)) + return Qfalse; + return f_zero_p(d_lite_cmp(self, other)); } /* @@ -5430,25 +5900,7 @@ static VALUE d_lite_hash(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(hash); - return rb_hash(d_lite_ajd(self)); -} - -static VALUE -d_right_to_s(VALUE self) -{ - VALUE a, argv[4]; - - get_d1(self); - assert(!light_mode_p(dat)); - - argv[0] = rb_usascii_str_new2("%.4d-%02d-%02d"); - a = d_right_civil(self); - argv[1] = RARRAY_PTR(a)[0]; - argv[2] = RARRAY_PTR(a)[1]; - argv[3] = RARRAY_PTR(a)[2]; - return rb_f_sprintf(4, argv); + return rb_hash(m_ajd(dat)); } /* @@ -5461,31 +5913,34 @@ static VALUE d_lite_to_s(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(to_s); - { - get_d_civil(dat); + + if (f_zero_p(m_nth(dat))) return rb_enc_sprintf(rb_usascii_encoding(), "%.4d-%02d-%02d", - dat->l.year, dat->l.mon, dat->l.mday); + m_year(dat), m_mon(dat), m_mday(dat)); + else { + VALUE argv[4]; + + argv[0] = rb_usascii_str_new2("%.4d-%02d-%02d"); + argv[1] = m_real_year(dat); + argv[2] = INT2FIX(m_mon(dat)); + argv[3] = INT2FIX(m_mday(dat)); + return rb_f_sprintf(4, argv); } } static VALUE -d_right_inspect(VALUE self) +inspect_flags(VALUE self) { - VALUE argv[6]; - get_d1(self); - assert(!light_mode_p(dat)); - argv[0] = rb_usascii_str_new2("#<%s[R]: %s (%s,%s,%s)>"); - argv[1] = rb_class_name(CLASS_OF(self)); - argv[2] = d_right_to_s(self); - argv[3] = dat->r.ajd; - argv[4] = dat->r.of; - argv[5] = dat->r.sg; - return rb_f_sprintf(6, argv); + return rb_enc_sprintf(rb_usascii_encoding(), + "%c%c%c%c%c", + (dat->flags & COMPLEX_DAT) ? 'C' : 'S', + (dat->flags & HAVE_JD) ? 'j' : '-', + (dat->flags & HAVE_DF) ? 'd' : '-', + (dat->flags & HAVE_CIVIL) ? 'c' : '-', + (dat->flags & HAVE_TIME) ? 't' : '-'); } /* @@ -5498,16 +5953,45 @@ static VALUE d_lite_inspect(VALUE self) { get_d1(self); - if (!light_mode_p(dat)) - return c_iforward0(inspect); - { - get_d_civil(dat); - get_d_jd(dat); + + if (simple_dat_p(dat)) { return rb_enc_sprintf(rb_usascii_encoding(), - "#<%s[L]: %.4d-%02d-%02d (%ldj,0,%.0f)>", + "#<%s: %s " + "((%sth,%dj),+0s,%.0fj; " + "%dy%dm%dd; %s)>", rb_obj_classname(self), - dat->l.year, dat->l.mon, dat->l.mday, - dat->l.jd, dat->l.sg); + RSTRING_PTR(f_to_s(self)), + RSTRING_PTR(f_inspect(dat->s.nth)), + dat->s.jd, dat->s.sg, +#ifndef USE_PACK + dat->s.year, dat->s.mon, dat->s.mday, +#else + dat->s.year, + EX_MON(dat->s.pd), EX_MDAY(dat->s.pd), +#endif + RSTRING_PTR(inspect_flags(self))); + } + else { + return rb_enc_sprintf(rb_usascii_encoding(), + "#<%s: %s " + "((%sth,%dj,%ds,%sn),%+ds,%.0fj; " + "%dy%dm%dd %dh%dm%ds; %s)>", + rb_obj_classname(self), + RSTRING_PTR(f_to_s(self)), + RSTRING_PTR(f_inspect(dat->c.nth)), + dat->c.jd, dat->c.df, + RSTRING_PTR(f_inspect(dat->c.sf)), + dat->c.of, dat->c.sg, +#ifndef USE_PACK + dat->c.year, dat->c.mon, dat->c.mday, + dat->c.hour, dat->c.min, dat->c.sec, +#else + dat->c.year, + EX_MON(dat->c.pd), EX_MDAY(dat->c.pd), + EX_HOUR(dat->c.pd), EX_MIN(dat->c.pd), + EX_SEC(dat->c.pd), +#endif + RSTRING_PTR(inspect_flags(self))); } } @@ -5555,36 +6039,29 @@ d_lite_set_tmx(VALUE self, struct tmx *tmx) { get_d1(self); - if (!light_mode_p(dat)) { - tmx->year = d_right_year(self); - tmx->yday = FIX2INT(d_right_yday(self)); - tmx->mon = FIX2INT(d_right_mon(self)); - tmx->mday = FIX2INT(d_right_mday(self)); - tmx->hour = FIX2INT(d_right_hour(self)); - tmx->min = FIX2INT(d_right_min(self)); - tmx->sec = FIX2INT(d_right_sec(self)); - tmx->wday = FIX2INT(d_right_wday(self)); - tmx->offset = f_mul(dat->r.of, INT2FIX(DAY_IN_SECONDS)); - tmx->zone = RSTRING_PTR(d_right_zone(self)); - tmx->timev = f_mul(f_sub(dat->r.ajd, UNIX_EPOCH_IN_AJD), - INT2FIX(DAY_IN_SECONDS)); - } - else { - get_d_jd(dat); - get_d_civil(dat); + tmx->year = m_real_year(dat); + tmx->yday = m_yday(dat); + tmx->mon = m_mon(dat); + tmx->mday = m_mday(dat); + tmx->wday = m_wday(dat); - tmx->year = LONG2NUM(dat->l.year); - tmx->yday = civil_to_yday(dat->l.year, dat->l.mon, dat->l.mday); - tmx->mon = dat->l.mon; - tmx->mday = dat->l.mday; + if (simple_dat_p(dat)) { tmx->hour = 0; tmx->min = 0; tmx->sec = 0; - tmx->wday = jd_to_wday(dat->l.jd); tmx->offset = INT2FIX(0); tmx->zone = "+00:00"; - tmx->timev = f_mul(INT2FIX(dat->l.jd - 2440588), - INT2FIX(DAY_IN_SECONDS)); + tmx->timev = day_to_sec(f_sub(m_real_jd(dat), + UNIX_EPOCH_IN_CJD)); + } + else { + tmx->hour = m_hour(dat); + tmx->min = m_min(dat); + tmx->sec = m_sec(dat); + tmx->offset = INT2FIX(m_of(dat)); + tmx->zone = RSTRING_PTR(m_zone(dat)); + tmx->timev = day_to_sec(f_sub(m_ajd(dat), + UNIX_EPOCH_IN_AJD)); } } @@ -5735,10 +6212,7 @@ d_lite_rfc2822(VALUE self) static VALUE d_lite_httpdate(VALUE self) { - VALUE argv[1], d; - - argv[0] = INT2FIX(0); - d = d_lite_new_offset(1, argv, self); + VALUE d = copy_obj_with_new_offset(self, 0); return strftimev("%a, %d %b %Y %T GMT", d, d_lite_set_tmx); } @@ -5777,8 +6251,10 @@ d_lite_jisx0301(VALUE self) { VALUE argv[2]; - if (!gengo(d_lite_jd(self), - d_lite_year(self), + get_d1(self); + + if (!gengo(m_real_local_jd(dat), + m_real_year(dat), argv)) return strftimev("%F", self, d_lite_set_tmx); return f_add(rb_f_sprintf(2, argv), @@ -5798,12 +6274,13 @@ d_lite_marshal_dump(VALUE self) get_d1(self); - if (!light_mode_p(dat)) - a = rb_ary_new3(3, dat->r.ajd, dat->r.of, dat->r.sg); - else { - get_d_jd(dat); - a = rb_assoc_new(LONG2NUM(dat->l.jd), DBL2NUM(dat->l.sg)); - } + a = rb_ary_new3(6, + m_nth(dat), + INT2FIX(m_jd(dat)), + INT2FIX(m_df(dat)), + m_sf(dat), + INT2FIX(m_of(dat)), + DBL2NUM(m_sg(dat))); if (FL_TEST(self, FL_EXIVAR)) { rb_copy_generic_ivar(a, self); @@ -5829,19 +6306,84 @@ d_lite_marshal_load(VALUE self, VALUE a) switch (RARRAY_LEN(a)) { case 3: - dat->r.ajd = RARRAY_PTR(a)[0]; - dat->r.of = RARRAY_PTR(a)[1]; - dat->r.sg = RARRAY_PTR(a)[2]; - dat->r.cache = rb_hash_new(); - dat->r.flags = 0; + { + VALUE ajd, of, sg, nth, sf; + int jd, df, rof; + double rsg; + unsigned flags; + + ajd = RARRAY_PTR(a)[0]; + of = RARRAY_PTR(a)[1]; + sg = RARRAY_PTR(a)[2]; + + old_to_new(ajd, of, sg, + &nth, &jd, &df, &sf, &rof, &rsg, &flags); + + dat->c.nth = nth; + dat->c.jd = jd; + dat->c.df = df; + dat->c.sf = sf; + dat->c.of = rof; + dat->c.sg = rsg; + dat->c.year = 0; +#ifndef USE_PACK + dat->c.mon = 0; + dat->c.mday = 0; + dat->c.hour = 0; + dat->c.min = 0; + dat->c.sec = 0; +#else + dat->c.pd = 0; +#endif + dat->c.flags = flags; + } break; - case 2: - dat->l.jd = NUM2LONG(RARRAY_PTR(a)[0]); - dat->l.sg = NUM2DBL(RARRAY_PTR(a)[1]); - dat->l.year = 0; - dat->l.mon = 0; - dat->l.mday = 0; - dat->l.flags = LIGHT_MODE | HAVE_JD; + case 6: + { + VALUE nth, sf; + int jd, df, of; + double sg; + + nth = RARRAY_PTR(a)[0]; + jd = NUM2INT(RARRAY_PTR(a)[1]); + df = NUM2INT(RARRAY_PTR(a)[2]); + sf = RARRAY_PTR(a)[3]; + of = NUM2INT(RARRAY_PTR(a)[4]); + sg = NUM2DBL(RARRAY_PTR(a)[5]); + + if (!df && f_zero_p(sf) && !of) { + dat->s.nth = nth; + dat->s.jd = jd; + dat->s.sg = sg; + dat->s.year = 0; +#ifndef USE_PACK + dat->s.mon = 0; + dat->s.mday = 0; +#else + dat->s.pd = 0; +#endif + dat->s.flags = HAVE_JD; + } + else { + dat->c.nth = nth; + dat->c.jd = jd; + dat->c.df = df; + dat->c.sf = sf; + dat->c.of = of; + dat->c.sg = sg; + dat->c.year = 0; +#ifndef USE_PACK + dat->c.mon = 0; + dat->c.mday = 0; + dat->c.hour = 0; + dat->c.min = 0; + dat->c.sec = 0; +#else + dat->c.pd = 0; +#endif + dat->c.flags = HAVE_JD | HAVE_DF | COMPLEX_DAT; + } + } break; default: rb_raise(rb_eTypeError, "invalid size"); @@ -5856,285 +6398,8 @@ d_lite_marshal_load(VALUE self, VALUE a) return self; } -/* datetime light */ - -static void -dt_right_gc_mark(union DateTimeData *dat) -{ - assert(!light_mode_p(dat)); - rb_gc_mark(dat->r.ajd); - rb_gc_mark(dat->r.of); - rb_gc_mark(dat->r.sg); - rb_gc_mark(dat->r.cache); -} - -#define dt_lite_gc_mark 0 - -inline static VALUE -dt_right_new_internal(VALUE klass, VALUE ajd, VALUE of, VALUE sg, - unsigned flags) -{ - union DateTimeData *dat; - VALUE obj; - - obj = Data_Make_Struct(klass, union DateTimeData, - dt_right_gc_mark, -1, dat); - - dat->r.ajd = ajd; - dat->r.of = of; - dat->r.sg = sg; - dat->r.cache = rb_hash_new(); - dat->r.flags = flags | DATETIME_OBJ; - - return obj; -} - -inline static VALUE -dt_lite_new_internal(VALUE klass, long jd, int df, - long sf, int of, double sg, - int y, int m, int d, - int h, int min, int s, - unsigned flags) -{ - union DateTimeData *dat; - VALUE obj; - - obj = Data_Make_Struct(klass, union DateTimeData, - dt_lite_gc_mark, -1, dat); - - dat->l.jd = jd; - dat->l.df = df; - dat->l.sf = sf; - dat->l.of = of; - dat->l.sg = sg; - dat->l.year = y; - dat->l.mon = m; - dat->l.mday = d; - dat->l.hour = h; - dat->l.min = min; - dat->l.sec = s; - dat->l.flags = flags | LIGHT_MODE | DATETIME_OBJ; - - return obj; -} - -static VALUE -dt_lite_new_internal_wo_civil(VALUE klass, long jd, int df, - long sf, int of, double sg, - unsigned flags) -{ - return dt_lite_new_internal(klass, jd, df, sf, of, sg, - 0, 0, 0, 0, 0, 0, flags); -} - -static VALUE -dt_lite_s_alloc(VALUE klass) -{ - return dt_lite_new_internal_wo_civil(klass, 0, 0, 0, 0, 0, 0); -} - -static VALUE -dt_right_new(VALUE klass, VALUE ajd, VALUE of, VALUE sg) -{ - return dt_right_new_internal(klass, ajd, of, sg, 0); -} - -static VALUE -dt_lite_new(VALUE klass, VALUE jd, VALUE df, VALUE sf, VALUE of, VALUE sg) -{ - return dt_lite_new_internal_wo_civil(klass, - NUM2LONG(jd), - FIX2INT(df), - NUM2LONG(sf), - FIX2INT(of), - NUM2DBL(sg), - HAVE_JD | HAVE_DF); -} - -static VALUE -dt_switch_new(VALUE klass, VALUE ajd, VALUE of, VALUE sg) -{ - VALUE t, jd, df, sf, ssf, odf, osf; - - t = rt_ajd_to_jd(ajd, INT2FIX(0)); /* as utc */ - jd = RARRAY_PTR(t)[0]; - df = RARRAY_PTR(t)[1]; - - t = f_mul(df, INT2FIX(DAY_IN_SECONDS)); - df = f_idiv(t, INT2FIX(1)); - sf = f_mod(t, INT2FIX(1)); - - t = f_mul(sf, INT2FIX(SECOND_IN_NANOSECONDS)); - sf = f_idiv(t, INT2FIX(1)); - ssf = f_mod(t, INT2FIX(1)); - - t = f_mul(of, INT2FIX(DAY_IN_SECONDS)); - odf = f_truncate(t); - osf = f_remainder(t, INT2FIX(1)); - -#ifdef FORCE_RIGHT - if (1) -#else - if (!FIXNUM_P(jd) || - f_lt_p(jd, sg) || !f_zero_p(ssf) || !f_zero_p(osf) || - !LIGHTABLE_JD(NUM2LONG(jd))) -#endif - return dt_right_new(klass, ajd, of, sg); - else - return dt_lite_new(klass, jd, df, sf, odf, sg); -} - -#ifndef NDEBUG -static VALUE -dt_right_new_m(int argc, VALUE *argv, VALUE klass) -{ - VALUE ajd, of, sg; - - rb_scan_args(argc, argv, "03", &ajd, &of, &sg); - - switch (argc) { - case 0: - ajd = INT2FIX(0); - case 1: - of = INT2FIX(0); - case 2: - sg = INT2FIX(ITALY); - } - - return dt_right_new(klass, ajd, of, sg); -} - -static VALUE -dt_lite_new_m(int argc, VALUE *argv, VALUE klass) -{ - VALUE jd, df, sf, of, sg; - - rb_scan_args(argc, argv, "05", &jd, &df, &sf, &of, &sg); - - switch (argc) { - case 0: - jd = INT2FIX(0); - case 1: - df = INT2FIX(0); - case 2: - sf = INT2FIX(0); - case 3: - of = INT2FIX(0); - case 4: - sg = INT2FIX(ITALY); - } - - return dt_lite_new(klass, jd, df, sf, of, sg); -} - -static VALUE -dt_switch_new_m(int argc, VALUE *argv, VALUE klass) -{ - VALUE ajd, of, sg; - - rb_scan_args(argc, argv, "03", &ajd, &of, &sg); - - switch (argc) { - case 0: - ajd = INT2FIX(0); - case 1: - of = INT2FIX(0); - case 2: - sg = INT2FIX(ITALY); - } - - return dt_switch_new(klass, ajd, of, sg); -} -#endif - -static VALUE -dt_right_new_jd(VALUE klass, VALUE jd, VALUE fr, VALUE of, VALUE sg) -{ - return dt_right_new(klass, - rt_jd_to_ajd(jd, fr, of), - of, - sg); -} - -#ifndef NDEBUG -static VALUE -dt_lite_new_jd(VALUE klass, VALUE jd, VALUE fr, VALUE of, VALUE sg) -{ - VALUE n, df, sf; - - n = f_mul(fr, INT2FIX(DAY_IN_SECONDS)); - df = f_idiv(n, INT2FIX(1)); - sf = f_mod(n, INT2FIX(1)); - n = f_mul(sf, INT2FIX(SECOND_IN_NANOSECONDS)); - sf = f_idiv(n, INT2FIX(1)); - return dt_lite_new(klass, jd, df, sf, of, sg); -} -#endif - -static VALUE -dt_switch_new_jd(VALUE klass, VALUE jd, VALUE fr, VALUE of, VALUE sg) -{ - return dt_switch_new(klass, - rt_jd_to_ajd(jd, fr, of), - of, - sg); -} -#ifndef NDEBUG -static VALUE -datetime_s_new_r_bang(int argc, VALUE *argv, VALUE klass) -{ - return dt_right_new_m(argc, argv, klass); -} - -static VALUE -datetime_s_new_l_bang(int argc, VALUE *argv, VALUE klass) -{ - return dt_lite_new_m(argc, argv, klass); -} - -static VALUE -datetime_s_new_bang(int argc, VALUE *argv, VALUE klass) -{ - return dt_switch_new_m(argc, argv, klass); -} -#endif - -#undef c_cforwardv -#define c_cforwardv(m) rt_datetime_s_##m(argc, argv, klass) - -static VALUE -rt_datetime_s_jd(int argc, VALUE *argv, VALUE klass) -{ - VALUE jd, h, min, s, of, sg, fr; - - rb_scan_args(argc, argv, "06", &jd, &h, &min, &s, &of, &sg); - - switch (argc) { - case 0: - jd = INT2FIX(0); - case 1: - h = INT2FIX(0); - case 2: - min = INT2FIX(0); - case 3: - s = INT2FIX(0); - case 4: - of = INT2FIX(0); - case 5: - sg = INT2FIX(ITALY); - } - - jd = rt__valid_jd_p(jd, sg); - fr = rt__valid_time_p(h, min, s); - - if (NIL_P(jd) || NIL_P(fr)) - rb_raise(rb_eArgError, "invalid date"); - - of = sof2nof(of); - - return dt_right_new_jd(klass, jd, fr, of, sg); -} +/* datetime light */ /* * call-seq: @@ -6157,90 +6422,56 @@ rt_datetime_s_jd(int argc, VALUE *argv, VALUE klass) static VALUE datetime_s_jd(int argc, VALUE *argv, VALUE klass) { - VALUE vjd, vh, vmin, vs, vof, vsg; - long jd; - int h, min, s, rh, rmin, rs, rof; + VALUE vjd, vh, vmin, vs, vof, vsg, jd, fr, fr2, ret; + int h, min, s, rof; double sg; -#ifdef FORCE_RIGHT - return c_cforwardv(jd); -#endif - rb_scan_args(argc, argv, "06", &vjd, &vh, &vmin, &vs, &vof, &vsg); - if (!FIXNUM_P(vjd)) - return c_cforwardv(jd); + jd = INT2FIX(0); - jd = h = min = s = 0; + h = min = s = 0; + fr2 = INT2FIX(0); rof = 0; - sg = ITALY; + sg = DEFAULT_SG; switch (argc) { case 6: - sg = NUM2DBL(vsg); + val2sg(vsg, sg); case 5: - vof = sof2nof(vof); - if (!daydiff_to_sec(vof, &rof)) - return c_cforwardv(jd); + val2off(vof, rof); case 4: - s = NUM2INT(vs); + num2int_with_frac(s, positive_inf); case 3: - min = NUM2INT(vmin); + num2int_with_frac(min, 3); case 2: - h = NUM2INT(vh); + num2int_with_frac(h, 2); case 1: - jd = NUM2LONG(vjd); - if (!LIGHTABLE_JD(jd)) - return c_cforwardv(jd); + num2num_with_frac(jd, 1); } - if (jd < sg) - return c_cforwardv(jd); - - if (!valid_time_p(h, min, s, &rh, &rmin, &rs)) - rb_raise(rb_eArgError, "invalid date"); - - return dt_lite_new_internal(klass, - jd_local_to_utc(jd, - time_to_df(rh, rmin, rs), - rof), - 0, 0, rof, sg, 0, 0, 0, rh, rmin, rs, - HAVE_JD | HAVE_TIME); -} + { + VALUE nth; + int rh, rmin, rs, rjd, rjd2; -static VALUE -rt_datetime_s_ordinal(int argc, VALUE *argv, VALUE klass) -{ - VALUE y, d, h, min, s, of, sg, jd, fr; + if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs)) + rb_raise(rb_eArgError, "invalid date"); - rb_scan_args(argc, argv, "07", &y, &d, &h, &min, &s, &of, &sg); + decode_jd(jd, &nth, &rjd); + rjd2 = jd_local_to_utc(rjd, + time_to_df(rh, rmin, rs), + rof); - switch (argc) { - case 0: - y = INT2FIX(-4712); - case 1: - d = INT2FIX(1); - case 2: - h = INT2FIX(0); - case 3: - min = INT2FIX(0); - case 4: - s = INT2FIX(0); - case 5: - of = INT2FIX(0); - case 6: - sg = INT2FIX(ITALY); + ret = d_complex_new_internal(klass, + nth, rjd2, + 0, INT2FIX(0), + rof, sg, + 0, 0, 0, + rh, rmin, rs, + HAVE_JD | HAVE_TIME); } - - jd = rt__valid_ordinal_p(y, d, sg); - fr = rt__valid_time_p(h, min, s); - - if (NIL_P(jd) || NIL_P(fr)) - rb_raise(rb_eArgError, "invalid date"); - - of = sof2nof(of); - - return dt_right_new_jd(klass, jd, fr, of, sg); + add_frac(); + return ret; } /* @@ -6265,108 +6496,63 @@ rt_datetime_s_ordinal(int argc, VALUE *argv, VALUE klass) static VALUE datetime_s_ordinal(int argc, VALUE *argv, VALUE klass) { - VALUE vy, vd, vh, vmin, vs, vof, vsg; - int y, d, rd, h, min, s, rh, rmin, rs, rof; + VALUE vy, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret; + int d, h, min, s, rof; double sg; -#ifdef FORCE_RIGHT - return c_cforwardv(ordinal); -#endif - rb_scan_args(argc, argv, "07", &vy, &vd, &vh, &vmin, &vs, &vof, &vsg); - if (!((NIL_P(vy) || FIXNUM_P(vy)) && - (NIL_P(vd) || FIXNUM_P(vd)) && - (NIL_P(vh) || FIXNUM_P(vh)) && - (NIL_P(vmin) || FIXNUM_P(vmin)) && - (NIL_P(vs) || FIXNUM_P(vs)))) - return c_cforwardv(ordinal); - - y = -4712; + y = INT2FIX(-4712); d = 1; h = min = s = 0; + fr2 = INT2FIX(0); rof = 0; - sg = ITALY; + sg = DEFAULT_SG; switch (argc) { case 7: - sg = NUM2DBL(vsg); + val2sg(vsg, sg); case 6: - vof = sof2nof(vof); - if (!daydiff_to_sec(vof, &rof)) - return c_cforwardv(ordinal); + val2off(vof, rof); case 5: - s = NUM2INT(vs); + num2int_with_frac(s, positive_inf); case 4: - min = NUM2INT(vmin); + num2int_with_frac(min, 4); case 3: - h = NUM2INT(vh); + num2int_with_frac(h, 3); case 2: - d = NUM2INT(vd); + num2int_with_frac(d, 2); case 1: - y = NUM2INT(vy); - if (!LIGHTABLE_YEAR(y)) - return c_cforwardv(ordinal); + y = vy; } { - long jd; - int ns; + VALUE nth; + int ry, rd, rh, rmin, rs, rjd, rjd2, ns; - if (!valid_ordinal_p(y, d, sg, &rd, &jd, &ns)) + if (!valid_ordinal_p(y, d, sg, + &nth, &ry, + &rd, &rjd, + &ns)) rb_raise(rb_eArgError, "invalid date"); - if (!valid_time_p(h, min, s, &rh, &rmin, &rs)) + if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs)) rb_raise(rb_eArgError, "invalid date"); - if (!LIGHTABLE_JD(jd) || !ns) - return c_cforwardv(ordinal); + rjd2 = jd_local_to_utc(rjd, + time_to_df(rh, rmin, rs), + rof); - return dt_lite_new_internal(klass, - jd_local_to_utc(jd, - time_to_df(rh, rmin, rs), - rof), - 0, 0, rof, sg, - 0, 0, 0, rh, rmin, rs, - HAVE_JD | HAVE_TIME); + ret = d_complex_new_internal(klass, + nth, rjd2, + 0, INT2FIX(0), + rof, sg, + 0, 0, 0, + rh, rmin, rs, + HAVE_JD | HAVE_TIME); } -} - -static VALUE -rt_datetime_s_civil(int argc, VALUE *argv, VALUE klass) -{ - VALUE y, m, d, h, min, s, of, sg, jd, fr; - - rb_scan_args(argc, argv, "08", &y, &m, &d, &h, &min, &s, &of, &sg); - - switch (argc) { - case 0: - y = INT2FIX(-4712); - case 1: - m = INT2FIX(1); - case 2: - d = INT2FIX(1); - case 3: - h = INT2FIX(0); - case 4: - min = INT2FIX(0); - case 5: - s = INT2FIX(0); - case 6: - of = INT2FIX(0); - case 7: - sg = INT2FIX(ITALY); - } - - jd = rt__valid_civil_p(y, m, d, sg); - fr = rt__valid_time_p(h, min, s); - - if (NIL_P(jd) || NIL_P(fr)) - rb_raise(rb_eArgError, "invalid date"); - - of = sof2nof(of); - - return dt_right_new_jd(klass, jd, fr, of, sg); + add_frac(); + return ret; } /* @@ -6392,122 +6578,85 @@ rt_datetime_s_civil(int argc, VALUE *argv, VALUE klass) static VALUE datetime_s_civil(int argc, VALUE *argv, VALUE klass) { - VALUE vy, vm, vd, vh, vmin, vs, vof, vsg; - int y, m, d, rm, rd, h, min, s, rh, rmin, rs, rof; + VALUE vy, vm, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret; + int m, d, h, min, s, rof; double sg; -#ifdef FORCE_RIGHT - return c_cforwardv(civil); -#endif - rb_scan_args(argc, argv, "08", &vy, &vm, &vd, &vh, &vmin, &vs, &vof, &vsg); - if (!((NIL_P(vy) || FIXNUM_P(vy)) && - (NIL_P(vm) || FIXNUM_P(vm)) && - (NIL_P(vd) || FIXNUM_P(vd)) && - (NIL_P(vh) || FIXNUM_P(vh)) && - (NIL_P(vmin) || FIXNUM_P(vmin)) && - (NIL_P(vs) || FIXNUM_P(vs)))) - return c_cforwardv(civil); - - y = -4712; + y = INT2FIX(-4712); m = 1; d = 1; h = min = s = 0; + fr2 = INT2FIX(0); rof = 0; - sg = ITALY; + sg = DEFAULT_SG; switch (argc) { case 8: - sg = NUM2DBL(vsg); + val2sg(vsg, sg); case 7: - vof = sof2nof(vof); - if (!daydiff_to_sec(vof, &rof)) - return c_cforwardv(civil); + val2off(vof, rof); case 6: - s = NUM2INT(vs); + num2int_with_frac(s, positive_inf); case 5: - min = NUM2INT(vmin); + num2int_with_frac(min, 5); case 4: - h = NUM2INT(vh); + num2int_with_frac(h, 4); case 3: - d = NUM2INT(vd); + num2int_with_frac(d, 3); case 2: m = NUM2INT(vm); case 1: - y = NUM2INT(vy); - if (!LIGHTABLE_YEAR(y)) - return c_cforwardv(civil); + y = vy; } if (isinf(sg) && sg < 0) { - if (!valid_gregorian_p(y, m, d, &rm, &rd)) + VALUE nth; + int ry, rm, rd, rh, rmin, rs; + + if (!valid_gregorian_p(y, m, d, + &nth, &ry, + &rm, &rd)) rb_raise(rb_eArgError, "invalid date"); - if (!valid_time_p(h, min, s, &rh, &rmin, &rs)) + if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs)) rb_raise(rb_eArgError, "invalid date"); - return dt_lite_new_internal(klass, 0, 0, 0, rof, sg, - y, rm, rd, rh, rmin, rs, - HAVE_CIVIL | HAVE_TIME); + ret = d_complex_new_internal(klass, + nth, 0, + 0, INT2FIX(0), + rof, sg, + ry, rm, rd, + rh, rmin, rs, + HAVE_CIVIL | HAVE_TIME); } else { - long jd; - int ns; + VALUE nth; + int ry, rm, rd, rh, rmin, rs, rjd, rjd2, ns; - if (!valid_civil_p(y, m, d, sg, &rm, &rd, &jd, &ns)) + if (!valid_civil_p(y, m, d, sg, + &nth, &ry, + &rm, &rd, &rjd, + &ns)) rb_raise(rb_eArgError, "invalid date"); - if (!valid_time_p(h, min, s, &rh, &rmin, &rs)) + if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs)) rb_raise(rb_eArgError, "invalid date"); - if (!LIGHTABLE_JD(jd) || !ns) - return c_cforwardv(civil); + rjd2 = jd_local_to_utc(rjd, + time_to_df(rh, rmin, rs), + rof); - return dt_lite_new_internal(klass, - jd_local_to_utc(jd, - time_to_df(rh, rmin, rs), - rof), - 0, 0, rof, sg, - y, rm, rd, rh, rmin, rs, - HAVE_JD | HAVE_CIVIL | HAVE_TIME); + ret = d_complex_new_internal(klass, + nth, rjd2, + 0, INT2FIX(0), + rof, sg, + ry, rm, rd, + rh, rmin, rs, + HAVE_JD | HAVE_CIVIL | HAVE_TIME); } -} - -static VALUE -rt_datetime_s_commercial(int argc, VALUE *argv, VALUE klass) -{ - VALUE y, w, d, h, min, s, of, sg, jd, fr; - - rb_scan_args(argc, argv, "08", &y, &w, &d, &h, &min, &s, &of, &sg); - - switch (argc) { - case 0: - y = INT2FIX(-4712); - case 1: - w = INT2FIX(1); - case 2: - d = INT2FIX(1); - case 3: - h = INT2FIX(0); - case 4: - min = INT2FIX(0); - case 5: - s = INT2FIX(0); - case 6: - of = INT2FIX(0); - case 7: - sg = INT2FIX(ITALY); - } - - jd = rt__valid_commercial_p(y, w, d, sg); - fr = rt__valid_time_p(h, min, s); - - if (NIL_P(jd) || NIL_P(fr)) - rb_raise(rb_eArgError, "invalid date"); - - of = sof2nof(of); - - return dt_right_new_jd(klass, jd, fr, of, sg); + add_frac(); + return ret; } /* @@ -6534,312 +6683,206 @@ rt_datetime_s_commercial(int argc, VALUE *argv, VALUE klass) static VALUE datetime_s_commercial(int argc, VALUE *argv, VALUE klass) { - VALUE vy, vw, vd, vh, vmin, vs, vof, vsg; - int y, w, d, rw, rd, h, min, s, rh, rmin, rs, rof; + VALUE vy, vw, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret; + int w, d, h, min, s, rof; double sg; -#ifdef FORCE_RIGHT - return c_cforwardv(commercial); -#endif - rb_scan_args(argc, argv, "08", &vy, &vw, &vd, &vh, &vmin, &vs, &vof, &vsg); - if (!((NIL_P(vy) || FIXNUM_P(vy)) && - (NIL_P(vw) || FIXNUM_P(vw)) && - (NIL_P(vd) || FIXNUM_P(vd)) && - (NIL_P(vh) || FIXNUM_P(vh)) && - (NIL_P(vmin) || FIXNUM_P(vmin)) && - (NIL_P(vs) || FIXNUM_P(vs)))) - return c_cforwardv(commercial); - - y = -4712; + y = INT2FIX(-4712); w = 1; d = 1; h = min = s = 0; + fr2 = INT2FIX(0); rof = 0; - sg = ITALY; + sg = DEFAULT_SG; switch (argc) { case 8: - sg = NUM2DBL(vsg); + val2sg(vsg, sg); case 7: - vof = sof2nof(vof); - if (!daydiff_to_sec(vof, &rof)) - return c_cforwardv(commercial); + val2off(vof, rof); case 6: - s = NUM2INT(vs); + num2int_with_frac(s, positive_inf); case 5: - min = NUM2INT(vmin); + num2int_with_frac(min, 5); case 4: - h = NUM2INT(vh); + num2int_with_frac(h, 4); case 3: - d = NUM2INT(vd); + num2int_with_frac(d, 3); case 2: w = NUM2INT(vw); case 1: - y = NUM2INT(vy); - if (!LIGHTABLE_CWYEAR(y)) - return c_cforwardv(commercial); + y = vy; } { - long jd; - int ns; + VALUE nth; + int ry, rw, rd, rh, rmin, rs, rjd, rjd2, ns; - if (!valid_commercial_p(y, w, d, sg, &rw, &rd, &jd, &ns)) + if (!valid_commercial_p(y, w, d, sg, + &nth, &ry, + &rw, &rd, &rjd, + &ns)) rb_raise(rb_eArgError, "invalid date"); - if (!valid_time_p(h, min, s, &rh, &rmin, &rs)) + if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs)) rb_raise(rb_eArgError, "invalid date"); - if (!LIGHTABLE_JD(jd) || !ns) - return c_cforwardv(commercial); - return dt_lite_new_internal(klass, - jd_local_to_utc(jd, - time_to_df(rh, rmin, rs), - rof), - 0, 0, rof, sg, - 0, 0, 0, rh, rmin, rs, - HAVE_JD | HAVE_TIME); - } -} - -#ifndef NDEBUG -static VALUE -rt_datetime_s_weeknum(int argc, VALUE *argv, VALUE klass) -{ - VALUE y, w, d, f, h, min, s, of, sg, jd, fr; - - rb_scan_args(argc, argv, "09", &y, &w, &d, &f, &h, &min, &s, &of, &sg); + rjd2 = jd_local_to_utc(rjd, + time_to_df(rh, rmin, rs), + rof); - switch (argc) { - case 0: - y = INT2FIX(-4712); - case 1: - w = INT2FIX(0); - case 2: - d = INT2FIX(1); - case 3: - f = INT2FIX(0); - case 4: - h = INT2FIX(0); - case 5: - min = INT2FIX(0); - case 6: - s = INT2FIX(0); - case 7: - of = INT2FIX(0); - case 8: - sg = INT2FIX(ITALY); + ret = d_complex_new_internal(klass, + nth, rjd2, + 0, INT2FIX(0), + rof, sg, + 0, 0, 0, + rh, rmin, rs, + HAVE_JD | HAVE_TIME); } - - jd = rt__valid_weeknum_p(y, w, d, f, sg); - fr = rt__valid_time_p(h, min, s); - - if (NIL_P(jd) || NIL_P(fr)) - rb_raise(rb_eArgError, "invalid date"); - - of = sof2nof(of); - - return dt_right_new_jd(klass, jd, fr, of, sg); + add_frac(); + return ret; } +#ifndef NDEBUG static VALUE datetime_s_weeknum(int argc, VALUE *argv, VALUE klass) { - VALUE vy, vw, vd, vf, vh, vmin, vs, vof, vsg; - int y, w, d, f, rw, rd, h, min, s, rh, rmin, rs, rof; + VALUE vy, vw, vd, vf, vh, vmin, vs, vof, vsg, y, fr, fr2, ret; + int w, d, f, h, min, s, rof; double sg; -#ifdef FORCE_RIGHT - return c_cforwardv(weeknum); -#endif - rb_scan_args(argc, argv, "09", &vy, &vw, &vd, &vf, &vh, &vmin, &vs, &vof, &vsg); - if (!((NIL_P(vy) || FIXNUM_P(vy)) && - (NIL_P(vw) || FIXNUM_P(vw)) && - (NIL_P(vd) || FIXNUM_P(vd)) && - (NIL_P(vf) || FIXNUM_P(vf)) && - (NIL_P(vh) || FIXNUM_P(vh)) && - (NIL_P(vmin) || FIXNUM_P(vmin)) && - (NIL_P(vs) || FIXNUM_P(vs)))) - return c_cforwardv(weeknum); - - y = -4712; + y = INT2FIX(-4712); w = 0; d = 1; f = 0; h = min = s = 0; + fr2 = INT2FIX(0); rof = 0; - sg = ITALY; + sg = DEFAULT_SG; switch (argc) { case 9: - sg = NUM2DBL(vsg); + val2sg(vsg, sg); case 8: - vof = sof2nof(vof); - if (!daydiff_to_sec(vof, &rof)) - return c_cforwardv(weeknum); + val2off(vof, rof); case 7: - s = NUM2INT(vs); + num2int_with_frac(s, positive_inf); case 6: - min = NUM2INT(vmin); + num2int_with_frac(min, 6); case 5: - h = NUM2INT(vh); + num2int_with_frac(h, 5); case 4: f = NUM2INT(vf); case 3: - d = NUM2INT(vd); + num2int_with_frac(d, 4); case 2: w = NUM2INT(vw); case 1: - y = NUM2INT(vy); - if (!LIGHTABLE_YEAR(y)) - return c_cforwardv(weeknum); + y = vy; } { - long jd; - int ns; + VALUE nth; + int ry, rw, rd, rh, rmin, rs, rjd, rjd2, ns; - if (!valid_weeknum_p(y, w, d, f, sg, &rw, &rd, &jd, &ns)) + if (!valid_weeknum_p(y, w, d, f, sg, + &nth, &ry, + &rw, &rd, &rjd, + &ns)) rb_raise(rb_eArgError, "invalid date"); - if (!valid_time_p(h, min, s, &rh, &rmin, &rs)) + if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs)) rb_raise(rb_eArgError, "invalid date"); - if (!LIGHTABLE_JD(jd) || !ns) - return c_cforwardv(weeknum); + rjd2 = jd_local_to_utc(rjd, + time_to_df(rh, rmin, rs), + rof); - return dt_lite_new_internal(klass, - jd_local_to_utc(jd, - time_to_df(rh, rmin, rs), - rof), - 0, 0, rof, sg, - 0, 0, 0, rh, rmin, rs, - HAVE_JD | HAVE_TIME); + ret = d_complex_new_internal(klass, + nth, rjd2, + 0, INT2FIX(0), + rof, sg, + 0, 0, 0, + rh, rmin, rs, + HAVE_JD | HAVE_TIME); } -} - -static VALUE -rt_datetime_s_nth_kday(int argc, VALUE *argv, VALUE klass) -{ - VALUE y, m, n, k, h, min, s, of, sg, jd, fr; - - rb_scan_args(argc, argv, "09", &y, &m, &n, &k, &h, &min, &s, &of, &sg); - - switch (argc) { - case 0: - y = INT2FIX(-4712); - case 1: - m = INT2FIX(1); - case 2: - n = INT2FIX(1); - case 3: - k = INT2FIX(1); - case 4: - h = INT2FIX(0); - case 5: - min = INT2FIX(0); - case 6: - s = INT2FIX(0); - case 7: - of = INT2FIX(0); - case 8: - sg = INT2FIX(ITALY); - } - - jd = rt__valid_nth_kday_p(y, m, n, k, sg); - fr = rt__valid_time_p(h, min, s); - - if (NIL_P(jd) || NIL_P(fr)) - rb_raise(rb_eArgError, "invalid date"); - - of = sof2nof(of); - - return dt_right_new_jd(klass, jd, fr, of, sg); + add_frac(); + return ret; } static VALUE datetime_s_nth_kday(int argc, VALUE *argv, VALUE klass) { - VALUE vy, vm, vn, vk, vh, vmin, vs, vof, vsg; - int y, m, n, k, rm, rn, rk, h, min, s, rh, rmin, rs, rof; + VALUE vy, vm, vn, vk, vh, vmin, vs, vof, vsg, y, fr, fr2, ret; + int m, n, k, h, min, s, rof; double sg; -#ifdef FORCE_RIGHT - return c_cforwardv(nth_kday); -#endif - rb_scan_args(argc, argv, "09", &vy, &vm, &vn, &vk, &vh, &vmin, &vs, &vof, &vsg); - if (!((NIL_P(vy) || FIXNUM_P(vy)) && - (NIL_P(vm) || FIXNUM_P(vm)) && - (NIL_P(vn) || FIXNUM_P(vn)) && - (NIL_P(vk) || FIXNUM_P(vk)) && - (NIL_P(vh) || FIXNUM_P(vh)) && - (NIL_P(vmin) || FIXNUM_P(vmin)) && - (NIL_P(vs) || FIXNUM_P(vs)))) - return c_cforwardv(nth_kday); - - y = -4712; + y = INT2FIX(-4712); m = 1; n = 1; k = 1; h = min = s = 0; + fr2 = INT2FIX(0); rof = 0; - sg = ITALY; + sg = DEFAULT_SG; switch (argc) { case 9: - sg = NUM2DBL(vsg); + val2sg(vsg, sg); case 8: - vof = sof2nof(vof); - if (!daydiff_to_sec(vof, &rof)) - return c_cforwardv(nth_kday); + val2off(vof, rof); case 7: - s = NUM2INT(vs); + num2int_with_frac(s, positive_inf); case 6: - min = NUM2INT(vmin); + num2int_with_frac(min, 6); case 5: - h = NUM2INT(vh); + num2int_with_frac(h, 5); case 4: - k = NUM2INT(vk); + num2int_with_frac(k, 4); case 3: n = NUM2INT(vn); case 2: m = NUM2INT(vm); case 1: - y = NUM2INT(vy); - if (!LIGHTABLE_YEAR(y)) - return c_cforwardv(nth_kday); + y = vy; } { - long jd; - int ns; + VALUE nth; + int ry, rm, rn, rk, rh, rmin, rs, rjd, rjd2, ns; - if (!valid_nth_kday_p(y, m, n, k, sg, &rm, &rn, &rk, &jd, &ns)) + if (!valid_nth_kday_p(y, m, n, k, sg, + &nth, &ry, + &rm, &rn, &rk, &rjd, + &ns)) rb_raise(rb_eArgError, "invalid date"); - if (!valid_time_p(h, min, s, &rh, &rmin, &rs)) + if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs)) rb_raise(rb_eArgError, "invalid date"); - if (!LIGHTABLE_JD(jd) || !ns) - return c_cforwardv(nth_kday); + rjd2 = jd_local_to_utc(rjd, + time_to_df(rh, rmin, rs), + rof); - return dt_lite_new_internal(klass, - jd_local_to_utc(jd, - time_to_df(rh, rmin, rs), - rof), - 0, 0, rof, sg, - 0, 0, 0, rh, rmin, rs, - HAVE_JD | HAVE_TIME); + ret = d_complex_new_internal(klass, + nth, rjd2, + 0, INT2FIX(0), + rof, sg, + 0, 0, 0, + rh, rmin, rs, + HAVE_JD | HAVE_TIME); } + add_frac(); + return ret; } #endif @@ -6854,7 +6897,7 @@ datetime_s_nth_kday(int argc, VALUE *argv, VALUE klass) static VALUE datetime_s_now(int argc, VALUE *argv, VALUE klass) { - VALUE vsg; + VALUE vsg, nth, ret; double sg; #ifdef HAVE_CLOCK_GETTIME struct timespec ts; @@ -6864,12 +6907,12 @@ datetime_s_now(int argc, VALUE *argv, VALUE klass) time_t sec; struct tm tm; long sf, of; - int y, m, d, h, min, s; + int y, ry, m, d, h, min, s; rb_scan_args(argc, argv, "01", &vsg); if (argc < 1) - sg = ITALY; + sg = DEFAULT_SG; else sg = NUM2DBL(vsg); @@ -6903,67 +6946,89 @@ datetime_s_now(int argc, VALUE *argv, VALUE klass) sf = tv.tv_usec * 1000; #endif -#ifdef FORCE_RIGHT - goto right; -#endif - - if (!LIGHTABLE_YEAR(y)) - goto right; - - if (of < -DAY_IN_SECONDS || of > DAY_IN_SECONDS) - goto right; - - if (isinf(sg) && sg < 0) - return dt_lite_new_internal(klass, 0, 0, sf, (int)of, sg, - y, m, d, h, min, s, - HAVE_CIVIL | HAVE_TIME); - else { - long jd; - int ns; + if (of < -DAY_IN_SECONDS || of > DAY_IN_SECONDS) { + of = 0; + rb_warning("invalid offset is ignored"); + } - civil_to_jd(y, m, d, sg, &jd, &ns); + decode_year(INT2FIX(y), -1, &nth, &ry); - return dt_lite_new_internal(klass, - jd_local_to_utc(jd, - time_to_df(h, min, s), - of), - 0, sf, of, sg, - y, m, d, h, min, s, - HAVE_JD | HAVE_CIVIL | HAVE_TIME); - } - right: + ret = d_complex_new_internal(klass, + nth, 0, + 0, LONG2NUM(sf), + (int)of, GREGORIAN, + ry, m, d, + h, min, s, + HAVE_CIVIL | HAVE_TIME); { - VALUE jd, fr, vof, ajd; - - jd = rt_civil_to_jd(INT2FIX(y), INT2FIX(m), INT2FIX(d), DBL2NUM(sg)); - fr = rt_time_to_day_fraction(INT2FIX(h), INT2FIX(min), INT2FIX(s)); - fr = f_add(fr, rb_rational_new(LONG2NUM(sf), day_in_nanoseconds)); - vof = rb_rational_new(LONG2NUM(of), INT2FIX(DAY_IN_SECONDS)); - ajd = rt_jd_to_ajd(jd, fr, vof); - return dt_right_new(klass, ajd, vof, DBL2NUM(sg)); + get_d1(ret); + set_sg(dat, sg); } + return ret; } static VALUE -dt_switch_new_by_frags(VALUE klass, VALUE hash, VALUE sg) +dt_new_by_frags(VALUE klass, VALUE hash, VALUE sg) { - VALUE jd, fr, of, t; + VALUE jd, sf, t; + int df, of; + + if (!c_valid_start_p(NUM2DBL(sg))) { + sg = INT2FIX(DEFAULT_SG); + rb_warning("invalid start is ignored"); + } hash = rt_rewrite_frags(hash); hash = rt_complete_frags(klass, hash); + jd = rt__valid_date_frags_p(hash, sg); - fr = rt__valid_time_frags_p(hash); - if (NIL_P(jd) || NIL_P(fr)) + if (NIL_P(jd)) rb_raise(rb_eArgError, "invalid date"); + + { + int rh, rmin, rs; + + if (!c_valid_time_p(NUM2INT(ref_hash("hour")), + NUM2INT(ref_hash("min")), + NUM2INT(ref_hash("sec")), + &rh, &rmin, &rs)) + rb_raise(rb_eArgError, "invalid date"); + + df = time_to_df(rh, rmin, rs); + } + t = ref_hash("sec_fraction"); - if (!NIL_P(t)) - fr = f_add(fr, f_div(t, INT2FIX(DAY_IN_SECONDS))); - t = ref_hash("offset"); if (NIL_P(t)) - of = INT2FIX(0); + sf = INT2FIX(0); else - of = rb_rational_new2(t, INT2FIX(DAY_IN_SECONDS)); - return dt_switch_new_jd(klass, jd, fr, of, sg); + sf = sec_to_ns(t); + + t = ref_hash("offset"); + if (NIL_P(t)) + of = 0; + else { + of = NUM2INT(t); + if (of < -DAY_IN_SECONDS || of > DAY_IN_SECONDS) { + of = 0; + rb_warning("invalid offset is ignored"); + } + } + { + VALUE nth; + int rjd, rjd2; + + decode_jd(jd, &nth, &rjd); + rjd2 = jd_local_to_utc(rjd, df, of); + df = df_local_to_utc(df, of); + + return d_complex_new_internal(klass, + nth, rjd2, + df, sf, + of, NUM2DBL(sg), + 0, 0, 0, + 0, 0, 0, + HAVE_JD | HAVE_DF); + } } /* @@ -7009,7 +7074,7 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass) case 1: fmt = rb_str_new2("%FT%T%z"); case 2: - sg = INT2FIX(ITALY); + sg = INT2FIX(DEFAULT_SG); } { @@ -7018,7 +7083,7 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass) argv2[0] = str; argv2[1] = fmt; hash = date_s__strptime(2, argv2, klass); - return dt_switch_new_by_frags(klass, hash, sg); + return dt_new_by_frags(klass, hash, sg); } } @@ -7054,7 +7119,7 @@ datetime_s_parse(int argc, VALUE *argv, VALUE klass) case 1: comp = Qtrue; case 2: - sg = INT2FIX(ITALY); + sg = INT2FIX(DEFAULT_SG); } { @@ -7063,7 +7128,7 @@ datetime_s_parse(int argc, VALUE *argv, VALUE klass) argv2[0] = str; argv2[1] = comp; hash = date_s__parse(2, argv2, klass); - return dt_switch_new_by_frags(klass, hash, sg); + return dt_new_by_frags(klass, hash, sg); } } @@ -7087,12 +7152,12 @@ datetime_s_iso8601(int argc, VALUE *argv, VALUE klass) case 1: comp = Qtrue; case 2: - sg = INT2FIX(ITALY); + sg = INT2FIX(DEFAULT_SG); } { VALUE hash = date_s__iso8601(klass, str); - return dt_switch_new_by_frags(klass, hash, sg); + return dt_new_by_frags(klass, hash, sg); } } @@ -7116,12 +7181,12 @@ datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass) case 1: comp = Qtrue; case 2: - sg = INT2FIX(ITALY); + sg = INT2FIX(DEFAULT_SG); } { VALUE hash = date_s__rfc3339(klass, str); - return dt_switch_new_by_frags(klass, hash, sg); + return dt_new_by_frags(klass, hash, sg); } } @@ -7145,12 +7210,12 @@ datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass) case 1: comp = Qtrue; case 2: - sg = INT2FIX(ITALY); + sg = INT2FIX(DEFAULT_SG); } { VALUE hash = date_s__xmlschema(klass, str); - return dt_switch_new_by_frags(klass, hash, sg); + return dt_new_by_frags(klass, hash, sg); } } @@ -7175,12 +7240,12 @@ datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass) case 1: comp = Qtrue; case 2: - sg = INT2FIX(ITALY); + sg = INT2FIX(DEFAULT_SG); } { VALUE hash = date_s__rfc2822(klass, str); - return dt_switch_new_by_frags(klass, hash, sg); + return dt_new_by_frags(klass, hash, sg); } } @@ -7204,12 +7269,12 @@ datetime_s_httpdate(int argc, VALUE *argv, VALUE klass) case 1: comp = Qtrue; case 2: - sg = INT2FIX(ITALY); + sg = INT2FIX(DEFAULT_SG); } { VALUE hash = date_s__httpdate(klass, str); - return dt_switch_new_by_frags(klass, hash, sg); + return dt_new_by_frags(klass, hash, sg); } } @@ -7233,1563 +7298,13 @@ datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass) case 1: comp = Qtrue; case 2: - sg = INT2FIX(ITALY); + sg = INT2FIX(DEFAULT_SG); } { VALUE hash = date_s__jisx0301(klass, str); - return dt_switch_new_by_frags(klass, hash, sg); - } -} - -/* - * call-seq: - * dt.ajd - * - * Get the date as an Astronomical Julian Day Number. - */ -static VALUE -dt_lite_ajd(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return dat->r.ajd; - { - VALUE r; - - get_dt_jd(dat); - get_dt_df(dat); - r = f_sub(INT2FIX(dat->l.jd), rhalf); - if (dat->l.df) - r = f_add(r, rb_rational_new2(INT2FIX(dat->l.df), - INT2FIX(DAY_IN_SECONDS))); - if (dat->l.sf) - r = f_add(r, rb_rational_new2(INT2FIX(dat->l.sf), - day_in_nanoseconds)); - return r; - } -} - -#undef c_iforward0 -#undef c_iforwardv -#undef c_iforwardop -#define c_iforward0(m) dt_right_##m(self) -#define c_iforwardv(m) dt_right_##m(argc, argv, self) -#define c_iforwardop(m) dt_right_##m(self, other) - -static VALUE -dt_right_amjd(VALUE self) -{ - get_dt1(self); - assert(!light_mode_p(dat)); - return rt_ajd_to_amjd(dat->r.ajd); -} - -/* - * call-seq: - * dt.amjd - * - * Get the date as an Astronomical Modified Julian Day Number. - */ -static VALUE -dt_lite_amjd(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(amjd); - { - VALUE r; - - get_dt_jd(dat); - get_dt_df(dat); - r = rb_rational_new1(LONG2NUM(dat->l.jd - 2400001L)); - if (dat->l.df) - r = f_add(r, rb_rational_new2(INT2FIX(dat->l.df), - INT2FIX(DAY_IN_SECONDS))); - if (dat->l.sf) - r = f_add(r, rb_rational_new2(INT2FIX(dat->l.sf), - day_in_nanoseconds)); - return r; - } -} - -#undef return_once -#define return_once(k, expr)\ -{\ - VALUE id, val;\ - get_dt1(self);\ - id = ID2SYM(rb_intern(#k));\ - val = rb_hash_aref(dat->r.cache, id);\ - if (!NIL_P(val))\ - return val;\ - val = expr;\ - rb_hash_aset(dat->r.cache, id, val);\ - return val;\ -} - -static VALUE -dt_right_daynum(VALUE self) -{ - get_dt1(self); - assert(!light_mode_p(dat)); - return_once(daynum, rt_ajd_to_jd(dat->r.ajd, dat->r.of)); -} - -static VALUE -dt_right_jd(VALUE self) -{ - return RARRAY_PTR(c_iforward0(daynum))[0]; -} - -/* - * call-seq: - * dt.jd - * - * Get the date as a Julian Day Number. - */ -static VALUE -dt_lite_jd(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(jd); - { - get_dt_jd(dat); - get_dt_df(dat); - return INT2FIX(local_jd(dat)); - } -} - -static VALUE -dt_right_mjd(VALUE self) -{ - get_dt1(self); - assert(!light_mode_p(dat)); - return rt_jd_to_mjd(dt_right_jd(self)); -} - -/* - * call-seq: - * dt.mjd - * - * Get the date as a Modified Julian Day Number. - */ -static VALUE -dt_lite_mjd(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(mjd); - { - get_dt_jd(dat); - get_dt_df(dat); - return LONG2NUM(local_jd(dat) - 2400001L); - } -} - -static VALUE -dt_right_ld(VALUE self) -{ - get_dt1(self); - assert(!light_mode_p(dat)); - return rt_jd_to_ld(dt_right_jd(self)); -} - -/* - * call-seq: - * dt.ld - * - * Get the date as a Lilian Day Number. - */ -static VALUE -dt_lite_ld(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(ld); - { - get_dt_jd(dat); - get_dt_df(dat); - return LONG2NUM(local_jd(dat) - 2299160L); - } -} - -static VALUE -dt_right_civil(VALUE self) -{ - get_dt1(self); - assert(!light_mode_p(dat)); - return_once(civil, rt_jd_to_civil(dt_right_jd(self), dat->r.sg)); -} - -static VALUE -dt_right_year(VALUE self) -{ - return RARRAY_PTR(c_iforward0(civil))[0]; -} - -/* - * call-seq: - * dt.year - * - * Get the year of this date. - */ -static VALUE -dt_lite_year(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(year); - { - get_dt_civil(dat); - return INT2FIX(dat->l.year); - } -} - -static VALUE -dt_right_ordinal(VALUE self) -{ - get_dt1(self); - assert(!light_mode_p(dat)); - return_once(ordinal, rt_jd_to_ordinal(dt_right_jd(self), dat->r.sg)); -} - -static VALUE -dt_right_yday(VALUE self) -{ - return RARRAY_PTR(c_iforward0(ordinal))[1]; -} - -/* - * call-seq: - * dt.yday - * - * Get the day-of-the-year of this date. - * - * January 1 is day-of-the-year 1 - */ -static VALUE -dt_lite_yday(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(yday); - { - get_dt_civil(dat); - return INT2FIX(civil_to_yday(dat->l.year, dat->l.mon, dat->l.mday)); - } -} - -static VALUE -dt_right_mon(VALUE self) -{ - return RARRAY_PTR(c_iforward0(civil))[1]; -} - -/* - * call-seq: - * dt.mon - * dt.month - * - * Get the month of this date. - * - * January is month 1. - */ -static VALUE -dt_lite_mon(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(mon); - { - get_dt_civil(dat); - return INT2FIX(dat->l.mon); - } -} - -static VALUE -dt_right_mday(VALUE self) -{ - return RARRAY_PTR(c_iforward0(civil))[2]; -} - -/* - * call-seq: - * dt.mday - * dt.day - * - * Get the day-of-the-month of this date. - */ -static VALUE -dt_lite_mday(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(mday); - { - get_dt_civil(dat); - return INT2FIX(dat->l.mday); - } -} - -static VALUE -dt_right_day_fraction(VALUE self) -{ - return RARRAY_PTR(c_iforward0(daynum))[1]; -} - -/* - * call-seq: - * dt.day_fraction - * - * Get any fractional day part of the date. - */ -static VALUE -dt_lite_day_fraction(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(day_fraction); - { - get_dt_df(dat); - return rb_rational_new2(INT2FIX(local_df(dat)), - INT2FIX(DAY_IN_SECONDS)); - } -} - -static VALUE -dt_right_weeknum0(VALUE self) -{ - get_dt1(self); - assert(!light_mode_p(dat)); - return_once(weeknum0, rt_jd_to_weeknum(dt_right_jd(self), - INT2FIX(0), dat->r.sg)); -} - -static VALUE -dt_right_wnum0(VALUE self) -{ - return RARRAY_PTR(c_iforward0(weeknum0))[1]; -} - -static VALUE -dt_lite_wnum0(VALUE self) -{ - int ry, rw, rd; - - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(wnum0); - { - get_dt_jd(dat); - get_dt_df(dat); - jd_to_weeknum(local_jd(dat), 0, dat->l.sg, &ry, &rw, &rd); - return INT2FIX(rw); - } -} - -static VALUE -dt_right_weeknum1(VALUE self) -{ - get_dt1(self); - assert(!light_mode_p(dat)); - return_once(weeknum1, rt_jd_to_weeknum(dt_right_jd(self), - INT2FIX(1), dat->r.sg)); -} - -static VALUE -dt_right_wnum1(VALUE self) -{ - return RARRAY_PTR(c_iforward0(weeknum1))[1]; -} - -static VALUE -dt_lite_wnum1(VALUE self) -{ - int ry, rw, rd; - - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(wnum1); - { - get_dt_jd(dat); - get_dt_df(dat); - jd_to_weeknum(local_jd(dat), 1, dat->l.sg, &ry, &rw, &rd); - return INT2FIX(rw); - } -} - -#ifndef NDEBUG -static VALUE -dt_right_time(VALUE self) -{ - get_dt1(self); - assert(!light_mode_p(dat)); - return_once(time, rt_day_fraction_to_time(dt_right_day_fraction(self))); -} -#endif - -static VALUE -dt_right_time_wo_sf(VALUE self) -{ - get_dt1(self); - assert(!light_mode_p(dat)); - return_once(time_wo_sf, - rt_day_fraction_to_time_wo_sf(dt_right_day_fraction(self))); -} - -static VALUE -dt_right_time_sf(VALUE self) -{ - get_dt1(self); - assert(!light_mode_p(dat)); - return_once(time_sf, f_mul(f_mod(dt_right_day_fraction(self), - SECONDS_IN_DAY), - INT2FIX(DAY_IN_SECONDS))); -} - -static VALUE -dt_right_hour(VALUE self) -{ -#if 0 - return RARRAY_PTR(c_iforward0(time))[0]; -#else - return RARRAY_PTR(c_iforward0(time_wo_sf))[0]; -#endif -} - -/* - * call-seq: - * dt.hour - * - * Get the hour of this date. - */ -static VALUE -dt_lite_hour(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(hour); - { - get_dt_time(dat); - return INT2FIX(dat->l.hour); - } -} - -static VALUE -dt_right_min(VALUE self) -{ -#if 0 - return RARRAY_PTR(c_iforward0(time))[1]; -#else - return RARRAY_PTR(c_iforward0(time_wo_sf))[1]; -#endif -} - -/* - * call-seq: - * dt.min - * dt.minute - * - * Get the minute of this date. - */ -static VALUE -dt_lite_min(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(min); - { - get_dt_time(dat); - return INT2FIX(dat->l.min); - } -} - -static VALUE -dt_right_sec(VALUE self) -{ -#if 0 - return RARRAY_PTR(c_iforward0(time))[2]; -#else - return RARRAY_PTR(c_iforward0(time_wo_sf))[2]; -#endif -} - -/* - * call-seq: - * dt.sec - * dt.second - * - * Get the second of this date. - */ -static VALUE -dt_lite_sec(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(sec); - { - get_dt_time(dat); - return INT2FIX(dat->l.sec); - } -} - -static VALUE -dt_right_sec_fraction(VALUE self) -{ -#if 0 - return RARRAY_PTR(c_iforward0(time))[3]; -#else - return c_iforward0(time_sf); -#endif -} - -/* - * call-seq: - * dt.sec_fraction - * dt.second_fraction - * - * Get the fraction-of-a-second of this date. - */ -static VALUE -dt_lite_sec_fraction(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(sec_fraction); - return rb_rational_new2(INT2FIX(dat->l.sf), INT2FIX(SECOND_IN_NANOSECONDS)); -} - -/* - * call-seq: - * dt.offset - * - * Get the offset of this date. - */ -static VALUE -dt_lite_offset(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return dat->r.of; - return rb_rational_new2(INT2FIX(dat->l.of), INT2FIX(DAY_IN_SECONDS)); -} - -#define decode_offset(of,s,h,m)\ -{\ - int a;\ - s = (of < 0) ? '-' : '+';\ - a = (of < 0) ? -of : of;\ - h = a / HOUR_IN_SECONDS;\ - m = a % HOUR_IN_SECONDS / MINUTE_IN_SECONDS;\ -} - -static VALUE -dt_right_zone(VALUE self) -{ - get_dt1(self); - assert(!light_mode_p(dat)); - { - int sign; - VALUE hh, mm, ss, fr; - - if (f_negative_p(dat->r.of)) { - sign = '-'; - fr = f_abs(dat->r.of); - } - else { - sign = '+'; - fr = dat->r.of; - } - ss = f_div(fr, SECONDS_IN_DAY); - - hh = f_idiv(ss, INT2FIX(HOUR_IN_SECONDS)); - ss = f_mod(ss, INT2FIX(HOUR_IN_SECONDS)); - - mm = f_idiv(ss, INT2FIX(MINUTE_IN_SECONDS)); - - return rb_enc_sprintf(rb_usascii_encoding(), - "%c%02d:%02d", - sign, NUM2INT(hh), NUM2INT(mm)); - } -} - -/* - * call-seq: - * dt.zone - * - * Get the zone name of this date. - */ -static VALUE -dt_lite_zone(VALUE self) -{ - int s, h, m; - - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(zone); - decode_offset(dat->l.of, s, h, m); - return rb_enc_sprintf(rb_usascii_encoding(), "%c%02d:%02d", s, h, m); -} - -static VALUE -dt_right_commercial(VALUE self) -{ - get_dt1(self); - assert(!light_mode_p(dat)); - return_once(commercial, rt_jd_to_commercial(dt_right_jd(self), dat->r.sg)); -} - -static VALUE -dt_right_cwyear(VALUE self) -{ - return RARRAY_PTR(c_iforward0(commercial))[0]; -} - -/* - * call-seq: - * dt.cwyear - * - * Get the commercial year of this date. See *Commercial* *Date* - * in the introduction for how this differs from the normal year. - */ -static VALUE -dt_lite_cwyear(VALUE self) -{ - int ry, rw, rd; - - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(cwyear); - { - get_dt_jd(dat); - get_dt_df(dat); - jd_to_commercial(local_jd(dat), dat->l.sg, &ry, &rw, &rd); - return INT2FIX(ry); - } -} - -static VALUE -dt_right_cweek(VALUE self) -{ - return RARRAY_PTR(c_iforward0(commercial))[1]; -} - -/* - * call-seq: - * dt.cweek - * - * Get the commercial week of the year of this date. - */ -static VALUE -dt_lite_cweek(VALUE self) -{ - int ry, rw, rd; - - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(cweek); - { - get_dt_jd(dat); - get_dt_df(dat); - jd_to_commercial(local_jd(dat), dat->l.sg, &ry, &rw, &rd); - return INT2FIX(rw); - } -} - -static VALUE -dt_right_cwday(VALUE self) -{ - return RARRAY_PTR(c_iforward0(commercial))[2]; -} - -/* - * call-seq: - * dt.cwday - * - * Get the commercial day of the week of this date. Monday is - * commercial day-of-week 1; Sunday is commercial day-of-week 7. - */ -static VALUE -dt_lite_cwday(VALUE self) -{ - int w; - - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(cwday); - { - get_dt_jd(dat); - get_dt_df(dat); - w = jd_to_wday(local_jd(dat)); - if (w == 0) - w = 7; - return INT2FIX(w); - } -} - -static VALUE -dt_right_wday(VALUE self) -{ - return rt_jd_to_wday(dt_right_jd(self)); -} - -/* - * call-seq: - * dt.wday - * - * Get the week day of this date. Sunday is day-of-week 0; - * Saturday is day-of-week 6. - */ -static VALUE -dt_lite_wday(VALUE self) -{ - int w; - - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(wday); - { - get_dt_jd(dat); - get_dt_df(dat); - w = jd_to_wday(local_jd(dat)); - return INT2FIX(w); - } -} - -/* - * call-seq: - * dt.monday? - * - * Is the current date Monday? - */ -static VALUE -dt_lite_sunday_p(VALUE self) -{ - return f_eqeq_p(dt_lite_wday(self), INT2FIX(0)); -} - -/* - * call-seq: - * dt.monday? - * - * Is the current date Monday? - */ -static VALUE -dt_lite_monday_p(VALUE self) -{ - return f_eqeq_p(dt_lite_wday(self), INT2FIX(1)); -} - -/* - * call-seq: - * dt.tuesday? - * - * Is the current date Tuesday? - */ -static VALUE -dt_lite_tuesday_p(VALUE self) -{ - return f_eqeq_p(dt_lite_wday(self), INT2FIX(2)); -} - -/* - * call-seq: - * dt.wednesday? - * - * Is the current date Wednesday? - */ -static VALUE -dt_lite_wednesday_p(VALUE self) -{ - return f_eqeq_p(dt_lite_wday(self), INT2FIX(3)); -} - -/* - * call-seq: - * dt.thursday? - * - * Is the current date Thursday? - */ -static VALUE -dt_lite_thursday_p(VALUE self) -{ - return f_eqeq_p(dt_lite_wday(self), INT2FIX(4)); -} - -/* - * call-seq: - * dt.friday? - * - * Is the current date Friday? - */ -static VALUE -dt_lite_friday_p(VALUE self) -{ - return f_eqeq_p(dt_lite_wday(self), INT2FIX(5)); -} - -/* - * call-seq: - * dt.saturday? - * - * Is the current date Saturday? - */ -static VALUE -dt_lite_saturday_p(VALUE self) -{ - return f_eqeq_p(dt_lite_wday(self), INT2FIX(6)); -} - -static VALUE -dt_right_julian_p(VALUE self) -{ - get_dt1(self); - assert(!light_mode_p(dat)); - return f_lt_p(dt_right_jd(self), dat->r.sg); -} - -/* - * call-seq: - * dt.julian? - * - * Is the current date old-style (Julian Calendar)? - */ -static VALUE -dt_lite_julian_p(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(julian_p); - return Qfalse; -} - -static VALUE -dt_right_gregorian_p(VALUE self) -{ - get_dt1(self); - assert(!light_mode_p(dat)); - return dt_right_julian_p(self) ? Qfalse : Qtrue; -} - -/* - * call-seq: - * dt.gregorian? - * - * Is the current date new-style (Gregorian Calendar)? - */ -static VALUE -dt_lite_gregorian_p(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(gregorian_p); - return Qtrue; -} - -static VALUE -dt_right_fix_style(VALUE self) -{ - if (dt_right_julian_p(self)) - return DBL2NUM(JULIAN); - return DBL2NUM(GREGORIAN); -} - -static VALUE -dt_right_leap_p(VALUE self) -{ - VALUE style, a; - - style = dt_right_fix_style(self); - a = rt_jd_to_civil(f_sub(rt_civil_to_jd(dt_right_year(self), - INT2FIX(3), INT2FIX(1), style), - INT2FIX(1)), - style); - if (f_eqeq_p(RARRAY_PTR(a)[2], INT2FIX(29))) - return Qtrue; - return Qfalse; -} - -/* - * call-seq: - * dt.leap? - * - * Is this a leap year? - */ -static VALUE -dt_lite_leap_p(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(leap_p); - { - get_dt_civil(dat); - return leap_p(dat->l.year) ? Qtrue : Qfalse; - } -} - -/* - * call-seq: - * dt.start - * - * When is the Day of Calendar Reform for this Date object? - */ -static VALUE -dt_lite_start(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return dat->r.sg; - return DBL2NUM(dat->l.sg); -} - -static VALUE -dt_right_new_start(int argc, VALUE *argv, VALUE self) -{ - get_dt1(self); - return dt_right_new(CLASS_OF(self), - dt_lite_ajd(self), - dt_lite_offset(self), - (argc >= 1) ? argv[0] : INT2FIX(ITALY)); -} - -/* - * call-seq: - * dt.new_start([start=Date::ITALY]) - * - * Create a copy of this Date object using a new Day of Calendar Reform. - */ -static VALUE -dt_lite_new_start(int argc, VALUE *argv, VALUE self) -{ - VALUE vsg; - double sg; - - get_dt1(self); - - if (!light_mode_p(dat)) - return c_iforwardv(new_start); - - rb_scan_args(argc, argv, "01", &vsg); - - sg = ITALY; - if (argc >= 1) - sg = NUM2DBL(vsg); - - { - get_dt_jd(dat); - get_dt_df(dat); - - if (dat->l.jd < sg) - return c_iforwardv(new_start); - - return dt_lite_new_internal_wo_civil(CLASS_OF(self), - dat->l.jd, - dat->l.df, - dat->l.sf, - dat->l.of, - sg, - HAVE_JD | HAVE_DF); - } -} - -/* - * call-seq: - * dt.italy - * - * Create a copy of this Date object that uses the Italian/Catholic - * Day of Calendar Reform. - */ -static VALUE -dt_lite_italy(VALUE self) -{ - VALUE argv[1]; - argv[0] = INT2FIX(ITALY); - return dt_lite_new_start(1, argv, self); -} - -/* - * call-seq: - * dt.england - * - * Create a copy of this Date object that uses the English/Colonial - * Day of Calendar Reform. - */ -static VALUE -dt_lite_england(VALUE self) -{ - VALUE argv[1]; - argv[0] = INT2FIX(ENGLAND); - return dt_lite_new_start(1, argv, self); -} - -/* - * call-seq: - * dt.julian - * - * Create a copy of this Date object that always uses the Julian - * Calendar. - */ -static VALUE -dt_lite_julian(VALUE self) -{ - VALUE argv[1]; - argv[0] = DBL2NUM(JULIAN); - return dt_lite_new_start(1, argv, self); -} - -/* - * call-seq: - * dt.gregorian - * - * Create a copy of this Date object that always uses the Gregorian - * Calendar. - */ -static VALUE -dt_lite_gregorian(VALUE self) -{ - VALUE argv[1]; - argv[0] = DBL2NUM(GREGORIAN); - return dt_lite_new_start(1, argv, self); -} - -static VALUE -dt_right_new_offset(int argc, VALUE *argv, VALUE self) -{ - get_dt1(self); - return dt_right_new(CLASS_OF(self), - dt_lite_ajd(self), - (argc >= 1) ? sof2nof(argv[0]) : INT2FIX(0), - dt_lite_start(self)); -} - -/* - * call-seq: - * dt.new_offset([offset=0]) - * - * Create a copy of this Date object using a new offset. - */ -static VALUE -dt_lite_new_offset(int argc, VALUE *argv, VALUE self) -{ - VALUE vof; - int rof; - - get_dt1(self); - - if (!light_mode_p(dat)) - return c_iforwardv(new_offset); - - rb_scan_args(argc, argv, "01", &vof); - - if (NIL_P(vof)) - rof = 0; - else { - vof = sof2nof(vof); - if (!daydiff_to_sec(vof, &rof)) - return c_iforwardv(new_offset); - } - - { - get_dt_jd(dat); - get_dt_df(dat); - - return dt_lite_new_internal_wo_civil(CLASS_OF(self), - dat->l.jd, - dat->l.df, - dat->l.sf, - rof, - dat->l.sg, - HAVE_JD | HAVE_DF); - } -} - -static VALUE -dt_right_plus(VALUE self, VALUE other) -{ - if (k_numeric_p(other)) { - get_dt1(self); - if (TYPE(other) == T_FLOAT) - other = rb_rational_new2(f_round(f_mul(other, day_in_nanoseconds)), - day_in_nanoseconds); - return dt_right_new(CLASS_OF(self), - f_add(dt_lite_ajd(self), other), - dt_lite_offset(self), - dt_lite_start(self)); - } - rb_raise(rb_eTypeError, "expected numeric"); -} - -/* - * call-seq: - * dt + other - * - * Return a new Date object that is +other+ days later than the - * current one. - * - * +other+ may be a negative value, in which case the new Date - * is earlier than the current one; however, #-() might be - * more intuitive. - * - * If +other+ is not a Numeric, a TypeError will be thrown. In - * particular, two Dates cannot be added to each other. - */ -static VALUE -dt_lite_plus(VALUE self, VALUE other) -{ - get_dt1(self); - - if (!light_mode_p(dat)) - return c_iforwardop(plus); - - switch (TYPE(other)) { - case T_FIXNUM: - { - long jd; - - get_dt1(self); - get_dt_jd(dat); - get_dt_df(dat); - - jd = dat->l.jd + FIX2LONG(other); - - if (LIGHTABLE_JD(jd) && jd >= dat->l.sg) - return dt_lite_new_internal(CLASS_OF(self), - jd, - dat->l.df, - dat->l.sf, - dat->l.of, - dat->l.sg, - 0, 0, 0, - dat->l.hour, - dat->l.min, - dat->l.sec, - (dat->l.flags | HAVE_JD) & - ~HAVE_CIVIL); - } - break; - case T_FLOAT: - { - long sf; - double jd, o, tmp; - int s, df; - - get_dt1(self); - get_dt_jd(dat); - get_dt_df(dat); - - jd = dat->l.jd; - o = NUM2DBL(other); - - if (o < 0) { - s = -1; - o = -o; - } - else - s = +1; - - o = modf(o, &jd); - o *= DAY_IN_SECONDS; - o = modf(o, &tmp); - df = (int)tmp; - o *= SECOND_IN_NANOSECONDS; - sf = (long)round(o); - - if (s < 0) { - jd = -jd; - df = -df; - sf = -sf; - } - - sf = dat->l.sf + sf; - if (sf < 0) { - df -= 1; - sf += SECOND_IN_NANOSECONDS; - } - else if (sf >= SECOND_IN_NANOSECONDS) { - df += 1; - sf -= SECOND_IN_NANOSECONDS; - } - - df = dat->l.df + df; - if (df < 0) { - jd -= 1; - df += DAY_IN_SECONDS; - } - else if (df >= DAY_IN_SECONDS) { - jd += 1; - df -= DAY_IN_SECONDS; - } - - jd = dat->l.jd + jd; - - if (LIGHTABLE_JD(jd) && jd >= dat->l.sg) - return dt_lite_new_internal(CLASS_OF(self), - (long)jd, - df, - sf, - dat->l.of, - dat->l.sg, - 0, 0, 0, - dat->l.hour, - dat->l.min, - dat->l.sec, - (dat->l.flags | - HAVE_JD | HAVE_DF) & - ~HAVE_CIVIL & - ~HAVE_TIME); - } - break; - } - return c_iforwardop(plus); -} - -static VALUE -dt_right_minus(VALUE self, VALUE other) -{ - if (k_numeric_p(other)) { - get_dt1(self); - if (TYPE(other) == T_FLOAT) - other = rb_rational_new2(f_round(f_mul(other, day_in_nanoseconds)), - day_in_nanoseconds); - return dt_right_new(CLASS_OF(self), - f_sub(dt_lite_ajd(self), other), - dt_lite_offset(self), - dt_lite_start(self)); - } - else if (k_date_p(other)) { - return f_sub(dt_lite_ajd(self), f_ajd(other)); - } - rb_raise(rb_eTypeError, "expected numeric"); -} - -/* - * call-seq: - * dt - other - * - * If +other+ is a Numeric value, create a new Date object that is - * +x+ days earlier than the current one. - * - * If +other+ is a Date, return the number of days between the - * two dates; or, more precisely, how many days later the current - * date is than +other+. - * - * If +ohter+ is neither Numeric nor a Date, a TypeError is raised. - */ -static VALUE -dt_lite_minus(VALUE self, VALUE other) -{ - if (k_date_p(other)) - return minus_dd(self, other); - - switch (TYPE(other)) { - case T_FIXNUM: - return dt_lite_plus(self, LONG2NUM(-FIX2LONG(other))); - case T_FLOAT: - return dt_lite_plus(self, DBL2NUM(-NUM2DBL(other))); - } - return c_iforwardop(minus); -} - -/* - * call-seq: - * dt.next_day([n=1]) - * - * Equivalent to dt + n. - */ -static VALUE -dt_lite_next_day(int argc, VALUE *argv, VALUE self) -{ - VALUE n; - - rb_scan_args(argc, argv, "01", &n); - if (argc < 1) - n = INT2FIX(1); - return dt_lite_plus(self, n); -} - -/* - * call-seq: - * dt.prev_day([n=1]) - * - * Equivalent to dt - n. - */ -static VALUE -dt_lite_prev_day(int argc, VALUE *argv, VALUE self) -{ - VALUE n; - - rb_scan_args(argc, argv, "01", &n); - if (argc < 1) - n = INT2FIX(1); - return dt_lite_minus(self, n); -} - -/* - * call-seq: - * dt.next - * - * Return a new Date one day after this one. - */ -static VALUE -dt_lite_next(VALUE self) -{ - return dt_lite_next_day(0, (VALUE *)NULL, self); -} - -/* - * call-seq: - * dt >> n - * - * Return a new Date object that is +n+ months later than - * the current one. - * - * If the day-of-the-month of the current Date is greater - * than the last day of the target month, the day-of-the-month - * of the returned Date will be the last day of the target month. - */ -static VALUE -dt_lite_rshift(VALUE self, VALUE other) -{ - VALUE t, y, m, d, sg, j; - - t = f_add3(f_mul(dt_lite_year(self), INT2FIX(12)), - f_sub(dt_lite_mon(self), INT2FIX(1)), - other); - y = f_idiv(t, INT2FIX(12)); - m = f_mod(t, INT2FIX(12)); - m = f_add(m, INT2FIX(1)); - d = dt_lite_mday(self); - sg = dt_lite_start(self); - - while (NIL_P(j = rt__valid_civil_p(y, m, d, sg))) { - d = f_sub(d, INT2FIX(1)); - if (f_lt_p(d, INT2FIX(1))) - rb_raise(rb_eArgError, "invalid date"); + return dt_new_by_frags(klass, hash, sg); } - return f_add(self, f_sub(j, dt_lite_jd(self))); -} - -/* - * call-seq: - * dt << n - * - * Return a new Date object that is +n+ months earlier than - * the current one. - * - * If the day-of-the-month of the current Date is greater - * than the last day of the target month, the day-of-the-month - * of the returned Date will be the last day of the target month. - */ -static VALUE -dt_lite_lshift(VALUE self, VALUE other) -{ - return dt_lite_rshift(self, f_negate(other)); -} - -/* - * call-seq: - * dt.next_month([n=1]) - * - * Equivalent to dt >> n - */ -static VALUE -dt_lite_next_month(int argc, VALUE *argv, VALUE self) -{ - VALUE n; - - rb_scan_args(argc, argv, "01", &n); - if (argc < 1) - n = INT2FIX(1); - return dt_lite_rshift(self, n); -} - -/* - * call-seq: - * dt.prev_month([n=1]) - * - * Equivalent to dt << n - */ -static VALUE -dt_lite_prev_month(int argc, VALUE *argv, VALUE self) -{ - VALUE n; - - rb_scan_args(argc, argv, "01", &n); - if (argc < 1) - n = INT2FIX(1); - return dt_lite_lshift(self, n); -} - -/* - * call-seq: - * dt.next_year([n=1]) - * - * Equivalent to dt >> (n * 12) - */ -static VALUE -dt_lite_next_year(int argc, VALUE *argv, VALUE self) -{ - VALUE n; - - rb_scan_args(argc, argv, "01", &n); - if (argc < 1) - n = INT2FIX(1); - return dt_lite_rshift(self, f_mul(n, INT2FIX(12))); -} - -/* - * call-seq: - * dt.prev_year([n=1]) - * - * Equivalent to dt << (n * 12) - */ -static VALUE -dt_lite_prev_year(int argc, VALUE *argv, VALUE self) -{ - VALUE n; - - rb_scan_args(argc, argv, "01", &n); - if (argc < 1) - n = INT2FIX(1); - return dt_lite_lshift(self, f_mul(n, INT2FIX(12))); -} - -static VALUE -dt_right_cmp(VALUE self, VALUE other) -{ - if (k_numeric_p(other)) { - get_dt1(self); - return f_cmp(dt_lite_ajd(self), other); - } - else if (k_date_p(other)) { - return f_cmp(dt_lite_ajd(self), f_ajd(other)); - } - return rb_num_coerce_cmp(self, other, rb_intern("<=>")); -} -/* - * call-seq: - * dt <=> other - * - * Compare this date with another date. - * - * +other+ can also be a Numeric value, in which case it is - * interpreted as an Astronomical Julian Day Number. - * - * Comparison is by Astronomical Julian Day Number, including - * fractional days. This means that both the time and the - * offset are taken into account when comparing - * two DateTime instances. When comparing a DateTime instance - * with a Date instance, the time of the latter will be - * considered as falling on midnight UTC. - */ -static VALUE -dt_lite_cmp(VALUE self, VALUE other) -{ - if (k_date_p(other)) - return cmp_dd(self, other); - return c_iforwardop(cmp); -} - -static VALUE -dt_right_equal(VALUE self, VALUE other) -{ - if (k_numeric_p(other)) { - get_dt1(self); - return f_eqeq_p(dt_lite_jd(self), other); - } - else if (k_date_p(other)) { - return f_eqeq_p(dt_lite_jd(self), f_jd(other)); - } - return rb_num_coerce_cmp(self, other, rb_intern("==")); -} - -/* - * call-seq: - * dt == other - * - * The relationship operator for Date. - * - * Compares dates by Julian Day Number. When comparing - * two DateTime instances, or a DateTime with a Date, - * the instances will be regarded as equivalent if they - * fall on the same date in local time. - */ -static VALUE -dt_lite_equal(VALUE self, VALUE other) -{ - if (k_date_p(other)) - return equal_dd(self, other); - return c_iforwardop(equal); -} - -static VALUE -dt_right_eql_p(VALUE self, VALUE other) -{ - if (k_date_p(other) && f_eqeq_p(self, other)) - return Qtrue; - return Qfalse; -} - -/* - * call-seq: - * dt.eql?(other) - * - * Is this Date equal to +other+? - * - * +other+ must both be a Date object, and represent the same date. - */ -static VALUE -dt_lite_eql_p(VALUE self, VALUE other) -{ - if (k_date_p(other)) - return eql_p_dd(self, other); - return c_iforwardop(eql_p); -} - -static VALUE -dt_right_hash(VALUE self) -{ - get_dt1(self); - assert(!light_mode_p(dat)); - return rb_hash(dat->r.ajd); -} - -/* - * call-seq: - * dt.hash - * - * Calculate a hash value for this date. - */ -static VALUE -dt_lite_hash(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(hash); - return rb_hash(dt_lite_ajd(self)); -} - -static VALUE -dt_right_to_s(VALUE self) -{ - VALUE a, b, c, argv[8]; - - get_dt1(self); - assert(!light_mode_p(dat)); - - argv[0] = rb_usascii_str_new2("%.4d-%02d-%02dT%02d:%02d:%02d%s"); - a = dt_right_civil(self); - b = dt_right_time_wo_sf(self); - c = dt_right_zone(self); - argv[1] = RARRAY_PTR(a)[0]; - argv[2] = RARRAY_PTR(a)[1]; - argv[3] = RARRAY_PTR(a)[2]; - argv[4] = RARRAY_PTR(b)[0]; - argv[5] = RARRAY_PTR(b)[1]; - argv[6] = RARRAY_PTR(b)[2]; - argv[7] = c; - return rb_f_sprintf(8, argv); } /* @@ -8801,110 +7316,38 @@ dt_right_to_s(VALUE self) static VALUE dt_lite_to_s(VALUE self) { - int s, h, m; - - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(to_s); - { - get_dt_civil(dat); - get_dt_time(dat); - decode_offset(dat->l.of, s, h, m); - return rb_enc_sprintf(rb_usascii_encoding(), - "%.4d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d", - dat->l.year, dat->l.mon, dat->l.mday, - dat->l.hour, dat->l.min, dat->l.sec, - s, h, m); - } -} - -static VALUE -dt_right_inspect(VALUE self) -{ - VALUE argv[6]; - - get_dt1(self); - assert(!light_mode_p(dat)); - - argv[0] = rb_usascii_str_new2("#<%s[R]: %s (%s,%s,%s)>"); - argv[1] = rb_class_name(CLASS_OF(self)); - argv[2] = dt_right_to_s(self); - argv[3] = dat->r.ajd; - argv[4] = dat->r.of; - argv[5] = dat->r.sg; - return rb_f_sprintf(6, argv); -} + get_d1(self); -/* - * call-seq: - * dt.inspect - * - * Return internal object state as a programmer-readable string. - */ -static VALUE -dt_lite_inspect(VALUE self) -{ - int s, h, m; + if (f_zero_p(m_nth(dat))) { + int s, h, m; - get_dt1(self); - if (!light_mode_p(dat)) - return c_iforward0(inspect); - { - get_dt_civil(dat); - get_dt_time(dat); - get_dt_jd(dat); - get_dt_df(dat); - decode_offset(dat->l.of, s, h, m); + decode_offset(m_of(dat), s, h, m); return rb_enc_sprintf(rb_usascii_encoding(), - "#<%s[L]: " - "%.4d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d " - "((%ldj,%ds,%.0fn),%d/86400,%.0f)>", - rb_obj_classname(self), - dat->l.year, dat->l.mon, dat->l.mday, - dat->l.hour, dat->l.min, dat->l.sec, - s, h, m, - dat->l.jd, dat->l.df, (double)dat->l.sf, - dat->l.of, dat->l.sg); - } -} - -static void -dt_lite_set_tmx(VALUE self, struct tmx *tmx) -{ - get_dt1(self); - - if (!light_mode_p(dat)) { - tmx->year = dt_right_year(self); - tmx->yday = FIX2INT(dt_right_yday(self)); - tmx->mon = FIX2INT(dt_right_mon(self)); - tmx->mday = FIX2INT(dt_right_mday(self)); - tmx->hour = FIX2INT(dt_right_hour(self)); - tmx->min = FIX2INT(dt_right_min(self)); - tmx->sec = FIX2INT(dt_right_sec(self)); - tmx->wday = FIX2INT(dt_right_wday(self)); - tmx->offset = f_mul(dat->r.of, INT2FIX(DAY_IN_SECONDS)); - tmx->zone = RSTRING_PTR(dt_right_zone(self)); - tmx->timev = f_mul(f_sub(dat->r.ajd, UNIX_EPOCH_IN_AJD), - INT2FIX(DAY_IN_SECONDS)); + "%.4d-%02d-%02dT" + "%02d:%02d:%02d" + "%c%02d:%02d", + m_year(dat), m_mon(dat), m_mday(dat), + m_hour(dat), m_min(dat), m_sec(dat), + s, h, m); } else { - get_dt_jd(dat); - get_dt_df(dat); - get_dt_civil(dat); - get_dt_time(dat); - - tmx->year = LONG2NUM(dat->l.year); - tmx->yday = civil_to_yday(dat->l.year, dat->l.mon, dat->l.mday); - tmx->mon = dat->l.mon; - tmx->mday = dat->l.mday; - tmx->hour = dat->l.hour; - tmx->min = dat->l.min; - tmx->sec = dat->l.sec; - tmx->wday = jd_to_wday(local_jd(dat)); - tmx->offset = INT2FIX(dat->l.of); - tmx->zone = RSTRING_PTR(dt_lite_zone(self)); - tmx->timev = f_mul(f_sub(dt_lite_ajd(self), UNIX_EPOCH_IN_AJD), - INT2FIX(DAY_IN_SECONDS)); + int s, h, m; + VALUE argv[10]; + + decode_offset(m_of(dat), s, h, m); + argv[0] = rb_usascii_str_new2("%.4d-%02d-%02dT" + "%02d:%02d:%02d" + "%c%02d:%02d"); + argv[1] = m_real_year(dat); + argv[2] = INT2FIX(m_mon(dat)); + argv[3] = INT2FIX(m_mday(dat)); + argv[4] = INT2FIX(m_hour(dat)); + argv[5] = INT2FIX(m_min(dat)); + argv[6] = INT2FIX(m_sec(dat)); + argv[7] = INT2FIX(s); + argv[8] = INT2FIX(h); + argv[9] = INT2FIX(m); + return rb_f_sprintf(10, argv); } } @@ -8918,7 +7361,7 @@ static VALUE dt_lite_strftime(int argc, VALUE *argv, VALUE self) { return date_strftime_internal(argc, argv, self, - "%FT%T%:z", dt_lite_set_tmx); + "%FT%T%:z", d_lite_set_tmx); } static VALUE @@ -8931,31 +7374,19 @@ dt_lite_iso8601_timediv(VALUE self, VALUE n) else { VALUE argv[3]; + get_d1(self); + argv[0] = rb_usascii_str_new2(".%0*d"); argv[1] = n; - argv[2] = f_round(f_div(dt_lite_sec_fraction(self), - rb_rational_new2(INT2FIX(1), - f_expt(INT2FIX(10), n)))); + argv[2] = f_round(f_quo(m_sf_in_sec(dat), + f_quo(INT2FIX(1), + f_expt(INT2FIX(10), n)))); f = rb_f_sprintf(3, argv); } fmt = f_add3(rb_usascii_str_new2("T%T"), f, rb_usascii_str_new2("%:z")); - return strftimev(RSTRING_PTR(fmt), self, dt_lite_set_tmx); -} - -/* - * call-seq: - * dt.asctime - * dt.ctime - * - * Equivalent to strftime('%c'). - * See also asctime(3) or ctime(3). - */ -static VALUE -dt_lite_asctime(VALUE self) -{ - return strftimev("%c", self, dt_lite_set_tmx); + return strftimev(RSTRING_PTR(fmt), self, d_lite_set_tmx); } /* @@ -8976,7 +7407,7 @@ dt_lite_iso8601(int argc, VALUE *argv, VALUE self) if (argc < 1) n = INT2FIX(0); - return f_add(strftimev("%F", self, dt_lite_set_tmx), + return f_add(strftimev("%F", self, d_lite_set_tmx), dt_lite_iso8601_timediv(self, n)); } @@ -8995,36 +7426,6 @@ dt_lite_rfc3339(int argc, VALUE *argv, VALUE self) /* * call-seq: - * dt.rfc2822 - * dt.rfc822 - * - * Equivalent to strftime('%a, %-d %b %Y %T %z'). - */ -static VALUE -dt_lite_rfc2822(VALUE self) -{ - return strftimev("%a, %-d %b %Y %T %z", self, dt_lite_set_tmx); -} - -/* - * call-seq: - * dt.httpdate - * - * Equivalent to strftime('%a, %d %b %Y %T GMT'). - * See also RFC 2616. - */ -static VALUE -dt_lite_httpdate(VALUE self) -{ - VALUE argv[1], d; - - argv[0] = INT2FIX(0); - d = dt_lite_new_offset(1, argv, self); - return strftimev("%a, %d %b %Y %T GMT", d, dt_lite_set_tmx); -} - -/* - * call-seq: * dt.jisx0301 * * Return a string as a JIS X 0301 format. @@ -9039,95 +7440,18 @@ dt_lite_jisx0301(int argc, VALUE *argv, VALUE self) if (argc < 1) n = INT2FIX(0); - if (!gengo(dt_lite_jd(self), - dt_lite_year(self), - argv2)) - return f_add(strftimev("%F", self, dt_lite_set_tmx), - dt_lite_iso8601_timediv(self, n)); - return f_add(f_add(rb_f_sprintf(2, argv2), - strftimev(".%m.%d", self, dt_lite_set_tmx)), - dt_lite_iso8601_timediv(self, n)); -} - -/* - * call-seq: - * dt.marshal_dump - * - * Dump to Marshal format. - */ -static VALUE -dt_lite_marshal_dump(VALUE self) -{ - VALUE a; - - get_dt1(self); - - if (!light_mode_p(dat)) - a = rb_ary_new3(3, dat->r.ajd, dat->r.of, dat->r.sg); - else { - get_dt_jd(dat); - get_dt_df(dat); - a = rb_ary_new3(5, - LONG2NUM(dat->l.jd), INT2FIX(dat->l.df), - INT2FIX(dat->l.sf), - INT2FIX(dat->l.of), DBL2NUM(dat->l.sg)); - } - - if (FL_TEST(self, FL_EXIVAR)) { - rb_copy_generic_ivar(a, self); - FL_SET(a, FL_EXIVAR); - } - - return a; -} - -/* - * call-seq: - * dt.marshal_load(ary) - * - * Load from Marshal format. - */ -static VALUE -dt_lite_marshal_load(VALUE self, VALUE a) -{ - get_dt1(self); - - if (TYPE(a) != T_ARRAY) - rb_raise(rb_eTypeError, "expected an array"); - - switch (RARRAY_LEN(a)) { - case 3: - dat->r.ajd = RARRAY_PTR(a)[0]; - dat->r.of = RARRAY_PTR(a)[1]; - dat->r.sg = RARRAY_PTR(a)[2]; - dat->r.cache = rb_hash_new(); - dat->r.flags = DATETIME_OBJ; - break; - case 5: - dat->l.jd = NUM2LONG(RARRAY_PTR(a)[0]); - dat->l.df = FIX2INT(RARRAY_PTR(a)[1]); - dat->l.sf = NUM2LONG(RARRAY_PTR(a)[2]); - dat->l.of = FIX2INT(RARRAY_PTR(a)[3]); - dat->l.sg = NUM2DBL(RARRAY_PTR(a)[4]); - dat->l.year = 0; - dat->l.mon = 0; - dat->l.mday = 0; - dat->l.hour = 0; - dat->l.min = 0; - dat->l.sec = 0; - dat->l.flags = LIGHT_MODE | HAVE_JD | HAVE_DF | DATETIME_OBJ; - break; - default: - rb_raise(rb_eTypeError, "invalid size"); - break; - } + { + get_d1(self); - if (FL_TEST(a, FL_EXIVAR)) { - rb_copy_generic_ivar(self, a); - FL_SET(self, FL_EXIVAR); + if (!gengo(m_real_local_jd(dat), + m_real_year(dat), + argv2)) + return f_add(strftimev("%F", self, d_lite_set_tmx), + dt_lite_iso8601_timediv(self, n)); + return f_add(f_add(rb_f_sprintf(2, argv2), + strftimev(".%m.%d", self, d_lite_set_tmx)), + dt_lite_iso8601_timediv(self, n)); } - - return self; } /* conversions */ @@ -9159,11 +7483,25 @@ time_to_time(VALUE self) static VALUE time_to_date(VALUE self) { - VALUE jd; + VALUE y, nth, ret; + int ry, m, d; + + y = f_year(self); + m = FIX2INT(f_mon(self)); + d = FIX2INT(f_mday(self)); + + decode_year(y, -1, &nth, &ry); - jd = rt_civil_to_jd(f_year(self), f_mon(self), f_mday(self), - INT2FIX(ITALY)); - return d_switch_new_jd(cDate, jd, INT2FIX(ITALY)); + ret = d_simple_new_internal(cDate, + nth, 0, + GREGORIAN, + ry, m, d, + HAVE_CIVIL); + { + get_d1(ret); + set_sg(dat, DEFAULT_SG); + } + return ret; } /* @@ -9175,17 +7513,36 @@ time_to_date(VALUE self) static VALUE time_to_datetime(VALUE self) { - VALUE jd, sec, fr, of; + VALUE y, sf, nth, ret; + int ry, m, d, h, min, s, of; + + y = f_year(self); + m = FIX2INT(f_mon(self)); + d = FIX2INT(f_mday(self)); + + h = FIX2INT(f_hour(self)); + min = FIX2INT(f_min(self)); + s = FIX2INT(f_sec(self)); + if (s == 60) + s = 59; + + sf = sec_to_ns(f_subsec(self)); + of = FIX2INT(f_utc_offset(self)); - jd = rt_civil_to_jd(f_year(self), f_mon(self), f_mday(self), - INT2FIX(ITALY)); - sec = f_sec(self); - if (f_gt_p(sec, INT2FIX(59))) - sec = INT2FIX(59); - fr = rt_time_to_day_fraction(f_hour(self), f_min(self), sec); - fr = f_add(fr, rb_Rational(f_subsec(self), INT2FIX(DAY_IN_SECONDS))); - of = rb_rational_new2(f_utc_offset(self), INT2FIX(DAY_IN_SECONDS)); - return dt_switch_new_jd(cDateTime, jd, fr, of, INT2FIX(ITALY)); + decode_year(y, -1, &nth, &ry); + + ret = d_complex_new_internal(cDateTime, + nth, 0, + 0, sf, + of, DEFAULT_SG, + ry, m, d, + h, min, s, + HAVE_CIVIL | HAVE_TIME); + { + get_d1(ret); + set_sg(dat, DEFAULT_SG); + } + return ret; } /* @@ -9197,10 +7554,12 @@ time_to_datetime(VALUE self) static VALUE date_to_time(VALUE self) { + get_d1(self); + return f_local3(rb_cTime, - d_lite_year(self), - d_lite_mon(self), - d_lite_mday(self)); + m_real_year(dat), + INT2FIX(m_mon(dat)), + INT2FIX(m_mday(dat))); } /* @@ -9224,52 +7583,43 @@ date_to_date(VALUE self) static VALUE date_to_datetime(VALUE self) { - return dt_switch_new_jd(cDateTime, - d_lite_jd(self), - INT2FIX(0), - d_lite_offset(self), - d_lite_start(self)); -} - -#ifndef NDEBUG -static VALUE -date_to_right(VALUE self) -{ get_d1(self); - if (!light_mode_p(dat)) - return self; - return d_right_new(CLASS_OF(self), - d_lite_ajd(self), - d_lite_offset(self), - d_lite_start(self)); -} - -static VALUE -date_to_light(VALUE self) -{ - get_d1(self); - if (light_mode_p(dat)) - return self; - { - VALUE t, jd, df; - - t = rt_ajd_to_jd(dat->r.ajd, INT2FIX(0)); /* as utc */ - jd = RARRAY_PTR(t)[0]; - df = RARRAY_PTR(t)[1]; - - if (!LIGHTABLE_JD(NUM2LONG(jd))) - rb_raise(rb_eRangeError, "jd too big to convert into light"); - - if (!f_zero_p(df)) - rb_warning("day fraction is ignored"); - - if (!f_zero_p(dat->r.of)) - rb_warning("nonzero offset is ignored"); - return d_lite_new(CLASS_OF(self), jd, dat->r.sg); - } -} + if (simple_dat_p(dat)) + return d_simple_new_internal(cDateTime, + dat->s.nth, + dat->s.jd, + dat->s.sg, + dat->s.year, +#ifndef USE_PACK + dat->s.mon, + dat->s.mday, +#else + EX_MON(dat->s.pd), + EX_MDAY(dat->s.pd), #endif + dat->s.flags); + else + return d_complex_new_internal(cDateTime, + dat->c.nth, + dat->c.jd, + 0, + INT2FIX(0), + dat->c.of, + dat->c.sg, + dat->c.year, +#ifndef USE_PACK + dat->c.mon, + dat->c.mday, +#else + EX_MON(dat->c.pd), + EX_MDAY(dat->c.pd), +#endif + 0, + 0, + 0, + dat->c.flags | HAVE_DF | HAVE_TIME); +} /* * call-seq: @@ -9280,18 +7630,22 @@ date_to_light(VALUE self) static VALUE datetime_to_time(VALUE self) { - VALUE argv[1], d; + VALUE d, t; - argv[0] = INT2FIX(0); - d = dt_lite_new_offset(1, argv, self); - d = f_utc6(rb_cTime, - dt_lite_year(d), - dt_lite_mon(d), - dt_lite_mday(d), - dt_lite_hour(d), - dt_lite_min(d), - f_add(dt_lite_sec(d), dt_lite_sec_fraction(d))); - return f_getlocal(d); + d = copy_obj_with_new_offset(self, 0); + { + get_d1(d); + + t = f_utc6(rb_cTime, + m_real_year(dat), + INT2FIX(m_mon(dat)), + INT2FIX(m_mday(dat)), + INT2FIX(m_hour(dat)), + INT2FIX(m_min(dat)), + f_add(INT2FIX(m_sec(dat)), + m_sf_in_sec(dat))); + return f_getlocal(t); + } } /* @@ -9303,9 +7657,37 @@ datetime_to_time(VALUE self) static VALUE datetime_to_date(VALUE self) { - return d_switch_new_jd(cDate, - dt_lite_jd(self), - dt_lite_start(self)); + get_d1(self); + + if (simple_dat_p(dat)) + return d_simple_new_internal(cDate, + dat->s.nth, + m_local_jd(dat), + dat->s.sg, + dat->s.year, +#ifndef USE_PACK + dat->s.mon, + dat->s.mday, +#else + EX_MON(dat->s.pd), + EX_MDAY(dat->s.pd), +#endif + dat->s.flags); + else + return d_simple_new_internal(cDate, + dat->c.nth, + m_local_jd(dat), + dat->c.sg, + dat->c.year, +#ifndef USE_PACK + dat->c.mon, + dat->c.mday, +#else + EX_MON(dat->c.pd), + EX_MDAY(dat->c.pd), +#endif + dat->c.flags & + ~(HAVE_DF | HAVE_TIME | COMPLEX_DAT)); } /* @@ -9321,78 +7703,27 @@ datetime_to_datetime(VALUE self) } #ifndef NDEBUG -static VALUE -datetime_to_right(VALUE self) -{ - get_dt1(self); - if (!light_mode_p(dat)) - return self; - return dt_right_new(CLASS_OF(self), - dt_lite_ajd(self), - dt_lite_offset(self), - dt_lite_start(self)); -} - -static VALUE -datetime_to_light(VALUE self) -{ - get_dt1(self); - if (light_mode_p(dat)) - return self; - { - VALUE t, jd, df, sf, odf; - - t = rt_ajd_to_jd(dat->r.ajd, INT2FIX(0)); /* as utc */ - jd = RARRAY_PTR(t)[0]; - df = RARRAY_PTR(t)[1]; - - if (!LIGHTABLE_JD(NUM2LONG(jd))) - rb_raise(rb_eRangeError, "jd too big to convert into light"); - - if (f_lt_p(dat->r.of, INT2FIX(-1)) || - f_gt_p(dat->r.of, INT2FIX(1))) - rb_raise(rb_eRangeError, "offset too big to convert into light"); - - t = f_mul(df, INT2FIX(DAY_IN_SECONDS)); - df = f_idiv(t, INT2FIX(1)); - sf = f_mod(t, INT2FIX(1)); - - t = f_mul(sf, INT2FIX(SECOND_IN_NANOSECONDS)); - sf = f_idiv(t, INT2FIX(1)); - - if (f_eqeq_p(t, sf)) - rb_warning("second fraction is truncated"); - - t = f_mul(dat->r.of, INT2FIX(DAY_IN_SECONDS)); - odf = f_truncate(t); - - if (f_eqeq_p(t, odf)) - rb_warning("offset is truncated"); - - return dt_lite_new(CLASS_OF(self), - jd, df, sf, odf, dat->r.sg); - } -} -#endif - -#ifndef NDEBUG /* tests */ +#define MIN_YEAR -4713 +#define MAX_YEAR 1000000 +#define MIN_JD -327 +#define MAX_JD 366963925 + static int -test_civil(long from, long to, double sg) +test_civil(int from, int to, double sg) { - long j; + int j; - fprintf(stderr, "test_civil: %ld...%ld (%ld) - %.0f\n", + fprintf(stderr, "test_civil: %d...%d (%d) - %.0f\n", from, to, to - from, sg); for (j = from; j <= to; j++) { - int y, m, d, ns; - long rj; + int y, m, d, rj, ns; - jd_to_civil(j, sg, &y, &m, &d); - civil_to_jd(y, m, d, sg, &rj, &ns); + c_jd_to_civil(j, sg, &y, &m, &d); + c_civil_to_jd(y, m, d, sg, &rj, &ns); if (j != rj) { - fprintf(stderr, "%ld != %ld\n", j, rj); + fprintf(stderr, "%d != %d\n", j, rj); return 0; } } @@ -9420,20 +7751,19 @@ date_s_test_civil(VALUE klass) } static int -test_ordinal(long from, long to, double sg) +test_ordinal(int from, int to, double sg) { - long j; + int j; - fprintf(stderr, "test_ordinal: %ld...%ld (%ld) - %.0f\n", + fprintf(stderr, "test_ordinal: %d...%d (%d) - %.0f\n", from, to, to - from, sg); for (j = from; j <= to; j++) { - int y, d, ns; - long rj; + int y, d, rj, ns; - jd_to_ordinal(j, sg, &y, &d); - ordinal_to_jd(y, d, sg, &rj, &ns); + c_jd_to_ordinal(j, sg, &y, &d); + c_ordinal_to_jd(y, d, sg, &rj, &ns); if (j != rj) { - fprintf(stderr, "%ld != %ld\n", j, rj); + fprintf(stderr, "%d != %d\n", j, rj); return 0; } } @@ -9461,20 +7791,19 @@ date_s_test_ordinal(VALUE klass) } static int -test_commercial(long from, long to, double sg) +test_commercial(int from, int to, double sg) { - long j; + int j; - fprintf(stderr, "test_commercial: %ld...%ld (%ld) - %.0f\n", + fprintf(stderr, "test_commercial: %d...%d (%d) - %.0f\n", from, to, to - from, sg); for (j = from; j <= to; j++) { - int y, w, d, ns; - long rj; + int y, w, d, rj, ns; - jd_to_commercial(j, sg, &y, &w, &d); - commercial_to_jd(y, w, d, sg, &rj, &ns); + c_jd_to_commercial(j, sg, &y, &w, &d); + c_commercial_to_jd(y, w, d, sg, &rj, &ns); if (j != rj) { - fprintf(stderr, "%ld != %ld\n", j, rj); + fprintf(stderr, "%d != %d\n", j, rj); return 0; } } @@ -9502,20 +7831,19 @@ date_s_test_commercial(VALUE klass) } static int -test_weeknum(long from, long to, int f, double sg) +test_weeknum(int from, int to, int f, double sg) { - long j; + int j; - fprintf(stderr, "test_weeknum: %ld...%ld (%ld) - %.0f\n", + fprintf(stderr, "test_weeknum: %d...%d (%d) - %.0f\n", from, to, to - from, sg); for (j = from; j <= to; j++) { - int y, w, d, ns; - long rj; + int y, w, d, rj, ns; - jd_to_weeknum(j, f, sg, &y, &w, &d); - weeknum_to_jd(y, w, d, f, sg, &rj, &ns); + c_jd_to_weeknum(j, f, sg, &y, &w, &d); + c_weeknum_to_jd(y, w, d, f, sg, &rj, &ns); if (j != rj) { - fprintf(stderr, "%ld != %ld\n", j, rj); + fprintf(stderr, "%d != %d\n", j, rj); return 0; } } @@ -9547,20 +7875,19 @@ date_s_test_weeknum(VALUE klass) } static int -test_nth_kday(long from, long to, double sg) +test_nth_kday(int from, int to, double sg) { - long j; + int j; - fprintf(stderr, "test_nth_kday: %ld...%ld (%ld) - %.0f\n", + fprintf(stderr, "test_nth_kday: %d...%d (%d) - %.0f\n", from, to, to - from, sg); for (j = from; j <= to; j++) { - int y, m, n, k, ns; - long rj; + int y, m, n, k, rj, ns; - jd_to_nth_kday(j, sg, &y, &m, &n, &k); - nth_kday_to_jd(y, m, n, k, sg, &rj, &ns); + c_jd_to_nth_kday(j, sg, &y, &m, &n, &k); + c_nth_kday_to_jd(y, m, n, k, sg, &rj, &ns); if (j != rj) { - fprintf(stderr, "%ld != %ld\n", j, rj); + fprintf(stderr, "%d != %d\n", j, rj); return 0; } } @@ -9587,119 +7914,6 @@ date_s_test_nth_kday(VALUE klass) return Qtrue; } -static int -print_emesg(VALUE x, VALUE y) -{ - VALUE argv[3]; - argv[0] = rb_usascii_str_new2("%s != %s\n"); - argv[1] = x; - argv[2] = y; - return fputs(RSTRING_PTR(rb_f_sprintf(3, argv)), stderr); -} - -static int -test_d_switch_new(long from, long to, double sg) -{ - long j; - - fprintf(stderr, "test_d_switch_new: %ld...%ld (%ld) - %.0f\n", - from, to, to - from, sg); - for (j = from; j <= to; j++) { - VALUE jd, ajd, rd, sd; - - jd = LONG2NUM(j); - ajd = rt_jd_to_ajd(jd, INT2FIX(0), INT2FIX(0)); - rd = d_right_new(cDate, ajd, INT2FIX(0), DBL2NUM(sg)); - sd = d_switch_new(cDate, ajd, INT2FIX(0), DBL2NUM(sg)); - if (!f_eqeq_p(rd, sd)) { - print_emesg(rd, sd); - return 0; - } - } - return 1; -} - -static VALUE -date_s_test_d_switch_new(VALUE klass) -{ - if (!test_d_switch_new(MIN_JD, MIN_JD + 366, GREGORIAN)) - return Qfalse; - if (!test_d_switch_new(2305814, 2598007, GREGORIAN)) - return Qfalse; - if (!test_d_switch_new(MAX_JD - 366, MAX_JD, GREGORIAN)) - return Qfalse; - - if (!test_d_switch_new(MIN_JD, MIN_JD + 366, ITALY)) - return Qfalse; - if (!test_d_switch_new(2305814, 2598007, ITALY)) - return Qfalse; - if (!test_d_switch_new(MAX_JD - 366, MAX_JD, ITALY)) - return Qfalse; - - return Qtrue; -} - -static int -test_dt_switch_new(long from, long to, double sg) -{ - long j; - - fprintf(stderr, "test_dt_switch_new: %ld...%ld (%ld) - %.0f\n", - from, to, to - from, sg); - for (j = from; j <= to; j++) { - VALUE jd, vof, ajd, rd, sd; - int of, df; - long sf; - - jd = LONG2NUM(j); - ajd = rt_jd_to_ajd(jd, INT2FIX(0), INT2FIX(0)); - rd = dt_right_new(cDateTime, ajd, INT2FIX(0), DBL2NUM(sg)); - sd = dt_switch_new(cDateTime, ajd, INT2FIX(0), DBL2NUM(sg)); - if (!f_eqeq_p(rd, sd)) { - print_emesg(rd, sd); - return 0; - } - - of = (int)((labs(j) % (DAY_IN_SECONDS * 2)) - DAY_IN_SECONDS); - vof = rb_rational_new2(INT2FIX(of), INT2FIX(DAY_IN_SECONDS)); - df = time_to_df(4, 5, 6); - sf = 123456789L; - ajd = rt_jd_to_ajd(jd, - f_add(rb_rational_new2(INT2FIX(df), - INT2FIX(DAY_IN_SECONDS)), - rb_rational_new2(LONG2NUM(sf), - day_in_nanoseconds)), - vof); - rd = dt_right_new(cDateTime, ajd, vof, DBL2NUM(sg)); - sd = dt_switch_new(cDateTime, ajd, vof, DBL2NUM(sg)); - if (!f_eqeq_p(rd, sd)) { - print_emesg(rd, sd); - return 0; - } - } - return 1; -} - -static VALUE -date_s_test_dt_switch_new(VALUE klass) -{ - if (!test_dt_switch_new(MIN_JD, MIN_JD + 366, GREGORIAN)) - return Qfalse; - if (!test_dt_switch_new(2305814, 2598007, GREGORIAN)) - return Qfalse; - if (!test_dt_switch_new(MAX_JD - 366, MAX_JD, GREGORIAN)) - return Qfalse; - - if (!test_dt_switch_new(MIN_JD, MIN_JD + 366, ITALY)) - return Qfalse; - if (!test_dt_switch_new(2305814, 2598007, ITALY)) - return Qfalse; - if (!test_dt_switch_new(MAX_JD - 366, MAX_JD, ITALY)) - return Qfalse; - - return Qtrue; -} - static VALUE date_s_test_all(VALUE klass) { @@ -9713,10 +7927,6 @@ date_s_test_all(VALUE klass) return Qfalse; if (date_s_test_nth_kday(klass) == Qfalse) return Qfalse; - if (date_s_test_d_switch_new(klass) == Qfalse) - return Qfalse; - if (date_s_test_dt_switch_new(klass) == Qfalse) - return Qfalse; return Qtrue; } #endif @@ -9798,7 +8008,7 @@ mk_ary_of_str(long len, const char *a[]) * This is known as the *Civil* *Date*, and abbreviated * as +civil+ in the Date class. * - * Instead of year, month-of-the-year, and day-of-the-month, + * Instead of year, month-of-the-year, and day-of-the-month, * the date can also be reckoned in terms of year and * day-of-the-year. This is known as the *Ordinal* *Date*, * and is abbreviated as +ordinal+ in the Date class. (Note @@ -9948,10 +8158,18 @@ mk_ary_of_str(long len, const char *a[]) void Init_date_core(void) { +#undef rb_intern +#define rb_intern(str) rb_intern_const(str) + assert(fprintf(stderr, "assert() is now active\n")); - rzero = rb_rational_new1(INT2FIX(0)); - rhalf = rb_rational_new2(INT2FIX(1), INT2FIX(2)); + id_cmp = rb_intern("<=>"); + id_le_p = rb_intern("<="); + id_ge_p = rb_intern(">="); + id_eqeq_p = rb_intern("=="); + + half_days_in_day = rb_rational_new2(INT2FIX(1), INT2FIX(2)); + unix_epoch_in_ajd = rb_rational_new2(INT2FIX(4881175), INT2FIX(2)); #if (LONG_MAX / DAY_IN_SECONDS) > SECOND_IN_NANOSECONDS day_in_nanoseconds = LONG2NUM((long)DAY_IN_SECONDS * @@ -9964,19 +8182,16 @@ Init_date_core(void) INT2FIX(SECOND_IN_NANOSECONDS)); #endif - rb_gc_register_mark_object(rzero); - rb_gc_register_mark_object(rhalf); + rb_gc_register_mark_object(half_days_in_day); + rb_gc_register_mark_object(unix_epoch_in_ajd); rb_gc_register_mark_object(day_in_nanoseconds); + positive_inf = NUM2DBL(rb_const_get(rb_cFloat, rb_intern("INFINITY"))); + negative_inf = -positive_inf; + /* * Class representing a date. * - * Internally, the date is represented as an Astronomical - * Julian Day Number, +ajd+. The Day of Calendar Reform, +start+, is - * also stored, for conversions to other date formats. (There - * is also an +offset+ field for a time zone offset, but this - * is only for the use of the DateTime subclass.) - * * A new Date object is created using one of the object creation * class methods named after the corresponding date format, and the * arguments appropriate to that date format; for instance, @@ -10045,12 +8260,6 @@ Init_date_core(void) rb_define_alloc_func(cDate, d_lite_s_alloc); #ifndef NDEBUG - rb_define_singleton_method(cDate, "new_r!", date_s_new_r_bang, -1); - rb_define_singleton_method(cDate, "new_l!", date_s_new_l_bang, -1); - rb_define_singleton_method(cDate, "new!", date_s_new_bang, -1); -#endif - -#ifndef NDEBUG rb_define_private_method(CLASS_OF(cDate), "_valid_jd?", date_s__valid_jd_p, -1); rb_define_private_method(CLASS_OF(cDate), "_valid_ordinal?", @@ -10090,6 +8299,10 @@ Init_date_core(void) rb_define_singleton_method(cDate, "leap?", date_s_gregorian_leap_p, 1); +#ifndef NDEBUG + rb_define_singleton_method(cDate, "new!", date_s_new_bang, -1); +#endif + rb_define_singleton_method(cDate, "jd", date_s_jd, -1); rb_define_singleton_method(cDate, "ordinal", date_s_ordinal, -1); rb_define_singleton_method(cDate, "civil", date_s_civil, -1); @@ -10121,6 +8334,12 @@ Init_date_core(void) rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, 1); rb_define_singleton_method(cDate, "jisx0301", date_s_jisx0301, -1); +#ifndef NDEBUG + rb_define_method(cDate, "fill", d_lite_fill, 0); +#endif + + rb_define_method(cDate, "initialize_copy", d_lite_initialize_copy, 1); + rb_define_method(cDate, "ajd", d_lite_ajd, 0); rb_define_method(cDate, "amjd", d_lite_amjd, 0); rb_define_method(cDate, "jd", d_lite_jd, 0); @@ -10176,6 +8395,7 @@ Init_date_core(void) rb_define_method(cDate, "england", d_lite_england, 0); rb_define_method(cDate, "julian", d_lite_julian, 0); rb_define_method(cDate, "gregorian", d_lite_gregorian, 0); + rb_define_private_method(cDate, "new_offset", d_lite_new_offset, -1); rb_define_method(cDate, "+", d_lite_plus, 1); @@ -10205,6 +8425,7 @@ Init_date_core(void) rb_define_method(cDate, "to_s", d_lite_to_s, 0); rb_define_method(cDate, "inspect", d_lite_inspect, 0); + rb_define_method(cDate, "strftime", d_lite_strftime, -1); rb_define_method(cDate, "asctime", d_lite_asctime, 0); @@ -10224,14 +8445,6 @@ Init_date_core(void) cDateTime = rb_define_class("DateTime", cDate); - rb_define_alloc_func(cDateTime, dt_lite_s_alloc); - -#ifndef NDEBUG - rb_define_singleton_method(cDateTime, "new_r!", datetime_s_new_r_bang, -1); - rb_define_singleton_method(cDateTime, "new_l!", datetime_s_new_l_bang, -1); - rb_define_singleton_method(cDateTime, "new!", datetime_s_new_bang, -1); -#endif - rb_undef_method(CLASS_OF(cDateTime), "today"); rb_define_singleton_method(cDateTime, "jd", datetime_s_jd, -1); @@ -10270,97 +8483,29 @@ Init_date_core(void) rb_define_singleton_method(cDateTime, "jisx0301", datetime_s_jisx0301, -1); - rb_define_method(cDateTime, "ajd", dt_lite_ajd, 0); - rb_define_method(cDateTime, "amjd", dt_lite_amjd, 0); - rb_define_method(cDateTime, "jd", dt_lite_jd, 0); - rb_define_method(cDateTime, "mjd", dt_lite_mjd, 0); - rb_define_method(cDateTime, "ld", dt_lite_ld, 0); - - rb_define_method(cDateTime, "year", dt_lite_year, 0); - rb_define_method(cDateTime, "yday", dt_lite_yday, 0); - rb_define_method(cDateTime, "mon", dt_lite_mon, 0); - rb_define_method(cDateTime, "month", dt_lite_mon, 0); - rb_define_method(cDateTime, "mday", dt_lite_mday, 0); - rb_define_method(cDateTime, "day", dt_lite_mday, 0); - rb_define_method(cDateTime, "day_fraction", dt_lite_day_fraction, 0); - - rb_define_private_method(cDateTime, "wnum0", dt_lite_wnum0, 0); - rb_define_private_method(cDateTime, "wnum1", dt_lite_wnum1, 0); - - rb_define_method(cDateTime, "hour", dt_lite_hour, 0); - rb_define_method(cDateTime, "min", dt_lite_min, 0); - rb_define_method(cDateTime, "minute", dt_lite_min, 0); - rb_define_method(cDateTime, "sec", dt_lite_sec, 0); - rb_define_method(cDateTime, "second", dt_lite_sec, 0); - rb_define_method(cDateTime, "sec_fraction", dt_lite_sec_fraction, 0); - rb_define_method(cDateTime, "second_fraction", dt_lite_sec_fraction, 0); - rb_define_method(cDateTime, "offset", dt_lite_offset, 0); - rb_define_method(cDateTime, "zone", dt_lite_zone, 0); - - rb_define_method(cDateTime, "cwyear", dt_lite_cwyear, 0); - rb_define_method(cDateTime, "cweek", dt_lite_cweek, 0); - rb_define_method(cDateTime, "cwday", dt_lite_cwday, 0); - - rb_define_method(cDateTime, "wday", dt_lite_wday, 0); - - rb_define_method(cDateTime, "sunday?", dt_lite_sunday_p, 0); - rb_define_method(cDateTime, "monday?", dt_lite_monday_p, 0); - rb_define_method(cDateTime, "tuesday?", dt_lite_tuesday_p, 0); - rb_define_method(cDateTime, "wednesday?", dt_lite_wednesday_p, 0); - rb_define_method(cDateTime, "thursday?", dt_lite_thursday_p, 0); - rb_define_method(cDateTime, "friday?", dt_lite_friday_p, 0); - rb_define_method(cDateTime, "saturday?", dt_lite_saturday_p, 0); - - rb_define_method(cDateTime, "julian?", dt_lite_julian_p, 0); - rb_define_method(cDateTime, "gregorian?", dt_lite_gregorian_p, 0); - rb_define_method(cDateTime, "leap?", dt_lite_leap_p, 0); - - rb_define_method(cDateTime, "start", dt_lite_start, 0); - rb_define_method(cDateTime, "new_start", dt_lite_new_start, -1); - rb_define_method(cDateTime, "italy", dt_lite_italy, 0); - rb_define_method(cDateTime, "england", dt_lite_england, 0); - rb_define_method(cDateTime, "julian", dt_lite_julian, 0); - rb_define_method(cDateTime, "gregorian", dt_lite_gregorian, 0); - rb_define_method(cDateTime, "new_offset", dt_lite_new_offset, -1); - - rb_define_method(cDateTime, "+", dt_lite_plus, 1); - rb_define_method(cDateTime, "-", dt_lite_minus, 1); - - rb_define_method(cDateTime, "next_day", dt_lite_next_day, -1); - rb_define_method(cDateTime, "prev_day", dt_lite_prev_day, -1); - rb_define_method(cDateTime, "next", dt_lite_next, 0); - rb_define_method(cDateTime, "succ", dt_lite_next, 0); - - rb_define_method(cDateTime, ">>", dt_lite_rshift, 1); - rb_define_method(cDateTime, "<<", dt_lite_lshift, 1); - - rb_define_method(cDateTime, "next_month", dt_lite_next_month, -1); - rb_define_method(cDateTime, "prev_month", dt_lite_prev_month, -1); - rb_define_method(cDateTime, "next_year", dt_lite_next_year, -1); - rb_define_method(cDateTime, "prev_year", dt_lite_prev_year, -1); - - rb_define_method(cDateTime, "<=>", dt_lite_cmp, 1); - rb_define_method(cDateTime, "===", dt_lite_equal, 1); - rb_define_method(cDateTime, "eql?", dt_lite_eql_p, 1); - rb_define_method(cDateTime, "hash", dt_lite_hash, 0); +#define f_public(m,s) rb_funcall(m, rb_intern("public"), 1,\ + ID2SYM(rb_intern(s))) + + f_public(cDateTime, "hour"); + f_public(cDateTime, "min"); + f_public(cDateTime, "minute"); + f_public(cDateTime, "sec"); + f_public(cDateTime, "second"); + f_public(cDateTime, "sec_fraction"); + f_public(cDateTime, "second_fraction"); + f_public(cDateTime, "offset"); + f_public(cDateTime, "zone"); + f_public(cDateTime, "new_offset"); rb_define_method(cDateTime, "to_s", dt_lite_to_s, 0); - rb_define_method(cDateTime, "inspect", dt_lite_inspect, 0); + rb_define_method(cDateTime, "strftime", dt_lite_strftime, -1); - rb_define_method(cDateTime, "asctime", dt_lite_asctime, 0); - rb_define_method(cDateTime, "ctime", dt_lite_asctime, 0); rb_define_method(cDateTime, "iso8601", dt_lite_iso8601, -1); rb_define_method(cDateTime, "xmlschema", dt_lite_iso8601, -1); rb_define_method(cDateTime, "rfc3339", dt_lite_rfc3339, -1); - rb_define_method(cDateTime, "rfc2822", dt_lite_rfc2822, 0); - rb_define_method(cDateTime, "rfc822", dt_lite_rfc2822, 0); - rb_define_method(cDateTime, "httpdate", dt_lite_httpdate, 0); rb_define_method(cDateTime, "jisx0301", dt_lite_jisx0301, -1); - rb_define_method(cDateTime, "marshal_dump", dt_lite_marshal_dump, 0); - rb_define_method(cDateTime, "marshal_load", dt_lite_marshal_load, 1); - /* conversions */ rb_define_method(rb_cTime, "to_time", time_to_time, 0); @@ -10371,21 +8516,11 @@ Init_date_core(void) rb_define_method(cDate, "to_date", date_to_date, 0); rb_define_method(cDate, "to_datetime", date_to_datetime, 0); -#ifndef NDEBUG - rb_define_method(cDate, "to_right", date_to_right, 0); - rb_define_method(cDate, "to_light", date_to_light, 0); -#endif - rb_define_method(cDateTime, "to_time", datetime_to_time, 0); rb_define_method(cDateTime, "to_date", datetime_to_date, 0); rb_define_method(cDateTime, "to_datetime", datetime_to_datetime, 0); #ifndef NDEBUG - rb_define_method(cDateTime, "to_right", datetime_to_right, 0); - rb_define_method(cDateTime, "to_light", datetime_to_light, 0); -#endif - -#ifndef NDEBUG /* tests */ rb_define_singleton_method(cDate, "test_civil", date_s_test_civil, 0); @@ -10394,10 +8529,6 @@ Init_date_core(void) date_s_test_commercial, 0); rb_define_singleton_method(cDate, "test_weeknum", date_s_test_weeknum, 0); rb_define_singleton_method(cDate, "test_nth_kday", date_s_test_nth_kday, 0); - rb_define_singleton_method(cDate, "test_d_switch_new", - date_s_test_d_switch_new, 0); - rb_define_singleton_method(cDate, "test_dt_switch_new", - date_s_test_dt_switch_new, 0); rb_define_singleton_method(cDate, "test_all", date_s_test_all, 0); #endif } diff --git a/ext/date/date_parse.c b/ext/date/date_parse.c index f08e99b02b..3e21e135f5 100644 --- a/ext/date/date_parse.c +++ b/ext/date/date_parse.c @@ -623,7 +623,7 @@ static int parse_time_cb(VALUE m, VALUE hash) { static const char pat_source[] = - "\\A(\\d+)h?" + "\\A(\\d+)h?" "(?:\\s*:?\\s*(\\d+)m?" "(?:" "\\s*:?\\s*(\\d+)(?:[,.](\\d+))?s?" |