From: Nobuyoshi Nakada Date: 2010-01-13T13:27:51+09:00 Subject: [ruby-dev:40063] [BUG] marshaling Time.utc_offset なかだです。 MarshalでTimeのutc_offsetが保存されません。 $ ./ruby -v -e 'p t=Time.now.localtime("-05:00"); p t.utc_offset; p t=Marshal.load(Marshal.dump(t)); p t.utc_offset' ruby 1.9.2dev (2010-01-13 trunk 26311) [universal.x86_64-darwin9.8.0] 2010-01-12 23:17:02 -0500 -18000 2010-01-13 13:17:02 +0900 32400 utc_offsetを分単位でdumpさせるパッチです。 ちなみにutc_offsetはRationalを想定しているようですが、分未満の時 差を持つタイムゾーンというのは実際にあり得るんでしょうか。 Index: time.c =================================================================== --- time.c (revision 26311) +++ time.c (working copy) @@ -104,5 +104,5 @@ rb_localtime(const time_t *tm, struct tm #endif -static ID id_divmod, id_mul, id_submicro, id_subnano; +static ID id_divmod, id_mul, id_submicro, id_subnano, id_offset; static ID id_eq, id_ne, id_quo, id_div, id_cmp, id_lshift; @@ -1826,4 +1826,6 @@ validate_utc_offset(VALUE utc_offset) if (le(utc_offset, INT2FIX(-86400)) || ge(utc_offset, INT2FIX(86400))) rb_raise(rb_eArgError, "utc_offset out of range"); + if (!rb_equal(mod(utc_offset, INT2FIX(60)), INT2FIX(0))) + rb_raise(rb_eArgError, "utc_offset not in minutes"); } @@ -3648,4 +3650,8 @@ time_mdump(VALUE time) rb_ivar_set(str, id_subnano, subnano); } + if (!TIME_UTC_P(tobj)) { + VALUE min = rb_Integer(rb_funcall(time_utc_offset(time), rb_intern("div"), 1, INT2FIX(60))); + rb_ivar_set(str, id_offset, min); + } return str; } @@ -3684,5 +3690,5 @@ time_mload(VALUE time, VALUE str) int i, gmt; long nsec; - VALUE timexv, submicro, subnano; + VALUE timexv, submicro, subnano, offset; time_modify(time); @@ -3696,4 +3702,10 @@ time_mload(VALUE time, VALUE str) st_delete(rb_generic_ivar_table(str), (st_data_t*)&id_subnano, 0); } + offset = rb_attr_get(str, id_offset); + if (offset != Qnil) { + offset = mul(offset, INT2FIX(60)); + validate_utc_offset(offset); + st_delete(rb_generic_ivar_table(str), (st_data_t*)&id_offset, 0); + } rb_copy_generic_ivar(time, str); @@ -3713,4 +3725,5 @@ time_mload(VALUE time, VALUE str) if ((p & (1UL<<31)) == 0) { + offset = Qnil; gmt = 0; sec = p; @@ -3766,6 +3779,12 @@ end_submicro: ; GetTimeval(time, tobj); tobj->tm_got = 0; - if (gmt) TIME_SET_UTC(tobj); tobj->timexv = timexv; + if (gmt) { + TIME_SET_UTC(tobj); + } + else if (!NIL_P(offset)) { + time_set_utc_offset(time, offset); + time_fixoff(time); + } return time; @@ -3821,4 +3840,5 @@ Init_Time(void) id_submicro = rb_intern("submicro"); id_subnano = rb_intern("subnano"); + id_offset = rb_intern("offset"); rb_cTime = rb_define_class("Time", rb_cObject); -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦