From 55970e3161160942c7410e6b26cb4cc3aaba27af Mon Sep 17 00:00:00 2001 From: Peter Weldon Date: Mon, 8 Nov 2010 16:53:32 -0800 Subject: [PATCH] Make syck's Time/timestamps write nsec precision fractional seconds, and read arbitary precision fractional seconds. --- ChangeLog | 8 ++++++++ ext/syck/lib/syck/rubytypes.rb | 2 +- ext/syck/rubyext.c | 27 +++++++++------------------ test/syck/test_yaml.rb | 4 +++- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index a755048..cf67ece 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +Tue Nov 9 09:51:10 2010 Peter Weldon + + * ext/syck/lib/syck/rubytypes.rb (Time#to_yaml): emit nsec + precision fractional seconds. + + * ext/syck/rubyext.c (mktime_do): support parsing of arbitary + precision fractional seconds. + Sat Nov 6 07:33:08 2010 Nobuyoshi Nakada * configure.in (rb_cv_export_prefix): check for prefixed diff --git a/ext/syck/lib/syck/rubytypes.rb b/ext/syck/lib/syck/rubytypes.rb index f8bbfea..b55052f 100644 --- a/ext/syck/lib/syck/rubytypes.rb +++ b/ext/syck/lib/syck/rubytypes.rb @@ -338,7 +338,7 @@ class Time tz = "%s%02d:%02d" % [ difference_sign, difference_minutes / 60, difference_minutes % 60] end standard = self.strftime( "%Y-%m-%d %H:%M:%S" ) - standard += ".%06d" % [usec] if usec.nonzero? + standard += ".%09d" % [nsec] if nsec.nonzero? standard += " %s" % [tz] if to_yaml_properties.empty? out.scalar( taguri, standard, :plain ) diff --git a/ext/syck/rubyext.c b/ext/syck/rubyext.c index 282f052..a6a4982 100644 --- a/ext/syck/rubyext.c +++ b/ext/syck/rubyext.c @@ -226,7 +226,7 @@ mktime_do(VALUE varg) VALUE hour = INT2FIX(0); VALUE min = INT2FIX(0); VALUE sec = INT2FIX(0); - long usec; + VALUE usec = INT2FIX(0); /* Year*/ if ( ptr[0] != '\0' && len > 0 ) { @@ -270,21 +270,12 @@ mktime_do(VALUE varg) /* Millisecond */ ptr += 2; - if ( len > ptr - str && *ptr == '.' ) - { - char padded[] = "000000"; - const char *end = ptr + 1; - const char *p = end; - while ( isdigit( *end ) ) end++; - if (end - p < (int)sizeof(padded)) { - MEMCPY(padded, ptr + 1, char, end - (ptr + 1)); - p = padded; - } - usec = strtol(p, NULL, 10); - } - else - { - usec = 0; + if ( len > ptr - str && *ptr == '.' ) { + const char *p = ptr; + ptr++; + while ( isdigit( *ptr ) ) ptr++; + usec = rb_Rational1(rb_str_new(p, ptr - p)); + usec = rb_funcall(usec, '*', 1, INT2FIX(1000000)); } /* Time Zone*/ @@ -312,12 +303,12 @@ mktime_do(VALUE varg) time = rb_funcall(rb_cTime, s_utc, 6, year, mon, day, hour, min, sec); tmp = rb_funcall(time, s_to_i, 0); tmp = rb_funcall(tmp, '-', 1, LONG2FIX(tz_offset)); - return rb_funcall(rb_cTime, s_at, 2, tmp, LONG2NUM(usec)); + return rb_funcall(rb_cTime, s_at, 2, tmp, usec); } else { /* Make UTC time*/ - return rb_funcall(rb_cTime, s_utc, 7, year, mon, day, hour, min, sec, LONG2NUM(usec)); + return rb_funcall(rb_cTime, s_utc, 7, year, mon, day, hour, min, sec, usec); } } diff --git a/test/syck/test_yaml.rb b/test/syck/test_yaml.rb index 3d9d7ab..ca78f2a 100644 --- a/test/syck/test_yaml.rb +++ b/test/syck/test_yaml.rb @@ -65,7 +65,7 @@ class YAML_Unit_Tests < Test::Unit::TestCase hour = zone[0,3].to_i * 3600 min = zone[3,2].to_i * 60 ofs = (hour + min) - val = Time.at( val.tv_sec - ofs, val.tv_nsec / 1000.0 ) + val = val - ofs end return val end @@ -1092,9 +1092,11 @@ EOY assert_parse_only( { "space separated" => mktime( 2001, 12, 14, 21, 59, 43, ".10", "-05:00" ), "canonical" => mktime( 2001, 12, 15, 2, 59, 43, ".10" ), + "nsec" => mktime( 2001, 12, 15, 2, 59, 43, ".000000001" ), "date (noon UTC)" => Date.new( 2002, 12, 14), "valid iso8601" => mktime( 2001, 12, 14, 21, 59, 43, ".10", "-05:00" ) }, <