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 0087bae0b2 GH-51271: [Ruby] Fix Date values in
ArrowFormat::Date32Array (#51272)
0087bae0b2 is described below
commit 0087bae0b2aadc0d08dfdbce4f9c7ca6d6d63bb8
Author: Yifan Chen <[email protected]>
AuthorDate: Thu Sep 10 18:13:10 2026 -0700
GH-51271: [Ruby] Fix Date values in ArrowFormat::Date32Array (#51272)
### Rationale for this change
`ArrowFormat::Date32Array` currently stores `Date#day`, the day of the
month, for Ruby `Date` values. Arrow Date32 values are signed day offsets from
the Unix epoch, so this can silently produce incorrect data. The same
conversion is used by `ArrowFormat::Array.build` when it infers Date32.
### What changes are included in this PR?
* Convert Ruby `Date` values from their Julian day to the Unix epoch day
offset.
* Cover dates before, at, and after the Unix epoch, including nulls.
* Make the ArrayBuilder regression assert the encoded payload instead of
comparing two arrays built through the same conversion path.
### Are these changes tested?
Yes. The full `red-arrow-format` suite passes locally: 691 tests and 695
assertions. The official rake runner used the current pure-Ruby sources with
the locally installed Arrow 25.0.1 native extension; the local system does not
have the Arrow C++ 26 dependency needed to build the native Ruby extension from
`main`.
### Are there any user-facing changes?
Yes. Ruby `Date` values now produce specification-compliant Date32 day
offsets.
**This PR contains a "Critical Fix".** It fixes incorrect Date32 data
produced from Ruby `Date` values.
### AI assistance
AI assistance was used to investigate the defect, draft the focused
implementation and tests, and run the verification described above. No human
review is claimed.
* GitHub Issue: #51271
Authored-by: Yifan Chen <[email protected]>
Signed-off-by: Sutou Kouhei <[email protected]>
---
ruby/red-arrow-format/lib/arrow-format/array.rb | 4 +++-
ruby/red-arrow-format/test/test-date32-array.rb | 12 ++++++++++++
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/ruby/red-arrow-format/lib/arrow-format/array.rb
b/ruby/red-arrow-format/lib/arrow-format/array.rb
index ebf8b1ec68..992abe815b 100644
--- a/ruby/red-arrow-format/lib/arrow-format/array.rb
+++ b/ruby/red-arrow-format/lib/arrow-format/array.rb
@@ -16,6 +16,7 @@
# under the License.
require "bigdecimal"
+require "date"
require_relative "array-builder"
require_relative "bitmap"
@@ -489,11 +490,12 @@ module ArrowFormat
end
private
+ UNIX_EPOCH = Date.new(1970, 1, 1).jd
def pack_value(value, template, type)
if value.nil?
[0].pack(template)
elsif value.is_a?(Date)
- [value.day].pack(template)
+ [value.jd - UNIX_EPOCH].pack(template)
else
[value].pack(template)
end
diff --git a/ruby/red-arrow-format/test/test-date32-array.rb
b/ruby/red-arrow-format/test/test-date32-array.rb
index 331daabd83..2d9a22c4c9 100644
--- a/ruby/red-arrow-format/test/test-date32-array.rb
+++ b/ruby/red-arrow-format/test/test-date32-array.rb
@@ -35,6 +35,18 @@ class TestDate32Array < Test::Unit::TestCase
assert_equal(values,
ArrowFormat::Date32Array.new(values).to_a)
end
+
+ def test_date
+ values = [
+ Date.new(1969, 12, 31),
+ Date.new(1970, 1, 1),
+ nil,
+ Date.new(2025, 12, 9),
+ ]
+ expected = [-1, 0, nil, @date_2025_12_09]
+ assert_equal(expected,
+ ArrowFormat::Date32Array.new(values).to_a)
+ end
end
sub_test_case("#==") do