diff --git a/Makefile.in b/Makefile.in
index 25075f5900..515cac832b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -233,7 +233,7 @@ miniruby$(EXEEXT):
 $(PROGRAM):
 		@$(RM) $@
 		$(ECHO) linking $@
-		$(Q) $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(MAINLIBS) $(LIBS) $(EXTLIBS) $(OUTFLAG)$@
+		$(Q) $(PURIFY) $(CC) -pie $(LDFLAGS) $(XLDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(MAINLIBS) $(LIBS) $(EXTLIBS) $(OUTFLAG)$@
 		$(Q) $(POSTLINK)
 
 # We must `rm' the library each time this rule is invoked because "updating" a
diff --git a/ext/bigdecimal/bigdecimal.gemspec b/ext/bigdecimal/bigdecimal.gemspec
index c8c90870ea..9cf22f7e0a 100644
--- a/ext/bigdecimal/bigdecimal.gemspec
+++ b/ext/bigdecimal/bigdecimal.gemspec
@@ -6,6 +6,7 @@
   s.name          = "bigdecimal"
   s.version       = bigdecimal_version
   s.authors       = ["Kenta Murata", "Zachary Scott", "Shigeo Kobayashi"]
+  s.date          = RUBY_RELEASE_DATE
   s.email         = ["mrkn@mrkn.jp"]
 
   s.summary       = "Arbitrary-precision decimal floating-point number library."
diff --git a/ext/date/date_core.c b/ext/date/date_core.c
index c250633426..1734ec0349 100644
--- a/ext/date/date_core.c
+++ b/ext/date/date_core.c
@@ -51,6 +51,9 @@ static double positive_inf, negative_inf;
 #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)
 
+static VALUE date_initialize(int argc, VALUE *argv, VALUE self);
+static VALUE datetime_initialize(int argc, VALUE *argv, VALUE self);
+
 inline static int
 f_cmp(VALUE x, VALUE y)
 {
@@ -94,7 +97,7 @@ f_ge_p(VALUE x, VALUE y)
 {
     if (FIXNUM_P(x) && FIXNUM_P(y))
 	return f_boolcast(FIX2LONG(x) >= FIX2LONG(y));
-    return rb_funcall(x, rb_intern(">="), 1, y);
+    return rb_funcall(x, id_ge_p, 1, y);
 }
 
 inline static VALUE
@@ -102,7 +105,7 @@ f_eqeq_p(VALUE x, VALUE y)
 {
     if (FIXNUM_P(x) && FIXNUM_P(y))
 	return f_boolcast(FIX2LONG(x) == FIX2LONG(y));
-    return rb_funcall(x, rb_intern("=="), 1, y);
+    return rb_funcall(x, id_eqeq_p, 1, y);
 }
 
 inline static VALUE
@@ -236,11 +239,8 @@ f_negative_p(VALUE x)
 struct SimpleDateData
 {
     unsigned flags;
-    VALUE nth;	/* not always canonicalized */
     int jd;	/* as utc */
-    /* df is zero */
-    /* sf is zero */
-    /* of is zero */
+    VALUE nth;	/* not always canonicalized */
     date_sg_t sg;  /* 2298874..2426355 or -/+oo -- at most 22 bits */
     /* decoded as utc=local */
     int year;	/* truncated */
@@ -259,11 +259,8 @@ struct SimpleDateData
 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 */
+    VALUE nth;	/* not always canonicalized */
     date_sg_t sg;  /* 2298874..2426355 or -/+oo -- at most 22 bits */
     /* decoded as local */
     int year;	/* truncated */
@@ -277,6 +274,9 @@ struct ComplexDateData
     /* packed civil */
     unsigned pc;
 #endif
+    int df;	/* as utc, in secs */
+    int of;	/* in secs */
+    VALUE sf;	/* in nano secs */
 };
 
 union DateData {
@@ -315,31 +315,31 @@ canon(VALUE x)
 
 #ifndef USE_PACK
 #define set_to_simple(obj, x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \
-{\
+do {\
     RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth)); \
     (x)->jd = _jd;\
     (x)->sg = (date_sg_t)(_sg);\
     (x)->year = _year;\
     (x)->mon = _mon;\
     (x)->mday = _mday;\
-    (x)->flags = _flags;\
-}
+    (x)->flags = (_flags) & ~COMPLEX_DAT;\
+} while (0)
 #else
 #define set_to_simple(obj, x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \
-{\
+do {\
     RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth)); \
     (x)->jd = _jd;\
     (x)->sg = (date_sg_t)(_sg);\
     (x)->year = _year;\
     (x)->pc = PACK2(_mon, _mday);\
-    (x)->flags = _flags;\
-}
+    (x)->flags = (_flags) & ~COMPLEX_DAT;\
+} while (0)
 #endif
 
 #ifndef USE_PACK
 #define set_to_complex(obj, x, _nth, _jd ,_df, _sf, _of, _sg,\
 _year, _mon, _mday, _hour, _min, _sec, _flags) \
-{\
+do {\
     RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth));\
     (x)->jd = _jd;\
     (x)->df = _df;\
@@ -352,12 +352,12 @@ _year, _mon, _mday, _hour, _min, _sec, _flags) \
     (x)->hour = _hour;\
     (x)->min = _min;\
     (x)->sec = _sec;\
-    (x)->flags = _flags;\
-}
+    (x)->flags = (_flags) | COMPLEX_DAT;\
+} while (0)
 #else
 #define set_to_complex(obj, x, _nth, _jd ,_df, _sf, _of, _sg,\
 _year, _mon, _mday, _hour, _min, _sec, _flags) \
-{\
+do {\
     RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth));\
     (x)->jd = _jd;\
     (x)->df = _df;\
@@ -366,13 +366,13 @@ _year, _mon, _mday, _hour, _min, _sec, _flags) \
     (x)->sg = (date_sg_t)(_sg);\
     (x)->year = _year;\
     (x)->pc = PACK5(_mon, _mday, _hour, _min, _sec);\
-    (x)->flags = _flags;\
-}
+    (x)->flags = (_flags) | COMPLEX_DAT;\
+} while (0)
 #endif
 
 #ifndef USE_PACK
 #define copy_simple_to_complex(obj, x, y) \
-{\
+do {\
     RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
     (x)->jd = (y)->jd;\
     (x)->df = 0;\
@@ -386,10 +386,10 @@ _year, _mon, _mday, _hour, _min, _sec, _flags) \
     (x)->min = 0;\
     (x)->sec = 0;\
     (x)->flags = (y)->flags;\
-}
+} while (0)
 #else
 #define copy_simple_to_complex(obj, x, y) \
-{\
+do {\
     RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
     (x)->jd = (y)->jd;\
     (x)->df = 0;\
@@ -399,12 +399,12 @@ _year, _mon, _mday, _hour, _min, _sec, _flags) \
     (x)->year = (y)->year;\
     (x)->pc = PACK5(EX_MON((y)->pc), EX_MDAY((y)->pc), 0, 0, 0);\
     (x)->flags = (y)->flags;\
-}
+} while (0)
 #endif
 
 #ifndef USE_PACK
 #define copy_complex_to_simple(obj, x, y) \
-{\
+do {\
     RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
     (x)->jd = (y)->jd;\
     (x)->sg = (date_sg_t)((y)->sg);\
@@ -412,17 +412,17 @@ _year, _mon, _mday, _hour, _min, _sec, _flags) \
     (x)->mon = (y)->mon;\
     (x)->mday = (y)->mday;\
     (x)->flags = (y)->flags;\
-}
+} while (0)
 #else
 #define copy_complex_to_simple(obj, x, y) \
-{\
+do {\
     RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
     (x)->jd = (y)->jd;\
     (x)->sg = (date_sg_t)((y)->sg);\
     (x)->year = (y)->year;\
     (x)->pc = PACK2(EX_MON((y)->pc), EX_MDAY((y)->pc));\
     (x)->flags = (y)->flags;\
-}
+} while (0)
 #endif
 
 /* base */
@@ -1109,7 +1109,7 @@ m_virtual_sg(union DateData *x)
 }
 
 #define canonicalize_jd(_nth, _jd) \
-{\
+do {\
     if (_jd < 0) {\
 	_nth = f_sub(_nth, INT2FIX(1));\
 	_jd += CM_PERIOD;\
@@ -1118,7 +1118,7 @@ m_virtual_sg(union DateData *x)
 	_nth = f_add(_nth, INT2FIX(1));\
 	_jd -= CM_PERIOD;\
     }\
-}
+} while (0)
 
 inline static void
 canonicalize_s_jd(VALUE obj, union DateData *x)
@@ -1928,13 +1928,13 @@ m_sec(union DateData *x)
 }
 
 #define decode_offset(of,s,h,m)\
-{\
+do {\
     int a;\
     s = (of < 0) ? '-' : '+';\
     a = (of < 0) ? -of : of;\
     h = a / HOUR_IN_SECONDS;\
     m = a % HOUR_IN_SECONDS / MINUTE_IN_SECONDS;\
-}
+} while (0)
 
 static VALUE
 of2str(int of)
@@ -2333,6 +2333,9 @@ VALUE date_zone_to_diff(VALUE);
 static int
 offset_to_sec(VALUE vof, int *rof)
 {
+    int try_rational = 1;
+
+  again:
     switch (TYPE(vof)) {
       case T_FIXNUM:
 	{
@@ -2359,10 +2362,11 @@ offset_to_sec(VALUE vof, int *rof)
       default:
 	expect_numeric(vof);
 	vof = f_to_r(vof);
-#ifdef CANONICALIZATION_FOR_MATHN
-	if (!k_rational_p(vof))
-	    return offset_to_sec(vof, rof);
-#endif
+	if (!k_rational_p(vof)) {
+	    if (!try_rational) Check_Type(vof, T_RATIONAL);
+	    try_rational = 0;
+	    goto again;
+	}
 	/* fall through */
       case T_RATIONAL:
 	{
@@ -2371,17 +2375,10 @@ offset_to_sec(VALUE vof, int *rof)
 
 	    vs = day_to_sec(vof);
 
-#ifdef CANONICALIZATION_FOR_MATHN
 	    if (!k_rational_p(vs)) {
-		if (!FIXNUM_P(vs))
-		    return 0;
-		n = FIX2LONG(vs);
-		if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
-		    return 0;
-		*rof = (int)n;
-		return 1;
+		vn = vs;
+		goto rounded;
 	    }
-#endif
 	    vn = rb_rational_num(vs);
 	    vd = rb_rational_den(vs);
 
@@ -2391,6 +2388,7 @@ offset_to_sec(VALUE vof, int *rof)
 		vn = f_round(vs);
 		if (!f_eqeq_p(vn, vs))
 		    rb_warning("fraction of offset is ignored");
+	      rounded:
 		if (!FIXNUM_P(vn))
 		    return 0;
 		n = FIX2LONG(vn);
@@ -2420,12 +2418,12 @@ offset_to_sec(VALUE vof, int *rof)
 /* date */
 
 #define valid_sg(sg) \
-{\
+do {\
     if (!c_valid_start_p(sg)) {\
 	sg = 0;\
 	rb_warning("invalid start is ignored");\
     }\
-}
+} while (0)
 
 static VALUE
 valid_jd_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
@@ -2968,7 +2966,7 @@ d_simple_new_internal(VALUE klass,
 
     obj = TypedData_Make_Struct(klass, struct SimpleDateData,
 				&d_lite_type, dat);
-    set_to_simple(obj, dat, nth, jd, sg, y, m, d, flags & ~COMPLEX_DAT);
+    set_to_simple(obj, dat, nth, jd, sg, y, m, d, flags);
 
     assert(have_jd_p(dat) || have_civil_p(dat));
 
@@ -2990,7 +2988,7 @@ d_complex_new_internal(VALUE klass,
     obj = TypedData_Make_Struct(klass, struct ComplexDateData,
 				&d_lite_type, dat);
     set_to_complex(obj, dat, nth, jd, df, sf, of, sg,
-		   y, m, d, h, min, s, flags | COMPLEX_DAT);
+		   y, m, d, h, min, s, flags);
 
     assert(have_jd_p(dat) || have_civil_p(dat));
     assert(have_df_p(dat) || have_time_p(dat));
@@ -3207,47 +3205,47 @@ s_trunc(VALUE s, VALUE *fr)
 }
 
 #define num2num_with_frac(s,n) \
-{\
+do {\
     s = s##_trunc(v##s, &fr);\
     if (f_nonzero_p(fr)) {\
 	if (argc > n)\
 	    rb_raise(rb_eArgError, "invalid fraction");\
 	fr2 = fr;\
     }\
-}
+} while (0)
 
 #define num2int_with_frac(s,n) \
-{\
+do {\
     s = NUM2INT(s##_trunc(v##s, &fr));\
     if (f_nonzero_p(fr)) {\
 	if (argc > n)\
 	    rb_raise(rb_eArgError, "invalid fraction");\
 	fr2 = fr;\
     }\
-}
+} while (0)
 
 #define canon24oc() \
-{\
+do {\
     if (rh == 24) {\
 	rh = 0;\
 	fr2 = f_add(fr2, INT2FIX(1));\
     }\
-}
+} while (0)
 
 #define add_frac() \
-{\
+do {\
     if (f_nonzero_p(fr2))\
 	ret = d_lite_plus(ret, fr2);\
-}
+} while (0)
 
 #define val2sg(vsg,dsg) \
-{\
+do {\
     dsg = NUM2DBL(vsg);\
     if (!c_valid_start_p(dsg)) {\
 	dsg = DEFAULT_SG;\
 	rb_warning("invalid start is ignored");\
     }\
-}
+} while (0)
 
 static VALUE d_lite_plus(VALUE, VALUE);
 
@@ -3384,10 +3382,21 @@ date_s_ordinal(int argc, VALUE *argv, VALUE klass)
  */
 static VALUE
 date_s_civil(int argc, VALUE *argv, VALUE klass)
+{
+    return date_initialize(argc, argv, d_lite_s_alloc_simple(klass));
+}
+
+static VALUE
+date_initialize(int argc, VALUE *argv, VALUE self)
 {
     VALUE vy, vm, vd, vsg, y, fr, fr2, ret;
     int m, d;
     double sg;
+    struct SimpleDateData *dat = rb_check_typeddata(self, &d_lite_type);
+
+    if (!simple_dat_p(dat)) {
+	rb_raise(rb_eTypeError, "Date expected");
+    }
 
     rb_scan_args(argc, argv, "04", &vy, &vm, &vd, &vsg);
 
@@ -3417,11 +3426,7 @@ date_s_civil(int argc, VALUE *argv, VALUE klass)
 			       &rm, &rd))
 	    rb_raise(rb_eArgError, "invalid date");
 
-	ret = d_simple_new_internal(klass,
-				    nth, 0,
-				    sg,
-				    ry, rm, rd,
-				    HAVE_CIVIL);
+	set_to_simple(self, dat, nth, 0, sg, ry, rm, rd, HAVE_CIVIL);
     }
     else {
 	VALUE nth;
@@ -3433,12 +3438,9 @@ date_s_civil(int argc, VALUE *argv, VALUE klass)
 			   &ns))
 	    rb_raise(rb_eArgError, "invalid date");
 
-	ret = d_simple_new_internal(klass,
-				    nth, rjd,
-				    sg,
-				    ry, rm, rd,
-				    HAVE_JD | HAVE_CIVIL);
+	set_to_simple(self, dat, nth, rjd, sg, ry, rm, rd, HAVE_JD | HAVE_CIVIL);
     }
+    ret = self;
     add_frac();
     return ret;
 }
@@ -3679,9 +3681,11 @@ date_s_today(int argc, VALUE *argv, VALUE klass)
 #define ref_hash0(k) rb_hash_aref(hash, k)
 #define del_hash0(k) rb_hash_delete(hash, k)
 
-#define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k)), v)
-#define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k)))
-#define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k)))
+#define sym(x) ID2SYM(rb_intern(x""))
+
+#define set_hash(k,v) set_hash0(sym(k), v)
+#define ref_hash(k) ref_hash0(sym(k))
+#define del_hash(k) del_hash0(sym(k))
 
 static VALUE
 rt_rewrite_frags(VALUE hash)
@@ -3718,8 +3722,6 @@ rt_rewrite_frags(VALUE hash)
     return hash;
 }
 
-#define sym(x) ID2SYM(rb_intern(x))
-
 static VALUE d_lite_year(VALUE);
 static VALUE d_lite_wday(VALUE);
 static VALUE d_lite_jd(VALUE);
@@ -4290,12 +4292,40 @@ date_s_strptime(int argc, VALUE *argv, VALUE klass)
 
 VALUE date__parse(VALUE str, VALUE comp);
 
+static size_t
+get_limit(VALUE opt)
+{
+    if (!NIL_P(opt)) {
+        VALUE limit = rb_hash_aref(opt, ID2SYM(rb_intern("limit")));
+        if (NIL_P(limit)) return SIZE_MAX;
+        return NUM2SIZET(limit);
+    }
+    return 128;
+}
+
+static void
+check_limit(VALUE str, VALUE opt)
+{
+    if (NIL_P(str)) return;
+    if (SYMBOL_P(str)) str = rb_sym2str(str);
+
+    StringValue(str);
+    size_t slen = RSTRING_LEN(str);
+    size_t limit = get_limit(opt);
+    if (slen > limit) {
+	rb_raise(rb_eArgError,
+		 "string length (%"PRI_SIZE_PREFIX"u) exceeds the limit %"PRI_SIZE_PREFIX"u", slen, limit);
+    }
+}
+
 static VALUE
 date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
 {
-    VALUE vstr, vcomp, hash;
+    VALUE vstr, vcomp, hash, opt;
 
-    rb_scan_args(argc, argv, "11", &vstr, &vcomp);
+    rb_scan_args(argc, argv, "11:", &vstr, &vcomp, &opt);
+    if (!NIL_P(opt)) argc--;
+    check_limit(vstr, opt);
     StringValue(vstr);
     if (!rb_enc_str_asciicompat_p(vstr))
 	rb_raise(rb_eArgError,
@@ -4320,7 +4350,7 @@ date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
 
 /*
  * call-seq:
- *    Date._parse(string[, comp=true])  ->  hash
+ *    Date._parse(string[, comp=true], limit: 128)  ->  hash
  *
  * Parses the given representation of date and time, and returns a
  * hash of parsed elements.  This method does not function as a
@@ -4331,6 +4361,10 @@ date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
  * it full.
  *
  *    Date._parse('2001-02-03')	#=> {:year=>2001, :mon=>2, :mday=>3}
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
 date_s__parse(int argc, VALUE *argv, VALUE klass)
@@ -4340,7 +4374,7 @@ date_s__parse(int argc, VALUE *argv, VALUE klass)
 
 /*
  * call-seq:
- *    Date.parse(string='-4712-01-01'[, comp=true[, start=Date::ITALY]])  ->  date
+ *    Date.parse(string='-4712-01-01'[, comp=true[, start=Date::ITALY]], limit: 128)  ->  date
  *
  * Parses the given representation of date and time, and creates a
  * date object.  This method does not function as a validator.
@@ -4352,13 +4386,18 @@ date_s__parse(int argc, VALUE *argv, VALUE klass)
  *    Date.parse('2001-02-03')		#=> #<Date: 2001-02-03 ...>
  *    Date.parse('20010203')		#=> #<Date: 2001-02-03 ...>
  *    Date.parse('3rd Feb 2001')	#=> #<Date: 2001-02-03 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
 date_s_parse(int argc, VALUE *argv, VALUE klass)
 {
-    VALUE str, comp, sg;
+    VALUE str, comp, sg, opt;
 
-    rb_scan_args(argc, argv, "03", &str, &comp, &sg);
+    rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt);
+    if (!NIL_P(opt)) argc--;
 
     switch (argc) {
       case 0:
@@ -4370,11 +4409,12 @@ date_s_parse(int argc, VALUE *argv, VALUE klass)
     }
 
     {
-	VALUE argv2[2], hash;
-
-	argv2[0] = str;
-	argv2[1] = comp;
-	hash = date_s__parse(2, argv2, klass);
+        int argc2 = 2;
+	VALUE argv2[3];
+        argv2[0] = str;
+        argv2[1] = comp;
+        if (!NIL_P(opt)) argv2[argc2++] = opt;
+	VALUE hash = date_s__parse(argc2, argv2, klass);
 	return d_new_by_frags(klass, hash, sg);
     }
 }
@@ -4388,19 +4428,28 @@ VALUE date__jisx0301(VALUE);
 
 /*
  * call-seq:
- *    Date._iso8601(string)  ->  hash
+ *    Date._iso8601(string, limit: 128)  ->  hash
  *
  * Returns a hash of parsed elements.
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
-date_s__iso8601(VALUE klass, VALUE str)
+date_s__iso8601(int argc, VALUE *argv, VALUE klass)
 {
+    VALUE str, opt;
+
+    rb_scan_args(argc, argv, "1:", &str, &opt);
+    check_limit(str, opt);
+
     return date__iso8601(str);
 }
 
 /*
  * call-seq:
- *    Date.iso8601(string='-4712-01-01'[, start=Date::ITALY])  ->  date
+ *    Date.iso8601(string='-4712-01-01'[, start=Date::ITALY], limit: 128)  ->  date
  *
  * Creates a new Date object by parsing from a string according to
  * some typical ISO 8601 formats.
@@ -4408,13 +4457,18 @@ date_s__iso8601(VALUE klass, VALUE str)
  *    Date.iso8601('2001-02-03')	#=> #<Date: 2001-02-03 ...>
  *    Date.iso8601('20010203')		#=> #<Date: 2001-02-03 ...>
  *    Date.iso8601('2001-W05-6')	#=> #<Date: 2001-02-03 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
 date_s_iso8601(int argc, VALUE *argv, VALUE klass)
 {
-    VALUE str, sg;
+    VALUE str, sg, opt;
 
-    rb_scan_args(argc, argv, "02", &str, &sg);
+    rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+    if (!NIL_P(opt)) argc--;
 
     switch (argc) {
       case 0:
@@ -4424,38 +4478,56 @@ date_s_iso8601(int argc, VALUE *argv, VALUE klass)
     }
 
     {
-	VALUE hash = date_s__iso8601(klass, str);
+        int argc2 = 1;
+        VALUE argv2[2];
+        argv2[0] = str;
+        if (!NIL_P(opt)) argv2[argc2++] = opt;
+	VALUE hash = date_s__iso8601(argc2, argv2, klass);
 	return d_new_by_frags(klass, hash, sg);
     }
 }
 
 /*
  * call-seq:
- *    Date._rfc3339(string)  ->  hash
+ *    Date._rfc3339(string, limit: 128)  ->  hash
  *
  * Returns a hash of parsed elements.
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
-date_s__rfc3339(VALUE klass, VALUE str)
+date_s__rfc3339(int argc, VALUE *argv, VALUE klass)
 {
+    VALUE str, opt;
+
+    rb_scan_args(argc, argv, "1:", &str, &opt);
+    check_limit(str, opt);
+
     return date__rfc3339(str);
 }
 
 /*
  * call-seq:
- *    Date.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY])  ->  date
+ *    Date.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128)  ->  date
  *
  * Creates a new Date object by parsing from a string according to
  * some typical RFC 3339 formats.
  *
  *    Date.rfc3339('2001-02-03T04:05:06+07:00')	#=> #<Date: 2001-02-03 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
 date_s_rfc3339(int argc, VALUE *argv, VALUE klass)
 {
-    VALUE str, sg;
+    VALUE str, sg, opt;
 
-    rb_scan_args(argc, argv, "02", &str, &sg);
+    rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+    if (!NIL_P(opt)) argc--;
 
     switch (argc) {
       case 0:
@@ -4465,38 +4537,56 @@ date_s_rfc3339(int argc, VALUE *argv, VALUE klass)
     }
 
     {
-	VALUE hash = date_s__rfc3339(klass, str);
+        int argc2 = 1;
+        VALUE argv2[2];
+        argv2[0] = str;
+        if (!NIL_P(opt)) argv2[argc2++] = opt;
+	VALUE hash = date_s__rfc3339(argc2, argv2, klass);
 	return d_new_by_frags(klass, hash, sg);
     }
 }
 
 /*
  * call-seq:
- *    Date._xmlschema(string)  ->  hash
+ *    Date._xmlschema(string, limit: 128)  ->  hash
  *
  * Returns a hash of parsed elements.
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
-date_s__xmlschema(VALUE klass, VALUE str)
+date_s__xmlschema(int argc, VALUE *argv, VALUE klass)
 {
+    VALUE str, opt;
+
+    rb_scan_args(argc, argv, "1:", &str, &opt);
+    check_limit(str, opt);
+
     return date__xmlschema(str);
 }
 
 /*
  * call-seq:
- *    Date.xmlschema(string='-4712-01-01'[, start=Date::ITALY])  ->  date
+ *    Date.xmlschema(string='-4712-01-01'[, start=Date::ITALY], limit: 128)  ->  date
  *
  * Creates a new Date object by parsing from a string according to
  * some typical XML Schema formats.
  *
  *    Date.xmlschema('2001-02-03')	#=> #<Date: 2001-02-03 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
 date_s_xmlschema(int argc, VALUE *argv, VALUE klass)
 {
-    VALUE str, sg;
+    VALUE str, sg, opt;
 
-    rb_scan_args(argc, argv, "02", &str, &sg);
+    rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+    if (!NIL_P(opt)) argc--;
 
     switch (argc) {
       case 0:
@@ -4506,41 +4596,58 @@ date_s_xmlschema(int argc, VALUE *argv, VALUE klass)
     }
 
     {
-	VALUE hash = date_s__xmlschema(klass, str);
+        int argc2 = 1;
+        VALUE argv2[2];
+        argv2[0] = str;
+        if (!NIL_P(opt)) argv2[argc2++] = opt;
+	VALUE hash = date_s__xmlschema(argc2, argv2, klass);
 	return d_new_by_frags(klass, hash, sg);
     }
 }
 
 /*
  * call-seq:
- *    Date._rfc2822(string)  ->  hash
- *    Date._rfc822(string)   ->  hash
+ *    Date._rfc2822(string, limit: 128)  ->  hash
+ *    Date._rfc822(string, limit: 128)   ->  hash
  *
  * Returns a hash of parsed elements.
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
-date_s__rfc2822(VALUE klass, VALUE str)
+date_s__rfc2822(int argc, VALUE *argv, VALUE klass)
 {
+    VALUE str, opt;
+
+    rb_scan_args(argc, argv, "1:", &str, &opt);
+    check_limit(str, opt);
+
     return date__rfc2822(str);
 }
 
 /*
  * call-seq:
- *    Date.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY])  ->  date
- *    Date.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY])   ->  date
+ *    Date.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128)  ->  date
+ *    Date.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128)   ->  date
  *
  * Creates a new Date object by parsing from a string according to
  * some typical RFC 2822 formats.
  *
  *    Date.rfc2822('Sat, 3 Feb 2001 00:00:00 +0000')
  *						#=> #<Date: 2001-02-03 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
 date_s_rfc2822(int argc, VALUE *argv, VALUE klass)
 {
-    VALUE str, sg;
+    VALUE str, sg, opt;
 
-    rb_scan_args(argc, argv, "02", &str, &sg);
+    rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
 
     switch (argc) {
       case 0:
@@ -4550,39 +4657,56 @@ date_s_rfc2822(int argc, VALUE *argv, VALUE klass)
     }
 
     {
-	VALUE hash = date_s__rfc2822(klass, str);
+        int argc2 = 1;
+        VALUE argv2[2];
+        argv2[0] = str;
+        if (!NIL_P(opt)) argv2[argc2++] = opt;
+	VALUE hash = date_s__rfc2822(argc2, argv2, klass);
 	return d_new_by_frags(klass, hash, sg);
     }
 }
 
 /*
  * call-seq:
- *    Date._httpdate(string)  ->  hash
+ *    Date._httpdate(string, limit: 128)  ->  hash
  *
  * Returns a hash of parsed elements.
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
-date_s__httpdate(VALUE klass, VALUE str)
+date_s__httpdate(int argc, VALUE *argv, VALUE klass)
 {
+    VALUE str, opt;
+
+    rb_scan_args(argc, argv, "1:", &str, &opt);
+    check_limit(str, opt);
+
     return date__httpdate(str);
 }
 
 /*
  * call-seq:
- *    Date.httpdate(string='Mon, 01 Jan -4712 00:00:00 GMT'[, start=Date::ITALY])  ->  date
+ *    Date.httpdate(string='Mon, 01 Jan -4712 00:00:00 GMT'[, start=Date::ITALY], limit: 128)  ->  date
  *
  * Creates a new Date object by parsing from a string according to
  * some RFC 2616 format.
  *
  *    Date.httpdate('Sat, 03 Feb 2001 00:00:00 GMT')
  *						#=> #<Date: 2001-02-03 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
 date_s_httpdate(int argc, VALUE *argv, VALUE klass)
 {
-    VALUE str, sg;
+    VALUE str, sg, opt;
 
-    rb_scan_args(argc, argv, "02", &str, &sg);
+    rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
 
     switch (argc) {
       case 0:
@@ -4592,38 +4716,60 @@ date_s_httpdate(int argc, VALUE *argv, VALUE klass)
     }
 
     {
-	VALUE hash = date_s__httpdate(klass, str);
+        int argc2 = 1;
+        VALUE argv2[2];
+        argv2[0] = str;
+        if (!NIL_P(opt)) argv2[argc2++] = opt;
+	VALUE hash = date_s__httpdate(argc2, argv2, klass);
 	return d_new_by_frags(klass, hash, sg);
     }
 }
 
 /*
  * call-seq:
- *    Date._jisx0301(string)  ->  hash
+ *    Date._jisx0301(string, limit: 128)  ->  hash
  *
  * Returns a hash of parsed elements.
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
-date_s__jisx0301(VALUE klass, VALUE str)
+date_s__jisx0301(int argc, VALUE *argv, VALUE klass)
 {
+    VALUE str, opt;
+
+    rb_scan_args(argc, argv, "1:", &str, &opt);
+    check_limit(str, opt);
+
     return date__jisx0301(str);
 }
 
 /*
  * call-seq:
- *    Date.jisx0301(string='-4712-01-01'[, start=Date::ITALY])  ->  date
+ *    Date.jisx0301(string='-4712-01-01'[, start=Date::ITALY], limit: 128)  ->  date
  *
  * Creates a new Date object by parsing from a string according to
  * some typical JIS X 0301 formats.
  *
  *    Date.jisx0301('H13.02.03')		#=> #<Date: 2001-02-03 ...>
+ *
+ * For no-era year, legacy format, Heisei is assumed.
+ *
+ *    Date.jisx0301('13.02.03') 		#=> #<Date: 2001-02-03 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
 date_s_jisx0301(int argc, VALUE *argv, VALUE klass)
 {
-    VALUE str, sg;
+    VALUE str, sg, opt;
 
-    rb_scan_args(argc, argv, "02", &str, &sg);
+    rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+    if (!NIL_P(opt)) argc--;
 
     switch (argc) {
       case 0:
@@ -4633,7 +4779,11 @@ date_s_jisx0301(int argc, VALUE *argv, VALUE klass)
     }
 
     {
-	VALUE hash = date_s__jisx0301(klass, str);
+        int argc2 = 1;
+        VALUE argv2[2];
+        argv2[0] = str;
+        if (!NIL_P(opt)) argv2[argc2++] = opt;
+	VALUE hash = date_s__jisx0301(argc2, argv2, klass);
 	return d_new_by_frags(klass, hash, sg);
     }
 }
@@ -4691,14 +4841,14 @@ dup_obj_as_complex(VALUE self)
 }
 
 #define val2off(vof,iof) \
-{\
+do {\
     if (!offset_to_sec(vof, &iof)) {\
 	iof = 0;\
 	rb_warning("invalid offset is ignored");\
     }\
-}
+} while (0)
 
-#ifndef NDEBUG
+#if 0
 static VALUE
 d_lite_initialize(int argc, VALUE *argv, VALUE self)
 {
@@ -4751,7 +4901,7 @@ d_lite_initialize(int argc, VALUE *argv, VALUE self)
 			 "cannot load complex into simple");
 
 	    set_to_complex(self, &dat->c, nth, rjd, df, sf, of, sg,
-			   0, 0, 0, 0, 0, 0, HAVE_JD | HAVE_DF | COMPLEX_DAT);
+			   0, 0, 0, 0, 0, 0, HAVE_JD | HAVE_DF);
 	}
     }
     return self;
@@ -4770,8 +4920,28 @@ d_lite_initialize_copy(VALUE copy, VALUE date)
     {
 	get_d2(copy, date);
 	if (simple_dat_p(bdat)) {
-	    adat->s = bdat->s;
-	    adat->s.flags &= ~COMPLEX_DAT;
+	    if (simple_dat_p(adat)) {
+		adat->s = bdat->s;
+	    }
+	    else {
+		adat->c.flags = bdat->s.flags | COMPLEX_DAT;
+		adat->c.nth = bdat->s.nth;
+		adat->c.jd = bdat->s.jd;
+		adat->c.df = 0;
+		adat->c.sf = INT2FIX(0);
+		adat->c.of = 0;
+		adat->c.sg = bdat->s.sg;
+		adat->c.year = bdat->s.year;
+#ifndef USE_PACK
+		adat->c.mon = bdat->s.mon;
+		adat->c.mday = bdat->s.mday;
+		adat->c.hour = bdat->s.hour;
+		adat->c.min = bdat->s.min;
+		adat->c.sec = bdat->s.sec;
+#else
+		adat->c.pc = bdat->s.pc;
+#endif
+	    }
 	}
 	else {
 	    if (!complex_dat_p(adat))
@@ -4779,7 +4949,6 @@ d_lite_initialize_copy(VALUE copy, VALUE date)
 			 "cannot load complex into simple");
 
 	    adat->c = bdat->c;
-	    adat->c.flags |= COMPLEX_DAT;
 	}
     }
     return copy;
@@ -5513,8 +5682,10 @@ d_lite_new_offset(int argc, VALUE *argv, VALUE self)
 static VALUE
 d_lite_plus(VALUE self, VALUE other)
 {
+    int try_rational = 1;
     get_d1(self);
 
+  again:
     switch (TYPE(other)) {
       case T_FIXNUM:
 	{
@@ -5724,18 +5895,21 @@ d_lite_plus(VALUE self, VALUE other)
       default:
 	expect_numeric(other);
 	other = f_to_r(other);
-#ifdef CANONICALIZATION_FOR_MATHN
-	if (!k_rational_p(other))
-	    return d_lite_plus(self, other);
-#endif
+	if (!k_rational_p(other)) {
+	    if (!try_rational) Check_Type(other, T_RATIONAL);
+	    try_rational = 0;
+	    goto again;
+	}
 	/* fall through */
       case T_RATIONAL:
 	{
 	    VALUE nth, sf, t;
 	    int jd, df, s;
 
-	    if (wholenum_p(other))
-		return d_lite_plus(self, rb_rational_num(other));
+	    if (wholenum_p(other)) {
+		other = rb_rational_num(other);
+		goto again;
+	    }
 
 	    if (f_positive_p(other))
 		s = +1;
@@ -6242,7 +6416,7 @@ cmp_gen(VALUE self, VALUE other)
 	return INT2FIX(f_cmp(m_ajd(dat), other));
     else if (k_date_p(other))
 	return INT2FIX(f_cmp(m_ajd(dat), f_ajd(other)));
-    return rb_num_coerce_cmp(self, other, rb_intern("<=>"));
+    return rb_num_coerce_cmp(self, other, id_cmp);
 }
 
 static VALUE
@@ -6371,7 +6545,7 @@ equal_gen(VALUE self, VALUE 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("=="));
+    return rb_num_coerce_cmp(self, other, id_eqeq_p);
 }
 
 /*
@@ -6469,7 +6643,7 @@ d_lite_to_s(VALUE self)
 static VALUE
 mk_inspect_raw(union DateData *x, VALUE klass)
 {
-    char flags[5];
+    char flags[6];
 
     flags[0] = (x->flags & COMPLEX_DAT) ? 'C' : 'S';
     flags[1] = (x->flags & HAVE_JD)     ? 'j' : '-';
@@ -6635,7 +6809,9 @@ tmx_m_of(union DateData *x)
 static char *
 tmx_m_zone(union DateData *x)
 {
-    return RSTRING_PTR(m_zone(x));
+    VALUE zone = m_zone(x);
+    /* TODO: fix potential dangling pointer */
+    return RSTRING_PTR(zone);
 }
 
 static const struct tmx_funcs tmx_funcs = {
@@ -6785,7 +6961,7 @@ date_strftime_internal(int argc, VALUE *argv, VALUE self,
  *
  *      %M - Minute of the hour (00..59)
  *
- *      %S - Second of the minute (00..59)
+ *      %S - Second of the minute (00..60)
  *
  *      %L - Millisecond of the second (000..999)
  *      %N - Fractional seconds digits, default is 9 digits (nanosecond)
@@ -7018,10 +7194,14 @@ jisx0301_date_format(char *fmt, size_t size, VALUE jd, VALUE y)
 	    c = 'S';
 	    s = 1925;
 	}
-	else {
+	else if (d < 2458605) {
 	    c = 'H';
 	    s = 1988;
 	}
+	else {
+	    c = 'R';
+	    s = 2018;
+	}
 	snprintf(fmt, size, "%c%02ld" ".%%m.%%d", c, FIX2INT(y) - s);
 	return fmt;
     }
@@ -7099,6 +7279,10 @@ d_lite_marshal_dump(VALUE self)
 static VALUE
 d_lite_marshal_load(VALUE self, VALUE a)
 {
+    VALUE nth, sf;
+    int jd, df, of;
+    double sg;
+
     get_d1(self);
 
     rb_check_frozen(self);
@@ -7111,63 +7295,33 @@ d_lite_marshal_load(VALUE self, VALUE a)
       case 2: /* 1.6.x */
       case 3: /* 1.8.x, 1.9.2 */
 	{
-	    VALUE ajd, of, sg, nth, sf;
-	    int jd, df, rof;
-	    double rsg;
-
+	    VALUE ajd, vof, vsg;
 
 	    if  (RARRAY_LEN(a) == 2) {
 		ajd = f_sub(RARRAY_AREF(a, 0), half_days_in_day);
-		of = INT2FIX(0);
-		sg = RARRAY_AREF(a, 1);
-		if (!k_numeric_p(sg))
-		    sg = DBL2NUM(RTEST(sg) ? GREGORIAN : JULIAN);
+		vof = INT2FIX(0);
+		vsg = RARRAY_AREF(a, 1);
+		if (!k_numeric_p(vsg))
+		    vsg = DBL2NUM(RTEST(vsg) ? GREGORIAN : JULIAN);
 	    }
 	    else {
 		ajd = RARRAY_AREF(a, 0);
-		of = RARRAY_AREF(a, 1);
-		sg = RARRAY_AREF(a, 2);
+		vof = RARRAY_AREF(a, 1);
+		vsg = RARRAY_AREF(a, 2);
 	    }
 
-	    old_to_new(ajd, of, sg,
-		       &nth, &jd, &df, &sf, &rof, &rsg);
-
-	    if (!df && f_zero_p(sf) && !rof) {
-		set_to_simple(self, &dat->s, nth, jd, rsg, 0, 0, 0, HAVE_JD);
-	    } else {
-		if (!complex_dat_p(dat))
-		    rb_raise(rb_eArgError,
-			     "cannot load complex into simple");
-
-		set_to_complex(self, &dat->c, nth, jd, df, sf, rof, rsg,
-			       0, 0, 0, 0, 0, 0,
-			       HAVE_JD | HAVE_DF | COMPLEX_DAT);
-	    }
+	    old_to_new(ajd, vof, vsg,
+		       &nth, &jd, &df, &sf, &of, &sg);
 	}
 	break;
       case 6:
 	{
-	    VALUE nth, sf;
-	    int jd, df, of;
-	    double sg;
-
 	    nth = RARRAY_AREF(a, 0);
 	    jd = NUM2INT(RARRAY_AREF(a, 1));
 	    df = NUM2INT(RARRAY_AREF(a, 2));
 	    sf = RARRAY_AREF(a, 3);
 	    of = NUM2INT(RARRAY_AREF(a, 4));
 	    sg = NUM2DBL(RARRAY_AREF(a, 5));
-	    if (!df && f_zero_p(sf) && !of) {
-		set_to_simple(self, &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(self, &dat->c, nth, jd, df, sf, of, sg,
-			       0, 0, 0, 0, 0, 0,
-			       HAVE_JD | HAVE_DF | COMPLEX_DAT);
-	    }
 	}
 	break;
       default:
@@ -7175,6 +7329,18 @@ d_lite_marshal_load(VALUE self, VALUE a)
 	break;
     }
 
+    if (simple_dat_p(dat)) {
+	if (df || !f_zero_p(sf) || of) {
+	    rb_raise(rb_eArgError,
+		     "cannot load complex into simple");
+	}
+	set_to_simple(self, &dat->s, nth, jd, sg, 0, 0, 0, HAVE_JD);
+    } else {
+	set_to_complex(self, &dat->c, nth, jd, df, sf, of, sg,
+		       0, 0, 0, 0, 0, 0,
+		       HAVE_JD | HAVE_DF);
+    }
+
     if (FL_TEST(a, FL_EXIVAR)) {
 	rb_copy_generic_ivar(self, a);
 	FL_SET(self, FL_EXIVAR);
@@ -7354,10 +7520,21 @@ datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
  */
 static VALUE
 datetime_s_civil(int argc, VALUE *argv, VALUE klass)
+{
+    return datetime_initialize(argc, argv, d_lite_s_alloc_complex(klass));
+}
+
+static VALUE
+datetime_initialize(int argc, VALUE *argv, VALUE self)
 {
     VALUE vy, vm, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
     int m, d, h, min, s, rof;
     double sg;
+    struct ComplexDateData *dat = rb_check_typeddata(self, &d_lite_type);
+
+    if (!complex_dat_p(dat)) {
+	rb_raise(rb_eTypeError, "DateTime expected");
+    }
 
     rb_scan_args(argc, argv, "08", &vy, &vm, &vd, &vh, &vmin, &vs, &vof, &vsg);
 
@@ -7401,13 +7578,13 @@ datetime_s_civil(int argc, VALUE *argv, VALUE klass)
 	    rb_raise(rb_eArgError, "invalid date");
 	canon24oc();
 
-	ret = d_complex_new_internal(klass,
-				     nth, 0,
-				     0, INT2FIX(0),
-				     rof, sg,
-				     ry, rm, rd,
-				     rh, rmin, rs,
-				     HAVE_CIVIL | HAVE_TIME);
+	set_to_complex(self, dat,
+		       nth, 0,
+		       0, INT2FIX(0),
+		       rof, sg,
+		       ry, rm, rd,
+		       rh, rmin, rs,
+		       HAVE_CIVIL | HAVE_TIME);
     }
     else {
 	VALUE nth;
@@ -7426,14 +7603,15 @@ datetime_s_civil(int argc, VALUE *argv, VALUE klass)
 			       time_to_df(rh, rmin, rs),
 			       rof);
 
-	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);
+	set_to_complex(self, dat,
+		       nth, rjd2,
+		       0, INT2FIX(0),
+		       rof, sg,
+		       ry, rm, rd,
+		       rh, rmin, rs,
+		       HAVE_JD | HAVE_CIVIL | HAVE_TIME);
     }
+    ret = self;
     add_frac();
     return ret;
 }
@@ -7925,7 +8103,7 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
 
 /*
  * call-seq:
- *    DateTime.parse(string='-4712-01-01T00:00:00+00:00'[, comp=true[, start=Date::ITALY]])  ->  datetime
+ *    DateTime.parse(string='-4712-01-01T00:00:00+00:00'[, comp=true[, start=Date::ITALY]], limit: 128)  ->  datetime
  *
  * Parses the given representation of date and time, and creates a
  * DateTime object.  This method does not function as a validator.
@@ -7939,13 +8117,18 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
  *				#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
  *    DateTime.parse('3rd Feb 2001 04:05:06 PM')
  *				#=> #<DateTime: 2001-02-03T16:05:06+00:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
 datetime_s_parse(int argc, VALUE *argv, VALUE klass)
 {
-    VALUE str, comp, sg;
+    VALUE str, comp, sg, opt;
 
-    rb_scan_args(argc, argv, "03", &str, &comp, &sg);
+    rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt);
+    if (!NIL_P(opt)) argc--;
 
     switch (argc) {
       case 0:
@@ -7957,18 +8140,20 @@ datetime_s_parse(int argc, VALUE *argv, VALUE klass)
     }
 
     {
-	VALUE argv2[2], hash;
-
-	argv2[0] = str;
-	argv2[1] = comp;
-	hash = date_s__parse(2, argv2, klass);
+        int argc2 = 2;
+        VALUE argv2[3];
+        argv2[0] = str;
+        argv2[1] = comp;
+        argv2[2] = opt;
+        if (!NIL_P(opt)) argc2++;
+	VALUE hash = date_s__parse(argc2, argv2, klass);
 	return dt_new_by_frags(klass, hash, sg);
     }
 }
 
 /*
  * call-seq:
- *    DateTime.iso8601(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY])  ->  datetime
+ *    DateTime.iso8601(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128)  ->  datetime
  *
  * Creates a new DateTime object by parsing from a string according to
  * some typical ISO 8601 formats.
@@ -7979,13 +8164,18 @@ datetime_s_parse(int argc, VALUE *argv, VALUE klass)
  *				#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
  *    DateTime.iso8601('2001-W05-6T04:05:06+07:00')
  *				#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
 datetime_s_iso8601(int argc, VALUE *argv, VALUE klass)
 {
-    VALUE str, sg;
+    VALUE str, sg, opt;
 
-    rb_scan_args(argc, argv, "02", &str, &sg);
+    rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+    if (!NIL_P(opt)) argc--;
 
     switch (argc) {
       case 0:
@@ -7995,27 +8185,37 @@ datetime_s_iso8601(int argc, VALUE *argv, VALUE klass)
     }
 
     {
-	VALUE hash = date_s__iso8601(klass, str);
+        int argc2 = 1;
+        VALUE argv2[2];
+        argv2[0] = str;
+        argv2[1] = opt;
+        if (!NIL_P(opt)) argc2--;
+	VALUE hash = date_s__iso8601(argc2, argv2, klass);
 	return dt_new_by_frags(klass, hash, sg);
     }
 }
 
 /*
  * call-seq:
- *    DateTime.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY])  ->  datetime
+ *    DateTime.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128)  ->  datetime
  *
  * Creates a new DateTime object by parsing from a string according to
  * some typical RFC 3339 formats.
  *
  *    DateTime.rfc3339('2001-02-03T04:05:06+07:00')
  *				#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
 datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass)
 {
-    VALUE str, sg;
+    VALUE str, sg, opt;
 
-    rb_scan_args(argc, argv, "02", &str, &sg);
+    rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+    if (!NIL_P(opt)) argc--;
 
     switch (argc) {
       case 0:
@@ -8025,27 +8225,37 @@ datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass)
     }
 
     {
-	VALUE hash = date_s__rfc3339(klass, str);
+        int argc2 = 1;
+        VALUE argv2[2];
+        argv2[0] = str;
+        argv2[1] = opt;
+        if (!NIL_P(opt)) argc2++;
+	VALUE hash = date_s__rfc3339(argc2, argv2, klass);
 	return dt_new_by_frags(klass, hash, sg);
     }
 }
 
 /*
  * call-seq:
- *    DateTime.xmlschema(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY])  ->  datetime
+ *    DateTime.xmlschema(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128)  ->  datetime
  *
  * Creates a new DateTime object by parsing from a string according to
  * some typical XML Schema formats.
  *
  *    DateTime.xmlschema('2001-02-03T04:05:06+07:00')
  *				#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
 datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass)
 {
-    VALUE str, sg;
+    VALUE str, sg, opt;
 
-    rb_scan_args(argc, argv, "02", &str, &sg);
+    rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+    if (!NIL_P(opt)) argc--;
 
     switch (argc) {
       case 0:
@@ -8055,28 +8265,38 @@ datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass)
     }
 
     {
-	VALUE hash = date_s__xmlschema(klass, str);
+        int argc2 = 1;
+        VALUE argv2[2];
+        argv2[0] = str;
+        argv2[1] = opt;
+        if (!NIL_P(opt)) argc2++;
+	VALUE hash = date_s__xmlschema(argc2, argv2, klass);
 	return dt_new_by_frags(klass, hash, sg);
     }
 }
 
 /*
  * call-seq:
- *    DateTime.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY])  ->  datetime
- *    DateTime.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY])   ->  datetime
+ *    DateTime.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128)  ->  datetime
+ *    DateTime.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128)   ->  datetime
  *
  * Creates a new DateTime object by parsing from a string according to
  * some typical RFC 2822 formats.
  *
  *     DateTime.rfc2822('Sat, 3 Feb 2001 04:05:06 +0700')
  *				#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
 datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
 {
-    VALUE str, sg;
+    VALUE str, sg, opt;
 
-    rb_scan_args(argc, argv, "02", &str, &sg);
+    rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+    if (!NIL_P(opt)) argc--;
 
     switch (argc) {
       case 0:
@@ -8086,7 +8306,12 @@ datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
     }
 
     {
-	VALUE hash = date_s__rfc2822(klass, str);
+        int argc2 = 1;
+        VALUE argv2[2];
+        argv2[0] = str;
+        argv2[1] = opt;
+        if (!NIL_P(opt)) argc2++;
+	VALUE hash = date_s__rfc2822(argc2, argv2, klass);
 	return dt_new_by_frags(klass, hash, sg);
     }
 }
@@ -8100,13 +8325,18 @@ datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
  *
  *    DateTime.httpdate('Sat, 03 Feb 2001 04:05:06 GMT')
  *				#=> #<DateTime: 2001-02-03T04:05:06+00:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
 datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
 {
-    VALUE str, sg;
+    VALUE str, sg, opt;
 
-    rb_scan_args(argc, argv, "02", &str, &sg);
+    rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+    if (!NIL_P(opt)) argc--;
 
     switch (argc) {
       case 0:
@@ -8116,27 +8346,42 @@ datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
     }
 
     {
-	VALUE hash = date_s__httpdate(klass, str);
+        int argc2 = 1;
+        VALUE argv2[2];
+        argv2[0] = str;
+        argv2[1] = opt;
+        if (!NIL_P(opt)) argc2++;
+	VALUE hash = date_s__httpdate(argc2, argv2, klass);
 	return dt_new_by_frags(klass, hash, sg);
     }
 }
 
 /*
  * call-seq:
- *    DateTime.jisx0301(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY])  ->  datetime
+ *    DateTime.jisx0301(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128)  ->  datetime
  *
  * Creates a new DateTime object by parsing from a string according to
  * some typical JIS X 0301 formats.
  *
  *    DateTime.jisx0301('H13.02.03T04:05:06+07:00')
  *				#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ *
+ * For no-era year, legacy format, Heisei is assumed.
+ *
+ *    DateTime.jisx0301('13.02.03T04:05:06+07:00')
+ *				#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing `limit: nil`, but note that
+ * it may take a long time to parse.
  */
 static VALUE
 datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass)
 {
-    VALUE str, sg;
+    VALUE str, sg, opt;
 
-    rb_scan_args(argc, argv, "02", &str, &sg);
+    rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+    if (!NIL_P(opt)) argc--;
 
     switch (argc) {
       case 0:
@@ -8146,7 +8391,12 @@ datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass)
     }
 
     {
-	VALUE hash = date_s__jisx0301(klass, str);
+        int argc2 = 1;
+        VALUE argv2[2];
+        argv2[0] = str;
+        argv2[1] = opt;
+        if (!NIL_P(opt)) argc2++;
+	VALUE hash = date_s__jisx0301(argc2, argv2, klass);
 	return dt_new_by_frags(klass, hash, sg);
     }
 }
@@ -8230,7 +8480,7 @@ dt_lite_to_s(VALUE self)
  *
  *      %M - Minute of the hour (00..59)
  *
- *      %S - Second of the minute (00..59)
+ *      %S - Second of the minute (00..60)
  *
  *      %L - Millisecond of the second (000..999)
  *      %N - Fractional seconds digits, default is 9 digits (nanosecond)
@@ -8643,7 +8893,7 @@ datetime_to_date(VALUE self)
 	VALUE new = d_lite_s_alloc_simple(cDate);
 	{
 	    get_d1b(new);
-	    copy_complex_to_simple(new, &bdat->s, &adat->c)
+	    copy_complex_to_simple(new, &bdat->s, &adat->c);
 	    bdat->s.jd = m_local_jd(adat);
 	    bdat->s.flags &= ~(HAVE_DF | HAVE_TIME | COMPLEX_DAT);
 	    return new;
@@ -9008,14 +9258,18 @@ mk_ary_of_str(long len, const char *a[])
     return o;
 }
 
+static VALUE
+d_lite_zero(VALUE x)
+{
+    return INT2FIX(0);
+}
+
 void
 Init_date_core(void)
 {
 #undef rb_intern
 #define rb_intern(str) rb_intern_const(str)
 
-    assert(fprintf(stderr, "assert() is now active\n"));
-
     id_cmp = rb_intern("<=>");
     id_le_p = rb_intern("<=");
     id_ge_p = rb_intern(">=");
@@ -9231,23 +9485,22 @@ Init_date_core(void)
      */
     rb_define_const(cDate, "GREGORIAN", DBL2NUM(GREGORIAN));
 
-    rb_define_alloc_func(cDate, d_lite_s_alloc);
+    rb_define_alloc_func(cDate, d_lite_s_alloc_simple);
 
 #ifndef NDEBUG
-#define de_define_private_method rb_define_private_method
-    de_define_private_method(CLASS_OF(cDate), "_valid_jd?",
+    rb_define_private_method(CLASS_OF(cDate), "_valid_jd?",
 			     date_s__valid_jd_p, -1);
-    de_define_private_method(CLASS_OF(cDate), "_valid_ordinal?",
+    rb_define_private_method(CLASS_OF(cDate), "_valid_ordinal?",
 			     date_s__valid_ordinal_p, -1);
-    de_define_private_method(CLASS_OF(cDate), "_valid_civil?",
+    rb_define_private_method(CLASS_OF(cDate), "_valid_civil?",
 			     date_s__valid_civil_p, -1);
-    de_define_private_method(CLASS_OF(cDate), "_valid_date?",
+    rb_define_private_method(CLASS_OF(cDate), "_valid_date?",
 			     date_s__valid_civil_p, -1);
-    de_define_private_method(CLASS_OF(cDate), "_valid_commercial?",
+    rb_define_private_method(CLASS_OF(cDate), "_valid_commercial?",
 			     date_s__valid_commercial_p, -1);
-    de_define_private_method(CLASS_OF(cDate), "_valid_weeknum?",
+    rb_define_private_method(CLASS_OF(cDate), "_valid_weeknum?",
 			     date_s__valid_weeknum_p, -1);
-    de_define_private_method(CLASS_OF(cDate), "_valid_nth_kday?",
+    rb_define_private_method(CLASS_OF(cDate), "_valid_nth_kday?",
 			     date_s__valid_nth_kday_p, -1);
 #endif
 
@@ -9260,11 +9513,11 @@ Init_date_core(void)
 			       date_s_valid_commercial_p, -1);
 
 #ifndef NDEBUG
-    de_define_private_method(CLASS_OF(cDate), "valid_weeknum?",
+    rb_define_private_method(CLASS_OF(cDate), "valid_weeknum?",
 			     date_s_valid_weeknum_p, -1);
-    de_define_private_method(CLASS_OF(cDate), "valid_nth_kday?",
+    rb_define_private_method(CLASS_OF(cDate), "valid_nth_kday?",
 			     date_s_valid_nth_kday_p, -1);
-    de_define_private_method(CLASS_OF(cDate), "zone_to_diff",
+    rb_define_private_method(CLASS_OF(cDate), "zone_to_diff",
 			     date_s_zone_to_diff, 1);
 #endif
 
@@ -9275,21 +9528,18 @@ Init_date_core(void)
 			       date_s_gregorian_leap_p, 1);
 
 #ifndef NDEBUG
-#define de_define_singleton_method rb_define_singleton_method
-#define de_define_alias rb_define_alias
-    de_define_singleton_method(cDate, "new!", date_s_new_bang, -1);
-    de_define_alias(rb_singleton_class(cDate), "new_l!", "new");
+    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);
     rb_define_singleton_method(cDate, "ordinal", date_s_ordinal, -1);
     rb_define_singleton_method(cDate, "civil", date_s_civil, -1);
-    rb_define_singleton_method(cDate, "new", date_s_civil, -1);
     rb_define_singleton_method(cDate, "commercial", date_s_commercial, -1);
 
 #ifndef NDEBUG
-    de_define_singleton_method(cDate, "weeknum", date_s_weeknum, -1);
-    de_define_singleton_method(cDate, "nth_kday", date_s_nth_kday, -1);
+    rb_define_singleton_method(cDate, "weeknum", date_s_weeknum, -1);
+    rb_define_singleton_method(cDate, "nth_kday", date_s_nth_kday, -1);
 #endif
 
     rb_define_singleton_method(cDate, "today", date_s_today, -1);
@@ -9297,29 +9547,26 @@ Init_date_core(void)
     rb_define_singleton_method(cDate, "strptime", date_s_strptime, -1);
     rb_define_singleton_method(cDate, "_parse", date_s__parse, -1);
     rb_define_singleton_method(cDate, "parse", date_s_parse, -1);
-    rb_define_singleton_method(cDate, "_iso8601", date_s__iso8601, 1);
+    rb_define_singleton_method(cDate, "_iso8601", date_s__iso8601, -1);
     rb_define_singleton_method(cDate, "iso8601", date_s_iso8601, -1);
-    rb_define_singleton_method(cDate, "_rfc3339", date_s__rfc3339, 1);
+    rb_define_singleton_method(cDate, "_rfc3339", date_s__rfc3339, -1);
     rb_define_singleton_method(cDate, "rfc3339", date_s_rfc3339, -1);
-    rb_define_singleton_method(cDate, "_xmlschema", date_s__xmlschema, 1);
+    rb_define_singleton_method(cDate, "_xmlschema", date_s__xmlschema, -1);
     rb_define_singleton_method(cDate, "xmlschema", date_s_xmlschema, -1);
-    rb_define_singleton_method(cDate, "_rfc2822", date_s__rfc2822, 1);
-    rb_define_singleton_method(cDate, "_rfc822", date_s__rfc2822, 1);
+    rb_define_singleton_method(cDate, "_rfc2822", date_s__rfc2822, -1);
+    rb_define_singleton_method(cDate, "_rfc822", date_s__rfc2822, -1);
     rb_define_singleton_method(cDate, "rfc2822", date_s_rfc2822, -1);
     rb_define_singleton_method(cDate, "rfc822", date_s_rfc2822, -1);
-    rb_define_singleton_method(cDate, "_httpdate", date_s__httpdate, 1);
+    rb_define_singleton_method(cDate, "_httpdate", date_s__httpdate, -1);
     rb_define_singleton_method(cDate, "httpdate", date_s_httpdate, -1);
-    rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, 1);
+    rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, -1);
     rb_define_singleton_method(cDate, "jisx0301", date_s_jisx0301, -1);
 
-#ifndef NDEBUG
-#define de_define_method rb_define_method
-    de_define_method(cDate, "initialize", d_lite_initialize, -1);
-#endif
+    rb_define_method(cDate, "initialize", date_initialize, -1);
     rb_define_method(cDate, "initialize_copy", d_lite_initialize_copy, 1);
 
 #ifndef NDEBUG
-    de_define_method(cDate, "fill", d_lite_fill, 0);
+    rb_define_method(cDate, "fill", d_lite_fill, 0);
 #endif
 
     rb_define_method(cDate, "ajd", d_lite_ajd, 0);
@@ -9341,8 +9588,8 @@ Init_date_core(void)
     rb_define_method(cDate, "cwday", d_lite_cwday, 0);
 
 #ifndef NDEBUG
-    de_define_private_method(cDate, "wnum0", d_lite_wnum0, 0);
-    de_define_private_method(cDate, "wnum1", d_lite_wnum1, 0);
+    rb_define_private_method(cDate, "wnum0", d_lite_wnum0, 0);
+    rb_define_private_method(cDate, "wnum1", d_lite_wnum1, 0);
 #endif
 
     rb_define_method(cDate, "wday", d_lite_wday, 0);
@@ -9356,18 +9603,14 @@ Init_date_core(void)
     rb_define_method(cDate, "saturday?", d_lite_saturday_p, 0);
 
 #ifndef NDEBUG
-    de_define_method(cDate, "nth_kday?", d_lite_nth_kday_p, 2);
+    rb_define_method(cDate, "nth_kday?", d_lite_nth_kday_p, 2);
 #endif
 
-    rb_define_private_method(cDate, "hour", d_lite_hour, 0);
-    rb_define_private_method(cDate, "min", d_lite_min, 0);
-    rb_define_private_method(cDate, "minute", d_lite_min, 0);
-    rb_define_private_method(cDate, "sec", d_lite_sec, 0);
-    rb_define_private_method(cDate, "second", d_lite_sec, 0);
-    rb_define_private_method(cDate, "sec_fraction", d_lite_sec_fraction, 0);
-    rb_define_private_method(cDate, "second_fraction", d_lite_sec_fraction, 0);
-    rb_define_private_method(cDate, "offset", d_lite_offset, 0);
-    rb_define_private_method(cDate, "zone", d_lite_zone, 0);
+    rb_define_private_method(cDate, "hour", d_lite_zero, 0);
+    rb_define_private_method(cDate, "min", d_lite_zero, 0);
+    rb_define_private_method(cDate, "minute", d_lite_zero, 0);
+    rb_define_private_method(cDate, "sec", d_lite_zero, 0);
+    rb_define_private_method(cDate, "second", d_lite_zero, 0);
 
     rb_define_method(cDate, "julian?", d_lite_julian_p, 0);
     rb_define_method(cDate, "gregorian?", d_lite_gregorian_p, 0);
@@ -9380,8 +9623,6 @@ Init_date_core(void)
     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);
     rb_define_method(cDate, "-", d_lite_minus, 1);
 
@@ -9409,7 +9650,7 @@ Init_date_core(void)
 
     rb_define_method(cDate, "to_s", d_lite_to_s, 0);
 #ifndef NDEBUG
-    de_define_method(cDate, "inspect_raw", d_lite_inspect_raw, 0);
+    rb_define_method(cDate, "inspect_raw", d_lite_inspect_raw, 0);
 #endif
     rb_define_method(cDate, "inspect", d_lite_inspect, 0);
 
@@ -9426,7 +9667,7 @@ Init_date_core(void)
     rb_define_method(cDate, "jisx0301", d_lite_jisx0301, 0);
 
 #ifndef NDEBUG
-    de_define_method(cDate, "marshal_dump_old", d_lite_marshal_dump_old, 0);
+    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);
@@ -9573,6 +9814,7 @@ Init_date_core(void)
      */
 
     cDateTime = rb_define_class("DateTime", cDate);
+    rb_define_alloc_func(cDateTime, d_lite_s_alloc_complex);
 
     rb_define_singleton_method(cDateTime, "jd", datetime_s_jd, -1);
     rb_define_singleton_method(cDateTime, "ordinal", datetime_s_ordinal, -1);
@@ -9582,9 +9824,9 @@ Init_date_core(void)
 			       datetime_s_commercial, -1);
 
 #ifndef NDEBUG
-    de_define_singleton_method(cDateTime, "weeknum",
+    rb_define_singleton_method(cDateTime, "weeknum",
 			       datetime_s_weeknum, -1);
-    de_define_singleton_method(cDateTime, "nth_kday",
+    rb_define_singleton_method(cDateTime, "nth_kday",
 			       datetime_s_nth_kday, -1);
 #endif
 
@@ -9612,19 +9854,16 @@ Init_date_core(void)
     rb_define_singleton_method(cDateTime, "jisx0301",
 			       datetime_s_jisx0301, -1);
 
-#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, "hour", d_lite_hour, 0);
+    rb_define_method(cDateTime, "min", d_lite_min, 0);
+    rb_define_method(cDateTime, "minute", d_lite_min, 0);
+    rb_define_method(cDateTime, "sec", d_lite_sec, 0);
+    rb_define_method(cDateTime, "second", d_lite_sec, 0);
+    rb_define_method(cDateTime, "sec_fraction", d_lite_sec_fraction, 0);
+    rb_define_method(cDateTime, "second_fraction", d_lite_sec_fraction, 0);
+    rb_define_method(cDateTime, "offset", d_lite_offset, 0);
+    rb_define_method(cDateTime, "zone", d_lite_zone, 0);
+    rb_define_method(cDateTime, "new_offset", d_lite_new_offset, -1);
 
     rb_define_method(cDateTime, "to_s", dt_lite_to_s, 0);
 
@@ -9652,15 +9891,15 @@ Init_date_core(void)
 #ifndef NDEBUG
     /* tests */
 
-    de_define_singleton_method(cDate, "test_civil", date_s_test_civil, 0);
-    de_define_singleton_method(cDate, "test_ordinal", date_s_test_ordinal, 0);
-    de_define_singleton_method(cDate, "test_commercial",
+    rb_define_singleton_method(cDate, "test_civil", date_s_test_civil, 0);
+    rb_define_singleton_method(cDate, "test_ordinal", date_s_test_ordinal, 0);
+    rb_define_singleton_method(cDate, "test_commercial",
 			       date_s_test_commercial, 0);
-    de_define_singleton_method(cDate, "test_weeknum", date_s_test_weeknum, 0);
-    de_define_singleton_method(cDate, "test_nth_kday", date_s_test_nth_kday, 0);
-    de_define_singleton_method(cDate, "test_unit_conv",
+    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_unit_conv",
 			       date_s_test_unit_conv, 0);
-    de_define_singleton_method(cDate, "test_all", date_s_test_all, 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 b74230d291..f06c07bae4 100644
--- a/ext/date/date_parse.c
+++ b/ext/date/date_parse.c
@@ -40,9 +40,9 @@ RUBY_EXTERN unsigned long ruby_scan_digits(const char *str, ssize_t len, int bas
 #define f_sub_bang(s,r,x) rb_funcall(s, rb_intern("sub!"), 2, r, x)
 #define f_gsub_bang(s,r,x) rb_funcall(s, rb_intern("gsub!"), 2, r, x)
 
-#define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k)), v)
-#define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k)))
-#define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k)))
+#define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k"")), v)
+#define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k"")))
+#define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k"")))
 
 #define cstr2num(s) rb_cstr_to_inum(s, 10, 0)
 #define str2num(s) rb_str_to_inum(s, 10, 0)
@@ -66,7 +66,13 @@ static const char abbr_months[][4] = {
 #define asubt_string() rb_str_new("\024", 1)
 #endif
 
-#define DECDIGIT "0123456789"
+static size_t
+digit_span(const char *s, const char *e)
+{
+    size_t i = 0;
+    while (s + i < e && isdigit(s[i])) i++;
+    return i;
+}
 
 static void
 s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
@@ -92,7 +98,7 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
 	    y = d;
 	    d = Qnil;
 	}
-	if (!NIL_P(d) && *RSTRING_PTR(d) == '\'') {
+	if (!NIL_P(d) && RSTRING_LEN(d) > 0 && *RSTRING_PTR(d) == '\'') {
 	    y = d;
 	    d = Qnil;
 	}
@@ -103,17 +109,20 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
 	size_t l;
 
 	s = RSTRING_PTR(y);
-	while (!issign((unsigned char)*s) && !isdigit((unsigned char)*s))
+	ep = RSTRING_END(y);
+	while (s < ep && !issign(*s) && !isdigit(*s))
 	    s++;
+	if (s >= ep) goto no_date;
 	bp = s;
 	if (issign((unsigned char)*s))
 	    s++;
-	l = strspn(s, DECDIGIT);
+	l = digit_span(s, ep);
 	ep = s + l;
 	if (*ep) {
 	    y = d;
 	    d = rb_str_new(bp, ep - bp);
 	}
+      no_date:;
     }
 
     if (!NIL_P(m)) {
@@ -152,8 +161,10 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
 	VALUE iy;
 
 	s = RSTRING_PTR(y);
-	while (!issign((unsigned char)*s) && !isdigit((unsigned char)*s))
+	ep = RSTRING_END(y);
+	while (s < ep && !issign(*s) && !isdigit(*s))
 	    s++;
+	if (s >= ep) goto no_year;
 	bp = s;
 	if (issign(*s)) {
 	    s++;
@@ -161,7 +172,7 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
 	}
 	if (sign)
 	    c = Qfalse;
-	l = strspn(s, DECDIGIT);
+	l = digit_span(s, ep);
 	ep = s + l;
 	if (l > 2)
 	    c = Qfalse;
@@ -175,6 +186,7 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
 	    ALLOCV_END(vbuf);
 	}
 	set_hash("year", iy);
+      no_year:;
     }
 
     if (bc)
@@ -186,10 +198,12 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
 	VALUE im;
 
 	s = RSTRING_PTR(m);
-	while (!isdigit((unsigned char)*s))
+	ep = RSTRING_END(m);
+	while (s < ep && !isdigit(*s))
 	    s++;
+	if (s >= ep) goto no_month;
 	bp = s;
-	l = strspn(s, DECDIGIT);
+	l = digit_span(s, ep);
 	ep = s + l;
 	{
 	    char *buf;
@@ -201,6 +215,7 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
 	    ALLOCV_END(vbuf);
 	}
 	set_hash("mon", im);
+      no_month:;
     }
 
     if (!NIL_P(d)) {
@@ -209,10 +224,12 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
 	VALUE id;
 
 	s = RSTRING_PTR(d);
-	while (!isdigit((unsigned char)*s))
+	ep = RSTRING_END(d);
+	while (s < ep && !isdigit(*s))
 	    s++;
+	if (s >= ep) goto no_mday;
 	bp = s;
-	l = strspn(s, DECDIGIT);
+	l = digit_span(s, ep);
 	ep = s + l;
 	{
 	    char *buf;
@@ -224,6 +241,7 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
 	    ALLOCV_END(vbuf);
 	}
 	set_hash("mday", id);
+      no_mday:;
     }
 
     if (!NIL_P(c))
@@ -263,18 +281,18 @@ regcomp(const char *source, long len, int opt)
 }
 
 #define REGCOMP(pat,opt) \
-{ \
+do { \
     if (NIL_P(pat)) \
 	pat = regcomp(pat##_source, sizeof pat##_source - 1, opt); \
-}
+} while (0)
 
 #define REGCOMP_0(pat) REGCOMP(pat, 0)
 #define REGCOMP_I(pat) REGCOMP(pat, ONIG_OPTION_IGNORECASE)
 
 #define MATCH(s,p,c) \
-{ \
+do { \
     return match(s, p, hash, c); \
-}
+} while (0)
 
 static int
 match(VALUE str, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE))
@@ -314,30 +332,30 @@ subx(VALUE str, VALUE rep, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE))
 }
 
 #define SUBS(s,p,c) \
-{ \
+do { \
     return subx(s, asp_string(), p, hash, c); \
-}
+} while (0)
 
 #ifdef TIGHT_PARSER
 #define SUBA(s,p,c) \
-{ \
+do { \
     return subx(s, asuba_string(), p, hash, c); \
-}
+} while (0)
 
 #define SUBB(s,p,c) \
-{ \
+do { \
     return subx(s, asubb_string(), p, hash, c); \
-}
+} while (0)
 
 #define SUBW(s,p,c) \
-{ \
+do { \
     return subx(s, asubw_string(), p, hash, c); \
-}
+} while (0)
 
 #define SUBT(s,p,c) \
-{ \
+do { \
     return subx(s, asubt_string(), p, hash, c); \
-}
+} while (0)
 #endif
 
 #include "zonetab.h"
@@ -706,16 +724,14 @@ parse_era(VALUE str, VALUE hash)
 static int
 check_year_width(VALUE y)
 {
-    char *s;
-    size_t l;
+    const char *s;
+    long l;
 
+    l = RSTRING_LEN(y);
+    if (l < 2) return 0;
     s = RSTRING_PTR(y);
-    l = strcspn(s, DECDIGIT);
-    s += l;
-    l = strspn(s, DECDIGIT);
-    if (l != 2)
-	return 0;
-    return 1;
+    if (!isdigit(s[1])) return 0;
+    return (l == 2 || !isdigit(s[2]));
 }
 
 static int
@@ -1196,6 +1212,9 @@ parse_iso2(VALUE str, VALUE hash)
     return 1;
 }
 
+#define JISX0301_ERA_INITIALS "mtshr"
+#define JISX0301_DEFAULT_ERA 'H' /* obsolete */
+
 static int
 gengo(int c)
 {
@@ -1206,6 +1225,7 @@ gengo(int c)
       case 'T': case 't': e = 1911; break;
       case 'S': case 's': e = 1925; break;
       case 'H': case 'h': e = 1988; break;
+      case 'R': case 'r': e = 2018; break;
       default:  e = 0; break;
     }
     return e;
@@ -1236,11 +1256,11 @@ parse_jis(VALUE str, VALUE hash)
 {
     static const char pat_source[] =
 #ifndef TIGHT_PARSER
-	"\\b([mtsh])(\\d+)\\.(\\d+)\\.(\\d+)"
+        "\\b([" JISX0301_ERA_INITIALS "])(\\d+)\\.(\\d+)\\.(\\d+)"
 #else
 	BOS
 	FPW_COM FPT_COM
-	"([mtsh])(\\d+)\\.(\\d+)\\.(\\d+)"
+        "([" JISX0301_ERA_INITIALS "])(\\d+)\\.(\\d+)\\.(\\d+)"
 	TEE_FPT COM_FPW
 	EOS
 #endif
@@ -2938,7 +2958,7 @@ jisx0301_cb(VALUE m, VALUE hash)
 	    s[i] = rb_reg_nth_match(i, m);
     }
 
-    ep = gengo(NIL_P(s[1]) ? 'h' : *RSTRING_PTR(s[1]));
+    ep = gengo(NIL_P(s[1]) ? JISX0301_DEFAULT_ERA : *RSTRING_PTR(s[1]));
     set_hash("year", f_add(str2num(s[2]), INT2FIX(ep)));
     set_hash("mon", str2num(s[3]));
     set_hash("mday", str2num(s[4]));
@@ -2963,7 +2983,7 @@ static int
 jisx0301(VALUE str, VALUE hash)
 {
     static const char pat_source[] =
-	"\\A\\s*([mtsh])?(\\d{2})\\.(\\d{2})\\.(\\d{2})"
+        "\\A\\s*([" JISX0301_ERA_INITIALS "])?(\\d{2})\\.(\\d{2})\\.(\\d{2})"
 	"(?:t"
 	"(?:(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d*))?)?"
 	"(z|[-+]\\d{2}(?::?\\d{2})?)?)?)?\\s*\\z";
diff --git a/ext/date/date_strptime.c b/ext/date/date_strptime.c
index 4f93219317..4383eb6fa1 100644
--- a/ext/date/date_strptime.c
+++ b/ext/date/date_strptime.c
@@ -79,14 +79,17 @@ read_digits(const char *s, VALUE *n, size_t width)
 {
     size_t l;
 
-    l = strspn(s, "0123456789");
+    if (!width)
+        return 0;
+
+    l = 0;
+    while (ISDIGIT(s[l])) {
+        if (++l == width) break;
+    }
 
     if (l == 0)
 	return 0;
 
-    if (width < l)
-	l = width;
-
     if ((4 * l * sizeof(char)) <= (sizeof(long)*CHAR_BIT)) {
 	const char *os = s;
 	long v;
@@ -113,26 +116,26 @@ read_digits(const char *s, VALUE *n, size_t width)
     }
 }
 
-#define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k)), v)
-#define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k)))
-#define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k)))
+#define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k"")), v)
+#define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k"")))
+#define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k"")))
 
 #define fail() \
-{ \
+do { \
     set_hash("_fail", Qtrue); \
     return 0; \
-}
+} while (0)
 
 #define fail_p() (!NIL_P(ref_hash("_fail")))
 
 #define READ_DIGITS(n,w) \
-{ \
+do { \
     size_t l; \
     l = read_digits(&str[si], &n, w); \
     if (l == 0) \
 	fail();	\
     si += l; \
-}
+} while (0)
 
 #define READ_DIGITS_MAX(n) READ_DIGITS(n, LONG_MAX)
 
@@ -147,14 +150,14 @@ valid_range_p(VALUE v, int a, int b)
 }
 
 #define recur(fmt) \
-{ \
+do { \
     size_t l; \
     l = date__strptime_internal(&str[si], slen - si, \
 				fmt, sizeof fmt - 1, hash); \
     if (fail_p()) \
 	return 0; \
     si += l; \
-}
+} while (0)
 
 VALUE date_zone_to_diff(VALUE);
 
@@ -237,9 +240,9 @@ date__strptime_internal(const char *str, size_t slen,
 		    VALUE n;
 
 		    if (NUM_PATTERN_P())
-			READ_DIGITS(n, 2)
+			READ_DIGITS(n, 2);
 		    else
-			READ_DIGITS_MAX(n)
+			READ_DIGITS_MAX(n);
 		    set_hash("_cent", n);
 		    goto matched;
 		}
@@ -278,9 +281,9 @@ date__strptime_internal(const char *str, size_t slen,
 		    VALUE n;
 
 		    if (NUM_PATTERN_P())
-			READ_DIGITS(n, 4)
+			READ_DIGITS(n, 4);
 		    else
-			READ_DIGITS_MAX(n)
+			READ_DIGITS_MAX(n);
 		    set_hash("cwyear", n);
 		    goto matched;
 		}
@@ -358,9 +361,9 @@ date__strptime_internal(const char *str, size_t slen,
 		    }
 		    osi = si;
 		    if (NUM_PATTERN_P())
-			READ_DIGITS(n, c == 'L' ? 3 : 9)
+			READ_DIGITS(n, c == 'L' ? 3 : 9);
 		    else
-			READ_DIGITS_MAX(n)
+			READ_DIGITS_MAX(n);
 		    if (sign == -1)
 			n = f_negate(n);
 		    set_hash("sec_fraction",
@@ -426,9 +429,7 @@ date__strptime_internal(const char *str, size_t slen,
 		    if (sign == -1)
 			n = f_negate(n);
 		    set_hash("seconds",
-			     rb_rational_new2(n,
-					      f_expt(INT2FIX(10),
-						     INT2FIX(3))));
+			     rb_rational_new2(n, INT2FIX(1000)));
 		    goto matched;
 		}
 
@@ -529,24 +530,24 @@ date__strptime_internal(const char *str, size_t slen,
 		goto matched;
 
 	      case 'Y':
-		  {
-		      VALUE n;
-		      int sign = 1;
-
-		      if (issign(str[si])) {
-			  if (str[si] == '-')
-			      sign = -1;
-			  si++;
-		      }
-		      if (NUM_PATTERN_P())
-			  READ_DIGITS(n, 4)
-		      else
-			  READ_DIGITS_MAX(n)
+		{
+		    VALUE n;
+		    int sign = 1;
+
+		    if (issign(str[si])) {
+			if (str[si] == '-')
+			    sign = -1;
+			si++;
+		    }
+		    if (NUM_PATTERN_P())
+			READ_DIGITS(n, 4);
+		    else
+			READ_DIGITS_MAX(n);
 		    if (sign == -1)
 			n = f_negate(n);
-		      set_hash("year", n);
-		      goto matched;
-		  }
+		    set_hash("year", n);
+		    goto matched;
+		}
 
 	      case 'y':
 		{
diff --git a/ext/io/console/io-console.gemspec b/ext/io/console/io-console.gemspec
index 1256162468..99e18bda9a 100644
--- a/ext/io/console/io-console.gemspec
+++ b/ext/io/console/io-console.gemspec
@@ -5,7 +5,7 @@
 Gem::Specification.new do |s|
   s.name = "io-console"
   s.version = _VERSION
-  s.date = date
+  s.date = RUBY_RELEASE_DATE
   s.summary = "Console interface"
   s.email = "nobu@ruby-lang.org"
   s.description = "add console capabilities to IO instances."
diff --git a/gc.c b/gc.c
index c02ac627f0..fc303879eb 100644
--- a/gc.c
+++ b/gc.c
@@ -47,7 +47,9 @@
 # endif
 #endif
 #ifdef HAVE_MALLOC_USABLE_SIZE
-# ifdef HAVE_MALLOC_H
+# ifdef RUBY_ALTERNATIVE_MALLOC_HEADER
+#  include RUBY_ALTERNATIVE_MALLOC_HEADER
+# elif HAVE_MALLOC_H
 #  include <malloc.h>
 # elif defined(HAVE_MALLOC_NP_H)
 #  include <malloc_np.h>
@@ -975,6 +977,31 @@ tick(void)
     return val;
 }
 
+#elif defined(__powerpc64__) && \
+	( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
+typedef unsigned long long tick_t;
+#define PRItick "llu"
+
+static __inline__ tick_t
+tick(void)
+{
+    unsigned long long val = __builtin_ppc_get_timebase();
+    return val;
+}
+
+#elif defined(__aarch64__) &&  defined(__GNUC__)
+typedef unsigned long tick_t;
+#define PRItick "lu"
+
+static __inline__ tick_t
+tick(void)
+{
+    unsigned long val;
+    __asm__ __volatile__ ("mrs %0, cntvct_el0", : "=r" (val));
+    return val;
+}
+
+
 #elif defined(_WIN32) && defined(_MSC_VER)
 #include <intrin.h>
 typedef unsigned __int64 tick_t;
diff --git a/gc.h b/gc.h
index 2c91e06620..0f8a56f94d 100644
--- a/gc.h
+++ b/gc.h
@@ -6,6 +6,8 @@
 #define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("movq\t%%rsp, %0" : "=r" (*(p)))
 #elif defined(__i386) && defined(__GNUC__)
 #define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("movl\t%%esp, %0" : "=r" (*(p)))
+#elif defined(__aarch64__) && defined(__GNUC__)
+#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("mov\t%0, sp" : "=r" (*(p)))
 #else
 NOINLINE(void rb_gc_set_stack_end(VALUE **stack_end_p));
 #define SET_MACHINE_STACK_END(p) rb_gc_set_stack_end(p)
diff --git a/include/ruby/defines.h b/include/ruby/defines.h
index 2c72a7cb8a..85f3bda3c1 100644
--- a/include/ruby/defines.h
+++ b/include/ruby/defines.h
@@ -358,7 +358,7 @@ void rb_ia64_flushrs(void);
 #ifndef UNALIGNED_WORD_ACCESS
 # if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
      defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \
-     defined(__powerpc64__) || \
+     defined(__powerpc64__) || defined(__aarch64__) || \
      defined(__mc68020__)
 #   define UNALIGNED_WORD_ACCESS 1
 # else
diff --git a/lib/rdoc/rdoc.gemspec b/lib/rdoc/rdoc.gemspec
index 8c92908a66..0e6c0c7292 100644
--- a/lib/rdoc/rdoc.gemspec
+++ b/lib/rdoc/rdoc.gemspec
@@ -7,6 +7,7 @@
 
 Gem::Specification.new do |s|
   s.name = "rdoc"
+  s.date = RUBY_RELEASE_DATE
   s.version = RDoc::VERSION
   s.date = "2017-12-24"
 
diff --git a/lib/rubygems/package.rb b/lib/rubygems/package.rb
index b472b97a07..3fd5566e6a 100644
--- a/lib/rubygems/package.rb
+++ b/lib/rubygems/package.rb
@@ -109,9 +109,12 @@ class TarInvalidError < Error; end
 
   def self.build spec, skip_validation=false
     gem_file = spec.file_name
+    spec_file = spec.loaded_from
+    spec_file = "Gemfile" if spec_file.nil? || spec_file.empty?
 
     package = new gem_file
     package.spec = spec
+    package.build_time = File.stat(spec_file).mtime.to_i
     package.build skip_validation
 
     gem_file
@@ -195,6 +198,7 @@ def add_contents tar # :nodoc:
     digests = tar.add_file_signed 'data.tar.gz', 0444, @signer do |io|
       gzip_to io do |gz_io|
         Gem::Package::TarWriter.new gz_io do |data_tar|
+          data_tar.mtime = @build_time
           add_files data_tar
         end
       end
diff --git a/lib/rubygems/package/tar_writer.rb b/lib/rubygems/package/tar_writer.rb
index 390f7851a3..e3fa2ee86d 100644
--- a/lib/rubygems/package/tar_writer.rb
+++ b/lib/rubygems/package/tar_writer.rb
@@ -91,12 +91,15 @@ def self.new(io)
     nil
   end
 
+  attr_accessor :mtime
+
   ##
   # Creates a new TarWriter that will write to +io+
 
   def initialize(io)
     @io = io
     @closed = false
+    @mtime = Time.now
   end
 
   ##
@@ -125,7 +128,7 @@ def add_file(name, mode) # :yields: io
 
     header = Gem::Package::TarHeader.new :name => name, :mode => mode,
                                          :size => size, :prefix => prefix,
-                                         :mtime => Time.now
+                                         :mtime => mtime
 
     @io.write header
     @io.pos = final_pos
@@ -220,7 +223,7 @@ def add_file_simple(name, mode, size) # :yields: io
 
     header = Gem::Package::TarHeader.new(:name => name, :mode => mode,
                                          :size => size, :prefix => prefix,
-                                         :mtime => Time.now).to_s
+                                         :mtime => mtime).to_s
 
     @io.write header
     os = BoundedStream.new @io, size
@@ -301,7 +304,7 @@ def mkdir(name, mode)
     header = Gem::Package::TarHeader.new :name => name, :mode => mode,
                                          :typeflag => "5", :size => 0,
                                          :prefix => prefix,
-                                         :mtime => Time.now
+                                         :mtime => mtime
 
     @io.write header
 
diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb
index 2560324b7a..07fdd30a62 100644
--- a/lib/rubygems/specification.rb
+++ b/lib/rubygems/specification.rb
@@ -1787,7 +1787,9 @@ def date= date
                 raise(Gem::InvalidSpecificationException,
                       "invalid date format in specification: #{date.inspect}")
               end
-            when Time, DateLike then
+            when Time then
+              Time.utc(date.utc.year, date.utc.month, date.utc.day)
+            when DateLike then
               Time.utc(date.year, date.month, date.day)
             else
               TODAY
diff --git a/regint.h b/regint.h
index a2f5bbba1d..0740429688 100644
--- a/regint.h
+++ b/regint.h
@@ -52,7 +52,7 @@
 #ifndef UNALIGNED_WORD_ACCESS
 # if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
      defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \
-     defined(__powerpc64__) || \
+     defined(__powerpc64__) || defined(__aarch64__) || \
      defined(__mc68020__)
 #  define UNALIGNED_WORD_ACCESS 1
 # else
diff --git a/siphash.c b/siphash.c
index 153d2c690a..ddf8ee245d 100644
--- a/siphash.c
+++ b/siphash.c
@@ -30,7 +30,7 @@
 #ifndef UNALIGNED_WORD_ACCESS
 # if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
      defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \
-     defined(__powerpc64__) || \
+     defined(__powerpc64__) || defined(__aarch64__) || \
      defined(__mc68020__)
 #   define UNALIGNED_WORD_ACCESS 1
 # endif
diff --git a/st.c b/st.c
index d44c979e19..e74523001b 100644
--- a/st.c
+++ b/st.c
@@ -1744,7 +1744,7 @@ st_values_check(st_table *tab, st_data_t *values, st_index_t size,
 #ifndef UNALIGNED_WORD_ACCESS
 # if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
      defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \
-     defined(__powerpc64__) || \
+     defined(__powerpc64__) || defined(__aarch64__) || \
      defined(__mc68020__)
 #   define UNALIGNED_WORD_ACCESS 1
 # endif
diff --git a/test/date/test_date_arith.rb b/test/date/test_date_arith.rb
index d0d27d72f7..e1f29dbf22 100644
--- a/test/date/test_date_arith.rb
+++ b/test/date/test_date_arith.rb
@@ -3,11 +3,18 @@
 require 'date'
 
 class TestDateArith < Test::Unit::TestCase
+  class Rat < Numeric
+    def to_r; self; end
+  end
 
-  def new_offset
+  def test_new_offset
     d = DateTime.new(2002, 3, 14)
     assert_equal(Rational(9, 24), d.new_offset(Rational(9, 24)).offset)
     assert_equal(Rational(9, 24), d.new_offset('+0900').offset)
+    n = Rat.new
+    assert_raise(TypeError) do
+      Timeout.timeout(1) {d.new_offset(n)}
+    end
   end
 
   def test__plus
@@ -37,6 +44,13 @@ def test__plus__ex
     assert_raise(e) do
       DateTime.new(2000,2,29) + Time.mktime(2000,2,29)
     end
+    n = Rat.new
+    assert_raise(e) do
+      Timeout.timeout(1) {Date.new(2000,2,29) + n}
+    end
+    assert_raise(e) do
+      Timeout.timeout(1) {DateTime.new(2000,2,29) + n}
+    end
   end
 
   def test__minus
diff --git a/test/date/test_date_attr.rb b/test/date/test_date_attr.rb
index b3b5d3a800..1e4d1bfd7a 100644
--- a/test/date/test_date_attr.rb
+++ b/test/date/test_date_attr.rb
@@ -88,16 +88,16 @@ def test__wday_predicate
   end
 
   def test_nth_kday
-    assert_equal(false, Date.new(2001,1,14).__send__(:nth_kday?, 1,0))
-    assert_equal(true, Date.new(2001,1,14).__send__(:nth_kday?, 2,0))
-    assert_equal(false, Date.new(2001,1,14).__send__(:nth_kday?, 3,0))
-    assert_equal(false, Date.new(2001,1,14).__send__(:nth_kday?, 4,0))
-    assert_equal(false, Date.new(2001,1,14).__send__(:nth_kday?, 5,0))
-    assert_equal(false, Date.new(2001,1,14).__send__(:nth_kday?, -1,0))
-    assert_equal(false, Date.new(2001,1,14).__send__(:nth_kday?, -2,0))
-    assert_equal(true, Date.new(2001,1,14).__send__(:nth_kday?, -3,0))
-    assert_equal(false, Date.new(2001,1,14).__send__(:nth_kday?, -4,0))
-    assert_equal(false, Date.new(2001,1,14).__send__(:nth_kday?, -5,0))
+    assert_equal(false, Date.new(2001,1,14).nth_kday?(1,0))
+    assert_equal(true, Date.new(2001,1,14).nth_kday?(2,0))
+    assert_equal(false, Date.new(2001,1,14).nth_kday?(3,0))
+    assert_equal(false, Date.new(2001,1,14).nth_kday?(4,0))
+    assert_equal(false, Date.new(2001,1,14).nth_kday?(5,0))
+    assert_equal(false, Date.new(2001,1,14).nth_kday?(-1,0))
+    assert_equal(false, Date.new(2001,1,14).nth_kday?(-2,0))
+    assert_equal(true, Date.new(2001,1,14).nth_kday?(-3,0))
+    assert_equal(false, Date.new(2001,1,14).nth_kday?(-4,0))
+    assert_equal(false, Date.new(2001,1,14).nth_kday?(-5,0))
   end if Date.new.respond_to?(:nth_kday?, true)
 
 end
diff --git a/test/date/test_date_marshal.rb b/test/date/test_date_marshal.rb
index 99a7239f95..c7ce737aac 100644
--- a/test/date/test_date_marshal.rb
+++ b/test/date/test_date_marshal.rb
@@ -30,13 +30,23 @@ def test_marshal
     a = d.marshal_dump
     d.freeze
     assert(d.frozen?)
-    assert_raise(FrozenError){d.marshal_load(a)}
+    expected_error = defined?(FrozenError) ? FrozenError : RuntimeError
+    assert_raise(expected_error){d.marshal_load(a)}
 
     d = DateTime.now
     a = d.marshal_dump
     d.freeze
     assert(d.frozen?)
-    assert_raise(FrozenError){d.marshal_load(a)}
+    expected_error = defined?(FrozenError) ? FrozenError : RuntimeError
+    assert_raise(expected_error){d.marshal_load(a)}
   end
 
+  def test_memsize
+    require 'objspace'
+    t = DateTime.new(2018, 11, 13)
+    size = ObjectSpace.memsize_of(t)
+    t2 = Marshal.load(Marshal.dump(t))
+    assert_equal(t, t2)
+    assert_equal(size, ObjectSpace.memsize_of(t2), "not reallocated but memsize changed")
+  end
 end
diff --git a/test/date/test_date_new.rb b/test/date/test_date_new.rb
index fe9a631ad0..d27116b198 100644
--- a/test/date/test_date_new.rb
+++ b/test/date/test_date_new.rb
@@ -203,46 +203,46 @@ def test_commercial__ex
   end
 
   def test_weeknum
-    d = Date.__send__(:weeknum)
-    dt = DateTime.__send__(:weeknum)
+    d = Date.weeknum
+    dt = DateTime.weeknum
     assert_equal([-4712, 1, 1], [d.year, d.mon, d.mday])
     assert_equal([-4712, 1, 1], [dt.year, dt.mon, dt.mday])
     assert_equal([0, 0, 0], [dt.hour, dt.min, dt.sec])
 
-    d = Date.__send__(:weeknum, 2002,11,4, 0)
+    d = Date.weeknum(2002,11,4, 0)
     assert_equal(2452355, d.jd)
 
-    d = DateTime.__send__(:weeknum, 2002,11,4, 0, 11,22,33)
+    d = DateTime.weeknum(2002,11,4, 0, 11,22,33)
     assert_equal(2452355, d.jd)
     assert_equal([11,22,33], [d.hour, d.min, d.sec])
 
     assert_raise(ArgumentError) do
-      Date.__send__(:weeknum, 1999,53,0, 0)
+      Date.weeknum(1999,53,0, 0)
     end
     assert_raise(ArgumentError) do
-      Date.__send__(:weeknum, 1999,-53,-1, 0)
+      Date.weeknum(1999,-53,-1, 0)
     end
   end if Date.respond_to?(:weeknum, true)
 
   def test_nth_kday
-    d = Date.__send__(:nth_kday)
-    dt = DateTime.__send__(:nth_kday)
+    d = Date.nth_kday
+    dt = DateTime.nth_kday
     assert_equal([-4712, 1, 1], [d.year, d.mon, d.mday])
     assert_equal([-4712, 1, 1], [dt.year, dt.mon, dt.mday])
     assert_equal([0, 0, 0], [dt.hour, dt.min, dt.sec])
 
-    d = Date.__send__(:nth_kday, 1992,2, 5,6)
+    d = Date.nth_kday(1992,2, 5,6)
     assert_equal(2448682, d.jd)
 
-    d = DateTime.__send__(:nth_kday, 1992,2, 5,6, 11,22,33)
+    d = DateTime.nth_kday(1992,2, 5,6, 11,22,33)
     assert_equal(2448682, d.jd)
     assert_equal([11,22,33], [d.hour, d.min, d.sec])
 
     assert_raise(ArgumentError) do
-      Date.__send__(:nth_kday, 2006,5, 5,0)
+      Date.nth_kday(2006,5, 5,0)
     end
     assert_raise(ArgumentError) do
-      Date.__send__(:nth_kday, 2006,5, -5,0)
+      Date.nth_kday(2006,5, -5,0)
     end
   end if Date.respond_to?(:nth_kday, true)
 
@@ -267,4 +267,12 @@ def test_now
     assert_in_delta(t, t2, t - z + 2)
   end
 
+  def test_memsize
+    require 'objspace'
+    t = DateTime.now
+    size = ObjectSpace.memsize_of(t)
+    t.__send__(:initialize_copy, Date.today)
+    assert_instance_of(DateTime, t)
+    assert_equal(size, ObjectSpace.memsize_of(t), "not reallocated but memsize changed")
+  end
 end
diff --git a/test/date/test_date_parse.rb b/test/date/test_date_parse.rb
index ac0eb85ca7..d1163b29cb 100644
--- a/test/date/test_date_parse.rb
+++ b/test/date/test_date_parse.rb
@@ -1,6 +1,7 @@
 # frozen_string_literal: true
 require 'test/unit'
 require 'date'
+require 'timeout'
 
 class TestDateParse < Test::Unit::TestCase
 
@@ -823,6 +824,13 @@ def test__iso8601
 
     h = Date._iso8601('')
     assert_equal({}, h)
+
+    h = Date._iso8601(nil)
+    assert_equal({}, h)
+
+    h = Date._iso8601('01-02-03T04:05:06Z'.to_sym)
+    assert_equal([2001, 2, 3, 4, 5, 6, 0],
+      h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
   end
 
   def test__rfc3339
@@ -838,6 +846,13 @@ def test__rfc3339
 
     h = Date._rfc3339('')
     assert_equal({}, h)
+
+    h = Date._rfc3339(nil)
+    assert_equal({}, h)
+
+    h = Date._rfc3339('2001-02-03T04:05:06Z'.to_sym)
+    assert_equal([2001, 2, 3, 4, 5, 6, 0],
+      h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
   end
 
   def test__xmlschema
@@ -920,6 +935,13 @@ def test__xmlschema
 
     h = Date._xmlschema('')
     assert_equal({}, h)
+
+    h = Date._xmlschema(nil)
+    assert_equal({}, h)
+
+    h = Date._xmlschema('2001-02-03'.to_sym)
+    assert_equal([2001, 2, 3, nil, nil, nil, nil],
+      h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
   end
 
   def test__rfc2822
@@ -952,6 +974,13 @@ def test__rfc2822
 
     h = Date._rfc2822('')
     assert_equal({}, h)
+
+    h = Date._rfc2822(nil)
+    assert_equal({}, h)
+
+    h = Date._rfc2822('Sat, 3 Feb 2001 04:05:06 UT'.to_sym)
+    assert_equal([2001, 2, 3, 4, 5, 6, 0],
+      h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
   end
 
   def test__httpdate
@@ -972,6 +1001,13 @@ def test__httpdate
 
     h = Date._httpdate('')
     assert_equal({}, h)
+
+    h = Date._httpdate(nil)
+    assert_equal({}, h)
+
+    h = Date._httpdate('Sat, 03 Feb 2001 04:05:06 GMT'.to_sym)
+    assert_equal([2001, 2, 3, 4, 5, 6, 0],
+      h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
   end
 
   def test__jisx0301
@@ -984,6 +1020,15 @@ def test__jisx0301
     h = Date._jisx0301('S63.02.03')
     assert_equal([1988, 2, 3, nil, nil, nil, nil],
 		 h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+    h = Date._jisx0301('H31.04.30')
+    assert_equal([2019, 4, 30, nil, nil, nil, nil],
+		 h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+    h = Date._jisx0301('H31.05.01')
+    assert_equal([2019, 5, 1, nil, nil, nil, nil],
+		 h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+    h = Date._jisx0301('R01.05.01')
+    assert_equal([2019, 5, 1, nil, nil, nil, nil],
+		 h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
 
     h = Date._jisx0301('H13.02.03T04:05:06')
     assert_equal([2001, 2, 3, 4, 5, 6, nil],
@@ -998,8 +1043,54 @@ def test__jisx0301
     assert_equal([2001, 2, 3, 4, 5, 6, 3600],
 		 h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
 
+    h = Date._jisx0301('H31.04.30T04:05:06')
+    assert_equal([2019, 4, 30, 4, 5, 6, nil],
+		 h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+    h = Date._jisx0301('H31.04.30T04:05:06,07')
+    assert_equal([2019, 4, 30, 4, 5, 6, nil],
+		 h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+    h = Date._jisx0301('H31.04.30T04:05:06Z')
+    assert_equal([2019, 4, 30, 4, 5, 6, 0],
+		 h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+    h = Date._jisx0301('H31.04.30T04:05:06.07+0100')
+    assert_equal([2019, 4, 30, 4, 5, 6, 3600],
+		 h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+    h = Date._jisx0301('H31.05.01T04:05:06')
+    assert_equal([2019, 5, 1, 4, 5, 6, nil],
+		 h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+    h = Date._jisx0301('H31.05.01T04:05:06,07')
+    assert_equal([2019, 5, 1, 4, 5, 6, nil],
+		 h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+    h = Date._jisx0301('H31.05.01T04:05:06Z')
+    assert_equal([2019, 5, 1, 4, 5, 6, 0],
+		 h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+    h = Date._jisx0301('H31.05.01T04:05:06.07+0100')
+    assert_equal([2019, 5, 1, 4, 5, 6, 3600],
+		 h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+    h = Date._jisx0301('R01.05.01T04:05:06')
+    assert_equal([2019, 5, 1, 4, 5, 6, nil],
+		 h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+    h = Date._jisx0301('R01.05.01T04:05:06,07')
+    assert_equal([2019, 5, 1, 4, 5, 6, nil],
+		 h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+    h = Date._jisx0301('R01.05.01T04:05:06Z')
+    assert_equal([2019, 5, 1, 4, 5, 6, 0],
+		 h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+    h = Date._jisx0301('R01.05.01T04:05:06.07+0100')
+    assert_equal([2019, 5, 1, 4, 5, 6, 3600],
+		 h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
     h = Date._jisx0301('')
     assert_equal({}, h)
+
+    h = Date._jisx0301(nil)
+    assert_equal({}, h)
+
+    h = Date._jisx0301('H13.02.03T04:05:06.07+0100'.to_sym)
+    assert_equal([2001, 2, 3, 4, 5, 6, 3600],
+      h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
   end
 
   def test_iso8601
@@ -1083,9 +1174,33 @@ def test_jisx0301
     assert_equal(Date.new(2001,2,3), d)
     assert_equal(Date::ITALY + 10, d.start)
 
+    d = Date.jisx0301('H31.04.30', Date::ITALY + 10)
+    assert_equal(Date.new(2019,4,30), d)
+    assert_equal(Date::ITALY + 10, d.start)
+
+    d = Date.jisx0301('H31.05.01', Date::ITALY + 10)
+    assert_equal(Date.new(2019,5,1), d)
+    assert_equal(Date::ITALY + 10, d.start)
+
+    d = Date.jisx0301('R01.05.01', Date::ITALY + 10)
+    assert_equal(Date.new(2019,5,1), d)
+    assert_equal(Date::ITALY + 10, d.start)
+
     d = DateTime.jisx0301('H13.02.03T04:05:06+07:00', Date::ITALY + 10)
     assert_equal(DateTime.new(2001,2,3,4,5,6,'+07:00'), d)
     assert_equal(Date::ITALY + 10, d.start)
+
+    d = DateTime.jisx0301('H31.04.30T04:05:06+07:00', Date::ITALY + 10)
+    assert_equal(DateTime.new(2019,4,30,4,5,6,'+07:00'), d)
+    assert_equal(Date::ITALY + 10, d.start)
+
+    d = DateTime.jisx0301('H31.05.01T04:05:06+07:00', Date::ITALY + 10)
+    assert_equal(DateTime.new(2019,5,1,4,5,6,'+07:00'), d)
+    assert_equal(Date::ITALY + 10, d.start)
+
+    d = DateTime.jisx0301('R01.05.01T04:05:06+07:00', Date::ITALY + 10)
+    assert_equal(DateTime.new(2019,5,1,4,5,6,'+07:00'), d)
+    assert_equal(Date::ITALY + 10, d.start)
   end
 
   def test_given_string
@@ -1122,4 +1237,32 @@ def test_given_string
     assert_equal(s0, s)
   end
 
+  def test_length_limit
+    assert_raise(ArgumentError) { Date._parse("1" * 1000) }
+    assert_raise(ArgumentError) { Date._iso8601("1" * 1000) }
+    assert_raise(ArgumentError) { Date._rfc3339("1" * 1000) }
+    assert_raise(ArgumentError) { Date._xmlschema("1" * 1000) }
+    assert_raise(ArgumentError) { Date._rfc2822("1" * 1000) }
+    assert_raise(ArgumentError) { Date._rfc822("1" * 1000) }
+    assert_raise(ArgumentError) { Date._jisx0301("1" * 1000) }
+
+    assert_raise(ArgumentError) { Date.parse("1" * 1000) }
+    assert_raise(ArgumentError) { Date.iso8601("1" * 1000) }
+    assert_raise(ArgumentError) { Date.rfc3339("1" * 1000) }
+    assert_raise(ArgumentError) { Date.xmlschema("1" * 1000) }
+    assert_raise(ArgumentError) { Date.rfc2822("1" * 1000) }
+    assert_raise(ArgumentError) { Date.rfc822("1" * 1000) }
+    assert_raise(ArgumentError) { Date.jisx0301("1" * 1000) }
+
+    assert_raise(ArgumentError) { DateTime.parse("1" * 1000) }
+    assert_raise(ArgumentError) { DateTime.iso8601("1" * 1000) }
+    assert_raise(ArgumentError) { DateTime.rfc3339("1" * 1000) }
+    assert_raise(ArgumentError) { DateTime.xmlschema("1" * 1000) }
+    assert_raise(ArgumentError) { DateTime.rfc2822("1" * 1000) }
+    assert_raise(ArgumentError) { DateTime.rfc822("1" * 1000) }
+    assert_raise(ArgumentError) { DateTime.jisx0301("1" * 1000) }
+
+    assert_raise(ArgumentError) { Date._parse("Jan " + "9" * 1000000) }
+    assert_raise(Timeout::Error) { Timeout.timeout(1) { Date._parse("Jan " + "9" * 1000000, limit: nil) } }
+  end
 end
diff --git a/test/date/test_date_strftime.rb b/test/date/test_date_strftime.rb
index a33eaa340f..dc237a909d 100644
--- a/test/date/test_date_strftime.rb
+++ b/test/date/test_date_strftime.rb
@@ -406,6 +406,8 @@ def test__different_format
     assert_equal('S64.01.07', Date.parse('1989-01-07').jisx0301)
     assert_equal('H01.01.08', Date.parse('1989-01-08').jisx0301)
     assert_equal('H18.09.01', Date.parse('2006-09-01').jisx0301)
+    assert_equal('H31.04.30', Date.parse('2019-04-30').jisx0301)
+    assert_equal('R01.05.01', Date.parse('2019-05-01').jisx0301)
 
     %w(M06.01.01
        M45.07.29
@@ -414,7 +416,10 @@ def test__different_format
        S01.12.25
        S64.01.07
        H01.01.08
-       H18.09.01).each do |s|
+       H18.09.01
+       H31.04.30
+       R01.05.01
+    ).each do |s|
       assert_equal(s, Date.parse(s).jisx0301)
     end
 
diff --git a/test/date/test_switch_hitter.rb b/test/date/test_switch_hitter.rb
index 16814d44df..4693cbd466 100644
--- a/test/date/test_switch_hitter.rb
+++ b/test/date/test_switch_hitter.rb
@@ -187,18 +187,18 @@ def test_fractional
     d = Date.jd(Rational(2451944))
     assert_equal(2451944, d.jd)
     d = Date.jd(2451944.5)
-    assert_equal([2451944, 12], [d.jd, d.send('hour')])
+    assert_equal(2451944, d.jd)
     d = Date.jd(Rational('2451944.5'))
-    assert_equal([2451944, 12], [d.jd, d.send('hour')])
+    assert_equal(2451944, d.jd)
 
     d = Date.civil(2001, 2, 3.0)
     assert_equal([2001, 2, 3], [d.year, d.mon, d.mday])
     d = Date.civil(2001, 2, Rational(3))
     assert_equal([2001, 2, 3], [d.year, d.mon, d.mday])
     d = Date.civil(2001, 2, 3.5)
-    assert_equal([2001, 2, 3, 12], [d.year, d.mon, d.mday, d.send('hour')])
+    assert_equal([2001, 2, 3], [d.year, d.mon, d.mday])
     d = Date.civil(2001, 2, Rational('3.5'))
-    assert_equal([2001, 2, 3, 12], [d.year, d.mon, d.mday, d.send('hour')])
+    assert_equal([2001, 2, 3], [d.year, d.mon, d.mday])
 
     d = Date.ordinal(2001, 2.0)
     assert_equal([2001, 2], [d.year, d.yday])
@@ -266,10 +266,8 @@ def test_canon24oc
   end
 
   def test_zone
-    d = Date.new(2001, 2, 3)
-    assert_equal(Encoding::US_ASCII, d.send(:zone).encoding)
     d = DateTime.new(2001, 2, 3)
-    assert_equal(Encoding::US_ASCII, d.send(:zone).encoding)
+    assert_equal(Encoding::US_ASCII, d.zone.encoding)
   end
 
   def test_to_s
@@ -534,7 +532,6 @@ def test_marshal14
     s = "\x04\x03u:\x01\x04Date\x01\v\x04\x03[\x01\x02i\x03\xE8i%T"
     d = Marshal.load(s)
     assert_equal(Rational(4903887,2), d.ajd)
-    assert_equal(0, d.send(:offset))
     assert_equal(Date::GREGORIAN, d.start)
   end
 
@@ -542,7 +539,6 @@ def test_marshal16
     s = "\x04\x06u:\tDate\x0F\x04\x06[\ai\x03\xE8i%T"
     d = Marshal.load(s)
     assert_equal(Rational(4903887,2), d.ajd)
-    assert_equal(0, d.send(:offset))
     assert_equal(Date::GREGORIAN, d.start)
   end
 
@@ -550,7 +546,6 @@ def test_marshal18
     s = "\x04\bu:\tDateP\x04\b[\bo:\rRational\a:\x0F@numeratori\x03\xCF\xD3J:\x11@denominatori\ai\x00o:\x13Date::Infinity\x06:\a@di\xFA"
     d = Marshal.load(s)
     assert_equal(Rational(4903887,2), d.ajd)
-    assert_equal(0, d.send(:offset))
     assert_equal(Date::GREGORIAN, d.start)
 
     s = "\x04\bu:\rDateTime`\x04\b[\bo:\rRational\a:\x0F@numeratorl+\b\xC9\xB0\x81\xBD\x02\x00:\x11@denominatori\x02\xC0\x12o;\x00\a;\x06i\b;\ai\ro:\x13Date::Infinity\x06:\a@di\xFA"
@@ -564,7 +559,6 @@ def test_marshal192
     s = "\x04\bU:\tDate[\bU:\rRational[\ai\x03\xCF\xD3Ji\ai\x00o:\x13Date::Infinity\x06:\a@di\xFA"
     d = Marshal.load(s)
     assert_equal(Rational(4903887,2), d.ajd)
-    assert_equal(Rational(0,24), d.send(:offset))
     assert_equal(Date::GREGORIAN, d.start)
 
     s = "\x04\bU:\rDateTime[\bU:\rRational[\al+\b\xC9\xB0\x81\xBD\x02\x00i\x02\xC0\x12U;\x06[\ai\bi\ro:\x13Date::Infinity\x06:\a@di\xFA"
diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb
index 7fabfd351d..78c63c26bf 100644
--- a/test/ruby/test_float.rb
+++ b/test/ruby/test_float.rb
@@ -171,6 +171,24 @@ def test_strtod
       assert_raise(ArgumentError, n += z + "A") {Float(n)}
       assert_raise(ArgumentError, n += z + ".0") {Float(n)}
     end
+
+    x = nil
+    2000.times do
+      x = Float("0x"+"0"*30)
+      break unless x == 0.0
+    end
+    assert_equal(0.0, x, ->{"%a" % x})
+    x = nil
+    2000.times do
+      begin
+        x = Float("0x1."+"0"*270)
+      rescue ArgumentError => e
+        raise unless /"0x1\.0{270}"/ =~ e.message
+      else
+        break
+      end
+    end
+    assert_nil(x, ->{"%a" % x})
   end
 
   def test_divmod
diff --git a/util.c b/util.c
index 757faee396..4e60f72c03 100644
--- a/util.c
+++ b/util.c
@@ -2046,6 +2046,7 @@ break2:
 	    if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0;
 	    if (*s == '0') {
 		while (*++s == '0');
+		if (!*s) goto ret;
 		s1 = strchr(hexdigit, *s);
 	    }
 	    if (s1 != NULL) {
@@ -2068,7 +2069,7 @@ break2:
 		for (; *s && (s1 = strchr(hexdigit, *s)); ++s) {
 		    adj += aadj * ((s1 - hexdigit) & 15);
 		    if ((aadj /= 16) == 0.0) {
-			while (strchr(hexdigit, *++s));
+			while (*++s && strchr(hexdigit, *s));
 			break;
 		    }
 		}
diff --git a/vm_exec.c b/vm_exec.c
index ce47ab2cc3..60788e55a7 100644
--- a/vm_exec.c
+++ b/vm_exec.c
@@ -27,6 +27,9 @@ static void vm_analysis_insn(int insn);
 #elif defined(__GNUC__) && defined(__powerpc64__)
 #define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("r" reg)
 
+#elif defined(__GNUC__) && defined(__aarch64__)
+#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("x" reg)
+
 #else
 #define DECL_SC_REG(type, r, reg) register type reg_##r
 #endif
@@ -74,6 +77,11 @@ vm_exec_core(rb_execution_context_t *ec, VALUE initial)
     DECL_SC_REG(rb_control_frame_t *, cfp, "15");
 #define USE_MACHINE_REGS 1
 
+#elif defined(__GNUC__) && defined(__aarch64__)
+    DECL_SC_REG(const VALUE *, pc, "19");
+    DECL_SC_REG(rb_control_frame_t *, cfp, "20");
+#define USE_MACHINE_REGS 1
+
 #else
     register rb_control_frame_t *reg_cfp;
     const VALUE *reg_pc;
