[glib: 1/4] gtimezone: Add new constructor which can report errors




commit 8105c36e84ed646805bcd214ac5071092969fc8e
Author: Philip Withnall <pwithnall endlessos org>
Date:   Wed Nov 18 11:31:15 2020 +0000

    gtimezone: Add new constructor which can report errors
    
    Add a new variant of `g_time_zone_new()` which returns `NULL` on
    failure to load a timezone, rather than silently returning UTC.
    
    Signed-off-by: Philip Withnall <pwithnall endlessos org>
    
    Fixes: #553

 docs/reference/glib/glib-sections.txt |  1 +
 glib/gtimezone.c                      | 70 ++++++++++++++++++++++++++---------
 glib/gtimezone.h                      |  3 ++
 glib/tests/gdatetime.c                | 11 ++++++
 4 files changed, 68 insertions(+), 17 deletions(-)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index 68574040d..81a3e0c24 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -1939,6 +1939,7 @@ g_time_zone_unref
 g_time_zone_ref
 <SUBSECTION>
 g_time_zone_new
+g_time_zone_new_identifier
 g_time_zone_new_local
 g_time_zone_new_utc
 g_time_zone_new_offset
diff --git a/glib/gtimezone.c b/glib/gtimezone.c
index 96510138e..3ec5773dd 100644
--- a/glib/gtimezone.c
+++ b/glib/gtimezone.c
@@ -1604,7 +1604,36 @@ parse_footertz (const gchar *footer, size_t footerlen)
  * g_time_zone_new:
  * @identifier: (nullable): a timezone identifier
  *
- * Creates a #GTimeZone corresponding to @identifier.
+ * A version of g_time_zone_new_identifier() which returns the UTC time zone
+ * if @identifier could not be parsed or loaded.
+ *
+ * If you need to check whether @identifier was loaded successfully, use
+ * g_time_zone_new_identifier().
+ *
+ * Returns: (transfer full) (not nullable): the requested timezone
+ *
+ * Since: 2.26
+ **/
+GTimeZone *
+g_time_zone_new (const gchar *identifier)
+{
+  GTimeZone *tz = g_time_zone_new_identifier (identifier);
+
+  /* Always fall back to UTC. */
+  if (tz == NULL)
+    tz = g_time_zone_new_utc ();
+
+  g_assert (tz != NULL);
+
+  return g_steal_pointer (&tz);
+}
+
+/**
+ * g_time_zone_new_identifier:
+ * @identifier: (nullable): a timezone identifier
+ *
+ * Creates a #GTimeZone corresponding to @identifier. If @identifier cannot be
+ * parsed or loaded, %NULL is returned.
  *
  * @identifier can either be an RFC3339/ISO 8601 time offset or
  * something that would pass as a valid value for the `TZ` environment
@@ -1669,12 +1698,12 @@ parse_footertz (const gchar *footer, size_t footerlen)
  * You should release the return value by calling g_time_zone_unref()
  * when you are done with it.
  *
- * Returns: the requested timezone
- *
- * Since: 2.26
- **/
+ * Returns: (transfer full) (nullable): the requested timezone, or %NULL on
+ *     failure
+ * Since: 2.68
+ */
 GTimeZone *
-g_time_zone_new (const gchar *identifier)
+g_time_zone_new_identifier (const gchar *identifier)
 {
   GTimeZone *tz = NULL;
   TimeZoneRule *rules;
@@ -1788,24 +1817,31 @@ g_time_zone_new (const gchar *identifier)
 
   g_free (resolved_identifier);
 
-  /* Always fall back to UTC. */
+  /* Failed to load the timezone. */
   if (tz->t_info == NULL)
-    zone_for_constant_offset (tz, "UTC");
+    {
+      g_slice_free (GTimeZone, tz);
+
+      if (identifier)
+        G_UNLOCK (time_zones);
+      else
+        G_UNLOCK (tz_default);
+
+      return NULL;
+    }
 
   g_assert (tz->name != NULL);
   g_assert (tz->t_info != NULL);
 
-  if (tz->t_info != NULL)
+  if (identifier)
+    g_hash_table_insert (time_zones, tz->name, tz);
+  else if (tz->name)
     {
-      if (identifier)
-        g_hash_table_insert (time_zones, tz->name, tz);
-      else if (tz->name)
-        {
-          /* Caching reference */
-          g_atomic_int_inc (&tz->ref_count);
-          tz_default = tz;
-        }
+      /* Caching reference */
+      g_atomic_int_inc (&tz->ref_count);
+      tz_default = tz;
     }
+
   g_atomic_int_inc (&tz->ref_count);
 
   if (identifier)
diff --git a/glib/gtimezone.h b/glib/gtimezone.h
index 4e8b10a71..5ff382f27 100644
--- a/glib/gtimezone.h
+++ b/glib/gtimezone.h
@@ -24,6 +24,7 @@
 #error "Only <glib.h> can be included directly."
 #endif
 
+#include <glib/gerror.h>
 #include <glib/gtypes.h>
 
 G_BEGIN_DECLS
@@ -54,6 +55,8 @@ typedef enum
 
 GLIB_AVAILABLE_IN_ALL
 GTimeZone *             g_time_zone_new                                 (const gchar *identifier);
+GLIB_AVAILABLE_IN_2_68
+GTimeZone *             g_time_zone_new_identifier                      (const gchar *identifier);
 GLIB_AVAILABLE_IN_ALL
 GTimeZone *             g_time_zone_new_utc                             (void);
 GLIB_AVAILABLE_IN_ALL
diff --git a/glib/tests/gdatetime.c b/glib/tests/gdatetime.c
index 4ea0fc6f4..9b17b00ea 100644
--- a/glib/tests/gdatetime.c
+++ b/glib/tests/gdatetime.c
@@ -2398,6 +2398,16 @@ test_no_header (void)
   g_time_zone_unref (tz);
 }
 
+static void
+test_no_header_identifier (void)
+{
+  GTimeZone *tz;
+
+  tz = g_time_zone_new_identifier ("blabla");
+
+  g_assert_null (tz);
+}
+
 static void
 test_posix_parse (void)
 {
@@ -2893,6 +2903,7 @@ main (gint   argc,
   g_test_add_func ("/GTimeZone/find-interval", test_find_interval);
   g_test_add_func ("/GTimeZone/adjust-time", test_adjust_time);
   g_test_add_func ("/GTimeZone/no-header", test_no_header);
+  g_test_add_func ("/GTimeZone/no-header-identifier", test_no_header_identifier);
   g_test_add_func ("/GTimeZone/posix-parse", test_posix_parse);
   g_test_add_func ("/GTimeZone/floating-point", test_GDateTime_floating_point);
   g_test_add_func ("/GTimeZone/identifier", test_identifier);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]