[前][次][番号順一覧][スレッド一覧]

ruby-changes:14998

From: akr <ko1@a...>
Date: Thu, 11 Mar 2010 22:39:31 +0900 (JST)
Subject: [ruby-changes:14998] Ruby:r26873 (trunk): * time.c (time_round): new method Time#round.

akr	2010-03-11 22:39:12 +0900 (Thu, 11 Mar 2010)

  New Revision: 26873

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=26873

  Log:
    * time.c (time_round): new method Time#round.  [ruby-dev:40595]

  Modified files:
    trunk/ChangeLog
    trunk/test/ruby/test_time.rb
    trunk/time.c

Index: time.c
===================================================================
--- time.c	(revision 26872)
+++ time.c	(revision 26873)
@@ -2997,7 +2997,65 @@
 
 #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:
  *     time.sec => fixnum
@@ -3918,6 +3976,8 @@
     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: ChangeLog
===================================================================
--- ChangeLog	(revision 26872)
+++ ChangeLog	(revision 26873)
@@ -1,3 +1,7 @@
+Thu Mar 11 22:35:27 2010  Tanaka Akira  <akr@f...>
+
+	* time.c (time_round): new method Time#round.  [ruby-dev:40595]
+
 Thu Mar 11 17:31:59 2010  Nobuyoshi Nakada  <nobu@r...>
 
 	* transcode.c (str_transcode0): confirm the code range.
Index: test/ruby/test_time.rb
===================================================================
--- test/ruby/test_time.rb	(revision 26872)
+++ test/ruby/test_time.rb	(revision 26873)
@@ -576,4 +576,37 @@
     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

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]