ruby-changes:55320
From: naruse <ko1@a...>
Date: Sun, 14 Apr 2019 00:14:09 +0900 (JST)
Subject: [ruby-changes:55320] naruse:r67527 (ruby_2_6): merge revision(s) 66745, 67397, 67398, 67399, 67400, 67409, 67410, 67411, 67412, 67425, 67426, 67473, 67474: [Backport #15742]
naruse 2019-04-14 00:14:02 +0900 (Sun, 14 Apr 2019) New Revision: 67527 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=67527 Log: merge revision(s) 66745,67397,67398,67399,67400,67409,67410,67411,67412,67425,67426,67473,67474: [Backport #15742] Bump version to date-2.0.0. I forgot to change it when Ruby 2.6.0 was released. date_parse.c: extract Japanese era initials * expand tabs. date_parse.c: removed 'r' which is not in JIS X 0301 yet Added tests for end of Heisei date: use del_hash to extract an element destructively * expand tabs. date_parse.c: renamed JAPANESE prefix as JISX0301 date_parse.c: name JISX0301_DEFAULT_ERA date: make zone a substring to copy encoding and taintedness * expand tabs. date_core.c: [DOC] Heisei will be assumed if no-era [ci skip] date: support for Reiwa, new Japanese era [Feature #15742] Modified directories: branches/ruby_2_6/ Modified files: branches/ruby_2_6/NEWS branches/ruby_2_6/ext/date/date_core.c branches/ruby_2_6/ext/date/date_parse.c branches/ruby_2_6/ext/date/date_strptime.c branches/ruby_2_6/test/date/test_date_parse.rb branches/ruby_2_6/test/date/test_date_strftime.rb branches/ruby_2_6/version.h Index: ruby_2_6/NEWS =================================================================== --- ruby_2_6/NEWS (revision 67526) +++ ruby_2_6/NEWS (revision 67527) @@ -529,6 +529,12 @@ sufficient information, see the ChangeLo https://github.com/ruby/ruby/blob/trunk/ruby_2_6/NEWS#L529 * Upgrade to 3.0.4. See https://github.com/ruby/csv/blob/master/NEWS.md. +Date:: + + * Date.jisx0301, Date#jisx0301, and Date.parse provisionally support the + new Japanese era as an informal extension, until the new JIS X 0301 is + issued. [Feature #15742] + [RSS] [New options] Index: ruby_2_6/version.h =================================================================== --- ruby_2_6/version.h (revision 67526) +++ ruby_2_6/version.h (revision 67527) @@ -1,6 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_6/version.h#L1 #define RUBY_VERSION "2.6.3" #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 56 +#define RUBY_PATCHLEVEL 57 #define RUBY_RELEASE_YEAR 2019 #define RUBY_RELEASE_MONTH 4 Index: ruby_2_6/test/date/test_date_parse.rb =================================================================== --- ruby_2_6/test/date/test_date_parse.rb (revision 67526) +++ ruby_2_6/test/date/test_date_parse.rb (revision 67527) @@ -121,6 +121,8 @@ class TestDateParse < Test::Unit::TestCa https://github.com/ruby/ruby/blob/trunk/ruby_2_6/test/date/test_date_parse.rb#L121 [['S40.05.23T23:55:21-09:00',false],[1965,5,23,23,55,21,'-09:00',-9*3600,nil], __LINE__], [['H11.05.23 23:55:21Z',false],[1999,5,23,23,55,21,'Z',0,nil], __LINE__], [['H11.05.23T23:55:21Z',false],[1999,5,23,23,55,21,'Z',0,nil], __LINE__], + [['H31.04.30 23:55:21Z',false],[2019,4,30,23,55,21,'Z',0,nil], __LINE__], + [['H31.04.30T23:55:21Z',false],[2019,4,30,23,55,21,'Z',0,nil], __LINE__], # ofx date [['19990523235521',false],[1999,5,23,23,55,21,nil,nil,nil], __LINE__], @@ -416,7 +418,14 @@ class TestDateParse < Test::Unit::TestCa https://github.com/ruby/ruby/blob/trunk/ruby_2_6/test/date/test_date_parse.rb#L418 a[1] = -1 a[2] = h[:yday] end - assert_equal(y, a, format('<failed at line %d>', l)) + l = format('<failed at line %d>', l) + assert_equal(y, a, l) + if y[6] + h = Date._parse(x[0].dup.taint, *x[1..-1]) + assert_equal(y[6], h[:zone], l) + assert_equal(y[6].encoding, h[:zone].encoding, l) + assert_predicate(h[:zone], :tainted?, l) + end end end @@ -984,6 +993,15 @@ class TestDateParse < Test::Unit::TestCa https://github.com/ruby/ruby/blob/trunk/ruby_2_6/test/date/test_date_parse.rb#L993 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,6 +1016,45 @@ class TestDateParse < Test::Unit::TestCa https://github.com/ruby/ruby/blob/trunk/ruby_2_6/test/date/test_date_parse.rb#L1016 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) end @@ -1083,9 +1140,33 @@ class TestDateParse < Test::Unit::TestCa https://github.com/ruby/ruby/blob/trunk/ruby_2_6/test/date/test_date_parse.rb#L1140 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 @@ -1120,6 +1201,16 @@ class TestDateParse < Test::Unit::TestCa https://github.com/ruby/ruby/blob/trunk/ruby_2_6/test/date/test_date_parse.rb#L1201 s0 = s.dup assert_not_equal({}, Date._jisx0301(s)) assert_equal(s0, s) + + s = 'H31.04.30T04:05:06,07Z' + s0 = s.dup + assert_not_equal({}, Date._jisx0301(s)) + assert_equal(s0, s) + + s = 'H31.05.01T04:05:06,07Z' + s0 = s.dup + assert_not_equal({}, Date._jisx0301(s)) + assert_equal(s0, s) end end Index: ruby_2_6/test/date/test_date_strftime.rb =================================================================== --- ruby_2_6/test/date/test_date_strftime.rb (revision 67526) +++ ruby_2_6/test/date/test_date_strftime.rb (revision 67527) @@ -406,6 +406,8 @@ class TestDateStrftime < Test::Unit::Tes https://github.com/ruby/ruby/blob/trunk/ruby_2_6/test/date/test_date_strftime.rb#L406 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 @@ class TestDateStrftime < Test::Unit::Tes https://github.com/ruby/ruby/blob/trunk/ruby_2_6/test/date/test_date_strftime.rb#L416 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 Index: ruby_2_6/ext/date/date_strptime.c =================================================================== --- ruby_2_6/ext/date/date_strptime.c (revision 67526) +++ ruby_2_6/ext/date/date_strptime.c (revision 67527) @@ -669,7 +669,7 @@ date__strptime(const char *str, size_t s https://github.com/ruby/ruby/blob/trunk/ruby_2_6/ext/date/date_strptime.c#L669 if (fail_p()) return Qnil; - cent = ref_hash("_cent"); + cent = del_hash("_cent"); if (!NIL_P(cent)) { VALUE year; @@ -679,10 +679,9 @@ date__strptime(const char *str, size_t s https://github.com/ruby/ruby/blob/trunk/ruby_2_6/ext/date/date_strptime.c#L679 year = ref_hash("year"); if (!NIL_P(year)) set_hash("year", f_add(year, f_mul(cent, INT2FIX(100)))); - del_hash("_cent"); } - merid = ref_hash("_merid"); + merid = del_hash("_merid"); if (!NIL_P(merid)) { VALUE hour; @@ -691,7 +690,6 @@ date__strptime(const char *str, size_t s https://github.com/ruby/ruby/blob/trunk/ruby_2_6/ext/date/date_strptime.c#L690 hour = f_mod(hour, INT2FIX(12)); set_hash("hour", f_add(hour, merid)); } - del_hash("_merid"); } return hash; Index: ruby_2_6/ext/date/date_core.c =================================================================== --- ruby_2_6/ext/date/date_core.c (revision 67526) +++ ruby_2_6/ext/date/date_core.c (revision 67527) @@ -3692,7 +3692,7 @@ rt_rewrite_frags(VALUE hash) https://github.com/ruby/ruby/blob/trunk/ruby_2_6/ext/date/date_core.c#L3692 { VALUE seconds; - seconds = ref_hash("seconds"); + seconds = del_hash("seconds"); if (!NIL_P(seconds)) { VALUE offset, d, h, min, s, fr; @@ -3717,7 +3717,6 @@ rt_rewrite_frags(VALUE hash) https://github.com/ruby/ruby/blob/trunk/ruby_2_6/ext/date/date_core.c#L3717 set_hash("min", min); set_hash("sec", s); set_hash("sec_fraction", fr); - del_hash("seconds"); } return hash; } @@ -4307,16 +4306,6 @@ date_s__parse_internal(int argc, VALUE * https://github.com/ruby/ruby/blob/trunk/ruby_2_6/ext/date/date_core.c#L4306 hash = date__parse(vstr, vcomp); - { - VALUE zone = ref_hash("zone"); - - if (!NIL_P(zone)) { - rb_enc_copy(zone, vstr); - OBJ_INFECT(zone, vstr); - set_hash("zone", zone); - } - } - return hash; } @@ -4619,6 +4608,10 @@ date_s__jisx0301(VALUE klass, VALUE str) https://github.com/ruby/ruby/blob/trunk/ruby_2_6/ext/date/date_core.c#L4608 * 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 ...> */ static VALUE date_s_jisx0301(int argc, VALUE *argv, VALUE klass) @@ -7046,10 +7039,14 @@ jisx0301_date_format(char *fmt, size_t s https://github.com/ruby/ruby/blob/trunk/ruby_2_6/ext/date/date_core.c#L7039 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; } @@ -8156,6 +8153,11 @@ datetime_s_httpdate(int argc, VALUE *arg https://github.com/ruby/ruby/blob/trunk/ruby_2_6/ext/date/date_core.c#L8153 * * 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 ...> */ static VALUE datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass) Index: ruby_2_6/ext/date/date_parse.c =================================================================== --- ruby_2_6/ext/date/date_parse.c (revision 67526) +++ ruby_2_6/ext/date/date_parse.c (revision 67527) @@ -1212,6 +1212,9 @@ parse_iso2(VALUE str, VALUE hash) https://github.com/ruby/ruby/blob/trunk/ruby_2_6/ext/date/date_parse.c#L1212 return 1; } +#define JISX0301_ERA_INITIALS "mtshr" +#define JISX0301_DEFAULT_ERA 'H' /* obsolete */ + static int gengo(int c) { @@ -1222,6 +1225,7 @@ gengo(int c) https://github.com/ruby/ruby/blob/trunk/ruby_2_6/ext/date/date_parse.c#L1225 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; @@ -1252,11 +1256,11 @@ parse_jis(VALUE str, VALUE hash) https://github.com/ruby/ruby/blob/trunk/ruby_2_6/ext/date/date_parse.c#L1256 { 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 @@ -1859,30 +1863,26 @@ parse_ddd_cb(VALUE m, VALUE hash) https://github.com/ruby/ruby/blob/trunk/ruby_2_6/ext/date/date_parse.c#L1863 set_hash("zone", s5); if (*cs5 == '[') { - VALUE vbuf = 0; - char *buf = ALLOCV_N(char, vbuf, l5 + 1); - char *s1, *s2, *s3; + const char *s1, *s2; VALUE zone; - memcpy(buf, cs5, l5); - buf[l5 - 1] = '\0'; - - s1 = buf + 1; - s2 = strchr(buf, ':'); + l5 -= 2; + s1 = cs5 + 1; + s2 = memchr(s1, ':', l5); if (s2) { - *s2 = '\0'; s2++; + zone = rb_str_subseq(s5, s2 - cs5, l5 - (s2 - s1)); + s5 = rb_str_subseq(s5, 1, s2 - s1); } - if (s2) - s3 = s2; - else - s3 = s1; - zone = rb_str_new2(s3); + else { + zone = rb_str_subseq(s5, 1, l5); + if (isdigit((unsigned char)*s1)) + s5 = rb_str_append(rb_str_new_cstr("+"), zone); + else + s5 = zone; + } set_hash("zone", zone); - if (isdigit((unsigned char)*s1)) - *--s1 = '+'; - set_hash("offset", date_zone_to_diff(rb_str_new2(s1))); - ALLOCV_END(vbuf); + set_hash("offset", date_zone_to_diff(s5)); } RB_GC_GUARD(s5); } @@ -2175,7 +2175,7 @@ date__parse(VALUE str, VALUE comp) https://github.com/ruby/ruby/blob/trunk/ruby_2_6/ext/date/date_parse.c#L2175 #endif { - if (RTEST(ref_hash("_bc"))) { + if (RTEST(del_hash("_bc"))) { VALUE y; y = ref_hash("cwyear"); @@ -2190,7 +2190,7 @@ date__parse(VALUE str, VALUE comp) https://github.com/ruby/ruby/blob/trunk/ruby_2_6/ext/date/date_parse.c#L2190 } } - if (RTEST(ref_hash("_comp"))) { + if (RTEST(del_hash("_comp"))) { VALUE y; y = ref_hash("cwyear"); @@ -2213,9 +2213,6 @@ date__parse(VALUE str, VALUE comp) https://github.com/ruby/ruby/blob/trunk/ruby_2_6/ext/date/date_parse.c#L2213 } - del_hash("_bc"); - del_hash("_comp"); - { VALUE zone = ref_hash("zone"); if (!NIL_P(zone) && NIL_P(ref_hash("offset"))) @@ -2954,7 +2951,7 @@ jisx0301_cb(VALUE m, VALUE hash) https://github.com/ruby/ruby/blob/trunk/ruby_2_6/ext/date/date_parse.c#L2951 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])); @@ -2979,7 +2976,7 @@ static int https://github.com/ruby/ruby/blob/trunk/ruby_2_6/ext/date/date_parse.c#L2976 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"; Index: ruby_2_6 =================================================================== --- ruby_2_6 (revision 67526) +++ ruby_2_6 (revision 67527) Property changes on: ruby_2_6 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /trunk:r67397-67400,67409-67412,67425-67426,67473-67474 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/