Skip to content

Commit 6166ef5

Browse files
authored
GH-50435: [Ruby] Add ArrowFormat::Time{32,64}.new(unit, values) (#50443)
### Rationale for this change Building a time{32,64} Arrow array from Ruby objects is convenient. ### What changes are included in this PR? Accept `ArrowFormat::Time{32,64}.new(unit, values)`. ### Are these changes tested? Yes. ### Are there any user-facing changes? Yes. * GitHub Issue: #50435 Authored-by: Sutou Kouhei <kou@clear-code.com> Signed-off-by: Sutou Kouhei <kou@clear-code.com>
1 parent 085493b commit 6166ef5

4 files changed

Lines changed: 174 additions & 0 deletions

File tree

ruby/red-arrow-format/lib/arrow-format/array.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ def initialize(*args)
192192
expected_n_args = "1 or 3"
193193
else
194194
type = args.shift
195+
unless type.is_a?(Type)
196+
type = self.class.type_class.try_convert(type) || type
197+
end
195198
expected_n_args = "2 or 4"
196199
end
197200
args = build_data(args[0], type) if args.size == 1
@@ -461,12 +464,27 @@ class TimeArray < TemporalArray
461464
end
462465

463466
class Time32Array < TimeArray
467+
class << self
468+
def type_class
469+
Time32Type
470+
end
471+
end
464472
end
465473

466474
class Time64Array < TimeArray
475+
class << self
476+
def type_class
477+
Time64Type
478+
end
479+
end
467480
end
468481

469482
class TimestampArray < TemporalArray
483+
class << self
484+
def type_class
485+
TimestampType
486+
end
487+
end
470488
end
471489

472490
class IntervalArray < TemporalArray

ruby/red-arrow-format/lib/arrow-format/type.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,20 @@ def to_flatbuffers
476476
end
477477

478478
class Time32Type < TimeType
479+
class << self
480+
def try_convert(value)
481+
case value
482+
when Symbol
483+
unit = value
484+
new(unit)
485+
when self
486+
value
487+
else
488+
nil
489+
end
490+
end
491+
end
492+
479493
def initialize(unit)
480494
super(32, unit)
481495
end
@@ -488,12 +502,30 @@ def buffer_type
488502
:s32
489503
end
490504

505+
def pack_template
506+
"l"
507+
end
508+
491509
def build_array(...)
492510
Time32Array.new(self, ...)
493511
end
494512
end
495513

496514
class Time64Type < TimeType
515+
class << self
516+
def try_convert(value)
517+
case value
518+
when Symbol
519+
unit = value
520+
new(unit)
521+
when self
522+
value
523+
else
524+
nil
525+
end
526+
end
527+
end
528+
497529
def initialize(unit)
498530
super(64, unit)
499531
end
@@ -506,6 +538,10 @@ def buffer_type
506538
:s64
507539
end
508540

541+
def pack_template
542+
"q"
543+
end
544+
509545
def build_array(...)
510546
Time64Array.new(self, ...)
511547
end
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
class TestTime32Array < Test::Unit::TestCase
19+
def setup
20+
@time_00_00_10 = 10
21+
@time_00_01_10 = 60 + 10
22+
end
23+
24+
sub_test_case("#initialize") do
25+
def test_no_null
26+
values = [@time_00_00_10, @time_00_01_10]
27+
assert_equal(values,
28+
ArrowFormat::Time32Array.new(:second, values).to_a)
29+
end
30+
31+
def test_mixed
32+
values = [@time_00_00_10, nil, @time_00_01_10]
33+
assert_equal(values,
34+
ArrowFormat::Time32Array.new(:second, values).to_a)
35+
end
36+
end
37+
38+
sub_test_case("#==") do
39+
def test_no_slice
40+
values = [@time_00_00_10, nil, @time_00_01_10]
41+
array1 = ArrowFormat::Time32Array.new(:second, values)
42+
array2 = ArrowFormat::Time32Array.new(:second, values)
43+
assert_equal(array1, array2)
44+
end
45+
46+
def test_sliced
47+
values = [@time_00_00_10, nil, @time_00_01_10]
48+
array1 = ArrowFormat::Time32Array.new(:second, values)
49+
array2 = ArrowFormat::Time32Array.new(:second, [0, *values, 0])
50+
assert_equal(array1, array2.slice(1, 3))
51+
end
52+
53+
def test_sliced_different_content
54+
values = [@time_00_00_10, nil, @time_00_01_10]
55+
array1 = ArrowFormat::Time32Array.new(:second, values)
56+
array2 = ArrowFormat::Time32Array.new(:second, [0, 0, *values, 0])
57+
assert_not_equal(array1, array2.slice(1, 3))
58+
end
59+
end
60+
end
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
class TestTime64Array < Test::Unit::TestCase
19+
def setup
20+
@time_00_00_10_000_000 = 10 * 1_000_000
21+
@time_00_01_10_000_000 = (60 + 10) * 1_000_000
22+
end
23+
24+
sub_test_case("#initialize") do
25+
def test_no_null
26+
values = [@time_00_00_10_000_000, @time_00_01_10_000_000]
27+
assert_equal(values,
28+
ArrowFormat::Time64Array.new(:microsecond, values).to_a)
29+
end
30+
31+
def test_mixed
32+
values = [@time_00_00_10_000_000, nil, @time_00_01_10_000_000]
33+
assert_equal(values,
34+
ArrowFormat::Time64Array.new(:microsecond, values).to_a)
35+
end
36+
end
37+
38+
sub_test_case("#==") do
39+
def test_no_slice
40+
values = [@time_00_00_10_000_000, nil, @time_00_01_10_000_000]
41+
array1 = ArrowFormat::Time64Array.new(:microsecond, values)
42+
array2 = ArrowFormat::Time64Array.new(:microsecond, values)
43+
assert_equal(array1, array2)
44+
end
45+
46+
def test_sliced
47+
values = [@time_00_00_10_000_000, nil, @time_00_01_10_000_000]
48+
array1 = ArrowFormat::Time64Array.new(:microsecond, values)
49+
array2 = ArrowFormat::Time64Array.new(:microsecond, [0, *values, 0])
50+
assert_equal(array1, array2.slice(1, 3))
51+
end
52+
53+
def test_sliced_different_content
54+
values = [@time_00_00_10_000_000, nil, @time_00_01_10_000_000]
55+
array1 = ArrowFormat::Time64Array.new(:microsecond, values)
56+
array2 = ArrowFormat::Time64Array.new(:microsecond, [0, 0, *values, 0])
57+
assert_not_equal(array1, array2.slice(1, 3))
58+
end
59+
end
60+
end

0 commit comments

Comments
 (0)