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

ruby-changes:74379

From: Nobuyoshi <ko1@a...>
Date: Mon, 7 Nov 2022 18:36:17 +0900 (JST)
Subject: [ruby-changes:74379] 011d4c57d2 (master): [Bug #19106] Normalize time at 24:00:00 with a timezone object

https://git.ruby-lang.org/ruby.git/commit/?id=011d4c57d2

From 011d4c57d21220249600dfb76db84840550da019 Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Mon, 7 Nov 2022 13:23:23 +0900
Subject: [Bug #19106] Normalize time at 24:00:00 with a timezone object

---
 test/ruby/test_time_tz.rb |  5 +++++
 time.c                    | 24 ++++++++++++++++--------
 2 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/test/ruby/test_time_tz.rb b/test/ruby/test_time_tz.rb
index 6ae12dea5d..6fdb95bafe 100644
--- a/test/ruby/test_time_tz.rb
+++ b/test/ruby/test_time_tz.rb
@@ -612,6 +612,11 @@ module TestTimeTZ::WithTZ https://github.com/ruby/ruby/blob/trunk/test/ruby/test_time_tz.rb#L612
     assert_raise(ArgumentError) {time_class.new(2018, 9, 1, 12, 0, 0, tzarg, in: tzarg)}
   end
 
+  def subtest_hour24(time_class, tz, tzarg, tzname, abbr, utc_offset)
+    t = time_class.new(2000, 1, 1, 24, 0, 0, tzarg)
+    assert_equal([0, 0, 0, 2, 1, 2000], [t.sec, t.min, t.hour, t.mday, t.mon, t.year])
+  end
+
   def subtest_now(time_class, tz, tzarg, tzname, abbr, utc_offset)
     t = time_class.now(in: tzarg)
     assert_equal(tz, t.zone)
diff --git a/time.c b/time.c
index b16a086537..b3604dd488 100644
--- a/time.c
+++ b/time.c
@@ -2331,6 +2331,19 @@ find_timezone(VALUE time, VALUE zone) https://github.com/ruby/ruby/blob/trunk/time.c#L2331
     return rb_check_funcall_default(klass, id_find_timezone, 1, &zone, Qnil);
 }
 
+/* Turn the special case 24:00:00 of already validated vtm into
+ * 00:00:00 the next day */
+static void
+vtm_day_wraparound(struct vtm *vtm)
+{
+    if (vtm->hour < 24) return;
+
+    /* Assuming UTC and no care of DST, just reset hour and advance
+     * date, not to discard the validated vtm. */
+    vtm->hour = 0;
+    vtm_add_day(vtm, 1);
+}
+
 static VALUE
 time_init_args(rb_execution_context_t *ec, VALUE time, VALUE year, VALUE mon, VALUE mday, VALUE hour, VALUE min, VALUE sec, VALUE zone)
 {
@@ -2386,6 +2399,7 @@ time_init_args(rb_execution_context_t *ec, VALUE time, VALUE year, VALUE mon, VA https://github.com/ruby/ruby/blob/trunk/time.c#L2399
 
     if (!NIL_P(zone)) {
         tobj->timew = timegmw(&vtm);
+        vtm_day_wraparound(&vtm);
         tobj->vtm = vtm;
         tobj->tm_got = 1;
         TZMODE_SET_LOCALTIME(tobj);
@@ -2400,13 +2414,7 @@ time_init_args(rb_execution_context_t *ec, VALUE time, VALUE year, VALUE mon, VA https://github.com/ruby/ruby/blob/trunk/time.c#L2414
 
     if (utc == UTC_ZONE) {
         tobj->timew = timegmw(&vtm);
-        if (vtm.hour == 24) { /* special case: 24:00:00 only */
-            /* Since no need to take care of DST in UTC, just reset
-             * hour and advance date, not to discard the validated
-             * vtm. */
-            vtm.hour = 0;
-            vtm_add_day(&vtm, 1);
-        }
+        vtm_day_wraparound(&vtm);
         tobj->vtm = vtm;
         tobj->tm_got = 1;
         TZMODE_SET_UTC(tobj);
@@ -4105,7 +4113,7 @@ time_inspect(VALUE time) https://github.com/ruby/ruby/blob/trunk/time.c#L4113
     GetTimeval(time, tobj);
     str = strftimev("%Y-%m-%d %H:%M:%S", time, rb_usascii_encoding());
     subsec = w2v(wmod(tobj->timew, WINT2FIXWV(TIME_SCALE)));
-    if (FIXNUM_P(subsec) && FIX2LONG(subsec) == 0) {
+    if (subsec == INT2FIX(0)) {
     }
     else if (FIXNUM_P(subsec) && FIX2LONG(subsec) < TIME_SCALE) {
         long len;
-- 
cgit v1.2.3


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

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