Skip to content

Commit 3946f88

Browse files
authored
GH-48503: [GLib][Ruby] Add RoundTemporalOptions (#48524)
### Rationale for this change The `RoundTemporalOptions` class is not available in GLib/Ruby, and it is used together with the `round_temporal` compute function. ### What changes are included in this PR? This adds the `RoundTemporalOptions` class to GLib. ### Are these changes tested? Yes, with Ruby unit tests. ### Are there any user-facing changes? Yes, a new class. * GitHub Issue: #48503 Authored-by: Sten Larsson <sten@burtcorp.com> Signed-off-by: Sutou Kouhei <kou@clear-code.com>
1 parent 8ef5ad3 commit 3946f88

File tree

4 files changed

+355
-0
lines changed

4 files changed

+355
-0
lines changed

c_glib/arrow-glib/compute.cpp

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,9 @@ G_BEGIN_DECLS
315315
* #GArrowRoundBinaryOptions is a class to customize the
316316
* `round_binary` function.
317317
*
318+
* #GArrowRoundTemporalOptions is a class to customize the `round_temporal`,
319+
* `floor_temporal`, and `ceil_temporal` functions.
320+
*
318321
* There are many functions to compute data on an array.
319322
*/
320323

@@ -9158,6 +9161,203 @@ garrow_round_binary_options_new(void)
91589161
g_object_new(GARROW_TYPE_ROUND_BINARY_OPTIONS, nullptr));
91599162
}
91609163

9164+
enum {
9165+
PROP_ROUND_TEMPORAL_OPTIONS_MULTIPLE = 1,
9166+
PROP_ROUND_TEMPORAL_OPTIONS_UNIT,
9167+
PROP_ROUND_TEMPORAL_OPTIONS_WEEK_STARTS_MONDAY,
9168+
PROP_ROUND_TEMPORAL_OPTIONS_CEIL_IS_STRICTLY_GREATER,
9169+
PROP_ROUND_TEMPORAL_OPTIONS_CALENDAR_BASED_ORIGIN,
9170+
};
9171+
9172+
G_DEFINE_TYPE(GArrowRoundTemporalOptions,
9173+
garrow_round_temporal_options,
9174+
GARROW_TYPE_FUNCTION_OPTIONS)
9175+
9176+
static void
9177+
garrow_round_temporal_options_set_property(GObject *object,
9178+
guint prop_id,
9179+
const GValue *value,
9180+
GParamSpec *pspec)
9181+
{
9182+
auto options =
9183+
garrow_round_temporal_options_get_raw(GARROW_ROUND_TEMPORAL_OPTIONS(object));
9184+
9185+
switch (prop_id) {
9186+
case PROP_ROUND_TEMPORAL_OPTIONS_MULTIPLE:
9187+
options->multiple = g_value_get_int(value);
9188+
break;
9189+
case PROP_ROUND_TEMPORAL_OPTIONS_UNIT:
9190+
options->unit = static_cast<arrow::compute::CalendarUnit>(g_value_get_enum(value));
9191+
break;
9192+
case PROP_ROUND_TEMPORAL_OPTIONS_WEEK_STARTS_MONDAY:
9193+
options->week_starts_monday = g_value_get_boolean(value);
9194+
break;
9195+
case PROP_ROUND_TEMPORAL_OPTIONS_CEIL_IS_STRICTLY_GREATER:
9196+
options->ceil_is_strictly_greater = g_value_get_boolean(value);
9197+
break;
9198+
case PROP_ROUND_TEMPORAL_OPTIONS_CALENDAR_BASED_ORIGIN:
9199+
options->calendar_based_origin = g_value_get_boolean(value);
9200+
break;
9201+
default:
9202+
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
9203+
break;
9204+
}
9205+
}
9206+
9207+
static void
9208+
garrow_round_temporal_options_get_property(GObject *object,
9209+
guint prop_id,
9210+
GValue *value,
9211+
GParamSpec *pspec)
9212+
{
9213+
auto options =
9214+
garrow_round_temporal_options_get_raw(GARROW_ROUND_TEMPORAL_OPTIONS(object));
9215+
9216+
switch (prop_id) {
9217+
case PROP_ROUND_TEMPORAL_OPTIONS_MULTIPLE:
9218+
g_value_set_int(value, options->multiple);
9219+
break;
9220+
case PROP_ROUND_TEMPORAL_OPTIONS_UNIT:
9221+
g_value_set_enum(value, static_cast<GArrowCalendarUnit>(options->unit));
9222+
break;
9223+
case PROP_ROUND_TEMPORAL_OPTIONS_WEEK_STARTS_MONDAY:
9224+
g_value_set_boolean(value, options->week_starts_monday);
9225+
break;
9226+
case PROP_ROUND_TEMPORAL_OPTIONS_CEIL_IS_STRICTLY_GREATER:
9227+
g_value_set_boolean(value, options->ceil_is_strictly_greater);
9228+
break;
9229+
case PROP_ROUND_TEMPORAL_OPTIONS_CALENDAR_BASED_ORIGIN:
9230+
g_value_set_boolean(value, options->calendar_based_origin);
9231+
break;
9232+
default:
9233+
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
9234+
break;
9235+
}
9236+
}
9237+
9238+
static void
9239+
garrow_round_temporal_options_init(GArrowRoundTemporalOptions *object)
9240+
{
9241+
auto arrow_priv = GARROW_FUNCTION_OPTIONS_GET_PRIVATE(object);
9242+
arrow_priv->options = static_cast<arrow::compute::FunctionOptions *>(
9243+
new arrow::compute::RoundTemporalOptions());
9244+
}
9245+
9246+
static void
9247+
garrow_round_temporal_options_class_init(GArrowRoundTemporalOptionsClass *klass)
9248+
{
9249+
auto gobject_class = G_OBJECT_CLASS(klass);
9250+
9251+
gobject_class->set_property = garrow_round_temporal_options_set_property;
9252+
gobject_class->get_property = garrow_round_temporal_options_get_property;
9253+
9254+
arrow::compute::RoundTemporalOptions options;
9255+
9256+
GParamSpec *spec;
9257+
/**
9258+
* GArrowRoundTemporalOptions:multiple:
9259+
*
9260+
* Number of units to round to.
9261+
*
9262+
* Since: 23.0.0
9263+
*/
9264+
spec = g_param_spec_int("multiple",
9265+
"Multiple",
9266+
"Number of units to round to",
9267+
G_MININT,
9268+
G_MAXINT,
9269+
options.multiple,
9270+
static_cast<GParamFlags>(G_PARAM_READWRITE));
9271+
g_object_class_install_property(gobject_class,
9272+
PROP_ROUND_TEMPORAL_OPTIONS_MULTIPLE,
9273+
spec);
9274+
9275+
/**
9276+
* GArrowRoundTemporalOptions:unit:
9277+
*
9278+
* The unit used for rounding of time.
9279+
*
9280+
* Since: 23.0.0
9281+
*/
9282+
spec = g_param_spec_enum("unit",
9283+
"Unit",
9284+
"The unit used for rounding of time",
9285+
GARROW_TYPE_CALENDAR_UNIT,
9286+
static_cast<GArrowCalendarUnit>(options.unit),
9287+
static_cast<GParamFlags>(G_PARAM_READWRITE));
9288+
g_object_class_install_property(gobject_class, PROP_ROUND_TEMPORAL_OPTIONS_UNIT, spec);
9289+
9290+
/**
9291+
* GArrowRoundTemporalOptions:week-starts-monday:
9292+
*
9293+
* What day does the week start with (Monday=true, Sunday=false).
9294+
*
9295+
* Since: 23.0.0
9296+
*/
9297+
spec =
9298+
g_param_spec_boolean("week-starts-monday",
9299+
"Week Starts Monday",
9300+
"What day does the week start with (Monday=true, Sunday=false)",
9301+
options.week_starts_monday,
9302+
static_cast<GParamFlags>(G_PARAM_READWRITE));
9303+
g_object_class_install_property(gobject_class,
9304+
PROP_ROUND_TEMPORAL_OPTIONS_WEEK_STARTS_MONDAY,
9305+
spec);
9306+
9307+
/**
9308+
* GArrowRoundTemporalOptions:ceil-is-strictly-greater:
9309+
*
9310+
* Enable this flag to return a rounded value that is strictly greater than the input.
9311+
* This applies for ceiling only.
9312+
*
9313+
* Since: 23.0.0
9314+
*/
9315+
spec = g_param_spec_boolean(
9316+
"ceil-is-strictly-greater",
9317+
"Ceil Is Strictly Greater",
9318+
"Enable this flag to return a rounded value that is strictly greater than the input",
9319+
options.ceil_is_strictly_greater,
9320+
static_cast<GParamFlags>(G_PARAM_READWRITE));
9321+
g_object_class_install_property(gobject_class,
9322+
PROP_ROUND_TEMPORAL_OPTIONS_CEIL_IS_STRICTLY_GREATER,
9323+
spec);
9324+
9325+
/**
9326+
* GArrowRoundTemporalOptions:calendar-based-origin:
9327+
*
9328+
* By default time is rounded to a multiple of units since 1970-01-01T00:00:00.
9329+
* By setting calendar_based_origin to true, time will be rounded to a number
9330+
* of units since the last greater calendar unit.
9331+
*
9332+
* Since: 23.0.0
9333+
*/
9334+
spec = g_param_spec_boolean(
9335+
"calendar-based-origin",
9336+
"Calendar Based Origin",
9337+
"By default time is rounded to a multiple of units since 1970-01-01T00:00:00. By "
9338+
"setting calendar_based_origin to true, time will be rounded to a number of units "
9339+
"since the last greater calendar unit",
9340+
options.calendar_based_origin,
9341+
static_cast<GParamFlags>(G_PARAM_READWRITE));
9342+
g_object_class_install_property(gobject_class,
9343+
PROP_ROUND_TEMPORAL_OPTIONS_CALENDAR_BASED_ORIGIN,
9344+
spec);
9345+
}
9346+
9347+
/**
9348+
* garrow_round_temporal_options_new:
9349+
*
9350+
* Returns: A newly created #GArrowRoundTemporalOptions.
9351+
*
9352+
* Since: 23.0.0
9353+
*/
9354+
GArrowRoundTemporalOptions *
9355+
garrow_round_temporal_options_new(void)
9356+
{
9357+
return GARROW_ROUND_TEMPORAL_OPTIONS(
9358+
g_object_new(GARROW_TYPE_ROUND_TEMPORAL_OPTIONS, nullptr));
9359+
}
9360+
91619361
G_END_DECLS
91629362

91639363
arrow::Result<arrow::FieldRef>
@@ -9393,6 +9593,11 @@ garrow_function_options_new_raw(const arrow::compute::FunctionOptions *arrow_opt
93939593
static_cast<const arrow::compute::RoundBinaryOptions *>(arrow_options);
93949594
auto options = garrow_round_binary_options_new_raw(arrow_round_binary_options);
93959595
return GARROW_FUNCTION_OPTIONS(options);
9596+
} else if (arrow_type_name == "RoundTemporalOptions") {
9597+
const auto arrow_round_temporal_options =
9598+
static_cast<const arrow::compute::RoundTemporalOptions *>(arrow_options);
9599+
auto options = garrow_round_temporal_options_new_raw(arrow_round_temporal_options);
9600+
return GARROW_FUNCTION_OPTIONS(options);
93969601
} else {
93979602
auto options = g_object_new(GARROW_TYPE_FUNCTION_OPTIONS, NULL);
93989603
return GARROW_FUNCTION_OPTIONS(options);
@@ -10343,3 +10548,29 @@ garrow_round_binary_options_get_raw(GArrowRoundBinaryOptions *options)
1034310548
return static_cast<arrow::compute::RoundBinaryOptions *>(
1034410549
garrow_function_options_get_raw(GARROW_FUNCTION_OPTIONS(options)));
1034510550
}
10551+
10552+
GArrowRoundTemporalOptions *
10553+
garrow_round_temporal_options_new_raw(
10554+
const arrow::compute::RoundTemporalOptions *arrow_options)
10555+
{
10556+
return GARROW_ROUND_TEMPORAL_OPTIONS(
10557+
g_object_new(GARROW_TYPE_ROUND_TEMPORAL_OPTIONS,
10558+
"multiple",
10559+
arrow_options->multiple,
10560+
"unit",
10561+
static_cast<GArrowCalendarUnit>(arrow_options->unit),
10562+
"week-starts-monday",
10563+
arrow_options->week_starts_monday,
10564+
"ceil-is-strictly-greater",
10565+
arrow_options->ceil_is_strictly_greater,
10566+
"calendar-based-origin",
10567+
arrow_options->calendar_based_origin,
10568+
nullptr));
10569+
}
10570+
10571+
arrow::compute::RoundTemporalOptions *
10572+
garrow_round_temporal_options_get_raw(GArrowRoundTemporalOptions *options)
10573+
{
10574+
return static_cast<arrow::compute::RoundTemporalOptions *>(
10575+
garrow_function_options_get_raw(GARROW_FUNCTION_OPTIONS(options)));
10576+
}

c_glib/arrow-glib/compute.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,4 +1599,54 @@ GARROW_AVAILABLE_IN_23_0
15991599
GArrowRoundBinaryOptions *
16001600
garrow_round_binary_options_new(void);
16011601

1602+
/**
1603+
* GArrowCalendarUnit:
1604+
* @GARROW_CALENDAR_UNIT_NANOSECOND: Nanosecond
1605+
* @GARROW_CALENDAR_UNIT_MICROSECOND: Microsecond
1606+
* @GARROW_CALENDAR_UNIT_MILLISECOND: Millisecond
1607+
* @GARROW_CALENDAR_UNIT_SECOND: Second
1608+
* @GARROW_CALENDAR_UNIT_MINUTE: Minute
1609+
* @GARROW_CALENDAR_UNIT_HOUR: Hour
1610+
* @GARROW_CALENDAR_UNIT_DAY: Day
1611+
* @GARROW_CALENDAR_UNIT_WEEK: Week
1612+
* @GARROW_CALENDAR_UNIT_MONTH: Month
1613+
* @GARROW_CALENDAR_UNIT_QUARTER: Quarter
1614+
* @GARROW_CALENDAR_UNIT_YEAR: Year
1615+
*
1616+
* They correspond to the values of `arrow::compute::CalendarUnit`.
1617+
*
1618+
* Since: 23.0.0
1619+
*/
1620+
typedef enum {
1621+
GARROW_CALENDAR_UNIT_NANOSECOND,
1622+
GARROW_CALENDAR_UNIT_MICROSECOND,
1623+
GARROW_CALENDAR_UNIT_MILLISECOND,
1624+
GARROW_CALENDAR_UNIT_SECOND,
1625+
GARROW_CALENDAR_UNIT_MINUTE,
1626+
GARROW_CALENDAR_UNIT_HOUR,
1627+
GARROW_CALENDAR_UNIT_DAY,
1628+
GARROW_CALENDAR_UNIT_WEEK,
1629+
GARROW_CALENDAR_UNIT_MONTH,
1630+
GARROW_CALENDAR_UNIT_QUARTER,
1631+
GARROW_CALENDAR_UNIT_YEAR,
1632+
} GArrowCalendarUnit;
1633+
1634+
#define GARROW_TYPE_CALENDAR_UNIT (garrow_calendar_unit_get_type())
1635+
1636+
#define GARROW_TYPE_ROUND_TEMPORAL_OPTIONS (garrow_round_temporal_options_get_type())
1637+
GARROW_AVAILABLE_IN_23_0
1638+
G_DECLARE_DERIVABLE_TYPE(GArrowRoundTemporalOptions,
1639+
garrow_round_temporal_options,
1640+
GARROW,
1641+
ROUND_TEMPORAL_OPTIONS,
1642+
GArrowFunctionOptions)
1643+
struct _GArrowRoundTemporalOptionsClass
1644+
{
1645+
GArrowFunctionOptionsClass parent_class;
1646+
};
1647+
1648+
GARROW_AVAILABLE_IN_23_0
1649+
GArrowRoundTemporalOptions *
1650+
garrow_round_temporal_options_new(void);
1651+
16021652
G_END_DECLS

c_glib/arrow-glib/compute.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,3 +292,9 @@ garrow_round_binary_options_new_raw(
292292
const arrow::compute::RoundBinaryOptions *arrow_options);
293293
arrow::compute::RoundBinaryOptions *
294294
garrow_round_binary_options_get_raw(GArrowRoundBinaryOptions *options);
295+
296+
GArrowRoundTemporalOptions *
297+
garrow_round_temporal_options_new_raw(
298+
const arrow::compute::RoundTemporalOptions *arrow_options);
299+
arrow::compute::RoundTemporalOptions *
300+
garrow_round_temporal_options_get_raw(GArrowRoundTemporalOptions *options);
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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 TestRoundTemporalOptions < Test::Unit::TestCase
19+
include Helper::Buildable
20+
21+
def setup
22+
@options = Arrow::RoundTemporalOptions.new
23+
end
24+
25+
def test_multiple
26+
assert_equal(1, @options.multiple)
27+
@options.multiple = 3
28+
assert_equal(3, @options.multiple)
29+
end
30+
31+
def test_unit
32+
assert_equal(Arrow::CalendarUnit::DAY, @options.unit)
33+
@options.unit = :hour
34+
assert_equal(Arrow::CalendarUnit::HOUR, @options.unit)
35+
end
36+
37+
def test_week_starts_monday
38+
assert_equal(true, @options.week_starts_monday?)
39+
@options.week_starts_monday = false
40+
assert_equal(false, @options.week_starts_monday?)
41+
end
42+
43+
def test_ceil_is_strictly_greater
44+
assert_equal(false, @options.ceil_is_strictly_greater?)
45+
@options.ceil_is_strictly_greater = true
46+
assert_equal(true, @options.ceil_is_strictly_greater?)
47+
end
48+
49+
def test_calendar_based_origin
50+
assert_equal(false, @options.calendar_based_origin?)
51+
@options.calendar_based_origin = true
52+
assert_equal(true, @options.calendar_based_origin?)
53+
end
54+
55+
def test_round_temporal_function
56+
# 1504953190000 = 2017-09-09 10:33:10 UTC
57+
args = [
58+
Arrow::ArrayDatum.new(build_timestamp_array(:milli, [1504953190000])),
59+
]
60+
@options.multiple = 5
61+
@options.unit = :minute
62+
round_temporal_function = Arrow::Function.find("round_temporal")
63+
result = round_temporal_function.execute(args, @options).value
64+
# 1504953300000 = 2017-09-09 10:35:00 UTC
65+
expected = build_timestamp_array(:milli, [1504953300000])
66+
assert_equal(expected, result)
67+
end
68+
end

0 commit comments

Comments
 (0)