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 c33ffb033a GH-39702: [GLib] Add support for time zone in 
GArrowTimestampDataType (#39717)
c33ffb033a is described below

commit c33ffb033a49c17619f2547d873569980ee91b9c
Author: Sutou Kouhei <[email protected]>
AuthorDate: Mon Jan 22 11:19:09 2024 +0900

    GH-39702: [GLib] Add support for time zone in GArrowTimestampDataType 
(#39717)
    
    ### Rationale for this change
    
    Timestamp data type in Apache Arrow supports time zone but Apache Arrow C 
GLib didn't support it. Timestamp data type has "timezone-aware" mode and 
"timezone-naive" mode. If a timestamp data type has a valid time zone 
information, it uses "timezone-aware" mode. If a timestamp data type doesn't 
have a valid time zone information, it uses "timezone-naive" mode. Apache Arrow 
C GLib should support both of them.
    
    ### What changes are included in this PR?
    
    This change adds a new `GTimeZone *time_zone` argument to 
`garrow_timestamp_data_type_new()` instead of adding a new 
`garrow_timestamp_data_type_new_time_zone()` function. This breaks backward 
compatibility for Apache Arrow C GLib users. But this still keeps backward 
compatibility for users of bindings such as Ruby and Vala. Because the new 
`GTimeZone *time_zone` is nullable.
    
    I tried to use the "adding a new
    `garrow_timestamp_data_type_new_time_zone()` function" approach but Vala 
didn't like it. Both of
    `garrow_timestamp_data_type_new_time_zone()` (constructor) and 
`garrow_timestamp_data_type_get_time_zone()` (instance method or property 
reader) were mapped to
    `GArrow.TimestampDataType.time_zone()`.
    
    So I chose the "adding a new argument to
    `garrow_timestamp_data_type_new()`" approach.
    
    ### Are these changes tested?
    
    Yes.
    
    ### Are there any user-facing changes?
    
    Yes.
    
    **This PR includes breaking changes to public APIs.**
    
    * Closes: #39702
    
    Authored-by: Sutou Kouhei <[email protected]>
    Signed-off-by: Sutou Kouhei <[email protected]>
---
 c_glib/arrow-glib/basic-data-type.cpp     | 109 +++++++++++++++++++++++++++---
 c_glib/arrow-glib/basic-data-type.h       |   6 +-
 c_glib/arrow-glib/version.h.in            |  23 +++++++
 c_glib/doc/arrow-glib/arrow-glib-docs.xml |   4 ++
 c_glib/test/test-timestamp-data-type.rb   |  17 +++++
 5 files changed, 147 insertions(+), 12 deletions(-)

diff --git a/c_glib/arrow-glib/basic-data-type.cpp 
b/c_glib/arrow-glib/basic-data-type.cpp
index 0697646e58..0de9466eee 100644
--- a/c_glib/arrow-glib/basic-data-type.cpp
+++ b/c_glib/arrow-glib/basic-data-type.cpp
@@ -125,9 +125,9 @@ G_BEGIN_DECLS
  * data types.
  */
 
-typedef struct GArrowDataTypePrivate_ {
+struct GArrowDataTypePrivate {
   std::shared_ptr<arrow::DataType> data_type;
-} GArrowDataTypePrivate;
+};
 
 enum {
   PROP_DATA_TYPE = 1
@@ -1113,9 +1113,71 @@ garrow_date64_data_type_new(void)
 }
 
 
-G_DEFINE_TYPE(GArrowTimestampDataType,
-              garrow_timestamp_data_type,
-              GARROW_TYPE_TEMPORAL_DATA_TYPE)
+struct GArrowTimestampDataTypePrivate {
+  GTimeZone *time_zone;
+};
+
+enum {
+  PROP_TIME_ZONE = 1
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE(GArrowTimestampDataType,
+                           garrow_timestamp_data_type,
+                           GARROW_TYPE_TEMPORAL_DATA_TYPE)
+
+#define GARROW_TIMESTAMP_DATA_TYPE_GET_PRIVATE(object)  \
+  static_cast<GArrowTimestampDataTypePrivate *>(        \
+    garrow_timestamp_data_type_get_instance_private(    \
+      GARROW_TIMESTAMP_DATA_TYPE(object)))
+
+static void
+garrow_timestamp_data_type_dispose(GObject *object)
+{
+  auto priv = GARROW_TIMESTAMP_DATA_TYPE_GET_PRIVATE(object);
+
+  if (priv->time_zone) {
+    g_time_zone_unref(priv->time_zone);
+    priv->time_zone = nullptr;
+  }
+
+  G_OBJECT_CLASS(garrow_timestamp_data_type_parent_class)->dispose(object);
+}
+
+static void
+garrow_timestamp_data_type_set_property(GObject *object,
+                                        guint prop_id,
+                                        const GValue *value,
+                                        GParamSpec *pspec)
+{
+  auto priv = GARROW_TIMESTAMP_DATA_TYPE_GET_PRIVATE(object);
+
+  switch (prop_id) {
+  case PROP_TIME_ZONE:
+    priv->time_zone = static_cast<GTimeZone *>(g_value_dup_boxed(value));
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+    break;
+  }
+}
+
+static void
+garrow_timestamp_data_type_get_property(GObject *object,
+                                        guint prop_id,
+                                        GValue *value,
+                                        GParamSpec *pspec)
+{
+  auto priv = GARROW_TIMESTAMP_DATA_TYPE_GET_PRIVATE(object);
+
+  switch (prop_id) {
+  case PROP_TIME_ZONE:
+    g_value_set_boxed(value, priv->time_zone);
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+    break;
+  }
+}
 
 static void
 garrow_timestamp_data_type_init(GArrowTimestampDataType *object)
@@ -1125,11 +1187,32 @@ garrow_timestamp_data_type_init(GArrowTimestampDataType 
*object)
 static void
 garrow_timestamp_data_type_class_init(GArrowTimestampDataTypeClass *klass)
 {
+  auto gobject_class = G_OBJECT_CLASS(klass);
+  gobject_class->dispose      = garrow_timestamp_data_type_dispose;
+  gobject_class->set_property = garrow_timestamp_data_type_set_property;
+  gobject_class->get_property = garrow_timestamp_data_type_get_property;
+
+  GParamSpec *spec;
+  /**
+   * GArrowTimestampDataType:time-zone:
+   *
+   * The time zone of this data type.
+   *
+   * Since: 16.0.0
+   */
+  spec = g_param_spec_boxed("time-zone",
+                            "Time zone",
+                            "The time zone of this data type",
+                            G_TYPE_TIME_ZONE,
+                            static_cast<GParamFlags>(G_PARAM_READWRITE |
+                                                     G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property(gobject_class, PROP_TIME_ZONE, spec);
 }
 
 /**
  * garrow_timestamp_data_type_new:
  * @unit: The unit of the timestamp data.
+ * @time_zone: (nullable): The time zone of the timestamp data.
  *
  * Returns: A newly created the number of
  *   seconds/milliseconds/microseconds/nanoseconds since UNIX epoch in
@@ -1138,30 +1221,36 @@ 
garrow_timestamp_data_type_class_init(GArrowTimestampDataTypeClass *klass)
  * Since: 0.7.0
  */
 GArrowTimestampDataType *
-garrow_timestamp_data_type_new(GArrowTimeUnit unit)
+garrow_timestamp_data_type_new(GArrowTimeUnit unit,
+                               GTimeZone *time_zone)
 {
   auto arrow_unit = garrow_time_unit_to_raw(unit);
-  auto arrow_data_type = arrow::timestamp(arrow_unit);
+  std::string arrow_timezone;
+  if (time_zone) {
+    arrow_timezone = g_time_zone_get_identifier(time_zone);
+  }
+  auto arrow_data_type = arrow::timestamp(arrow_unit, arrow_timezone);
   auto data_type =
     GARROW_TIMESTAMP_DATA_TYPE(g_object_new(GARROW_TYPE_TIMESTAMP_DATA_TYPE,
                                             "data-type", &arrow_data_type,
+                                            "time-zone", time_zone,
                                             NULL));
   return data_type;
 }
 
 /**
  * garrow_timestamp_data_type_get_unit:
- * @timestamp_data_type: The #GArrowTimestampDataType.
+ * @data_type: The #GArrowTimestampDataType.
  *
  * Returns: The unit of the timestamp data type.
  *
  * Since: 0.8.0
  */
 GArrowTimeUnit
-garrow_timestamp_data_type_get_unit(GArrowTimestampDataType 
*timestamp_data_type)
+garrow_timestamp_data_type_get_unit(GArrowTimestampDataType *data_type)
 {
   const auto arrow_data_type =
-    garrow_data_type_get_raw(GARROW_DATA_TYPE(timestamp_data_type));
+    garrow_data_type_get_raw(GARROW_DATA_TYPE(data_type));
   const auto arrow_timestamp_data_type =
     std::static_pointer_cast<arrow::TimestampType>(arrow_data_type);
   return garrow_time_unit_from_raw(arrow_timestamp_data_type->unit());
diff --git a/c_glib/arrow-glib/basic-data-type.h 
b/c_glib/arrow-glib/basic-data-type.h
index affbfcf13c..f1c5af409c 100644
--- a/c_glib/arrow-glib/basic-data-type.h
+++ b/c_glib/arrow-glib/basic-data-type.h
@@ -425,9 +425,11 @@ struct _GArrowTimestampDataTypeClass
   GArrowTemporalDataTypeClass parent_class;
 };
 
-GArrowTimestampDataType *garrow_timestamp_data_type_new   (GArrowTimeUnit 
unit);
+GArrowTimestampDataType *
+garrow_timestamp_data_type_new(GArrowTimeUnit unit,
+                               GTimeZone *time_zone);
 GArrowTimeUnit
-garrow_timestamp_data_type_get_unit (GArrowTimestampDataType 
*timestamp_data_type);
+garrow_timestamp_data_type_get_unit(GArrowTimestampDataType *data_type);
 
 
 #define GARROW_TYPE_TIME_DATA_TYPE (garrow_time_data_type_get_type())
diff --git a/c_glib/arrow-glib/version.h.in b/c_glib/arrow-glib/version.h.in
index abb8ba0870..01760fbfed 100644
--- a/c_glib/arrow-glib/version.h.in
+++ b/c_glib/arrow-glib/version.h.in
@@ -110,6 +110,15 @@
 #  define GARROW_UNAVAILABLE(major, minor) G_UNAVAILABLE(major, minor)
 #endif
 
+/**
+ * GARROW_VERSION_16_0:
+ *
+ * You can use this macro value for compile time API version check.
+ *
+ * Since: 16.0.0
+ */
+#define GARROW_VERSION_16_0 G_ENCODE_VERSION(16, 0)
+
 /**
  * GARROW_VERSION_15_0:
  *
@@ -355,6 +364,20 @@
 
 #define GARROW_AVAILABLE_IN_ALL
 
+#if GARROW_VERSION_MIN_REQUIRED >= GARROW_VERSION_16_0
+#  define GARROW_DEPRECATED_IN_16_0                GARROW_DEPRECATED
+#  define GARROW_DEPRECATED_IN_16_0_FOR(function)  
GARROW_DEPRECATED_FOR(function)
+#else
+#  define GARROW_DEPRECATED_IN_16_0
+#  define GARROW_DEPRECATED_IN_16_0_FOR(function)
+#endif
+
+#if GARROW_VERSION_MAX_ALLOWED < GARROW_VERSION_16_0
+#  define GARROW_AVAILABLE_IN_16_0 GARROW_UNAVAILABLE(16, 0)
+#else
+#  define GARROW_AVAILABLE_IN_16_0
+#endif
+
 #if GARROW_VERSION_MIN_REQUIRED >= GARROW_VERSION_15_0
 #  define GARROW_DEPRECATED_IN_15_0                GARROW_DEPRECATED
 #  define GARROW_DEPRECATED_IN_15_0_FOR(function)  
GARROW_DEPRECATED_FOR(function)
diff --git a/c_glib/doc/arrow-glib/arrow-glib-docs.xml 
b/c_glib/doc/arrow-glib/arrow-glib-docs.xml
index 57b4b98701..e92eb95567 100644
--- a/c_glib/doc/arrow-glib/arrow-glib-docs.xml
+++ b/c_glib/doc/arrow-glib/arrow-glib-docs.xml
@@ -193,6 +193,10 @@
     <title>Index of deprecated API</title>
     <xi:include href="xml/api-index-deprecated.xml"><xi:fallback 
/></xi:include>
   </index>
+  <index id="api-index-16-0-0" role="16.0.0">
+    <title>Index of new symbols in 16.0.0</title>
+    <xi:include href="xml/api-index-16.0.0.xml"><xi:fallback /></xi:include>
+  </index>
   <index id="api-index-13-0-0" role="13.0.0">
     <title>Index of new symbols in 13.0.0</title>
     <xi:include href="xml/api-index-13.0.0.xml"><xi:fallback /></xi:include>
diff --git a/c_glib/test/test-timestamp-data-type.rb 
b/c_glib/test/test-timestamp-data-type.rb
index dac3a9bc63..69437609fe 100644
--- a/c_glib/test/test-timestamp-data-type.rb
+++ b/c_glib/test/test-timestamp-data-type.rb
@@ -26,6 +26,23 @@ class TestTimestampDataType < Test::Unit::TestCase
     assert_equal("timestamp", data_type.name)
   end
 
+  sub_test_case("time_zone") do
+    def test_nil
+      data_type = Arrow::TimestampDataType.new(:micro)
+      assert_nil(data_type.time_zone)
+    end
+
+    def test_time_zone
+      data_type = Arrow::TimestampDataType.new(:micro, 
GLib::TimeZone.new("UTC"))
+      time_zone = data_type.time_zone
+      assert_not_nil(time_zone)
+      # glib2 gem 4.2.1 or later is required
+      if time_zone.respond_to?(:identifier)
+        assert_equal("UTC", time_zone.identifier)
+      end
+    end
+  end
+
   sub_test_case("second") do
     def setup
       @data_type = Arrow::TimestampDataType.new(:second)

Reply via email to