[前][次][番号順一覧][スレッド一覧]

ruby-changes:19873

From: tadf <ko1@a...>
Date: Sat, 4 Jun 2011 17:02:44 +0900 (JST)
Subject: [ruby-changes:19873] tadf:r31920 (trunk): * ext/date/date_core.c (d_lite_inspect): changed the format.

tadf	2011-06-04 17:02:37 +0900 (Sat, 04 Jun 2011)

  New Revision: 31920

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=31920

  Log:
    * ext/date/date_core.c (d_lite_inspect): changed the format.
    * ext/date/date_core.c: refactoring and fixing some bugs.

  Modified files:
    trunk/ChangeLog
    trunk/ext/date/date_core.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 31919)
+++ ChangeLog	(revision 31920)
@@ -1,3 +1,8 @@
+Sat Jun  4 16:59:26 2011  Tadayoshi Funaba  <tadf@d...>
+
+	* ext/date/date_core.c (d_lite_inspect): changed the format.
+	* ext/date/date_core.c: refactoring and fixing some bugs.
+
 Sat Jun  4 11:30:57 2011  Nobuyoshi Nakada  <nobu@r...>
 
 	* class.c (check_mix_method_i, do_mix_method_i): not mix methods
Index: ext/date/date_core.c
===================================================================
--- ext/date/date_core.c	(revision 31919)
+++ ext/date/date_core.c	(revision 31920)
@@ -14,131 +14,13 @@
 #include RUBY_EXTCONF_H
 #endif
 
-#define USE_DPK
+#define USE_PACK
 
 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 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 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 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
-
-#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
-
-struct SimpleDateData
-{
-    unsigned flags;
-    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
-};
-
-struct ComplexDateData
-{
-    unsigned flags;
-    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);
-
-#define get_d2(x,y)\
-    union DateData *adat, *bdat;\
-    Data_Get_Struct(x, union DateData, adat);\
-    Data_Get_Struct(y, union DateData, bdat);
-
 #define f_boolcast(x) ((x) ? Qtrue : Qfalse)
 
 #define f_abs(x) rb_funcall(x, rb_intern("abs"), 0)
@@ -218,8 +100,6 @@
     return rb_funcall(x, rb_intern("=="), 1, y);
 }
 
-#define f_equal_p(x,y) rb_funcall(x, rb_intern("==="), 1, y)
-
 inline static VALUE
 f_zero_p(VALUE x)
 {
@@ -231,7 +111,6 @@
       case T_RATIONAL:
 	{
 	    VALUE num = RRATIONAL(x)->num;
-
 	    return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 0);
 	}
     }
@@ -268,8 +147,272 @@
 #define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d))
 #define MOD(n,d) ((n)<0 ? NMOD((n),(d)) : (n)%(d))
 
-/* light base */
+#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 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 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 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
+
+#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)
+
+#define REFORM_BEGIN_YEAR 1582
+#define REFORM_END_YEAR   1930
+#define REFORM_BEGIN_JD 2298874	/* ns 1582-01-01 */
+#define REFORM_END_JD   2426355	/* os 1930-12-31 */
+
+#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
+
+#ifdef HAVE_FLOAT_H
+#include <float.h>
+#endif
+
+#if defined(FLT_RADIX) && defined(FLT_MANT_DIG)
+#if FLT_RADIX == 2 && FLT_MANT_DIG > 22
+#define USE_FLOAT
+#define sg_cast float
+#else
+#define sg_cast double
+#endif
+#endif
+
+struct SimpleDateData
+{
+    unsigned flags;
+    VALUE nth;	/* not always canonicalized */
+    int jd;	/* as utc */
+#ifndef USE_FLOAT
+    double sg;  /* 2298874..2426355 or -/+oo */
+#else
+    float sg;	/* at most 22 bits */
+#endif
+    /* decoded as utc=local */
+    int year;	/* truncated */
+#ifndef USE_PACK
+    int mon;
+    int mday;
+#else
+    /* packed civil */
+    unsigned pc;
+#endif
+};
+
+struct ComplexDateData
+{
+    unsigned flags;
+    VALUE nth;	/* not always canonicalized */
+    int jd; 	/* as utc */
+    int df;	/* as utc, in secs */
+    VALUE sf;	/* in nano secs */
+    int of;	/* in secs */
+#ifndef USE_FLOAT
+    double sg;  /* 2298874..2426355 or -/+oo */
+#else
+    float sg;	/* at most 22 bits */
+#endif
+    /* decoded as local */
+    int year;	/* truncated */
+#ifndef USE_PACK
+    int mon;
+    int mday;
+    int hour;
+    int min;
+    int sec;
+#else
+    /* packed civil */
+    unsigned pc;
+#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);
+
+#define get_d1a(x)\
+    union DateData *adat;\
+    Data_Get_Struct(x, union DateData, adat);
+
+#define get_d1b(x)\
+    union DateData *bdat;\
+    Data_Get_Struct(x, union DateData, bdat);
+
+#define get_d2(x,y)\
+    union DateData *adat, *bdat;\
+    Data_Get_Struct(x, union DateData, adat);\
+    Data_Get_Struct(y, union DateData, bdat);
+
+#ifndef USE_PACK
+#define set_to_simple(x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \
+{\
+    (x)->nth = _nth;\
+    (x)->jd = _jd;\
+    (x)->sg = (sg_cast)(_sg);\
+    (x)->year = _year;\
+    (x)->mon = _mon;\
+    (x)->mday = _mday;\
+    (x)->flags = _flags;\
+}
+#else
+#define set_to_simple(x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \
+{\
+    (x)->nth = _nth;\
+    (x)->jd = _jd;\
+    (x)->sg = (sg_cast)(_sg);\
+    (x)->year = _year;\
+    (x)->pc = PACK2(_mon, _mday);\
+    (x)->flags = _flags;\
+}
+#endif
+
+#ifndef USE_PACK
+#define set_to_complex(x, _nth, _jd ,_df, _sf, _of, _sg,\
+_year, _mon, _mday, _hour, _min, _sec, _flags) \
+{\
+    (x)->nth = _nth;\
+    (x)->jd = _jd;\
+    (x)->df = _df;\
+    (x)->sf = _sf;\
+    (x)->of = _of;\
+    (x)->sg = (sg_cast)(_sg);\
+    (x)->year = _year;\
+    (x)->mon = _mon;\
+    (x)->mday = _mday;\
+    (x)->hour = _hour;\
+    (x)->min = _min;\
+    (x)->sec = _sec;\
+    (x)->flags = _flags;\
+}
+#else
+#define set_to_complex(x, _nth, _jd ,_df, _sf, _of, _sg,\
+_year, _mon, _mday, _hour, _min, _sec, _flags) \
+{\
+    (x)->nth = _nth;\
+    (x)->jd = _jd;\
+    (x)->df = _df;\
+    (x)->sf = _sf;\
+    (x)->of = _of;\
+    (x)->sg = (sg_cast)(_sg);\
+    (x)->year = _year;\
+    (x)->pc = PACK5(_mon, _mday, _hour, _min, _sec);\
+    (x)->flags = _flags;\
+}
+#endif
+
+#ifndef USE_PACK
+#define copy_simple_to_complex(x, y) \
+{\
+    (x)->nth = (y)->nth;\
+    (x)->jd = (y)->jd;\
+    (x)->df = 0;\
+    (x)->sf = INT2FIX(0);\
+    (x)->of = 0;\
+    (x)->sg = (sg_cast)((y)->sg);\
+    (x)->year = (y)->year;\
+    (x)->mon = (y)->mon;\
+    (x)->mday = (y)->mday;\
+    (x)->hour = 0;\
+    (x)->min = 0;\
+    (x)->sec = 0;\
+    (x)->flags = (y)->flags;\
+}
+#else
+#define copy_simple_to_complex(x, y) \
+{\
+    (x)->nth = (y)->nth;\
+    (x)->jd = (y)->jd;\
+    (x)->df = 0;\
+    (x)->sf = INT2FIX(0);\
+    (x)->of = 0;\
+    (x)->sg = (sg_cast)((y)->sg);\
+    (x)->year = (y)->year;\
+    (x)->pc = PACK5(EX_MON((y)->pc), EX_MDAY((y)->pc), 0, 0, 0);\
+    (x)->flags = (y)->flags;\
+}
+#endif
+
+#ifndef USE_PACK
+#define copy_complex_to_simple(x, y) \
+{\
+    (x)->nth = (y)->nth;\
+    (x)->jd = (y)->jd;\
+    (x)->sg = (sg_cast)((y)->sg);\
+    (x)->year = (y)->year;\
+    (x)->mon = (y)->mon;\
+    (x)->mday = (y)->mday;\
+    (x)->flags = (y)->flags;\
+}
+#else
+#define copy_complex_to_simple(x, y) \
+{\
+    (x)->nth = (y)->nth;\
+    (x)->jd = (y)->jd;\
+    (x)->sg = (sg_cast)((y)->sg);\
+    (x)->year = (y)->year;\
+    (x)->pc = PACK5(EX_MON((y)->pc), EX_MDAY((y)->pc), 0, 0, 0);\
+    (x)->flags = (y)->flags;\
+}
+#endif
+
+/* base */
+
 static int c_valid_civil_p(int, int, int, double,
 			   int *, int *, int *, int *);
 
@@ -518,33 +661,67 @@
 };
 
 inline static int
-c_leap_p(int y)
+c_julian_leap_p(int y)
 {
-    return (MOD(y, 4) == 0 && y % 100 != 0) || (MOD(y, 400) == 0);
+    return MOD(y, 4) == 0;
 }
 
+inline static int
+c_gregorian_leap_p(int y)
+{
+    return MOD(y, 4) == 0 && y % 100 != 0 || MOD(y, 400) == 0;
+}
+
 static int
-c_last_day_of_month(int y, int m)
+c_julian_last_day_of_month(int y, int m)
 {
-    return monthtab[c_leap_p(y) ? 1 : 0][m];
+    assert(m >= 1 && m <= 12);
+    return monthtab[c_julian_leap_p(y) ? 1 : 0][m];
 }
 
 static int
+c_gregorian_last_day_of_month(int y, int m)
+{
+    assert(m >= 1 && m <= 12);
+    return monthtab[c_gregorian_leap_p(y) ? 1 : 0][m];
+}
+
+static int
+c_valid_julian_p(int y, int m, int d, int *rm, int *rd)
+{
+    int last;
+
+    if (m < 0)
+	m += 13;
+    if (m < 0 || m > 12)
+	return 0;
+    last = c_julian_last_day_of_month(y, m);
+    if (d < 0)
+	d = last + d + 1;
+    if (d < 1 || d > last)
+	return 0;
+    *rm = m;
+    *rd = d;
+    return 1;
+}
+
+static int
 c_valid_gregorian_p(int y, int m, int d, int *rm, int *rd)
 {
     int last;
 
     if (m < 0)
 	m += 13;
-    last = c_last_day_of_month(y, m);
+    if (m < 0 || m > 12)
+	return 0;
+    last = c_gregorian_last_day_of_month(y, m);
     if (d < 0)
 	d = last + d + 1;
-
+    if (d < 1 || d > last)
+	return 0;
     *rm = m;
     *rd = d;
-
-    return !(m < 0 || m > 12 ||
-	     d < 1 || d > last);
+    return 1;
 }
 
 static int
@@ -666,15 +843,16 @@
 	     (h == 24 && (min > 0 || s > 0)));
 }
 
-static int
+inline static int
 c_valid_start_p(double sg)
 {
     if (!isinf(sg)) {
-	if (sg < ITALY)
+	if (sg < REFORM_BEGIN_JD)
 	    return 0;
-	if (sg > 2451910)
+	if (sg > REFORM_END_JD)
 	    return 0;
-    }
+    } else if (isnan(sg))
+	return 0;
     return 1;
 }
 
@@ -728,13 +906,22 @@
     return h * HOUR_IN_SECONDS + min * MINUTE_IN_SECONDS + s;
 }
 
+inline static void
+df_to_time(int df, int *h, int *min, int *s)
+{
+    *h = df / HOUR_IN_SECONDS;
+    df %= HOUR_IN_SECONDS;
+    *min = df / MINUTE_IN_SECONDS;
+    *s = df % MINUTE_IN_SECONDS;
+}
+
 static VALUE
 sec_to_day(VALUE s)
 {
     return f_quo(s, INT2FIX(DAY_IN_SECONDS));
 }
 
-static VALUE
+inline static VALUE
 isec_to_day(int s)
 {
     return sec_to_day(INT2FIX(s));
@@ -753,16 +940,31 @@
 }
 
 #ifndef NDEBUG
-static VALUE
+inline static VALUE
 ins_to_day(int n)
 {
     return ns_to_day(INT2FIX(n));
 }
 #endif
 
+static int
+safe_mul_p(VALUE x, long m)
+{
+    long ix;
+
+    if (!FIXNUM_P(x))
+	return 0;
+    ix = FIX2LONG(x);
+    if (ix >= (FIXNUM_MAX / m))
+	return 0;
+    return 1;
+}
+
 static VALUE
 day_to_sec(VALUE d)
 {
+    if (safe_mul_p(d, DAY_IN_SECONDS))
+	return LONG2FIX(FIX2LONG(d) * DAY_IN_SECONDS);
     return f_mul(d, INT2FIX(DAY_IN_SECONDS));
 }
 
@@ -777,6 +979,8 @@
 static VALUE
 sec_to_ns(VALUE s)
 {
+    if (safe_mul_p(s, SECOND_IN_NANOSECONDS))
+	return LONG2FIX(FIX2LONG(s) * SECOND_IN_NANOSECONDS);
     return f_mul(s, INT2FIX(SECOND_IN_NANOSECONDS));
 }
 
@@ -844,6 +1048,15 @@
     return negative_inf;
 }
 
+inline static double
+x_sg(union DateData *x)
+{
+    if (simple_dat_p(x))
+	return s_sg(x);
+    else
+	return c_sg(x);
+}
+
 inline static void
 get_s_jd(union DateData *x)
 {
@@ -855,7 +1068,7 @@
 #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),
+	c_civil_to_jd(x->s.year, EX_MON(x->s.pc), EX_MDAY(x->s.pc),
 		      s_sg(x), &jd, &ns);
 #endif
 	x->s.jd = jd;
@@ -877,7 +1090,7 @@
 	x->s.mon = m;
 	x->s.mday = d;
 #else
-	x->s.pd = PACK2(m, d);
+	x->s.pc = PACK2(m, d);
 #endif
 	x->s.flags |= HAVE_CIVIL;
     }
@@ -893,9 +1106,9 @@
 	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.df = df_local_to_utc(time_to_df(EX_HOUR(x->c.pc),
+					     EX_MIN(x->c.pc),
+					     EX_SEC(x->c.pc)),
 				  x->c.of);
 #endif
 	x->c.flags |= HAVE_DF;
@@ -911,23 +1124,17 @@
 	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;
+	df_to_time(r, &x->c.hour, &x->c.min, &x->c.sec);
 	x->c.flags |= HAVE_TIME;
 #else
 	int r, m, d, h, min, s;
 
 	assert(have_df_p(x));
+	m = EX_MON(x->c.pc);
+	d = EX_MDAY(x->c.pc);
 	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;
-	min = r / MINUTE_IN_SECONDS;
-	s = r % MINUTE_IN_SECONDS;
-	x->c.pd = PACK5(m, d, h, min, s);
+	df_to_time(r, &h, &min, &s);
+	x->c.pc = PACK5(m, d, h, min, s);
 	x->c.flags |= HAVE_TIME;
 #endif
     }
@@ -944,7 +1151,7 @@
 #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_civil_to_jd(x->c.year, EX_MON(x->c.pc), EX_MDAY(x->c.pc),
 		      c_sg(x), &jd, &ns);
 #endif
 
@@ -955,9 +1162,9 @@
 				  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)),
+				  time_to_df(EX_HOUR(x->c.pc),
+					     EX_MIN(x->c.pc),
+					     EX_SEC(x->c.pc)),
 				  x->c.of);
 #endif
 	x->c.flags |= HAVE_JD;
@@ -984,10 +1191,10 @@
 	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);
+	h = EX_HOUR(x->c.pc);
+	min = EX_MIN(x->c.pc);
+	s = EX_SEC(x->c.pc);
+	x->c.pc = PACK5(m, d, h, min, s);
 #endif
 	x->c.flags |= HAVE_CIVIL;
     }
@@ -1020,6 +1227,21 @@
     period = (style < 0) ?
 	CM_PERIOD_GCY :
 	CM_PERIOD_JCY;
+    if (FIXNUM_P(y)) {
+	long iy, it, inth;
+
+	iy = FIX2LONG(y);
+	if (iy >= (FIXNUM_MAX - 4712))
+	    goto big;
+	it = iy + 4712; /* shift */
+	inth = DIV(it, ((long)period));
+	*nth = LONG2FIX(inth);
+	if (inth)
+	    it = MOD(it, ((long)period));
+	*ry = (int)it - 4712; /* unshift */
+	return;
+    }
+  big:
     t = f_add(y, INT2FIX(4712)); /* shift */
     *nth = f_idiv(t, INT2FIX(period));
     if (f_nonzero_p(*nth))
@@ -1067,37 +1289,39 @@
     *rjd = f_add(f_mul(INT2FIX(CM_PERIOD), nth), INT2FIX(jd));
 }
 
-static double
+inline static double
 style_p(VALUE y, double sg)
 {
     double style = 0;
 
     if (isinf(sg))
-	style = (sg < 0) ? negative_inf : positive_inf;
+	style = sg;
     else if (!FIXNUM_P(y))
-	style = (f_positive_p(y)) ? negative_inf : positive_inf;
+	style = f_positive_p(y) ? negative_inf : positive_inf;
     else {
-	if (f_lt_p(y, INT2FIX(1582)))
+	long iy = FIX2LONG(y);
+
+	assert(FIXNUM_P(y));
+	if (iy < REFORM_BEGIN_YEAR)
 	    style = positive_inf;
-	else if (f_gt_p(y, INT2FIX(2001)))
+	else if (iy > REFORM_END_YEAR)
 	    style = negative_inf;
     }
     return style;
 }
 
-static VALUE
+inline static VALUE
 m_nth(union DateData *x)
 {
-    if (simple_dat_p(x)) {
+    if (simple_dat_p(x))
 	return x->s.nth;
-    }
     else {
 	get_c_civil(x);
 	return x->c.nth;
     }
 }
 
-static int
+inline static int
 m_jd(union DateData *x)
 {
     if (simple_dat_p(x)) {
@@ -1150,7 +1374,7 @@
     return rjd;
 }
 
-static int
+inline static int
 m_df(union DateData *x)
 {
     if (simple_dat_p(x))
@@ -1188,7 +1412,7 @@
 }
 #endif
 
-static VALUE
+inline static VALUE
 m_sf(union DateData *x)
 {
     if (simple_dat_p(x))
@@ -1235,14 +1459,37 @@
     VALUE r, sf;
     int df;
 
+    if (simple_dat_p(x))
+	return rb_rational_new2(f_sub(f_mul(m_real_jd(x),
+					    INT2FIX(2)),
+				      INT2FIX(1)),
+				INT2FIX(2));
+
     r = f_sub(m_real_jd(x), half_days_in_day);
+    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 VALUE
+m_amjd(union DateData *x)
+{
+    VALUE r, sf;
+    int df;
+
+    r = rb_rational_new1(f_sub(m_real_jd(x), INT2FIX(2400001)));
+
     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));
@@ -1250,7 +1497,7 @@
     return r;
 }
 
-static int
+inline static int
 m_of(union DateData *x)
 {
     if (simple_dat_p(x))
@@ -1267,7 +1514,7 @@
     return isec_to_day(m_of(x));
 }
 
-static double
+inline static double
 m_sg(union DateData *x)
 {
     if (simple_dat_p(x))
@@ -1285,10 +1532,12 @@
     double sg;
 
     if (simple_dat_p(x)) {
+	get_s_jd(x);
 	jd = x->s.jd;
 	sg = s_sg(x);
     }
     else {
+	get_c_jd(x);
 	jd = x->c.jd;
 	sg = c_sg(x);
     }
@@ -1297,13 +1546,35 @@
     return jd < sg;
 }
 
-static int
+inline static int
 m_gregorian_p(union DateData *x)
 {
     return !m_julian_p(x);
 }
 
-static int
+inline static int
+m_proleptic_julian_p(union DateData *x)
+{
+    double sg;
+
+    sg = m_sg(x);
+    if (isinf(sg) && sg > 0)
+	return 1;
+    return 0;
+}
+
+inline static int
+m_proleptic_gregorian_p(union DateData *x)
+{
+    double sg;
+
+    sg = m_sg(x);
+    if (isinf(sg) && sg < 0)
+	return 1;
+    return 0;
+}
+
+inline static int
 m_year(union DateData *x)
 {
     if (simple_dat_p(x)) {
@@ -1325,6 +1596,9 @@
     nth = m_nth(x);
     year = m_year(x);
 
+    if (f_zero_p(nth))
+	return INT2FIX(year);
+
     encode_year(nth, year,
 		m_gregorian_p(x) ? -1 : +1,
 		&ry);
@@ -1333,21 +1607,22 @@
 
 
 #ifdef USE_PACK
-static int
-m_pd(union DateData *x)
+inline static int
+m_pc(union DateData *x)
 {
     if (simple_dat_p(x)) {
 	get_s_civil(x);
-	return x->s.pd;
+	return x->s.pc;
     }
     else {
 	get_c_civil(x);
-	return x->c.pd;
+	get_c_time(x);
+	return x->c.pc;
     }
 }
 #endif
 
-static int
+inline static int
 m_mon(union DateData *x)
 {
     if (simple_dat_p(x)) {
@@ -1355,7 +1630,7 @@
 #ifndef USE_PACK
 	return x->s.mon;
 #else
-	return EX_MON(x->s.pd);
+	return EX_MON(x->s.pc);
 #endif
     }
     else {
@@ -1363,12 +1638,12 @@
 #ifndef USE_PACK
 	return x->c.mon;
 #else
-	return EX_MON(x->c.pd);
+	return EX_MON(x->c.pc);
 #endif
     }
 }
 
-static int
+inline static int
 m_mday(union DateData *x)
 {
     if (simple_dat_p(x)) {
@@ -1376,7 +1651,7 @@
 #ifndef USE_PACK
 	return x->s.mday;
 #else
-	return EX_MDAY(x->s.pd);
+	return EX_MDAY(x->s.pc);
 #endif
     }
     else {
@@ -1384,55 +1659,64 @@
 #ifndef USE_PACK
 	return x->c.mday;
 #else
-	return EX_MDAY(x->c.pd);
+	return EX_MDAY(x->c.pc);
 #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_julian_to_yday(int y, int m, int d)
+{
+    assert(m >= 1 && m <= 12);
+    return yeartab[c_julian_leap_p(y) ? 1 : 0][m] + d;
+}
+
+static int
 c_gregorian_to_yday(int y, int m, int d)
 {
-    return yeartab[c_leap_p(y) ? 1 : 0][m] + d;
+    assert(m >= 1 && m <= 12);
+    return yeartab[c_gregorian_leap_p(y) ? 1 : 0][m] + d;
 }
 
-static void c_jd_to_ordinal(int, double, int *, int *);
-
 static int
 m_yday(union DateData *x)
 {
+    int jd, ry, rd;
     double sg;
-    int jd, ry, rd;
 
-    sg = m_sg(x);
     jd = m_local_jd(x);
-    if ((isinf(sg) && sg < 0) ||
+    sg = x_sg(x); /* !=m_sg() */
+
+    if (m_proleptic_gregorian_p(x) ||
 	(jd - sg) > 366)
 	return c_gregorian_to_yday(m_year(x), m_mon(x), m_mday(x));
+    if (m_proleptic_julian_p(x))
+	return c_julian_to_yday(m_year(x), m_mon(x), m_mday(x));
     c_jd_to_ordinal(jd, sg, &ry, &rd);
     return rd;
 }
 
-static int
+inline 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.pc);
+#endif
+    }
+}
+
+inline static int
 m_min(union DateData *x)
 {
     if (simple_dat_p(x))
@@ -1442,12 +1726,12 @@
 #ifndef USE_PACK
 	return x->c.min;
 #else
-	return EX_MIN(x->c.pd);
+	return EX_MIN(x->c.pc);
 #endif
     }
 }
 
-static int
+inline static int
 m_sec(union DateData *x)
 {
     if (simple_dat_p(x))
@@ -1457,7 +1741,7 @@
 #ifndef USE_PACK
 	return x->c.sec;
 #else
-	return EX_SEC(x->c.pd);
+	return EX_SEC(x->c.pc);
 #endif
     }
 }
@@ -1708,6 +1992,8 @@
 	int jd;
 
 	r = c_valid_ordinal_p(FIX2INT(y), d, sg, rd, &jd, ns);
+	if (!r)
+	    return 0;
 	decode_jd(INT2FIX(jd), nth, rjd);
 	if (f_zero_p(*nth))
 	    *ry = FIX2INT(y);
@@ -1745,6 +2031,8 @@
 	int jd;
 
 	r = c_valid_civil_p(FIX2INT(y), m, d, sg, rm, rd, &jd, ns);
+	if (!r)
+	    return 0;
 	decode_jd(INT2FIX(jd), nth, rjd);
 	if (f_zero_p(*nth))
 	    *ry = FIX2INT(y);
@@ -1753,6 +2041,13 @@
 	    decode_year(y, ns ? -1 : +1, &nth2, ry);
 	}
     }
+    else if (style > 1) {
+	decode_year(y, style, nth, ry);
+	r = c_valid_julian_p(*ry, m, d, rm, rd);
+	if (!r)
+	    return 0;
+	c_civil_to_jd(*ry, *rm, *rd, style, rjd, ns);
+    }
     else {
 	decode_year(y, style, nth, ry);
 	r = c_valid_civil_p(*ry, m, d, style, rm, rd, rjd, ns);
@@ -1773,6 +2068,8 @@
 	int jd;
 
 	r = c_valid_commercial_p(FIX2INT(y), w, d, sg, rw, rd, &jd, ns);
+	if (!r)
+	    return 0;
 	decode_jd(INT2FIX(jd), nth, rjd);
 	if (f_zero_p(*nth))
 	    *ry = FIX2INT(y);
@@ -1801,6 +2098,8 @@
 	int jd;
 
 	r = c_valid_weeknum_p(FIX2INT(y), w, d, f, sg, rw, rd, &jd, ns);
+	if (!r)
+	    return 0;
 	decode_jd(INT2FIX(jd), nth, rjd);
 	if (f_zero_p(*nth))
 	    *ry = FIX2INT(y);
@@ -1830,6 +2129,8 @@
 	int jd;
 
 	r = c_valid_nth_kday_p(FIX2INT(y), m, n, k, sg, rm, rn, rk, &jd, ns);
+	if (!r)
+	    return 0;
 	decode_jd(INT2FIX(jd), nth, rjd);
 	if (f_zero_p(*nth))
 	    *ry = FIX2INT(y);
@@ -1846,8 +2147,6 @@
 }
 #endif
 
-/* date light */
-
 VALUE date_zone_to_diff(VALUE);
 
 static int
@@ -1876,6 +2175,11 @@
 		rb_warning("fraction of offset is ignored");
 	    return 1;
 	}
+      default:
+	if (!k_numeric_p(vof))
+	    rb_raise(rb_eTypeError, "expected numeric");
+	vof = f_to_r(vof);
+	/* fall through */
       case T_RATIONAL:
 	{
 	    VALUE vs = day_to_sec(vof);
@@ -1915,9 +2219,20 @@
     return 0;
 }
 
+/* date */
+
+#define valid_sg(sg) \
+{\
+    if (!c_valid_start_p(sg)) {\
+	sg = 0;\
+	rb_warning("invalid start is ignored");\
+    }\
+}
+
 static VALUE
 valid_jd_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
 {
+    valid_sg(argv[1]);
     return argv[0];
 }
 
@@ -1932,9 +2247,9 @@
 
     argv2[0] = vjd;
     if (argc < 2)
-	argv[1] = DBL2NUM(GREGORIAN);
+	argv2[1] = DBL2NUM(GREGORIAN);
     else
-	argv[1] = vsg;
+	argv2[1] = vsg;
 
     return valid_jd_sub(2, argv2, klass, 1);
 }
@@ -1957,23 +2272,15 @@
 
     argv2[0] = vjd;
     if (argc < 2)
-	argv[1] = INT2FIX(DEFAULT_SG);
+	argv2[1] = INT2FIX(DEFAULT_SG);
     else
-	argv[1] = vsg;
+	argv2[1] = vsg;
 
     if (NIL_P(valid_jd_sub(2, argv2, klass, 0)))
 	return Qfalse;
     return Qtrue;
 }
 
-#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)
 {
@@ -1988,7 +2295,7 @@
 
     valid_sg(sg);
 
-    if (!need_jd && isinf(sg) && sg < 0) {
+    if (!need_jd && (style_p(y, sg) < 0)) {
 	if (!valid_gregorian_p(y, m, d,
 			       &nth, &ry,
 			       &rm, &rd))
@@ -2407,9 +2714,11 @@
 static VALUE
 date_s_julian_leap_p(VALUE klass, VALUE y)
 {
-    if (f_zero_p(f_mod(y, INT2FIX(4))))
-	return Qtrue;
-    return Qfalse;
+    VALUE nth;
+    int ry;
+
+    decode_year(y, +1, &nth, &ry);
+    return f_boolcast(c_julian_leap_p(ry));
 }
 
 /*
@@ -2422,17 +2731,23 @@
 static VALUE
 date_s_gregorian_leap_p(VALUE klass, VALUE y)
 {
-    if (f_zero_p(f_mod(y, INT2FIX(4))) &&
-	f_nonzero_p(f_mod(y, INT2FIX(100))) ||
-	f_zero_p(f_mod(y, INT2FIX(400))))
-	return Qtrue;
-    return Qfalse;
+    VALUE nth;
+    int ry;
+
+    decode_year(y, -1, &nth, &ry);
+    return f_boolcast(c_gregorian_leap_p(ry));
 }
 
 static void
-d_simple_gc_mark(struct SimpleDateData *dat)
+d_lite_gc_mark(union DateData *dat)
 {
-    rb_gc_mark(dat->nth);
+    if (simple_dat_p(dat))
+	rb_gc_mark(dat->s.nth);
+    else {
+	rb_gc_mark(dat->c.nth);
+	rb_gc_mark(dat->c.sf);
+
+    }
 }
 
 inline static VALUE
@@ -2446,32 +2761,14 @@
     VALUE obj;
 
     obj = Data_Make_Struct(klass, struct SimpleDateData,
-			   d_simple_gc_mark, -1, dat);
+			   d_lite_gc_mark, -1, dat);
+    set_to_simple(dat, nth, jd, sg, y, m, d, flags & ~COMPLEX_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;
-
     assert(have_jd_p(dat) || have_civil_p(dat));
 
     return obj;
 }
 
-static void
-d_complex_gc_mark(struct ComplexDateData *dat)
-{
-    rb_gc_mark(dat->nth);
-    rb_gc_mark(dat->sf);
-}
-
 inline static VALUE
 d_complex_new_internal(VALUE klass,
 		       VALUE nth, int jd,
@@ -2485,88 +2782,48 @@
     VALUE obj;
 
     obj = Data_Make_Struct(klass, struct ComplexDateData,
-			   d_complex_gc_mark, -1, dat);
+			   d_lite_gc_mark, -1, dat);
+    set_to_complex(dat, nth, jd, df, sf, of, sg,
+		   y, m, d, h, min, s, flags | COMPLEX_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;
-
     assert(have_jd_p(dat) || have_civil_p(dat));
     assert(have_df_p(dat) || have_time_p(dat));
 
     return obj;
 }
 
-static void
-d_date_gc_mark(union DateData *dat)
+static VALUE
+d_lite_s_alloc_simple(VALUE klass)
 {
-    if (simple_dat_p(dat))
-	rb_gc_mark(dat->s.nth);
-    else {
-	rb_gc_mark(dat->c.nth);
-	rb_gc_mark(dat->c.sf);
-    }
+    return d_simple_new_internal(klass,
+				 INT2FIX(0), 0,
+				 DEFAULT_SG,
+				 0, 0, 0,
+				 HAVE_JD);
 }
 
-inline static VALUE
-d_date_new_internal(VALUE klass,
-		    VALUE nth, int jd,
-		    double sg,
-		    int y, int m, int d,
-		    unsigned flags)
+static VALUE
+d_lite_s_alloc_complex(VALUE klass)
 {
-    union DateData *dat;
-    VALUE obj;
-
-    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;
-
-    assert(have_jd_p(dat) || have_civil_p(dat));
-
-    return obj;
+    return d_complex_new_internal(klass,
+				  INT2FIX(0), 0,
+				  0, INT2FIX(0),
+				  0, DEFAULT_SG,
+				  0, 0, 0,
+				  0, 0, 0,
+				  HAVE_JD | HAVE_DF);
 }
 
 static VALUE
 d_lite_s_alloc(VALUE klass)
 {
-    return d_date_new_internal(klass,
-			       INT2FIX(0), 0,
-			       DEFAULT_SG,
-			       0, 0, 0,
-			       HAVE_JD);
+    return d_lite_s_alloc_complex(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)
+	   int *rof, double *rsg)
 {
     VALUE jd, df, sf, of2, t;
 
@@ -2585,7 +2842,13 @@
     *rof = NUM2INT(of2);
     *rsg = NUM2DBL(sg);
 
-    if (*rof < -1 || *rof > 1) {
+    if (*rdf < 0 || *rdf >= DAY_IN_SECONDS)
+	rb_raise(rb_eArgError, "invalid day fraction");
+
+    if (f_lt_p(*rsf, INT2FIX(0)) ||
+	f_ge_p(*rsf, INT2FIX(SECOND_IN_NANOSECONDS)))
+
+    if (*rof < -DAY_IN_SECONDS || *rof > DAY_IN_SECONDS) {
 	*rof = 0;
 	rb_warning("invalid offset is ignored");
     }
@@ -2594,8 +2857,6 @@
 	*rsg = DEFAULT_SG;
 	rb_warning("invalid start is ignored");
     }
-
-    *flags = HAVE_JD | HAVE_DF | COMPLEX_DAT;
 }
 
 #ifndef NDEBUG
@@ -2605,7 +2866,6 @@
     VALUE ajd, of, sg, nth, sf;
     int jd, df, rof;
     double rsg;
-    unsigned flags;
 
     rb_scan_args(argc, argv, "03", &ajd, &of, &sg);
 
@@ -2619,15 +2879,22 @@
     }
 
     old_to_new(ajd, of, sg,
-	       &nth, &jd, &df, &sf, &rof, &rsg, &flags);
+	       &nth, &jd, &df, &sf, &rof, &rsg);
 
-    return d_complex_new_internal(klass,
-				  nth, jd,
-				  df, sf,
-				  rof, rsg,
-				  0, 0, 0,
-				  0, 0, 0,
-				  flags);
+    if (!df && f_zero_p(sf) && !rof)
+	return d_simple_new_internal(klass,
+				     nth, jd,
+				     rsg,
+				     0, 0, 0,
+				     HAVE_JD);
+    else
+	return d_complex_new_internal(klass,
+				      nth, jd,
+				      df, sf,
+				      rof, rsg,
+				      0, 0, 0,
+				      0, 0, 0,
+				      HAVE_JD | HAVE_DF);
 }
 #endif
 
@@ -2642,14 +2909,15 @@
       case T_FLOAT:
 	{
 	    double d = NUM2DBL(x);
-	    if (round(d) == d)
-		return 1;
+	    return round(d) == d;
 	}
+	break;
       case T_RATIONAL:
 	{
-	    if (RRATIONAL(x)->den == 1)
-		return 1;
+	    VALUE den = RRATIONAL(x)->den;
+	    return FIXNUM_P(den) && FIX2LONG(den) == 1;
 	}
+	break;
     }
     return 0;
 }
@@ -2790,7 +3058,6 @@
 	int rjd;
 
 	decode_jd(jd, &nth, &rjd);
-
 	ret = d_simple_new_internal(klass,
 				    nth, rjd,
 				    sg,
@@ -2904,7 +3171,7 @@
 	y = vy;
     }
 
-    if (isinf(sg) && sg < 0) {
+    if (style_p(y, sg) < 0) {
 	VALUE nth;
 	int ry, rm, rd;
 
@@ -3213,7 +3480,7 @@
 fv_values_at(VALUE h, VALUE a)
 {
     return rb_funcall2(h, rb_intern("values_at"),
-			RARRAY_LENINT(a), RARRAY_PTR(a));
+		       RARRAY_LENINT(a), RARRAY_PTR(a));
 }
 
 static VALUE d_lite_wday(VALUE);
@@ -3638,7 +3905,6 @@
 	int rjd;
 
 	decode_jd(jd, &nth, &rjd);
-
 	return d_simple_new_internal(klass,
 				     nth, rjd,
 				     NUM2DBL(sg),
@@ -3647,9 +3913,8 @@
     }
 }
 
-VALUE
-date__strptime(const char *str, size_t slen,
-	       const char *fmt, size_t flen, VALUE hash);
+VALUE date__strptime(const char *str, size_t slen,
+		     const char *fmt, size_t flen, VALUE hash);
 
 static VALUE
 date_s__strptime_internal(int argc, VALUE *argv, VALUE klass,
@@ -3759,8 +4024,7 @@
     }
 }
 
-VALUE
-date__parse(VALUE str, VALUE comp);
+VALUE date__parse(VALUE str, VALUE comp);
 
 static VALUE
 date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
@@ -4090,119 +4354,117 @@
     }
 }
 
-#ifndef NDEBUG
 static VALUE
-d_lite_fill(VALUE self)
+dup_obj(VALUE self)
 {
-    get_d1(self);
+    get_d1a(self);
 
-    if (simple_dat_p(dat)) {
-	get_s_jd(dat);
-	get_s_civil(dat);
+    if (simple_dat_p(adat)) {
+	VALUE new = d_lite_s_alloc_simple(CLASS_OF(self));
+	{
+	    get_d1b(new);
+	    bdat->s = adat->s;
+	    return new;
+	}
     }
     else {
-	get_c_jd(dat);
-	get_c_civil(dat);
-	get_c_df(dat);
-	get_c_time(dat);
+	VALUE new = d_lite_s_alloc_complex(CLASS_OF(self));
+	{
+	    get_d1b(new);
+	    bdat->c = adat->c;
+	    return new;
+	}
     }
-    return self;
 }
-#endif
 
 static VALUE
-copy_obj(VALUE self)
+dup_obj_as_complex(VALUE self)
 {
-    get_d1(self);
+    get_d1a(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);
+    if (simple_dat_p(adat)) {
+	VALUE new = d_lite_s_alloc_complex(CLASS_OF(self));
+	{
+	    get_d1b(new);
+	    copy_simple_to_complex(&bdat->c, &adat->s);
+	    bdat->c.flags |= HAVE_DF | COMPLEX_DAT;
+	    return new;
+	}
+    }
+    else {
+	VALUE new = d_lite_s_alloc_complex(CLASS_OF(self));
+	{
+	    get_d1b(new);
+	    bdat->c = adat->c;
+	    return new;
+	}
+    }
 }
 
+#define val2off(vof,iof) \
+{\
+    if (!offset_to_sec(vof, &iof)) {\
+	iof = 0;\
+	rb_warning("invalid offset is ignored");\
+    }\
+}
+
+#ifndef NDEBUG
 static VALUE
-copy_obj_as_complex(VALUE self)
+d_lite_initialize(int argc, VALUE *argv, VALUE self)
 {
-    get_d1(self);
+    VALUE jd, vjd, vdf, sf, vsf, vof, vsg;
+    int df, of;
+    double sg;
 
-    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),
+    rb_scan_args(argc, argv, "05", &vjd, &vdf, &vsf, &vof, &vsg);
+
+    jd = INT2FIX(0);
+    df = 0;
+    sf = INT2FIX(0);
+    of = 0;
+    sg = DEFAULT_SG;
+
+    switch (argc) {
+      case 5:
+	val2sg(vsg, sg);
+      case 4:
+	val2off(vof, of);
+      case 3:
+	sf = vsf;
+	if (f_lt_p(sf, INT2FIX(0)) ||
+	    f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS)))
+	    rb_raise(rb_eArgError, "invalid second fraction");
+      case 2:
+	df = NUM2INT(vdf);
+	if (df < 0 || df >= DAY_IN_SECONDS)
+	    rb_raise(rb_eArgError, "invalid day fraction");
+      case 1:
+	jd = vjd;
+    }
+
+    {
+	VALUE nth;
+	int rjd;
+
+	get_d1(self);
+
+	decode_jd(jd, &nth, &rjd);
+	if (!df && f_zero_p(sf) && !of) {
+	    set_to_simple(&dat->s, nth, rjd, sg, 0, 0, 0, HAVE_JD);
+	}
+	else {
+	    if (!complex_dat_p(dat))
+		rb_raise(rb_eArgError,
+			 "cannot load complex into simple");
+
+	    set_to_complex(&dat->c, nth, rjd, df, sf, of, sg,
+			   0, 0, 0, 0, 0, 0, HAVE_JD | HAVE_DF | COMPLEX_DAT);
+	}
+    }
+    return self;
+}
 #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
@@ -4213,41 +4475,41 @@
     {
 	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;
+	    adat->s = bdat->s;
+	    adat->s.flags &= ~COMPLEX_DAT;
 	}
 	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;
+	    if (!complex_dat_p(adat))
+		rb_raise(rb_eArgError,
+			 "cannot load complex into simple");
+
+	    adat->c = bdat->c;
+	    adat->c.flags |= COMPLEX_DAT;
 	}
     }
     return copy;
 }
 
+#ifndef NDEBUG
+static VALUE
+d_lite_fill(VALUE self)
+{
+    get_d1(self);
+
+    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
+
 /*
  * call-seq:
  *    d.ajd
@@ -4270,39 +4532,10 @@
 static VALUE
 d_lite_amjd(VALUE self)
 {
-    VALUE r, sf;
-    int df;
-
     get_d1(self);
-
-    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;
+    return m_amjd(dat);
 }
 
-#define return_once(k, expr)\
-{\
-    VALUE id, val;\
-    get_d1(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;\
-}
-
 /*
  * call-seq:
  *    d.jd
@@ -4421,7 +4654,7 @@
     int ry, rw, rd;
 
     get_d1(self);
-    c_jd_to_weeknum(m_local_jd(dat), 0, m_sg(dat),
+    c_jd_to_weeknum(m_local_jd(dat), 0, x_sg(dat), /* !=m_sg() */
 		    &ry, &rw, &rd);
     return INT2FIX(rw);
 }
@@ -4432,7 +4665,7 @@
     int ry, rw, rd;
 
     get_d1(self);
-    c_jd_to_weeknum(m_local_jd(dat), 1, m_sg(dat),
+    c_jd_to_weeknum(m_local_jd(dat), 1, x_sg(dat), /* !=m_sg() */
 		    &ry, &rw, &rd);
     return INT2FIX(rw);
 }
@@ -4528,13 +4761,15 @@
 static VALUE
 d_lite_cwyear(VALUE self)
 {
+    double sg;
     int ry, rw, rd;
     VALUE ry2;
 
     get_d1(self);
-    c_jd_to_commercial(m_local_jd(dat), m_sg(dat),
+    sg = x_sg(dat); /* !=m_sg() */
+    c_jd_to_commercial(m_local_jd(dat), sg,
 		       &ry, &rw, &rd);
-    encode_year(m_nth(dat), ry, +1, &ry2);
+    encode_year(m_nth(dat), ry, sg, &ry2);
     return ry2;
 }
 
@@ -4550,7 +4785,7 @@
     int ry, rw, rd;
 
     get_d1(self);
-    c_jd_to_commercial(m_local_jd(dat), m_sg(dat),
+    c_jd_to_commercial(m_local_jd(dat), x_sg(dat), /* !=m_sg() */
 		       &ry, &rw, &rd);
     return INT2FIX(rw);
 }
@@ -4681,7 +4916,7 @@
 
 #ifndef NDEBUG
 static VALUE
-generic_nth_kday_p(VALUE self, VALUE n, VALUE k)
+d_lite_nth_kday_p(VALUE self, VALUE n, VALUE k)
 {
     int rjd, ns;
 
@@ -4691,7 +4926,7 @@
 	return Qfalse;
 
     c_nth_kday_to_jd(m_year(dat), m_mon(dat),
-		     NUM2INT(n), NUM2INT(k), m_sg(dat),
+		     NUM2INT(n), NUM2INT(k), x_sg(dat), /* !=m_sg() */
 		     &rjd, &ns);
     if (m_local_jd(dat) != rjd)
 	return Qfalse;
@@ -4736,13 +4971,11 @@
 static VALUE
 d_lite_leap_p(VALUE self)
 {
-    double sg;
     int rjd, ns, ry, rm, rd;
 
     get_d1(self);
-    sg = m_sg(dat);
-    if (isinf(sg) && sg < 0)
-	return f_boolcast(c_leap_p(m_year(dat)));
+    if (m_gregorian_p(dat))
+	return f_boolcast(c_gregorian_leap_p(m_year(dat)));
 
     c_civil_to_jd(m_year(dat), 3, 1, fix_style(dat),
 		  &rjd, &ns);
@@ -4772,7 +5005,7 @@
 	x->s.mon = 0;
 	x->s.mday = 0;
 #else
-	x->s.pd = 0;
+	x->s.pc = 0;
 #endif
 	x->s.flags &= ~HAVE_CIVIL;
     }
@@ -4785,7 +5018,7 @@
 	x->c.min = 0;
 	x->c.sec = 0;
 #else
-	x->c.pd = 0;
+	x->c.pc = 0;
 #endif
 	x->c.flags &= ~(HAVE_CIVIL | HAVE_TIME);
     }
@@ -4797,24 +5030,24 @@
     if (simple_dat_p(x)) {
 	get_s_jd(x);
 	clear_civil(x);
-	x->s.sg = sg;
+	x->s.sg = (sg_cast)sg;
     } else {
 	get_c_jd(x);
 	get_c_df(x);
 	clear_civil(x);
-	x->c.sg = sg;
+	x->c.sg = (sg_cast)sg;
     }
 }
 
 static VALUE
-copy_obj_with_new_start(VALUE obj, double sg)
+dup_obj_with_new_start(VALUE obj, double sg)
 {
-    VALUE copy = copy_obj(obj);
+    volatile VALUE dup = dup_obj(obj);
     {
-	get_d1(copy);
+	get_d1(dup);
 	set_sg(dat, sg);
     }
-    return copy;
+    return dup;
 }
 
 /*
@@ -4835,7 +5068,7 @@
     if (argc >= 1)
 	val2sg(vsg, sg);
 
-    return copy_obj_with_new_start(self, sg);
+    return dup_obj_with_new_start(self, sg);
 }
 
 /*
@@ -4848,7 +5081,7 @@
 static VALUE
 d_lite_italy(VALUE self)
 {
-    return copy_obj_with_new_start(self, ITALY);
+    return dup_obj_with_new_start(self, ITALY);
 }
 
 /*
@@ -4861,7 +5094,7 @@
 static VALUE
 d_lite_england(VALUE self)
 {
-    return copy_obj_with_new_start(self, ENGLAND);
+    return dup_obj_with_new_start(self, ENGLAND);
 }
 
 /*
@@ -4874,7 +5107,7 @@
 static VALUE
 d_lite_julian(VALUE self)
 {
-    return copy_obj_with_new_start(self, JULIAN);
+    return dup_obj_with_new_start(self, JULIAN);
 }
 
 /*
@@ -4887,7 +5120,7 @@
 static VALUE
 d_lite_gregorian(VALUE self)
 {
-    return copy_obj_with_new_start(self, GREGORIAN);
+    return dup_obj_with_new_start(self, GREGORIAN);
 }
 
 static void
@@ -4901,24 +5134,16 @@
 }
 
 static VALUE
-copy_obj_with_new_offset(VALUE obj, int of)
+dup_obj_with_new_offset(VALUE obj, int of)
 {
-    VALUE copy = copy_obj_as_complex(obj);
+    volatile VALUE dup = dup_obj_as_complex(obj);
     {
-	get_d1(copy);
+	get_d1(dup);
 	set_of(dat, of);
     }
-    return copy;
+    return dup;
 }
 
-#define val2off(vof,iof) \
-{\
-    if (!offset_to_sec(vof, &iof)) {\
-	iof = 0;\
-	rb_warning("invalid offset is ignored");\
-    }\
-}
-
 /*
  * call-seq:
  *    d.new_offset([offset=0])
@@ -4937,7 +5162,7 @@
     if (argc >= 1)
 	val2off(vof, rof);
 
-    return copy_obj_with_new_offset(self, rof);
+    return dup_obj_with_new_offset(self, rof);
 }
 
 /*
@@ -4972,16 +5197,21 @@
 		nth = f_add(nth, INT2FIX(DIV(t, CM_PERIOD)));
 		t = MOD(t, CM_PERIOD);
 	    }
-	    jd = m_jd(dat) + (int)t;
 
-	    if (jd < 0) {
-		nth = f_sub(nth, INT2FIX(1));
-		jd += CM_PERIOD;
+	    if (!t)
+		jd = m_jd(dat);
+	    else {
+		jd = m_jd(dat) + (int)t;
+
+		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;
+		}
 	    }
-	    else if (jd >= CM_PERIOD) {
-		nth = f_add(nth, INT2FIX(1));
-		jd -= CM_PERIOD;
-	    }
 
 	    if (simple_dat_p(dat))
 		return d_simple_new_internal(CLASS_OF(self),
@@ -5023,17 +5253,25 @@
 		jd = -jd;
 	    }
 
-	    jd = m_jd(dat) + jd;
-	    if (jd < 0) {
-		nth = f_sub(nth, INT2FIX(1));
-		jd += CM_PERIOD;
+	    if (!jd)
+		jd = m_jd(dat);
+	    else {
+		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;
+		}
 	    }
-	    else if (jd >= CM_PERIOD) {
-		nth = f_add(nth, INT2FIX(1));
-		jd -= CM_PERIOD;
-	    }
-	    nth = f_add(m_nth(dat), nth);
 
+	    if (f_zero_p(nth))
+		nth = m_nth(dat);
+	    else
+		nth = f_add(m_nth(dat), nth);
+
 	    if (simple_dat_p(dat))
 		return d_simple_new_internal(CLASS_OF(self),
 					     nth, jd,
@@ -5095,37 +5333,53 @@
 		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));
+	    if (f_zero_p(sf))
+		sf = m_sf(dat);
+	    else {
+		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));
+		}
 	    }
-	    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;
+	    if (!df)
+		df = m_df(dat);
+	    else {
+		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;
+		}
 	    }
-	    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;
+	    if (!jd)
+		jd = m_jd(dat);
+	    else {
+		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;
+		}
 	    }
-	    else if (jd >= CM_PERIOD) {
-		nth = f_add(nth, INT2FIX(1));
-		jd -= CM_PERIOD;
-	    }
-	    nth = f_add(m_nth(dat), nth);
 
+	    if (f_zero_p(nth))
+		nth = m_nth(dat);
+	    else
+		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, (int)jd,
@@ -5150,11 +5404,15 @@
 	if (!k_numeric_p(other))
 	    rb_raise(rb_eTypeError, "expected numeric");
 	other = f_to_r(other);
+	/* fall through */
       case T_RATIONAL:
 	{
 	    VALUE nth, sf, t;
 	    int jd, df, s;
 
+	    if (integer_p(other))
+		return d_lite_plus(self, RRATIONAL(other)->num);
+
 	    if (f_positive_p(other))
 		s = +1;
 	    else {
@@ -5181,37 +5439,53 @@
 		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));
+	    if (f_zero_p(sf))
+		sf = m_sf(dat);
+	    else {
+		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));
+		}
 	    }
-	    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;
+	    if (!df)
+		df = m_df(dat); 
+	    else {
+		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;
+		}
 	    }
-	    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;
+	    if (!jd)
+		jd = m_jd(dat);
+	    else {
+		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;
+		}
 	    }
-	    else if (jd >= CM_PERIOD) {
-		nth = f_add(nth, INT2FIX(1));
-		jd -= CM_PERIOD;
-	    }
-	    nth = f_add(m_nth(dat), nth);
 
+	    if (f_zero_p(nth))
+		nth = m_nth(dat);
+	    else
+		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,
@@ -5498,6 +5772,8 @@
     return d_lite_lshift(self, f_mul(n, INT2FIX(12)));
 }
 
+static VALUE d_lite_cmp(VALUE, VALUE);
+
 /*
  * call-seq:
  *    d.step(limit[, step=1])
@@ -5509,7 +5785,7 @@
  * date at each step.
  */
 static VALUE
-generic_step(int argc, VALUE *argv, VALUE self)
+d_lite_step(int argc, VALUE *argv, VALUE self)
 {
     VALUE limit, step, date;
 
@@ -5528,9 +5804,9 @@
     date = self;
     switch (FIX2INT(f_cmp(step, INT2FIX(0)))) {
       case -1:
-	while (f_ge_p(date, limit)) {
+	while (FIX2INT(d_lite_cmp(date, limit)) >= 0) {
 	    rb_yield(date);
-	    date = f_add(date, step);
+	    date = d_lite_plus(date, step);
 	}
 	break;
       case 0:
@@ -5538,9 +5814,9 @@
 	    rb_yield(date);
 	break;
       case 1:
-	while (f_le_p(date, limit)) {
+	while (FIX2INT(d_lite_cmp(date, limit)) <= 0) {
 	    rb_yield(date);
-	    date = f_add(date, step);
+	    date = d_lite_plus(date, step);
 	}
 	break;
       default:
@@ -5558,16 +5834,16 @@
  * (inclusive), yielding each date as we go.
  */
 static VALUE
-generic_upto(VALUE self, VALUE max)
+d_lite_upto(VALUE self, VALUE max)
 {
     VALUE date;
 
     RETURN_ENUMERATOR(self, 1, &max);
 
     date = self;
-    while (f_le_p(date, max)) {
+    while (FIX2INT(d_lite_cmp(date, max)) <= 0) {
 	rb_yield(date);
-	date = f_add(date, INT2FIX(1));
+	date = d_lite_plus(date, INT2FIX(1));
     }
     return self;
 }
@@ -5581,16 +5857,16 @@
  * (inclusive), yielding each date as we go.
  */
 static VALUE
-generic_downto(VALUE self, VALUE min)
+d_lite_downto(VALUE self, VALUE min)
 {
     VALUE date;
 
     RETURN_ENUMERATOR(self, 1, &min);
 
     date = self;
-    while (f_ge_p(date, min)) {
+    while (FIX2INT(d_lite_cmp(date, min)) >= 0) {
 	rb_yield(date);
-	date = f_add(date, INT2FIX(-1));
+	date = d_lite_plus(date, INT2FIX(-1));
     }
     return self;
 }
@@ -5759,8 +6035,8 @@
 			return INT2FIX(1);
 		    }
 #else
-		    a_pd = m_pd(adat);
-		    b_pd = m_pd(bdat);
+		    a_pd = m_pc(adat);
+		    b_pd = m_pc(bdat);
 		    if (a_pd == b_pd) {
 			return INT2FIX(0);
 		    }
@@ -5867,8 +6143,8 @@
 		    }
 #else
 		    /* mon and mday only */
-		    a_pd = (m_pd(adat) >> MDAY_SHIFT);
-		    b_pd = (m_pd(bdat) >> MDAY_SHIFT);
+		    a_pd = (m_pc(adat) >> MDAY_SHIFT);
+		    b_pd = (m_pc(bdat) >> MDAY_SHIFT);
 		    if (a_pd == b_pd) {
 			return Qtrue;
 		    }
@@ -5905,10 +6181,20 @@
 static VALUE
 d_lite_hash(VALUE self)
 {
+    st_index_t v, h[4];
+
     get_d1(self);
-    return rb_hash(m_ajd(dat));
+    h[0] = m_nth(dat);
+    h[1] = m_jd(dat);
+    h[2] = m_df(dat);
+    h[3] = m_sf(dat);
+    v = rb_memhash(h, sizeof(h));
+    return LONG2FIX(v);
 }
 
+#define AVOID_SPRINTF_BUG
+#define FMT_TO_S "%.4d-%02d-%02d"
+
 /*
  * call-seq:
  *    d.to_s
@@ -5920,14 +6206,17 @@
 {
     get_d1(self);
 
-    if (f_zero_p(m_nth(dat)))
-	return rb_enc_sprintf(rb_usascii_encoding(),
-			      "%.4d-%02d-%02d",
+    if (f_zero_p(m_nth(dat))
+#ifdef AVOID_SPRINTF_BUG
+	&& m_year(dat) >= 0
+#endif
+	)
+	return rb_enc_sprintf(rb_usascii_encoding(), FMT_TO_S,
 			      m_year(dat), m_mon(dat), m_mday(dat));
     else {
 	VALUE argv[4];
 
-	argv[0] = rb_usascii_str_new2("%.4d-%02d-%02d");
+	argv[0] = rb_usascii_str_new2(FMT_TO_S);
 	argv[1] = m_real_year(dat);
 	argv[2] = INT2FIX(m_mon(dat));
 	argv[3] = INT2FIX(m_mday(dat));
@@ -5935,72 +6224,95 @@
     }
 }
 
+#ifndef NDEBUG
 static VALUE
-inspect_flags(VALUE self)
+mk_inspect_flags(union DateData *x)
 {
-    get_d1(self);
-
     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' : '-');
+			  (x->flags & COMPLEX_DAT) ? 'C' : 'S',
+			  (x->flags & HAVE_JD)     ? 'j' : '-',
+			  (x->flags & HAVE_DF)     ? 'd' : '-',
+			  (x->flags & HAVE_CIVIL)  ? 'c' : '-',
+			  (x->flags & HAVE_TIME)   ? 't' : '-');
 }
 
-/*
- * call-seq:
- *    d.inspect
- *
- * Return internal object state as a programmer-readable string.
- */
 static VALUE
-d_lite_inspect(VALUE self)
+mk_inspect_raw(union DateData *x, const char *klass)
 {
-    get_d1(self);
-
-    if (simple_dat_p(dat)) {
+    if (simple_dat_p(x)) {
 	return rb_enc_sprintf(rb_usascii_encoding(),
-			      "#<%s: %s "
-			      "((%sth,%dj),+0s,%.0fj; "
-			      "%dy%dm%dd; %s)>",
-			      rb_obj_classname(self),
-			      RSTRING_PTR(f_to_s(self)),
-			      RSTRING_PTR(f_inspect(dat->s.nth)),
-			      dat->s.jd, dat->s.sg,
+			      "#<%s: "
+			      "(%sth,%dj),+0s,%.0fj; "
+			      "%dy%dm%dd; %s>",
+			      klass ? klass : "?",
+			      RSTRING_PTR(f_inspect(x->s.nth)),
+			      x->s.jd, x->s.sg,
 #ifndef USE_PACK
-			      dat->s.year, dat->s.mon, dat->s.mday,
+			      x->s.year, x->s.mon, x->s.mday,
 #else
-			      dat->s.year,
-			      EX_MON(dat->s.pd), EX_MDAY(dat->s.pd),
+			      x->s.year,
+			      EX_MON(x->s.pc), EX_MDAY(x->s.pc),
 #endif
-			      RSTRING_PTR(inspect_flags(self)));
+			      RSTRING_PTR(mk_inspect_flags(x)));
     }
     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,
+			      "#<%s: "
+			      "(%sth,%dj,%ds,%sn),%+ds,%.0fj; "
+			      "%dy%dm%dd %dh%dm%ds; %s>",
+			      klass ? klass : "?",
+			      RSTRING_PTR(f_inspect(x->c.nth)),
+			      x->c.jd, x->c.df,
+			      RSTRING_PTR(f_inspect(x->c.sf)),
+			      x->c.of, x->c.sg,
 #ifndef USE_PACK
-			      dat->c.year, dat->c.mon, dat->c.mday,
-			      dat->c.hour, dat->c.min, dat->c.sec,
+			      x->c.year, x->c.mon, x->c.mday,
+			      x->c.hour, x->c.min, x->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),
+			      x->c.year,
+			      EX_MON(x->c.pc), EX_MDAY(x->c.pc),
+			      EX_HOUR(x->c.pc), EX_MIN(x->c.pc),
+			      EX_SEC(x->c.pc),
 #endif
-			      RSTRING_PTR(inspect_flags(self)));
+			      RSTRING_PTR(mk_inspect_flags(x)));
     }
 }
 
+static VALUE
+d_lite_inspect_raw(VALUE self)
+{
+    get_d1(self);
+    return mk_inspect_raw(dat, rb_obj_classname(self));
+}
+#endif
+
+static VALUE
+mk_inspect(union DateData *x, const char *klass, const char *to_s)
+{
+    return rb_enc_sprintf(rb_usascii_encoding(),
+			  "#<%s: %s ((%sj,%ds,%sn),%+ds,%.0fj)>",
+			  klass ? klass : "?",
+			  to_s ? to_s : "?",
+			  RSTRING_PTR(f_inspect(m_real_jd(x))), m_df(x),
+			  RSTRING_PTR(f_inspect(m_sf(x))),
+			  m_of(x), m_sg(x));
+}
+
+/*
+ * call-seq:
+ *    d.inspect
+ *
+ * Return internal object state as a programmer-readable string.
+ */
+static VALUE
+d_lite_inspect(VALUE self)
+{
+    get_d1(self);
+    return mk_inspect(dat, rb_obj_classname(self),
+		      RSTRING_PTR(f_to_s(self)));
+}
+
 #include <errno.h>
 #include "date_tmx.h"
 
@@ -6218,8 +6530,8 @@
 static VALUE
 d_lite_httpdate(VALUE self)
 {
-    VALUE d = copy_obj_with_new_offset(self, 0);
-    return strftimev("%a, %d %b %Y %T GMT", d, d_lite_set_tmx);
+    volatile VALUE dup = dup_obj_with_new_offset(self, 0);
+    return strftimev("%a, %d %b %Y %T GMT", dup, d_lite_set_tmx);
 }
 
 static VALUE
@@ -6267,6 +6579,28 @@
 		 strftimev(".%m.%d", self, d_lite_set_tmx));
 }
 
+#ifndef NDEBUG
+static VALUE
+d_lite_marshal_dump_old(VALUE self)
+{
+    VALUE a;
+
+    get_d1(self);
+
+    a = rb_ary_new3(3,
+		    m_ajd(dat),
+		    m_of_in_day(dat),
+		    DBL2NUM(m_sg(dat)));
+
+    if (FL_TEST(self, FL_EXIVAR)) {
+	rb_copy_generic_ivar(a, self);
+	FL_SET(a, FL_EXIVAR);
+    }
+
+    return a;
+}
+#endif
+
 /*
  * call-seq:
  *    d.marshal_dump
@@ -6316,32 +6650,25 @@
 	    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);
+		       &nth, &jd, &df, &sf, &rof, &rsg);
 
-	    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;
+	    if (!df && f_zero_p(sf) && !rof) {
+		set_to_simple(&dat->s, nth, jd, sg, 0, 0, 0, HAVE_JD);
+	    } else {
+		if (!complex_dat_p(dat))
+		    rb_raise(rb_eArgError,
+			     "cannot load complex into simple");
+
+		set_to_complex(&dat->c, nth, jd, df, sf, rof, rsg,
+			       0, 0, 0, 0, 0, 0,
+			       HAVE_JD | HAVE_DF | COMPLEX_DAT);
+	    }
 	}
 	break;
       case 6:
@@ -6356,39 +6683,17 @@
 	    sf = RARRAY_PTR(a)[3];
 	    of = NUM2INT(RARRAY_PTR(a)[4]);
 	    sg = NUM2DBL(RARRAY_PTR(a)[5]);
+	    if (!df && f_zero_p(sf) && !of) {
+		set_to_simple(&dat->s, nth, jd, sg, 0, 0, 0, HAVE_JD);
+	    } else {
+		if (!complex_dat_p(dat))
+		    rb_raise(rb_eArgError,
+			     "cannot load complex into simple");
 
-	    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;
+		set_to_complex(&dat->c, nth, jd, df, sf, of, sg,
+			       0, 0, 0, 0, 0, 0,
+			       HAVE_JD | HAVE_DF | COMPLEX_DAT);
 	    }
-	    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:
@@ -6405,7 +6710,7 @@
 }
 
 
-/* datetime light */
+/* datetime */
 
 /*
  * call-seq:
@@ -6618,7 +6923,7 @@
 	y = vy;
     }
 
-    if (isinf(sg) && sg < 0) {
+    if (style_p(y, sg) < 0) {
 	VALUE nth;
 	int ry, rm, rd, rh, rmin, rs;
 
@@ -7313,6 +7618,9 @@
     }
 }
 
+#undef FMT_TO_S
+#define FMT_TO_S "%.4d-%02d-%02d" "T" "%02d:%02d:%02d" "%c%02d:%02d"
+
 /*
  * call-seq:
  *    dt.to_s
@@ -7324,14 +7632,15 @@
 {
     get_d1(self);
 
-    if (f_zero_p(m_nth(dat))) {
+    if (f_zero_p(m_nth(dat))
+#ifdef AVOID_SPRINTF_BUG
+	&& m_year(dat) >= 0
+#endif
+	) {
 	int s, h, m;
 
 	decode_offset(m_of(dat), s, h, m);
-	return rb_enc_sprintf(rb_usascii_encoding(),
-			      "%.4d-%02d-%02dT"
-			      "%02d:%02d:%02d"
-			      "%c%02d:%02d",
+	return rb_enc_sprintf(rb_usascii_encoding(), FMT_TO_S,
 			      m_year(dat), m_mon(dat), m_mday(dat),
 			      m_hour(dat), m_min(dat), m_sec(dat),
 			      s, h, m);
@@ -7341,9 +7650,7 @@
 	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[0] = rb_usascii_str_new2(FMT_TO_S);
 	argv[1] = m_real_year(dat);
 	argv[2] = INT2FIX(m_mon(dat));
 	argv[3] = INT2FIX(m_mday(dat));
@@ -7466,7 +7773,8 @@
 #define f_subsec(x) rb_funcall(x, rb_intern("subsec"), 0)
 #define f_utc_offset(x) rb_funcall(x, rb_intern("utc_offset"), 0)
 #define f_local3(x,y,m,d) rb_funcall(x, rb_intern("local"), 3, y, m, d)
-#define f_utc6(x,y,m,d,h,min,s) rb_funcall(x, rb_intern("utc"), 6, y, m, d, h, min, s)
+#define f_utc6(x,y,m,d,h,min,s) rb_funcall(x, rb_intern("utc"), 6,\
+					   y, m, d, h, min, s)
 
 /*
  * call-seq:
@@ -7589,42 +7897,35 @@
 static VALUE
 date_to_datetime(VALUE self)
 {
-    get_d1(self);
+    get_d1a(self);
 
-    if (simple_dat_p(dat))
-	return d_simple_new_internal(cDateTime,
-				     dat->s.nth,
-				     dat->s.jd,
-				     dat->s.sg,
-				     dat->s.year,
+    if (simple_dat_p(adat)) {
+	VALUE new = d_lite_s_alloc_simple(cDateTime);
+	{
+	    get_d1b(new);
+	    bdat->s = adat->s;
+	    return new;
+	}
+    }
+    else {
+	VALUE new = d_lite_s_alloc_complex(cDateTime);
+	{
+	    get_d1b(new);
+	    bdat->c = adat->c;
+	    bdat->c.df = 0;
+	    bdat->c.sf = INT2FIX(0);
 #ifndef USE_PACK
-				     dat->s.mon,
-				     dat->s.mday,
+	    bdat->c.hour = 0;
+	    bdat->c.min = 0;
+	    bdat->c.sec = 0;
 #else
-				     EX_MON(dat->s.pd),
-				     EX_MDAY(dat->s.pd),
+	    bdat->c.pc = PACK5(EX_MON(adat->c.pc), EX_MDAY(adat->c.pc),
+			       0, 0, 0);
+	    bdat->c.flags |= HAVE_DF | HAVE_TIME;
 #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);
+	    return new;
+	}
+    }
 }
 
 /*
@@ -7636,12 +7937,12 @@
 static VALUE
 datetime_to_time(VALUE self)
 {
-    VALUE d, t;
-
-    d = copy_obj_with_new_offset(self, 0);
+    volatile VALUE dup = dup_obj_with_new_offset(self, 0);
     {
-	get_d1(d);
+	VALUE t;
 
+	get_d1(dup);
+
 	t = f_utc6(rb_cTime,
 		   m_real_year(dat),
 		   INT2FIX(m_mon(dat)),
@@ -7663,37 +7964,27 @@
 static VALUE
 datetime_to_date(VALUE self)
 {
-    get_d1(self);
+    get_d1a(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));
+    if (simple_dat_p(adat)) {
+	VALUE new = d_lite_s_alloc_simple(cDate);
+	{
+	    get_d1b(new);
+	    bdat->s = adat->s;
+	    bdat->s.jd = m_local_jd(adat);
+	    return new;
+	}
+    }
+    else {
+	VALUE new = d_lite_s_alloc_simple(cDate);
+	{
+	    get_d1b(new);
+	    copy_complex_to_simple(&bdat->s, &adat->c)
+	    bdat->s.jd = m_local_jd(adat);
+	    bdat->s.flags &= ~(HAVE_DF | HAVE_TIME | COMPLEX_DAT);
+	    return new;
+	}
+    }
 }
 
 /*
@@ -8192,8 +8483,8 @@
     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;
+    positive_inf = +INFINITY;
+    negative_inf = -INFINITY;
 
     /*
      * Class representing a date.
@@ -8307,6 +8598,7 @@
 
 #ifndef NDEBUG
     rb_define_singleton_method(cDate, "new!", date_s_new_bang, -1);
+    rb_define_alias(rb_singleton_class(cDate), "new_l!", "new");
 #endif
 
     rb_define_singleton_method(cDate, "jd", date_s_jd, -1);
@@ -8341,11 +8633,14 @@
     rb_define_singleton_method(cDate, "jisx0301", date_s_jisx0301, -1);
 
 #ifndef NDEBUG
+    rb_define_method(cDate, "initialize", d_lite_initialize, -1);
+#endif
+    rb_define_method(cDate, "initialize_copy", d_lite_initialize_copy, 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);
@@ -8388,7 +8683,7 @@
     rb_define_method(cDate, "saturday?", d_lite_saturday_p, 0);
 
 #ifndef NDEBUG
-    rb_define_method(cDate, "nth_kday?", generic_nth_kday_p, 2);
+    rb_define_method(cDate, "nth_kday?", d_lite_nth_kday_p, 2);
 #endif
 
     rb_define_method(cDate, "julian?", d_lite_julian_p, 0);
@@ -8420,9 +8715,9 @@
     rb_define_method(cDate, "next_year", d_lite_next_year, -1);
     rb_define_method(cDate, "prev_year", d_lite_prev_year, -1);
 
-    rb_define_method(cDate, "step", generic_step, -1);
-    rb_define_method(cDate, "upto", generic_upto, 1);
-    rb_define_method(cDate, "downto", generic_downto, 1);
+    rb_define_method(cDate, "step", d_lite_step, -1);
+    rb_define_method(cDate, "upto", d_lite_upto, 1);
+    rb_define_method(cDate, "downto", d_lite_downto, 1);
 
     rb_define_method(cDate, "<=>", d_lite_cmp, 1);
     rb_define_method(cDate, "===", d_lite_equal, 1);
@@ -8430,6 +8725,9 @@
     rb_define_method(cDate, "hash", d_lite_hash, 0);
 
     rb_define_method(cDate, "to_s", d_lite_to_s, 0);
+#ifndef NDEBUG
+    rb_define_method(cDate, "inspect_raw", d_lite_inspect_raw, 0);
+#endif
     rb_define_method(cDate, "inspect", d_lite_inspect, 0);
 
     rb_define_method(cDate, "strftime", d_lite_strftime, -1);
@@ -8444,6 +8742,9 @@
     rb_define_method(cDate, "httpdate", d_lite_httpdate, 0);
     rb_define_method(cDate, "jisx0301", d_lite_jisx0301, 0);
 
+#ifndef NDEBUG
+    rb_define_method(cDate, "marshal_dump_old", d_lite_marshal_dump_old, 0);
+#endif
     rb_define_method(cDate, "marshal_dump", d_lite_marshal_dump, 0);
     rb_define_method(cDate, "marshal_load", d_lite_marshal_load, 1);
 
@@ -8451,8 +8752,6 @@
 
     cDateTime = rb_define_class("DateTime", cDate);
 
-    rb_undef_method(CLASS_OF(cDateTime), "today");
-
     rb_define_singleton_method(cDateTime, "jd", datetime_s_jd, -1);
     rb_define_singleton_method(cDateTime, "ordinal", datetime_s_ordinal, -1);
     rb_define_singleton_method(cDateTime, "civil", datetime_s_civil, -1);
@@ -8467,6 +8766,8 @@
 			       datetime_s_nth_kday, -1);
 #endif
 
+    rb_undef_method(CLASS_OF(cDateTime), "today");
+
     rb_define_singleton_method(cDateTime, "now", datetime_s_now, -1);
     rb_define_singleton_method(cDateTime, "_strptime",
 			       datetime_s__strptime, -1);

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]