[libgda] Fixed bug #712143



commit c5021e4238b99652ac80a73e95ae442cbf8f9df6
Author: Vivien Malerba <malerba gnome-db org>
Date:   Sat Nov 16 15:03:09 2013 +0100

    Fixed bug #712143

 libgda/gda-value.c |   80 +++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 64 insertions(+), 16 deletions(-)
---
diff --git a/libgda/gda-value.c b/libgda/gda-value.c
index 7ad6e58..80a930d 100644
--- a/libgda/gda-value.c
+++ b/libgda/gda-value.c
@@ -1627,13 +1627,43 @@ gda_value_new_blob_from_file (const gchar *filename)
         return value;
 }
 
+/*
+ * Warning: modifies @gmttm and loctm
+ *
+ * Returns: the offset, or G_MAXLONG in case of error
+ */
+static glong
+compute_tz_offset (struct tm *gmttm, struct tm *loctm)
+{
+       time_t lt, gt;
+       if (! gmttm || !loctm)
+               return G_MAXLONG;
+
+       gmttm->tm_isdst = 0;
+       loctm->tm_isdst = 0;
+
+       lt = mktime (loctm);
+       if (lt == -1)
+               return G_MAXLONG;
+       gt = mktime (gmttm);
+       if (gt == -1)
+               return G_MAXLONG;
+
+       glong off;
+       off = lt - gt;
+       if ((off >= 24 * 3600) || (off <= - 24 * 3600))
+               return G_MAXLONG;
+       else
+               return off;
+}
+
 /**
  * gda_value_new_timestamp_from_timet: (skip)
  * @val: value to set for the new #GValue.
  *
  * Makes a new #GValue of type #GDA_TYPE_TIMESTAMP with value @val
- * (of type time_t). The returned timestamp has a timezone initialized with the
- * current timezone, taking into account the daylight savings.
+ * (of type time_t). The returned timestamp's value is relative to the current
+ * timezone (i.e. is localtime).
  *
  * For example, to get a time stamp representing the current date and time, use:
  *
@@ -1641,30 +1671,46 @@ gda_value_new_blob_from_file (const gchar *filename)
  * ts = gda_value_new_timestamp_from_timet (time (NULL));
  * </code>
  *
- * Returns: (transfer full): the newly created #GValue.
+ * Returns: (transfer full): the newly created #GValue, or %NULL in case of error
  *
  * Free-function: gda_value_free
  */
 GValue *
 gda_value_new_timestamp_from_timet (time_t val)
 {
-       GValue *value;
-
-       struct tm *ltm;
+       GValue *value = NULL;
+       struct tm *ltm = NULL;
+       glong tz = 0;
 
-        value = g_new0 (GValue, 1);
 #ifdef HAVE_LOCALTIME_R
-       struct tm tmpstm;
+       struct tm gmttm, loctm;
        tzset ();
-       ltm = localtime_r ((const time_t *) &val, &tmpstm);
-#elif HAVE_LOCALTIME_S
-       struct tm tmpstm;
-       if (localtime_s (&tmpstm, (const time_t *) &val) == 0)
-               ltm = &tmpstm;
-       else
+       ltm = localtime_r ((const time_t *) &val, &loctm);
+       tz = compute_tz_offset (gmtime_r ((const time_t *) &val, &gmttm), &loctm);
+       if (tz == G_MAXLONG)
                ltm = NULL;
+#elif HAVE_LOCALTIME_S
+       struct tm gmttm, loctm;
+       if ((localtime_s (&loctm, (const time_t *) &val) == 0) &&
+           (gmtime_s (&gmttm, (const time_t *) &val) == 0)) {
+               tz = compute_tz_offset (&gmttm, &loctm);
+               if (tz != G_MAXLONG)
+                       ltm = &loctm;
+       }
 #else
-       ltm = localtime ((const time_t *) &val);
+       struct tm gmttm, loctm;
+       ltm = gmtime ((const time_t *) &val);
+       if (ltm) {
+               gmttm = *ltm;
+               ltm = localtime ((const time_t *) &val);
+               if (ltm) {
+                       loctm = *ltm;
+                       tz = compute_tz_offset (&gmttm, &loctm);
+                       if (tz == G_MAXLONG)
+                               ltm = NULL;
+               }
+       }
+       
 #endif
 
         if (ltm) {
@@ -1676,7 +1722,9 @@ gda_value_new_timestamp_from_timet (time_t val)
                 tstamp.minute = ltm->tm_min;
                 tstamp.second = ltm->tm_sec;
                 tstamp.fraction = 0;
-                tstamp.timezone = - timezone + daylight * 3600;
+                tstamp.timezone = tz;
+
+               value = g_new0 (GValue, 1);
                 gda_value_set_timestamp (value, (const GdaTimestamp *) &tstamp);
         }
 


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