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 ca5cb9238c GH-48363: [GLib][Ruby] Add AssumeTimezoneOptions (#48370)
ca5cb9238c is described below

commit ca5cb9238c0ec5b8235e19cabd7636b41185cbec
Author: Sten Larsson <[email protected]>
AuthorDate: Fri Dec 5 15:36:46 2025 +0100

    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]>
---
 c_glib/arrow-glib/compute.cpp               | 180 ++++++++++++++++++++++++++++
 c_glib/arrow-glib/compute.h                 |  51 ++++++++
 c_glib/arrow-glib/compute.hpp               |   6 +
 c_glib/test/test-assume-timezone-options.rb |  61 ++++++++++
 4 files changed, 298 insertions(+)

diff --git a/c_glib/arrow-glib/compute.cpp b/c_glib/arrow-glib/compute.cpp
index 5f494f3bc7..db5be7a6f1 100644
--- a/c_glib/arrow-glib/compute.cpp
+++ b/c_glib/arrow-glib/compute.cpp
@@ -251,6 +251,9 @@ G_BEGIN_DECLS
  * #GArrowStructFieldOptions is a class to customize the `struct_field`
  * function.
  *
+ * #GArrowAssumeTimezoneOptions is a class to customize the `assume_timezone`
+ * function.
+ *
  * There are many functions to compute data on an array.
  */
 
@@ -6338,6 +6341,156 @@ garrow_struct_field_options_new(void)
   return GARROW_STRUCT_FIELD_OPTIONS(options);
 }
 
+enum {
+  PROP_ASSUME_TIMEZONE_OPTIONS_TIMEZONE = 1,
+  PROP_ASSUME_TIMEZONE_OPTIONS_AMBIGUOUS,
+  PROP_ASSUME_TIMEZONE_OPTIONS_NONEXISTENT,
+};
+
+G_DEFINE_TYPE(GArrowAssumeTimezoneOptions,
+              garrow_assume_timezone_options,
+              GARROW_TYPE_FUNCTION_OPTIONS)
+
+static void
+garrow_assume_timezone_options_set_property(GObject *object,
+                                            guint prop_id,
+                                            const GValue *value,
+                                            GParamSpec *pspec)
+{
+  auto options =
+    
garrow_assume_timezone_options_get_raw(GARROW_ASSUME_TIMEZONE_OPTIONS(object));
+
+  switch (prop_id) {
+  case PROP_ASSUME_TIMEZONE_OPTIONS_TIMEZONE:
+    options->timezone = g_value_get_string(value);
+    break;
+  case PROP_ASSUME_TIMEZONE_OPTIONS_AMBIGUOUS:
+    options->ambiguous = 
static_cast<arrow::compute::AssumeTimezoneOptions::Ambiguous>(
+      g_value_get_enum(value));
+    break;
+  case PROP_ASSUME_TIMEZONE_OPTIONS_NONEXISTENT:
+    options->nonexistent =
+      static_cast<arrow::compute::AssumeTimezoneOptions::Nonexistent>(
+        g_value_get_enum(value));
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+    break;
+  }
+}
+
+static void
+garrow_assume_timezone_options_get_property(GObject *object,
+                                            guint prop_id,
+                                            GValue *value,
+                                            GParamSpec *pspec)
+{
+  auto options =
+    
garrow_assume_timezone_options_get_raw(GARROW_ASSUME_TIMEZONE_OPTIONS(object));
+
+  switch (prop_id) {
+  case PROP_ASSUME_TIMEZONE_OPTIONS_TIMEZONE:
+    g_value_set_string(value, options->timezone.c_str());
+    break;
+  case PROP_ASSUME_TIMEZONE_OPTIONS_AMBIGUOUS:
+    g_value_set_enum(value,
+                     
static_cast<GArrowAssumeTimezoneAmbiguous>(options->ambiguous));
+    break;
+  case PROP_ASSUME_TIMEZONE_OPTIONS_NONEXISTENT:
+    g_value_set_enum(value,
+                     
static_cast<GArrowAssumeTimezoneNonexistent>(options->nonexistent));
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+    break;
+  }
+}
+
+static void
+garrow_assume_timezone_options_init(GArrowAssumeTimezoneOptions *object)
+{
+  auto priv = GARROW_FUNCTION_OPTIONS_GET_PRIVATE(object);
+  priv->options = static_cast<arrow::compute::FunctionOptions *>(
+    new arrow::compute::AssumeTimezoneOptions());
+}
+
+static void
+garrow_assume_timezone_options_class_init(GArrowAssumeTimezoneOptionsClass 
*klass)
+{
+  auto gobject_class = G_OBJECT_CLASS(klass);
+
+  gobject_class->set_property = garrow_assume_timezone_options_set_property;
+  gobject_class->get_property = garrow_assume_timezone_options_get_property;
+
+  arrow::compute::AssumeTimezoneOptions options;
+
+  GParamSpec *spec;
+  /**
+   * GArrowAssumeTimezoneOptions:timezone:
+   *
+   * Timezone to convert timestamps from.
+   *
+   * Since: 23.0.0
+   */
+  spec = g_param_spec_string("timezone",
+                             "Timezone",
+                             "Timezone to convert timestamps from",
+                             options.timezone.c_str(),
+                             static_cast<GParamFlags>(G_PARAM_READWRITE));
+  g_object_class_install_property(gobject_class,
+                                  PROP_ASSUME_TIMEZONE_OPTIONS_TIMEZONE,
+                                  spec);
+
+  /**
+   * GArrowAssumeTimezoneOptions:ambiguous:
+   *
+   * How to interpret ambiguous local times (due to DST shifts).
+   *
+   * Since: 23.0.0
+   */
+  spec = g_param_spec_enum("ambiguous",
+                           "Ambiguous",
+                           "How to interpret ambiguous local times (due to DST 
shifts)",
+                           GARROW_TYPE_ASSUME_TIMEZONE_AMBIGUOUS,
+                           
static_cast<GArrowAssumeTimezoneAmbiguous>(options.ambiguous),
+                           static_cast<GParamFlags>(G_PARAM_READWRITE));
+  g_object_class_install_property(gobject_class,
+                                  PROP_ASSUME_TIMEZONE_OPTIONS_AMBIGUOUS,
+                                  spec);
+
+  /**
+   * GArrowAssumeTimezoneOptions:nonexistent:
+   *
+   * How to interpret nonexistent local times (due to DST shifts).
+   *
+   * Since: 23.0.0
+   */
+  spec =
+    g_param_spec_enum("nonexistent",
+                      "Nonexistent",
+                      "How to interpret nonexistent local times (due to DST 
shifts)",
+                      GARROW_TYPE_ASSUME_TIMEZONE_NONEXISTENT,
+                      
static_cast<GArrowAssumeTimezoneNonexistent>(options.nonexistent),
+                      static_cast<GParamFlags>(G_PARAM_READWRITE));
+  g_object_class_install_property(gobject_class,
+                                  PROP_ASSUME_TIMEZONE_OPTIONS_NONEXISTENT,
+                                  spec);
+}
+
+/**
+ * garrow_assume_timezone_options_new:
+ *
+ * Returns: A newly created #GArrowAssumeTimezoneOptions.
+ *
+ * Since: 23.0.0
+ */
+GArrowAssumeTimezoneOptions *
+garrow_assume_timezone_options_new(void)
+{
+  auto options = g_object_new(GARROW_TYPE_ASSUME_TIMEZONE_OPTIONS, NULL);
+  return GARROW_ASSUME_TIMEZONE_OPTIONS(options);
+}
+
 G_END_DECLS
 
 arrow::Result<arrow::FieldRef>
@@ -6469,6 +6622,11 @@ garrow_function_options_new_raw(const 
arrow::compute::FunctionOptions *arrow_opt
       static_cast<const arrow::compute::StructFieldOptions *>(arrow_options);
     auto options = 
garrow_struct_field_options_new_raw(arrow_struct_field_options);
     return GARROW_FUNCTION_OPTIONS(options);
+  } else if (arrow_type_name == "AssumeTimezoneOptions") {
+    const auto arrow_assume_timezone_options =
+      static_cast<const arrow::compute::AssumeTimezoneOptions 
*>(arrow_options);
+    auto options = 
garrow_assume_timezone_options_new_raw(arrow_assume_timezone_options);
+    return GARROW_FUNCTION_OPTIONS(options);
   } else {
     auto options = g_object_new(GARROW_TYPE_FUNCTION_OPTIONS, NULL);
     return GARROW_FUNCTION_OPTIONS(options);
@@ -6987,3 +7145,25 @@ 
garrow_struct_field_options_get_raw(GArrowStructFieldOptions *options)
   return static_cast<arrow::compute::StructFieldOptions *>(
     garrow_function_options_get_raw(GARROW_FUNCTION_OPTIONS(options)));
 }
+
+GArrowAssumeTimezoneOptions *
+garrow_assume_timezone_options_new_raw(
+  const arrow::compute::AssumeTimezoneOptions *arrow_options)
+{
+  return GARROW_ASSUME_TIMEZONE_OPTIONS(
+    g_object_new(GARROW_TYPE_ASSUME_TIMEZONE_OPTIONS,
+                 "timezone",
+                 arrow_options->timezone.c_str(),
+                 "ambiguous",
+                 
static_cast<GArrowAssumeTimezoneAmbiguous>(arrow_options->ambiguous),
+                 "nonexistent",
+                 
static_cast<GArrowAssumeTimezoneNonexistent>(arrow_options->nonexistent),
+                 NULL));
+}
+
+arrow::compute::AssumeTimezoneOptions *
+garrow_assume_timezone_options_get_raw(GArrowAssumeTimezoneOptions *options)
+{
+  return static_cast<arrow::compute::AssumeTimezoneOptions *>(
+    garrow_function_options_get_raw(GARROW_FUNCTION_OPTIONS(options)));
+}
diff --git a/c_glib/arrow-glib/compute.h b/c_glib/arrow-glib/compute.h
index 0f689d147e..eb3db5eeb3 100644
--- a/c_glib/arrow-glib/compute.h
+++ b/c_glib/arrow-glib/compute.h
@@ -1122,4 +1122,55 @@ GARROW_AVAILABLE_IN_16_0
 GArrowStructFieldOptions *
 garrow_struct_field_options_new(void);
 
+/**
+ * GArrowAssumeTimezoneAmbiguous:
+ * @GARROW_ASSUME_TIMEZONE_AMBIGUOUS_RAISE: Raise an error on ambiguous times.
+ * @GARROW_ASSUME_TIMEZONE_AMBIGUOUS_EARLIEST: Emit the earliest instant.
+ * @GARROW_ASSUME_TIMEZONE_AMBIGUOUS_LATEST: Emit the latest instant.
+ *
+ * They correspond to the values of
+ * `arrow::compute::AssumeTimezoneOptions::Ambiguous`.
+ *
+ * Since: 23.0.0
+ */
+typedef enum {
+  GARROW_ASSUME_TIMEZONE_AMBIGUOUS_RAISE,
+  GARROW_ASSUME_TIMEZONE_AMBIGUOUS_EARLIEST,
+  GARROW_ASSUME_TIMEZONE_AMBIGUOUS_LATEST,
+} GArrowAssumeTimezoneAmbiguous;
+
+/**
+ * GArrowAssumeTimezoneNonexistent:
+ * @GARROW_ASSUME_TIMEZONE_NONEXISTENT_RAISE: Raise an error on nonexistent 
times.
+ * @GARROW_ASSUME_TIMEZONE_NONEXISTENT_EARLIEST: Emit the instant just before 
the DST
+ * shift.
+ * @GARROW_ASSUME_TIMEZONE_NONEXISTENT_LATEST: Emit the DST shift instant.
+ *
+ * They correspond to the values of
+ * `arrow::compute::AssumeTimezoneOptions::Nonexistent`.
+ *
+ * Since: 23.0.0
+ */
+typedef enum {
+  GARROW_ASSUME_TIMEZONE_NONEXISTENT_RAISE,
+  GARROW_ASSUME_TIMEZONE_NONEXISTENT_EARLIEST,
+  GARROW_ASSUME_TIMEZONE_NONEXISTENT_LATEST,
+} GArrowAssumeTimezoneNonexistent;
+
+#define GARROW_TYPE_ASSUME_TIMEZONE_OPTIONS 
(garrow_assume_timezone_options_get_type())
+GARROW_AVAILABLE_IN_23_0
+G_DECLARE_DERIVABLE_TYPE(GArrowAssumeTimezoneOptions,
+                         garrow_assume_timezone_options,
+                         GARROW,
+                         ASSUME_TIMEZONE_OPTIONS,
+                         GArrowFunctionOptions)
+struct _GArrowAssumeTimezoneOptionsClass
+{
+  GArrowFunctionOptionsClass parent_class;
+};
+
+GARROW_AVAILABLE_IN_23_0
+GArrowAssumeTimezoneOptions *
+garrow_assume_timezone_options_new(void);
+
 G_END_DECLS
diff --git a/c_glib/arrow-glib/compute.hpp b/c_glib/arrow-glib/compute.hpp
index 0abf62f7d2..55df617daf 100644
--- a/c_glib/arrow-glib/compute.hpp
+++ b/c_glib/arrow-glib/compute.hpp
@@ -175,3 +175,9 @@ garrow_struct_field_options_new_raw(
   const arrow::compute::StructFieldOptions *arrow_options);
 arrow::compute::StructFieldOptions *
 garrow_struct_field_options_get_raw(GArrowStructFieldOptions *options);
+
+GArrowAssumeTimezoneOptions *
+garrow_assume_timezone_options_new_raw(
+  const arrow::compute::AssumeTimezoneOptions *arrow_options);
+arrow::compute::AssumeTimezoneOptions *
+garrow_assume_timezone_options_get_raw(GArrowAssumeTimezoneOptions *options);
diff --git a/c_glib/test/test-assume-timezone-options.rb 
b/c_glib/test/test-assume-timezone-options.rb
new file mode 100644
index 0000000000..ac2e1b8615
--- /dev/null
+++ b/c_glib/test/test-assume-timezone-options.rb
@@ -0,0 +1,61 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+class TestAssumeTimezoneOptions < Test::Unit::TestCase
+  include Helper::Buildable
+
+  def setup
+    @options = Arrow::AssumeTimezoneOptions.new
+  end
+
+  def test_timezone_property
+    assert_equal("UTC", @options.timezone)
+    @options.timezone = "America/New_York"
+    assert_equal("America/New_York", @options.timezone)
+  end
+
+  def test_ambiguous_property
+    assert_equal(Arrow::AssumeTimezoneAmbiguous::RAISE, @options.ambiguous)
+    @options.ambiguous = :earliest
+    assert_equal(Arrow::AssumeTimezoneAmbiguous::EARLIEST, @options.ambiguous)
+    @options.ambiguous = :latest
+    assert_equal(Arrow::AssumeTimezoneAmbiguous::LATEST, @options.ambiguous)
+  end
+
+  def test_nonexistent_property
+    assert_equal(Arrow::AssumeTimezoneNonexistent::RAISE, @options.nonexistent)
+    @options.nonexistent = :earliest
+    assert_equal(Arrow::AssumeTimezoneNonexistent::EARLIEST, 
@options.nonexistent)
+    @options.nonexistent = :latest
+    assert_equal(Arrow::AssumeTimezoneNonexistent::LATEST, 
@options.nonexistent)
+  end
+
+  def test_assume_timezone_function
+    omit("Missing tzdata on Windows") if Gem.win_platform?
+    args = [
+      Arrow::ArrayDatum.new(build_timestamp_array(:milli, [1504953190000])),
+    ]
+    @options.timezone = "America/New_York"
+    @options.ambiguous = :earliest
+    @options.nonexistent = :earliest
+    assume_timezone_function = Arrow::Function.find("assume_timezone")
+    result = assume_timezone_function.execute(args, @options).value
+    assert_equal(Arrow::TimestampDataType.new(:milli, "America/New_York"),
+                 result.value_data_type)
+  end
+end
+

Reply via email to