Try Time.find_timezone to convert name to timezone

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66076 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2018-11-28 14:08:31 +00:00
Родитель fe08f99e93
Коммит 337b4b6344
2 изменённых файлов: 74 добавлений и 28 удалений

Просмотреть файл

@ -503,41 +503,49 @@ End
def abbr(t)
@abbr
end
def ==(other)
@name == other.name and @abbr == other.abbr(0) and @offset == other.offset
end
def inspect
"#<TZ: #@name #@abbr #@offset>"
end
end
end
module TestTimeTZ::WithTZ
def subtest_new(time_class, tz, tzname, abbr, utc_offset)
t = time_class.new(2018, 9, 1, 12, 0, 0, tz)
def subtest_new(time_class, tz, tzarg, tzname, abbr, utc_offset)
t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg)
assert_equal([2018, 9, 1, 12, 0, 0, tz], [t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.zone])
h, m = (-utc_offset / 60).divmod(60)
assert_equal(time_class.utc(2018, 9, 1, 12+h, m, 0).to_i, t.to_i)
end
def subtest_getlocal(time_class, tz, tzname, abbr, utc_offset)
t = time_class.utc(2018, 9, 1, 12, 0, 0).getlocal(tz)
def subtest_getlocal(time_class, tz, tzarg, tzname, abbr, utc_offset)
t = time_class.utc(2018, 9, 1, 12, 0, 0).getlocal(tzarg)
h, m = (utc_offset / 60).divmod(60)
assert_equal([2018, 9, 1, 12+h, m, 0, tz], [t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.zone])
assert_equal(time_class.utc(2018, 9, 1, 12, 0, 0), t)
end
def subtest_strftime(time_class, tz, tzname, abbr, utc_offset)
t = time_class.new(2018, 9, 1, 12, 0, 0, tz)
def subtest_strftime(time_class, tz, tzarg, tzname, abbr, utc_offset)
t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg)
h, m = (utc_offset.abs / 60).divmod(60)
h = -h if utc_offset < 0
assert_equal("%+.2d%.2d %s" % [h, m, abbr], t.strftime("%z %Z"))
end
def subtest_plus(time_class, tz, tzname, abbr, utc_offset)
t = time_class.new(2018, 9, 1, 12, 0, 0, tz) + 4000
def subtest_plus(time_class, tz, tzarg, tzname, abbr, utc_offset)
t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg) + 4000
assert_equal([2018, 9, 1, 13, 6, 40, tz], [t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.zone])
m, s = (4000-utc_offset).divmod(60)
h, m = m.divmod(60)
assert_equal(time_class.utc(2018, 9, 1, 12+h, m, s), t)
end
def subtest_marshal(time_class, tz, tzname, abbr, utc_offset)
t = time_class.new(2018, 9, 1, 12, 0, 0, tz)
def subtest_marshal(time_class, tz, tzarg, tzname, abbr, utc_offset)
t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg)
t2 = Marshal.load(Marshal.dump(t))
assert_equal(t, t2)
assert_equal(t.utc_offset, t2.utc_offset)
@ -561,7 +569,8 @@ module TestTimeTZ::WithTZ
define_method("#{test}@#{tzname}") do
tz = make_timezone(tzname, abbr, utc_offset)
time_class = self.class::TIME_CLASS
__send__(subtest, time_class, tz, tzname, abbr, utc_offset)
__send__(subtest, time_class, tz, tz, tzname, abbr, utc_offset)
__send__(subtest, time_class, tz, tzname, tzname, abbr, utc_offset)
end
end
end

71
time.c
Просмотреть файл

@ -642,6 +642,7 @@ static uint32_t obj2subsecx(VALUE obj, VALUE *subsecx);
static VALUE time_gmtime(VALUE);
static VALUE time_localtime(VALUE);
static VALUE time_fixoff(VALUE);
static VALUE time_zonelocal(VALUE time, VALUE off);
static time_t timegm_noleapsecond(struct tm *tm);
static int tmcmp(struct tm *a, struct tm *b);
@ -2040,6 +2041,13 @@ maybe_tzobj_p(VALUE obj)
return TRUE;
}
NORETURN(static void invalid_utc_offset(void));
static void
invalid_utc_offset(void)
{
rb_raise(rb_eArgError, "\"+HH:MM\" or \"-HH:MM\" expected for utc_offset");
}
static VALUE
utc_offset_arg(VALUE arg)
{
@ -2049,7 +2057,7 @@ utc_offset_arg(VALUE arg)
char *s = RSTRING_PTR(tmp);
if (!rb_enc_str_asciicompat_p(tmp)) {
invalid_utc_offset:
rb_raise(rb_eArgError, "\"+HH:MM\" or \"-HH:MM\" expected for utc_offset");
return Qnil;
}
switch (RSTRING_LEN(tmp)) {
case 9:
@ -2263,8 +2271,9 @@ time_init_1(int argc, VALUE *argv, VALUE time)
vtm.isdst = 0;
else if (maybe_tzobj_p(arg))
zone = arg;
else
vtm.utc_offset = utc_offset_arg(arg);
else if (NIL_P(vtm.utc_offset = utc_offset_arg(arg)))
if (NIL_P(zone = find_timezone(time, arg)))
invalid_utc_offset();
}
validate_vtm(&vtm);
@ -2280,8 +2289,9 @@ time_init_1(int argc, VALUE *argv, VALUE time)
if (zone_timelocal(zone, time)) {
return time;
}
else {
vtm.utc_offset = utc_offset_arg(zone);
else if (NIL_P(vtm.utc_offset = utc_offset_arg(zone))) {
if (NIL_P(zone = find_timezone(time, zone)) || !zone_timelocal(zone, time))
invalid_utc_offset();
}
}
@ -2480,11 +2490,18 @@ rb_time_num_new(VALUE timev, VALUE off)
VALUE time = time_new_timew(rb_cTime, rb_time_magnify(v2w(timev)));
if (!NIL_P(off)) {
if (maybe_tzobj_p(off)) {
VALUE zone = off;
if (maybe_tzobj_p(zone)) {
time_gmtime(time);
if (zone_timelocal(off, time)) return time;
if (zone_timelocal(zone, time)) return time;
}
if (NIL_P(off = utc_offset_arg(off))) {
if (NIL_P(zone = find_timezone(time, zone))) invalid_utc_offset();
time_gmtime(time);
if (!zone_timelocal(zone, time)) invalid_utc_offset();
return time;
}
off = utc_offset_arg(off);
validate_utc_offset(off);
time_set_utc_offset(time, off);
return time;
@ -3682,6 +3699,23 @@ time_localtime(VALUE time)
return time;
}
static VALUE
time_zonelocal(VALUE time, VALUE off)
{
VALUE zone = off;
if (zone_localtime(zone, time)) return time;
if (NIL_P(off = utc_offset_arg(off))) {
if (NIL_P(zone = find_timezone(time, zone))) invalid_utc_offset();
if (!zone_localtime(zone, time)) invalid_utc_offset();
return time;
}
validate_utc_offset(off);
time_set_utc_offset(time, off);
return time_fixoff(time);
}
/*
* call-seq:
* time.localtime -> time
@ -3712,13 +3746,7 @@ time_localtime_m(int argc, VALUE *argv, VALUE time)
rb_scan_args(argc, argv, "01", &off);
if (!NIL_P(off)) {
if (zone_localtime(off, time)) return time;
off = utc_offset_arg(off);
validate_utc_offset(off);
time_set_utc_offset(time, off);
return time_fixoff(time);
return time_zonelocal(time, off);
}
return time_localtime(time);
@ -3835,12 +3863,18 @@ time_getlocaltime(int argc, VALUE *argv, VALUE time)
rb_scan_args(argc, argv, "01", &off);
if (!NIL_P(off)) {
if (maybe_tzobj_p(off)) {
VALUE zone = off;
if (maybe_tzobj_p(zone)) {
VALUE t = time_dup(time);
if (zone_localtime(off, t)) return t;
}
off = utc_offset_arg(off);
if (NIL_P(off = utc_offset_arg(off))) {
if (NIL_P(zone = find_timezone(time, zone))) invalid_utc_offset();
time = time_dup(time);
if (!zone_localtime(zone, time)) invalid_utc_offset();
return time;
}
validate_utc_offset(off);
time = time_dup(time);
@ -5417,6 +5451,9 @@ rb_time_zone_abbreviation(VALUE zone, VALUE time)
*
* At loading marshaled data, a timezone name will be converted to a timezone
* object by +find_timezone+ class method, if the method is defined.
*
* Similary, that class method will be called when a timezone argument does
* not have the necessary methods mentioned above.
*/
void