This is an automated email from the ASF dual-hosted git repository.

kou pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/main by this push:
     new 93c4e002c6 GH-49093: [Ruby] Add support for writing duration array 
(#49094)
93c4e002c6 is described below

commit 93c4e002c652d41ac262ed5eab377214a038b2b4
Author: Sutou Kouhei <[email protected]>
AuthorDate: Mon Feb 2 20:36:17 2026 +0900

    GH-49093: [Ruby] Add support for writing duration array (#49094)
    
    ### Rationale for this change
    
    It has unit parameter.
    
    ### What changes are included in this PR?
    
    * Add `ArrowFormat::DurationType#to_flatbuffers`
    * Add duration support to `#values` and `raw_records`
    
    ### Are these changes tested?
    
    Yes.
    
    ### Are there any user-facing changes?
    
    Yes.
    * GitHub Issue: #49093
    
    Authored-by: Sutou Kouhei <[email protected]>
    Signed-off-by: Sutou Kouhei <[email protected]>
---
 ruby/red-arrow-format/lib/arrow-format/type.rb     |  6 +++
 ruby/red-arrow-format/test/test-writer.rb          | 62 ++++++++++++++++++++++
 ruby/red-arrow/ext/arrow/converters.hpp            | 16 ++++--
 ruby/red-arrow/ext/arrow/raw-records.cpp           |  2 +
 ruby/red-arrow/ext/arrow/values.cpp                |  1 +
 .../test/raw-records/test-basic-arrays.rb          | 40 ++++++++++++++
 ruby/red-arrow/test/values/test-basic-arrays.rb    | 40 ++++++++++++++
 7 files changed, 162 insertions(+), 5 deletions(-)

diff --git a/ruby/red-arrow-format/lib/arrow-format/type.rb 
b/ruby/red-arrow-format/lib/arrow-format/type.rb
index 5be6a506d7..c12d2d6e08 100644
--- a/ruby/red-arrow-format/lib/arrow-format/type.rb
+++ b/ruby/red-arrow-format/lib/arrow-format/type.rb
@@ -536,6 +536,12 @@ module ArrowFormat
     def build_array(size, validity_buffer, values_buffer)
       DurationArray.new(self, size, validity_buffer, values_buffer)
     end
+
+    def to_flatbuffers
+      fb_type = FB::Duration::Data.new
+      fb_type.unit = FB::TimeUnit.try_convert(@unit.to_s.upcase)
+      fb_type
+    end
   end
 
   class VariableSizeBinaryType < Type
diff --git a/ruby/red-arrow-format/test/test-writer.rb 
b/ruby/red-arrow-format/test/test-writer.rb
index 17c0b9ede1..c0e4dd4607 100644
--- a/ruby/red-arrow-format/test/test-writer.rb
+++ b/ruby/red-arrow-format/test/test-writer.rb
@@ -67,6 +67,8 @@ module WriterTests
       ArrowFormat::DayTimeIntervalType.singleton
     when Arrow::MonthDayNanoIntervalDataType
       ArrowFormat::MonthDayNanoIntervalType.singleton
+    when Arrow::DurationDataType
+      ArrowFormat::DurationType.new(convert_time_unit(red_arrow_type.unit))
     when Arrow::BinaryDataType
       ArrowFormat::BinaryType.singleton
     when Arrow::LargeBinaryDataType
@@ -622,6 +624,66 @@ module WriterTests
           end
         end
 
+        sub_test_case("Duration(:second)") do
+          def build_array
+            Arrow::DurationArray.new(:second, [0, nil, 100])
+          end
+
+          def test_write
+            assert_equal([0, nil, 100],
+                         @values)
+          end
+
+          def test_type
+            assert_equal(Arrow::TimeUnit::SECOND, @type.unit)
+          end
+        end
+
+        sub_test_case("Duration(:millisecond)") do
+          def build_array
+            Arrow::DurationArray.new(:milli, [0, nil, 100])
+          end
+
+          def test_write
+            assert_equal([0, nil, 100],
+                         @values)
+          end
+
+          def test_type
+            assert_equal(Arrow::TimeUnit::MILLI, @type.unit)
+          end
+        end
+
+        sub_test_case("Duration(:microsecond)") do
+          def build_array
+            Arrow::DurationArray.new(:micro, [0, nil, 100])
+          end
+
+          def test_write
+            assert_equal([0, nil, 100],
+                         @values)
+          end
+
+          def test_type
+            assert_equal(Arrow::TimeUnit::MICRO, @type.unit)
+          end
+        end
+
+        sub_test_case("Duration(:nanosecond)") do
+          def build_array
+            Arrow::DurationArray.new(:nano, [0, nil, 100])
+          end
+
+          def test_write
+            assert_equal([0, nil, 100],
+                         @values)
+          end
+
+          def test_type
+            assert_equal(Arrow::TimeUnit::NANO, @type.unit)
+          end
+        end
+
         sub_test_case("Binary") do
           def build_array
             Arrow::BinaryArray.new(["Hello".b, nil, "World".b])
diff --git a/ruby/red-arrow/ext/arrow/converters.hpp 
b/ruby/red-arrow/ext/arrow/converters.hpp
index 6a1ceb20b8..b4838c8f79 100644
--- a/ruby/red-arrow/ext/arrow/converters.hpp
+++ b/ruby/red-arrow/ext/arrow/converters.hpp
@@ -241,11 +241,6 @@ namespace red_arrow {
       return rb_time_num_new(sec, Qnil);
     }
 
-    // TODO
-    // inline VALUE convert(const arrow::IntervalArray& array,
-    //                      const int64_t i) {
-    // };
-
     inline VALUE convert(const arrow::MonthIntervalArray& array,
                          const int64_t i) {
       return INT2NUM(array.Value(i));
@@ -280,6 +275,11 @@ namespace red_arrow {
       return value;
     }
 
+    inline VALUE convert(const arrow::DurationArray& array,
+                         const int64_t i) {
+      return LL2NUM(array.Value(i));
+    }
+
     VALUE convert(const arrow::ListArray& array,
                   const int64_t i);
 
@@ -382,6 +382,7 @@ namespace red_arrow {
     VISIT(MonthInterval)
     VISIT(DayTimeInterval)
     VISIT(MonthDayNanoInterval)
+    VISIT(Duration)
     VISIT(List)
     VISIT(LargeList)
     VISIT(Struct)
@@ -481,6 +482,7 @@ namespace red_arrow {
     VISIT(MonthInterval)
     VISIT(DayTimeInterval)
     VISIT(MonthDayNanoInterval)
+    VISIT(Duration)
     VISIT(List)
     VISIT(LargeList)
     VISIT(Struct)
@@ -588,6 +590,7 @@ namespace red_arrow {
     VISIT(MonthInterval)
     VISIT(DayTimeInterval)
     VISIT(MonthDayNanoInterval)
+    VISIT(Duration)
     VISIT(List)
     VISIT(LargeList)
     VISIT(Struct)
@@ -691,6 +694,7 @@ namespace red_arrow {
     VISIT(MonthInterval)
     VISIT(DayTimeInterval)
     VISIT(MonthDayNanoInterval)
+    VISIT(Duration)
     VISIT(List)
     VISIT(LargeList)
     VISIT(Struct)
@@ -795,6 +799,7 @@ namespace red_arrow {
     VISIT(MonthInterval)
     VISIT(DayTimeInterval)
     VISIT(MonthDayNanoInterval)
+    VISIT(Duration)
     VISIT(List)
     VISIT(LargeList)
     VISIT(Struct)
@@ -907,6 +912,7 @@ namespace red_arrow {
     VISIT(MonthInterval)
     VISIT(DayTimeInterval)
     VISIT(MonthDayNanoInterval)
+    VISIT(Duration)
     VISIT(List)
     VISIT(LargeList)
     VISIT(Struct)
diff --git a/ruby/red-arrow/ext/arrow/raw-records.cpp 
b/ruby/red-arrow/ext/arrow/raw-records.cpp
index 67f1dab13e..7f643bad41 100644
--- a/ruby/red-arrow/ext/arrow/raw-records.cpp
+++ b/ruby/red-arrow/ext/arrow/raw-records.cpp
@@ -100,6 +100,7 @@ namespace red_arrow {
       VISIT(MonthInterval)
       VISIT(DayTimeInterval)
       VISIT(MonthDayNanoInterval)
+      VISIT(Duration)
       VISIT(List)
       VISIT(Struct)
       VISIT(Map)
@@ -238,6 +239,7 @@ namespace red_arrow {
       VISIT(MonthInterval)
       VISIT(DayTimeInterval)
       VISIT(MonthDayNanoInterval)
+      VISIT(Duration)
       VISIT(List)
       VISIT(Struct)
       VISIT(Map)
diff --git a/ruby/red-arrow/ext/arrow/values.cpp 
b/ruby/red-arrow/ext/arrow/values.cpp
index 9a26baf1d5..0296f27398 100644
--- a/ruby/red-arrow/ext/arrow/values.cpp
+++ b/ruby/red-arrow/ext/arrow/values.cpp
@@ -81,6 +81,7 @@ namespace red_arrow {
       VISIT(MonthInterval)
       VISIT(DayTimeInterval)
       VISIT(MonthDayNanoInterval)
+      VISIT(Duration)
       VISIT(List)
       VISIT(LargeList)
       VISIT(Struct)
diff --git a/ruby/red-arrow/test/raw-records/test-basic-arrays.rb 
b/ruby/red-arrow/test/raw-records/test-basic-arrays.rb
index 1c21a493c5..7a6e6115d6 100644
--- a/ruby/red-arrow/test/raw-records/test-basic-arrays.rb
+++ b/ruby/red-arrow/test/raw-records/test-basic-arrays.rb
@@ -406,6 +406,46 @@ module RawRecordsBasicArraysTests
     target = build({column: :month_day_nano_interval}, records)
     assert_equal(records, actual_records(target))
   end
+
+  def test_duration_second
+    records = [
+      [0],
+      [nil],
+      [100],
+    ]
+    target = build({column: {type: :duration, unit: :second}}, records)
+    assert_equal(records, actual_records(target))
+  end
+
+  def test_duration_milli
+    records = [
+      [0],
+      [nil],
+      [100],
+    ]
+    target = build({column: {type: :duration, unit: :milli}}, records)
+    assert_equal(records, actual_records(target))
+  end
+
+  def test_duration_micro
+    records = [
+      [0],
+      [nil],
+      [100],
+    ]
+    target = build({column: {type: :duration, unit: :micro}}, records)
+    assert_equal(records, actual_records(target))
+  end
+
+  def test_duration_nano
+    records = [
+      [0],
+      [nil],
+      [100],
+    ]
+    target = build({column: {type: :duration, unit: :nano}}, records)
+    assert_equal(records, actual_records(target))
+  end
 end
 
 class EachRawRecordRecordBatchBasicArraysTest < Test::Unit::TestCase
diff --git a/ruby/red-arrow/test/values/test-basic-arrays.rb 
b/ruby/red-arrow/test/values/test-basic-arrays.rb
index ddaaa3db64..b3c8e18172 100644
--- a/ruby/red-arrow/test/values/test-basic-arrays.rb
+++ b/ruby/red-arrow/test/values/test-basic-arrays.rb
@@ -336,6 +336,46 @@ module ValuesBasicArraysTests
     target = build(Arrow::MonthDayNanoIntervalArray.new(values))
     assert_equal(values, target.values)
   end
+
+  def test_duration_second
+    values = [
+      0,
+      nil,
+      100,
+    ]
+    target = build(Arrow::DurationArray.new(:second, values))
+    assert_equal(values, target.values)
+  end
+
+  def test_duration_milli
+    values = [
+      0,
+      nil,
+      100,
+    ]
+    target = build(Arrow::DurationArray.new(:milli, values))
+    assert_equal(values, target.values)
+  end
+
+  def test_duration_micro
+    values = [
+      0,
+      nil,
+      100,
+    ]
+    target = build(Arrow::DurationArray.new(:micro, values))
+    assert_equal(values, target.values)
+  end
+
+  def test_duration_nano
+    values = [
+      0,
+      nil,
+      100,
+    ]
+    target = build(Arrow::DurationArray.new(:nano, values))
+    assert_equal(values, target.values)
+  end
 end
 
 class ValuesArrayBasicArraysTest < Test::Unit::TestCase

Reply via email to