Skip to content

Commit ca5cb92

Browse files
authored
GH-48363: [GLib][Ruby] Add AssumeTimezoneOptions (#48370)
### Rationale for this change The `AssumeTimezoneOptions` class is not available in GLib/Ruby, and it is used together with the `assume_timezone` compute function. ### What changes are included in this PR? This adds the `GArrowAssumeTimezoneOptions` to GLib. ### Are these changes tested? Yes, with Ruby unit tests. ### Are there any user-facing changes? Yes, a new class. * GitHub Issue: #48363 Authored-by: Sten Larsson <[email protected]> Signed-off-by: Sutou Kouhei <[email protected]>
1 parent c1a8255 commit ca5cb92

File tree

4 files changed

+298
-0
lines changed

4 files changed

+298
-0
lines changed

c_glib/arrow-glib/compute.cpp

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ G_BEGIN_DECLS
251251
* #GArrowStructFieldOptions is a class to customize the `struct_field`
252252
* function.
253253
*
254+
* #GArrowAssumeTimezoneOptions is a class to customize the `assume_timezone`
255+
* function.
256+
*
254257
* There are many functions to compute data on an array.
255258
*/
256259

@@ -6338,6 +6341,156 @@ garrow_struct_field_options_new(void)
63386341
return GARROW_STRUCT_FIELD_OPTIONS(options);
63396342
}
63406343

6344+
enum {
6345+
PROP_ASSUME_TIMEZONE_OPTIONS_TIMEZONE = 1,
6346+
PROP_ASSUME_TIMEZONE_OPTIONS_AMBIGUOUS,
6347+
PROP_ASSUME_TIMEZONE_OPTIONS_NONEXISTENT,
6348+
};
6349+
6350+
G_DEFINE_TYPE(GArrowAssumeTimezoneOptions,
6351+
garrow_assume_timezone_options,
6352+
GARROW_TYPE_FUNCTION_OPTIONS)
6353+
6354+
static void
6355+
garrow_assume_timezone_options_set_property(GObject *object,
6356+
guint prop_id,
6357+
const GValue *value,
6358+
GParamSpec *pspec)
6359+
{
6360+
auto options =
6361+
garrow_assume_timezone_options_get_raw(GARROW_ASSUME_TIMEZONE_OPTIONS(object));
6362+
6363+
switch (prop_id) {
6364+
case PROP_ASSUME_TIMEZONE_OPTIONS_TIMEZONE:
6365+
options->timezone = g_value_get_string(value);
6366+
break;
6367+
case PROP_ASSUME_TIMEZONE_OPTIONS_AMBIGUOUS:
6368+
options->ambiguous = static_cast<arrow::compute::AssumeTimezoneOptions::Ambiguous>(
6369+
g_value_get_enum(value));
6370+
break;
6371+
case PROP_ASSUME_TIMEZONE_OPTIONS_NONEXISTENT:
6372+
options->nonexistent =
6373+
static_cast<arrow::compute::AssumeTimezoneOptions::Nonexistent>(
6374+
g_value_get_enum(value));
6375+
break;
6376+
default:
6377+
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
6378+
break;
6379+
}
6380+
}
6381+
6382+
static void
6383+
garrow_assume_timezone_options_get_property(GObject *object,
6384+
guint prop_id,
6385+
GValue *value,
6386+
GParamSpec *pspec)
6387+
{
6388+
auto options =
6389+
garrow_assume_timezone_options_get_raw(GARROW_ASSUME_TIMEZONE_OPTIONS(object));
6390+
6391+
switch (prop_id) {
6392+
case PROP_ASSUME_TIMEZONE_OPTIONS_TIMEZONE:
6393+
g_value_set_string(value, options->timezone.c_str());
6394+
break;
6395+
case PROP_ASSUME_TIMEZONE_OPTIONS_AMBIGUOUS:
6396+
g_value_set_enum(value,
6397+
static_cast<GArrowAssumeTimezoneAmbiguous>(options->ambiguous));
6398+
break;
6399+
case PROP_ASSUME_TIMEZONE_OPTIONS_NONEXISTENT:
6400+
g_value_set_enum(value,
6401+
static_cast<GArrowAssumeTimezoneNonexistent>(options->nonexistent));
6402+
break;
6403+
default:
6404+
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
6405+
break;
6406+
}
6407+
}
6408+
6409+
static void
6410+
garrow_assume_timezone_options_init(GArrowAssumeTimezoneOptions *object)
6411+
{
6412+
auto priv = GARROW_FUNCTION_OPTIONS_GET_PRIVATE(object);
6413+
priv->options = static_cast<arrow::compute::FunctionOptions *>(
6414+
new arrow::compute::AssumeTimezoneOptions());
6415+
}
6416+
6417+
static void
6418+
garrow_assume_timezone_options_class_init(GArrowAssumeTimezoneOptionsClass *klass)
6419+
{
6420+
auto gobject_class = G_OBJECT_CLASS(klass);
6421+
6422+
gobject_class->set_property = garrow_assume_timezone_options_set_property;
6423+
gobject_class->get_property = garrow_assume_timezone_options_get_property;
6424+
6425+
arrow::compute::AssumeTimezoneOptions options;
6426+
6427+
GParamSpec *spec;
6428+
/**
6429+
* GArrowAssumeTimezoneOptions:timezone:
6430+
*
6431+
* Timezone to convert timestamps from.
6432+
*
6433+
* Since: 23.0.0
6434+
*/
6435+
spec = g_param_spec_string("timezone",
6436+
"Timezone",
6437+
"Timezone to convert timestamps from",
6438+
options.timezone.c_str(),
6439+
static_cast<GParamFlags>(G_PARAM_READWRITE));
6440+
g_object_class_install_property(gobject_class,
6441+
PROP_ASSUME_TIMEZONE_OPTIONS_TIMEZONE,
6442+
spec);
6443+
6444+
/**
6445+
* GArrowAssumeTimezoneOptions:ambiguous:
6446+
*
6447+
* How to interpret ambiguous local times (due to DST shifts).
6448+
*
6449+
* Since: 23.0.0
6450+
*/
6451+
spec = g_param_spec_enum("ambiguous",
6452+
"Ambiguous",
6453+
"How to interpret ambiguous local times (due to DST shifts)",
6454+
GARROW_TYPE_ASSUME_TIMEZONE_AMBIGUOUS,
6455+
static_cast<GArrowAssumeTimezoneAmbiguous>(options.ambiguous),
6456+
static_cast<GParamFlags>(G_PARAM_READWRITE));
6457+
g_object_class_install_property(gobject_class,
6458+
PROP_ASSUME_TIMEZONE_OPTIONS_AMBIGUOUS,
6459+
spec);
6460+
6461+
/**
6462+
* GArrowAssumeTimezoneOptions:nonexistent:
6463+
*
6464+
* How to interpret nonexistent local times (due to DST shifts).
6465+
*
6466+
* Since: 23.0.0
6467+
*/
6468+
spec =
6469+
g_param_spec_enum("nonexistent",
6470+
"Nonexistent",
6471+
"How to interpret nonexistent local times (due to DST shifts)",
6472+
GARROW_TYPE_ASSUME_TIMEZONE_NONEXISTENT,
6473+
static_cast<GArrowAssumeTimezoneNonexistent>(options.nonexistent),
6474+
static_cast<GParamFlags>(G_PARAM_READWRITE));
6475+
g_object_class_install_property(gobject_class,
6476+
PROP_ASSUME_TIMEZONE_OPTIONS_NONEXISTENT,
6477+
spec);
6478+
}
6479+
6480+
/**
6481+
* garrow_assume_timezone_options_new:
6482+
*
6483+
* Returns: A newly created #GArrowAssumeTimezoneOptions.
6484+
*
6485+
* Since: 23.0.0
6486+
*/
6487+
GArrowAssumeTimezoneOptions *
6488+
garrow_assume_timezone_options_new(void)
6489+
{
6490+
auto options = g_object_new(GARROW_TYPE_ASSUME_TIMEZONE_OPTIONS, NULL);
6491+
return GARROW_ASSUME_TIMEZONE_OPTIONS(options);
6492+
}
6493+
63416494
G_END_DECLS
63426495

63436496
arrow::Result<arrow::FieldRef>
@@ -6469,6 +6622,11 @@ garrow_function_options_new_raw(const arrow::compute::FunctionOptions *arrow_opt
64696622
static_cast<const arrow::compute::StructFieldOptions *>(arrow_options);
64706623
auto options = garrow_struct_field_options_new_raw(arrow_struct_field_options);
64716624
return GARROW_FUNCTION_OPTIONS(options);
6625+
} else if (arrow_type_name == "AssumeTimezoneOptions") {
6626+
const auto arrow_assume_timezone_options =
6627+
static_cast<const arrow::compute::AssumeTimezoneOptions *>(arrow_options);
6628+
auto options = garrow_assume_timezone_options_new_raw(arrow_assume_timezone_options);
6629+
return GARROW_FUNCTION_OPTIONS(options);
64726630
} else {
64736631
auto options = g_object_new(GARROW_TYPE_FUNCTION_OPTIONS, NULL);
64746632
return GARROW_FUNCTION_OPTIONS(options);
@@ -6987,3 +7145,25 @@ garrow_struct_field_options_get_raw(GArrowStructFieldOptions *options)
69877145
return static_cast<arrow::compute::StructFieldOptions *>(
69887146
garrow_function_options_get_raw(GARROW_FUNCTION_OPTIONS(options)));
69897147
}
7148+
7149+
GArrowAssumeTimezoneOptions *
7150+
garrow_assume_timezone_options_new_raw(
7151+
const arrow::compute::AssumeTimezoneOptions *arrow_options)
7152+
{
7153+
return GARROW_ASSUME_TIMEZONE_OPTIONS(
7154+
g_object_new(GARROW_TYPE_ASSUME_TIMEZONE_OPTIONS,
7155+
"timezone",
7156+
arrow_options->timezone.c_str(),
7157+
"ambiguous",
7158+
static_cast<GArrowAssumeTimezoneAmbiguous>(arrow_options->ambiguous),
7159+
"nonexistent",
7160+
static_cast<GArrowAssumeTimezoneNonexistent>(arrow_options->nonexistent),
7161+
NULL));
7162+
}
7163+
7164+
arrow::compute::AssumeTimezoneOptions *
7165+
garrow_assume_timezone_options_get_raw(GArrowAssumeTimezoneOptions *options)
7166+
{
7167+
return static_cast<arrow::compute::AssumeTimezoneOptions *>(
7168+
garrow_function_options_get_raw(GARROW_FUNCTION_OPTIONS(options)));
7169+
}

c_glib/arrow-glib/compute.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,4 +1122,55 @@ GARROW_AVAILABLE_IN_16_0
11221122
GArrowStructFieldOptions *
11231123
garrow_struct_field_options_new(void);
11241124

1125+
/**
1126+
* GArrowAssumeTimezoneAmbiguous:
1127+
* @GARROW_ASSUME_TIMEZONE_AMBIGUOUS_RAISE: Raise an error on ambiguous times.
1128+
* @GARROW_ASSUME_TIMEZONE_AMBIGUOUS_EARLIEST: Emit the earliest instant.
1129+
* @GARROW_ASSUME_TIMEZONE_AMBIGUOUS_LATEST: Emit the latest instant.
1130+
*
1131+
* They correspond to the values of
1132+
* `arrow::compute::AssumeTimezoneOptions::Ambiguous`.
1133+
*
1134+
* Since: 23.0.0
1135+
*/
1136+
typedef enum {
1137+
GARROW_ASSUME_TIMEZONE_AMBIGUOUS_RAISE,
1138+
GARROW_ASSUME_TIMEZONE_AMBIGUOUS_EARLIEST,
1139+
GARROW_ASSUME_TIMEZONE_AMBIGUOUS_LATEST,
1140+
} GArrowAssumeTimezoneAmbiguous;
1141+
1142+
/**
1143+
* GArrowAssumeTimezoneNonexistent:
1144+
* @GARROW_ASSUME_TIMEZONE_NONEXISTENT_RAISE: Raise an error on nonexistent times.
1145+
* @GARROW_ASSUME_TIMEZONE_NONEXISTENT_EARLIEST: Emit the instant just before the DST
1146+
* shift.
1147+
* @GARROW_ASSUME_TIMEZONE_NONEXISTENT_LATEST: Emit the DST shift instant.
1148+
*
1149+
* They correspond to the values of
1150+
* `arrow::compute::AssumeTimezoneOptions::Nonexistent`.
1151+
*
1152+
* Since: 23.0.0
1153+
*/
1154+
typedef enum {
1155+
GARROW_ASSUME_TIMEZONE_NONEXISTENT_RAISE,
1156+
GARROW_ASSUME_TIMEZONE_NONEXISTENT_EARLIEST,
1157+
GARROW_ASSUME_TIMEZONE_NONEXISTENT_LATEST,
1158+
} GArrowAssumeTimezoneNonexistent;
1159+
1160+
#define GARROW_TYPE_ASSUME_TIMEZONE_OPTIONS (garrow_assume_timezone_options_get_type())
1161+
GARROW_AVAILABLE_IN_23_0
1162+
G_DECLARE_DERIVABLE_TYPE(GArrowAssumeTimezoneOptions,
1163+
garrow_assume_timezone_options,
1164+
GARROW,
1165+
ASSUME_TIMEZONE_OPTIONS,
1166+
GArrowFunctionOptions)
1167+
struct _GArrowAssumeTimezoneOptionsClass
1168+
{
1169+
GArrowFunctionOptionsClass parent_class;
1170+
};
1171+
1172+
GARROW_AVAILABLE_IN_23_0
1173+
GArrowAssumeTimezoneOptions *
1174+
garrow_assume_timezone_options_new(void);
1175+
11251176
G_END_DECLS

c_glib/arrow-glib/compute.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,9 @@ garrow_struct_field_options_new_raw(
175175
const arrow::compute::StructFieldOptions *arrow_options);
176176
arrow::compute::StructFieldOptions *
177177
garrow_struct_field_options_get_raw(GArrowStructFieldOptions *options);
178+
179+
GArrowAssumeTimezoneOptions *
180+
garrow_assume_timezone_options_new_raw(
181+
const arrow::compute::AssumeTimezoneOptions *arrow_options);
182+
arrow::compute::AssumeTimezoneOptions *
183+
garrow_assume_timezone_options_get_raw(GArrowAssumeTimezoneOptions *options);
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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 TestAssumeTimezoneOptions < Test::Unit::TestCase
19+
include Helper::Buildable
20+
21+
def setup
22+
@options = Arrow::AssumeTimezoneOptions.new
23+
end
24+
25+
def test_timezone_property
26+
assert_equal("UTC", @options.timezone)
27+
@options.timezone = "America/New_York"
28+
assert_equal("America/New_York", @options.timezone)
29+
end
30+
31+
def test_ambiguous_property
32+
assert_equal(Arrow::AssumeTimezoneAmbiguous::RAISE, @options.ambiguous)
33+
@options.ambiguous = :earliest
34+
assert_equal(Arrow::AssumeTimezoneAmbiguous::EARLIEST, @options.ambiguous)
35+
@options.ambiguous = :latest
36+
assert_equal(Arrow::AssumeTimezoneAmbiguous::LATEST, @options.ambiguous)
37+
end
38+
39+
def test_nonexistent_property
40+
assert_equal(Arrow::AssumeTimezoneNonexistent::RAISE, @options.nonexistent)
41+
@options.nonexistent = :earliest
42+
assert_equal(Arrow::AssumeTimezoneNonexistent::EARLIEST, @options.nonexistent)
43+
@options.nonexistent = :latest
44+
assert_equal(Arrow::AssumeTimezoneNonexistent::LATEST, @options.nonexistent)
45+
end
46+
47+
def test_assume_timezone_function
48+
omit("Missing tzdata on Windows") if Gem.win_platform?
49+
args = [
50+
Arrow::ArrayDatum.new(build_timestamp_array(:milli, [1504953190000])),
51+
]
52+
@options.timezone = "America/New_York"
53+
@options.ambiguous = :earliest
54+
@options.nonexistent = :earliest
55+
assume_timezone_function = Arrow::Function.find("assume_timezone")
56+
result = assume_timezone_function.execute(args, @options).value
57+
assert_equal(Arrow::TimestampDataType.new(:milli, "America/New_York"),
58+
result.value_data_type)
59+
end
60+
end
61+

0 commit comments

Comments
 (0)