Time#round

e$BA0$K$A$g$C$H=q$-$^$7$?$,!"e(BTime#round
e$B$rDI2C$9$k$N$O$I$&$G$7$g$&!#e(B
e$B$3$l$O!"ICL$K~$N;~9o$r4]$a$k%a%=%C%I$G$9!#e(B

e$B$A$g$&$Ie(B [ruby-core:28602] e$B$K$b$"$j$^$7$?$,!“e(B
Time e$B%*%V%8%’%/%HFb$K8m:9$r4^$`CM$rF~$l$F$7$^$&$3$H$,$”$j$^$9!#e(B

e$B$^$!!";~9o$K8m:9$,$"$k$N$OB,Dj$N$3$H$b9M$($k$H$7$+$?$,$J$$$H;W$&$N$G$9$,!“e(B
e$B8m:9$N$”$k;~9o$r6a;w$9$kCM$rI=<($9$k$3$H$,Fq$7$$$H$$$&LdBj$,$"$j$^$9!#e(B

strftime e$B$Ne(B %N e$B$O!">.?tE@0J2<$NIC?t$rI=<($9$k$b$N$J$N$G!"e(B
e$B;EMM>e!“4]$a$k$N$O:$Fq$G!”@Z$j<N$F$K$;$6$k$rF@$^$;$s!#e(B
e$B4]$a$k$H!"IC$X$N7+$j>e$,$j$,@8$8$?;~$K$I$&$9$k$+$H$$$&LdBj$,@8$8$^$9!#e(B

%N e$B$@$1$G$J$/!"e(Busec e$B$de(B nsec
e$B$bF1MM$JM}M3$G@Z$j<N$F$G$9!#e(B

e$B$3$N$?$a!"$?$H$($Pe(B 0.9999999 e$BIC$rI=<($9$k$He(B
0e$BIC$K$J$C$F!“e(B
1e$BIC$r4|BT$7$F$$$k?M$K$O!”$&$^$/F0$+$J$$$h$&$K8+$($k$3$H$K$J$j$^$9!#e(B

e$B$3$3$G!“e(BTime#round e$B$r;H$&$H!”>.?tE@0J2<$r;M<N8^F~$7$?e(B
Time e$B%*%V%8%’%/%H$rF@$i$l$^$9!#e(B

% ./ruby -e ’
t = Time.utc(1999,12,31, 23,59,59,876543)
p t, t.subsec
t = t.round
p t, t.subsec’
1999-12-31 23:59:59 UTC
(876543/1000000)
2000-01-01 00:00:00 UTC
0

e$B$^$?!“e(BInteger#round
e$B$HF1MM$K!”>JN,2DG=$J0z?t$G7e?t$r;XDj$9$k$3$H$,$G$-$^$9!#e(B

e$B$3$l$K$h$j!"IC$r>.?tE@0J2<e(B3e$B7e$G4]$a$FI=<($7$?$1$l$P!"e(B
strftime e$B$NA0$Ke(B round(3) e$B$r8F$V$3$H$G<B8=$G$-$^$9!#e(B

% ./ruby -e ’
t = Time.utc(1999,12,31, 23,59,59,876543)
p t, t.subsec, t.strftime("%T.%3N")
t = t.round(3)
p t, t.subsec, t.strftime("%T.%3N")

1999-12-31 23:59:59 UTC
(876543/1000000)
“23:59:59.876”
1999-12-31 23:59:59 UTC
(877/1000)
“23:59:59.877”

e$B$I$&$G$7$g$&e(B?

% svn diff --diff-cmd diff -x ‘-u -p’
Index: time.c

— time.c (revision 26871)
+++ time.c (working copy)
@@ -2997,6 +2997,64 @@ rb_time_succ(VALUE time)

#define time_succ rb_time_succ

+/*

    • call-seq:
    • time.round([ndigits]) => new_time
    • Rounds sub seconds to a given precision in decimal digits (0
      digits by default).
    • It returns a new time object.
    • ndigits should be zero or positive integer.
    • require 'time'
      
    • t = Time.utc(1999,12,31, 23,59,59)
      
    • p((t + 0.4).round.iso8601(3))    #=> "1999-12-31T23:59:59.000Z"
      
    • p((t + 0.49).round.iso8601(3))   #=> "1999-12-31T23:59:59.000Z"
      
    • p((t + 0.5).round.iso8601(3))    #=> "2000-01-01T00:00:00.000Z"
      
    • p((t + 1.4).round.iso8601(3))    #=> "2000-01-01T00:00:00.000Z"
      
    • p((t + 1.49).round.iso8601(3))   #=> "2000-01-01T00:00:00.000Z"
      
    • p((t + 1.5).round.iso8601(3))    #=> "2000-01-01T00:00:01.000Z"
      
    • t = Time.utc(1999,12,31, 23,59,59)
      
    • p (t + 0.123456789).round(4).iso8601(6)  #=>
      

“1999-12-31T23:59:59.123500Z”

  • */

+static VALUE
+time_round(int argc, VALUE *argv, VALUE time)
+{

  • VALUE ndigits, v, a, b, den;
  • long nd;
  • struct time_object *tobj;
  • rb_scan_args(argc, argv, “01”, &ndigits);
  • if (NIL_P(ndigits))
  •    ndigits = INT2FIX(0);
    
  • else
  •    ndigits = rb_to_int(ndigits);
    
  • nd = NUM2LONG(ndigits);
  • if (nd < 0)
  • rb_raise(rb_eArgError, “negative ndigits given”);
  • GetTimeval(time, tobj);
  • v = rb_time_unmagnify(tobj->timexv);
  • a = INT2FIX(1);
  • b = INT2FIX(10);
  • while (0 < nd) {
  •    if (nd & 1)
    
  •        a = mul(a, b);
    
  •    b = mul(b, b);
    
  •    nd = nd >> 1;
    
  • }
  • den = quo(INT2FIX(1), a);
  • v = mod(v, den);
  • if (lt(v, quo(den, INT2FIX(2))))
  •    return time_add(tobj, v, -1);
    
  • else
  •    return time_add(tobj, sub(den, v), 1);
    

+}

/*

  • call-seq:
    @@ -3918,6 +3976,8 @@ Init_Time(void)
    rb_define_method(rb_cTime, “-”, time_minus, 1);

    rb_define_method(rb_cTime, “succ”, time_succ, 0);

  • rb_define_method(rb_cTime, “round”, time_round, -1);
  • rb_define_method(rb_cTime, “sec”, time_sec, 0);
    rb_define_method(rb_cTime, “min”, time_min, 0);
    rb_define_method(rb_cTime, “hour”, time_hour, 0);
    Index: test/ruby/test_time.rb
    ===================================================================
    — test/ruby/test_time.rb (revision 26871)
    +++ test/ruby/test_time.rb (working copy)
    @@ -576,4 +576,37 @@ class TestTime < Test::Unit::TestCase
    assert_kind_of(Rational, Time.new(2000,1,1,0,0,Rational(4,3)).to_r)
    assert_kind_of(Rational, Time.utc(1970).to_r)
    end
  • def test_round
  • t = Time.utc(1999,12,31, 23,59,59)
  • t2 = (t+0.4).round
  • assert_equal([59,59,23, 31,12,1999, 5,365,false,“UTC”], t2.to_a)
  • assert_equal(0, t2.subsec)
  • t2 = (t+0.49).round
  • assert_equal([59,59,23, 31,12,1999, 5,365,false,“UTC”], t2.to_a)
  • assert_equal(0, t2.subsec)
  • t2 = (t+0.5).round
  • assert_equal([0,0,0, 1,1,2000, 6,1,false,“UTC”], t2.to_a)
  • assert_equal(0, t2.subsec)
  • t2 = (t+1.4).round
  • assert_equal([0,0,0, 1,1,2000, 6,1,false,“UTC”], t2.to_a)
  • assert_equal(0, t2.subsec)
  • t2 = (t+1.49).round
  • assert_equal([0,0,0, 1,1,2000, 6,1,false,“UTC”], t2.to_a)
  • assert_equal(0, t2.subsec)
  • t2 = (t+1.5).round
  • assert_equal([1,0,0, 1,1,2000, 6,1,false,“UTC”], t2.to_a)
  • assert_equal(0, t2.subsec)
  • t2 = (t+0.123456789).round(4)
  • assert_equal([59,59,23, 31,12,1999, 5,365,false,“UTC”], t2.to_a)
  • assert_equal(Rational(1235,10000), t2.subsec)
  • off = 0.0
  • 100.times {|i|
  •  t2 = (t+off).round(1)
    
  •  assert_equal(Rational(i % 10, 10), t2.subsec)
    
  •  off += 0.1
    
  • }
  • end
    end

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:40595] Time#round”
on Thu, 11 Mar 2010 15:09:45 +0900, Tanaka A. [email protected]
writes:

|e$BA0$K$A$g$C$H=q$-$^$7$?$,!"e(BTime#round e$B$rDI2C$9$k$N$O$I$&$G$7$g$&!#e(B
|e$B$3$l$O!"ICL$K~$N;~9o$r4]$a$k%a%=%C%I$G$9!#e(B

e$B$$$$$s$8$c$J$$$G$7$g$&$+!#e(B