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

ruby-changes:47898

From: naruse <ko1@a...>
Date: Mon, 25 Sep 2017 15:20:17 +0900 (JST)
Subject: [ruby-changes:47898] naruse:r60017 (trunk): Time#at receives 3rd argument which specifies the unit of 2nd argument [Feature #13919]

naruse	2017-09-25 15:20:10 +0900 (Mon, 25 Sep 2017)

  New Revision: 60017

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=60017

  Log:
    Time#at receives 3rd argument which specifies the unit of 2nd argument [Feature #13919]

  Modified files:
    trunk/NEWS
    trunk/test/ruby/test_time.rb
    trunk/time.c
Index: NEWS
===================================================================
--- NEWS	(revision 60016)
+++ NEWS	(revision 60017)
@@ -109,6 +109,11 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L109
 
   * Description set by Thread#name= is now visible on Windows 10.
 
+* Time
+
+  * Time#at receives 3rd argument which specifies the unit of 2nd argument.
+    [Feature #13919]
+
 * KeyError
 
   * KeyError#receiver [Feature #12063]
Index: test/ruby/test_time.rb
===================================================================
--- test/ruby/test_time.rb	(revision 60016)
+++ test/ruby/test_time.rb	(revision 60017)
@@ -236,6 +236,17 @@ class TestTime < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_time.rb#L236
     assert_equal(1, Time.at(0, 0.001).nsec)
   end
 
+  def test_at_with_unit
+    assert_equal(123456789, Time.at(0, 123456789, :nanosecond).nsec)
+    assert_equal(123456789, Time.at(0, 123456789, :nsec).nsec)
+    assert_equal(123456000, Time.at(0, 123456, :microsecond).nsec)
+    assert_equal(123456000, Time.at(0, 123456, :usec).nsec)
+    assert_equal(123000000, Time.at(0, 123, :millisecond).nsec)
+    assert_raise(ArgumentError){ Time.at(0, 1, 2) }
+    assert_raise(ArgumentError){ Time.at(0, 1, :invalid) }
+    assert_raise(ArgumentError){ Time.at(0, 1, nil) }
+  end
+
   def test_at_rational
     assert_equal(1, Time.at(Rational(1,1) / 1000000000).nsec)
     assert_equal(1, Time.at(1167609600 + Rational(1,1) / 1000000000).nsec)
Index: time.c
===================================================================
--- time.c	(revision 60016)
+++ time.c	(revision 60017)
@@ -36,6 +36,7 @@ https://github.com/ruby/ruby/blob/trunk/time.c#L36
 
 static ID id_divmod, id_submicro, id_nano_num, id_nano_den, id_offset, id_zone;
 static ID id_quo, id_div;
+static ID id_nanosecond, id_microsecond, id_millisecond, id_nsec, id_usec;
 
 #define NDIV(x,y) (-(-((x)+1)/(y))-1)
 #define NMOD(x,y) ((y)-(-((x)+1)%(y))-1)
@@ -2347,11 +2348,32 @@ time_s_now(VALUE klass) https://github.com/ruby/ruby/blob/trunk/time.c#L2348
     return rb_class_new_instance(0, NULL, klass);
 }
 
+static int
+get_scale(VALUE unit) {
+    if (unit == ID2SYM(id_nanosecond) || unit == ID2SYM(id_nsec)) {
+        return 1000000000;
+    }
+    else if (unit == ID2SYM(id_microsecond) || unit == ID2SYM(id_usec)) {
+        return 1000000;
+    }
+    else if (unit == ID2SYM(id_millisecond)) {
+        return 1000;
+    }
+    else {
+        rb_raise(rb_eArgError, "unexpected unit: %"PRIsVALUE, unit);
+    }
+}
+
 /*
  *  call-seq:
  *     Time.at(time) -> time
  *     Time.at(seconds_with_frac) -> time
  *     Time.at(seconds, microseconds_with_frac) -> time
+ *     Time.at(seconds, milliseconds, :millisecond) -> time
+ *     Time.at(seconds, microseconds, :usec) -> time
+ *     Time.at(seconds, microseconds, :microsecond) -> time
+ *     Time.at(seconds, nanoseconds, :nsec) -> time
+ *     Time.at(seconds, nanoseconds, :nanosecond) -> time
  *
  *  Creates a new Time object with the value given by +time+,
  *  the given number of +seconds_with_frac+, or
@@ -2362,24 +2384,26 @@ time_s_now(VALUE klass) https://github.com/ruby/ruby/blob/trunk/time.c#L2384
  *
  *  If a numeric argument is given, the result is in local time.
  *
- *     Time.at(0)                           #=> 1969-12-31 18:00:00 -0600
- *     Time.at(Time.at(0))                  #=> 1969-12-31 18:00:00 -0600
- *     Time.at(946702800)                   #=> 1999-12-31 23:00:00 -0600
- *     Time.at(-284061600)                  #=> 1960-12-31 00:00:00 -0600
- *     Time.at(946684800.2).usec            #=> 200000
- *     Time.at(946684800, 123456.789).nsec  #=> 123456789
+ *     Time.at(0)                                #=> 1969-12-31 18:00:00 -0600
+ *     Time.at(Time.at(0))                       #=> 1969-12-31 18:00:00 -0600
+ *     Time.at(946702800)                        #=> 1999-12-31 23:00:00 -0600
+ *     Time.at(-284061600)                       #=> 1960-12-31 00:00:00 -0600
+ *     Time.at(946684800.2).usec                 #=> 200000
+ *     Time.at(946684800, 123456.789).nsec       #=> 123456789
+ *     Time.at(946684800, 123456789, :nsec).nsec  #=> 123456789
  */
 
 static VALUE
 time_s_at(int argc, VALUE *argv, VALUE klass)
 {
-    VALUE time, t;
+    VALUE time, t, unit = Qundef;
     wideval_t timew;
 
-    if (rb_scan_args(argc, argv, "11", &time, &t) == 2) {
+    if (rb_scan_args(argc, argv, "12", &time, &t, &unit) >= 2) {
+        int scale = argc == 3 ? get_scale(unit) : 1000000;
         time = num_exact(time);
         t = num_exact(t);
-        timew = wadd(rb_time_magnify(v2w(time)), wmulquoll(v2w(t), TIME_SCALE, 1000000));
+        timew = wadd(rb_time_magnify(v2w(time)), wmulquoll(v2w(t), TIME_SCALE, scale));
         t = time_new_timew(klass, timew);
     }
     else if (IsTimeval(time)) {
@@ -4819,6 +4843,11 @@ Init_Time(void) https://github.com/ruby/ruby/blob/trunk/time.c#L4843
     id_nano_den = rb_intern("nano_den");
     id_offset = rb_intern("offset");
     id_zone = rb_intern("zone");
+    id_nanosecond = rb_intern("nanosecond");
+    id_microsecond = rb_intern("microsecond");
+    id_millisecond = rb_intern("millisecond");
+    id_nsec = rb_intern("nsec");
+    id_usec = rb_intern("usec");
 
     rb_cTime = rb_define_class("Time", rb_cObject);
     rb_include_module(rb_cTime, rb_mComparable);

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

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