[glib/wip/date-time-fixes] tests are passing once more



commit 2d7f50c533cbd726bf87335609cbd915d4c2d848
Author: Ryan Lortie <desrt desrt ca>
Date:   Fri Sep 17 00:59:27 2010 -0400

    tests are passing once more

 glib/gdatetime.c       | 1455 ++++++++++++++++++++----------------------------
 glib/gdatetime.h       |  239 +++++----
 glib/glib.symbols      |   27 +-
 glib/gtimezone.c       |   47 +-
 glib/gtimezone.h       |   18 +-
 glib/tests/gdatetime.c |  285 +++-------
 6 files changed, 877 insertions(+), 1194 deletions(-)
---
diff --git a/glib/gdatetime.c b/glib/gdatetime.c
index 1fa9776..29896bf 100644
--- a/glib/gdatetime.c
+++ b/glib/gdatetime.c
@@ -104,9 +104,28 @@
  * #GDateTime is available since GLib 2.26.
  */
 
+struct _GDateTime
+{
+  /* 1 is 0001-01-01 in Proleptic Gregorian */
+  gint32 days;
+
+  /* Microsecond timekeeping within Day */
+  guint64 usec;
+
+  /* TimeZone information */
+  GTimeZone *tz;
+  gint interval;
+
+  volatile gint ref_count;
+};
+
 /* Time conversion {{{1 */
 
 #define UNIX_EPOCH_START     719163
+#define INSTANT_TO_UNIX(instant) \
+  ((instant)/USEC_PER_SECOND - UNIX_EPOCH_START * SEC_PER_DAY)
+#define UNIX_TO_INSTANT(unix) \
+  (((unix) + UNIX_EPOCH_START * SEC_PER_DAY) * USEC_PER_SECOND)
 
 #define DAYS_IN_4YEARS    1461    /* days in 4 years */
 #define DAYS_IN_100YEARS  36524   /* days in 100 years */
@@ -151,21 +170,6 @@
 #define SECS_PER_YEAR   (365 * SECS_PER_DAY)
 #define SECS_PER_JULIAN (DAYS_PER_PERIOD * SECS_PER_DAY)
 
-struct _GDateTime
-{
-  /* 1 is 0001-01-01 in Proleptic Gregorian */
-  gint32 days;
-
-  /* Microsecond timekeeping within Day */
-  guint64 usec;
-
-  /* TimeZone information */
-  GTimeZone *tz;
-  gint interval;
-
-  volatile gint ref_count;
-};
-
 static const guint16 days_in_months[2][13] =
 {
   { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
@@ -307,9 +311,9 @@ get_weekday_name_abbr (gint day)
 }
 
 static inline gint
-date_to_proleptic_gregorian (gint year,
-                             gint month,
-                             gint day)
+ymd_to_days (gint year,
+             gint month,
+             gint day)
 {
   gint64 days;
 
@@ -360,6 +364,7 @@ g_date_time_deal_with_date_change (GDateTime *datetime)
 
   full_time = datetime->days * USEC_PER_DAY + datetime->usec;
 
+
   usec = full_time % USEC_PER_SECOND;
   full_time /= USEC_PER_SECOND;
   full_time -= UNIX_EPOCH_START * SEC_PER_DAY;
@@ -379,261 +384,374 @@ g_date_time_deal_with_date_change (GDateTime *datetime)
   return TRUE;
 }
 
-/*< internal >
- * g_date_time_add_usec:
+/* Lifecycle {{{1 */
+
+static GDateTime *
+g_date_time_alloc (GTimeZone *tz)
+{
+  GDateTime *datetime;
+
+  datetime = g_slice_new0 (GDateTime);
+  datetime->tz = g_time_zone_ref (tz);
+  datetime->ref_count = 1;
+
+  return datetime;
+}
+
+/**
+ * g_date_time_ref:
  * @datetime: a #GDateTime
- * @usec: number of microseconds to add
  *
- * This function is the only function that should be used to adjust a
- * #GDateTime by adding a particular timespan (as measured in hours,
- * minutes, seconds, microseconds).
+ * Atomically increments the reference count of @datetime by one.
  *
- * We avoid incontinuities in the local time zone by first converting to
- * UTC, adding the proper amount of time and converting back.
+ * Return value: the #GDateTime with the reference count increased
  *
- * Finally, we ensure that the resulting date falls between 0001-01-01
- * and 9999-12-31, returning %FALSE if it does not.
+ * Since: 2.26
  */
-static gboolean
-g_date_time_add_usec (GDateTime *datetime,
-                      gint64     usec)
+GDateTime *
+g_date_time_ref (GDateTime *datetime)
 {
-  gint64 full_time;
-
-  /* This is enough to drive any valid time out of the valid region.
-   * We check for it here to avoid wrapping the full_time below.
-   */
-  if (ABS (usec) > 1000000000000000000)
-   return FALSE;
-
-  full_time = datetime->days * USEC_PER_DAY + datetime->usec;
-  full_time += usec;
-
-  usec = full_time % USEC_PER_SECOND;
-  full_time /= USEC_PER_SECOND;
-  full_time -= UNIX_EPOCH_START * SEC_PER_DAY;
-
-  full_time -= g_time_zone_get_offset (datetime->tz, datetime->interval);
-  datetime->interval = g_time_zone_find_interval (datetime->tz,
-                                                  G_TIME_TYPE_UNIVERSAL,
-                                                  full_time);
-  full_time += g_time_zone_get_offset (datetime->tz, datetime->interval);
-
-  full_time += UNIX_EPOCH_START * SEC_PER_DAY;
-  full_time *= USEC_PER_SECOND;
-  full_time += usec;
+  g_return_val_if_fail (datetime != NULL, NULL);
+  g_return_val_if_fail (datetime->ref_count > 0, NULL);
 
-  datetime->days = full_time / USEC_PER_DAY;
-  datetime->usec = full_time % USEC_PER_DAY;
+  g_atomic_int_inc (&datetime->ref_count);
 
-  return 1 <= datetime->days || datetime->days <= 3652059;
+  return datetime;
 }
 
-/*< internal >
- * g_date_time_change_zone:
+/**
+ * g_date_time_unref:
  * @datetime: a #GDateTime
- * @new_tz: the new #GTimeZone
  *
- * This function is the only function that should be used to change the
- * timezone of a #GDateTime.
+ * Atomically decrements the reference count of @datetime by one.
  *
- * First, we convert the time to UTC using the old time zone.  Then we
- * install the new timezone and convert ourselves into it.
+ * When the reference count reaches zero, the resources allocated by
+ * @datetime are freed
  *
- * Finally, we ensure that the resulting date falls between 0001-01-01
- * and 9999-12-31, returning %FALSE if it does not.
+ * Since: 2.26
  */
-static gboolean
-g_date_time_change_zone (GDateTime *datetime,
-                         GTimeZone *new_tz)
+void
+g_date_time_unref (GDateTime *datetime)
 {
-  if (datetime->tz != new_tz)
-    {
-      gint64 full_time;
-      gint64 usec;
-
-      full_time = datetime->days * USEC_PER_DAY + datetime->usec;
-
-      usec = full_time % USEC_PER_SECOND;
-      full_time /= USEC_PER_SECOND;
-      full_time -= UNIX_EPOCH_START * SEC_PER_DAY;
+  g_return_if_fail (datetime != NULL);
+  g_return_if_fail (datetime->ref_count > 0);
 
-      full_time -= g_time_zone_get_offset (datetime->tz, datetime->interval);
+  if (g_atomic_int_dec_and_test (&datetime->ref_count))
+    {
       g_time_zone_unref (datetime->tz);
-      datetime->tz = g_time_zone_ref (new_tz);
-      datetime->interval = g_time_zone_find_interval (datetime->tz,
-                                                      G_TIME_TYPE_UNIVERSAL,
-                                                      full_time);
-      full_time += g_time_zone_get_offset (datetime->tz, datetime->interval);
+      g_slice_free (GDateTime, datetime);
+    }
+}
 
-      full_time += UNIX_EPOCH_START * SEC_PER_DAY;
-      full_time *= USEC_PER_SECOND;
-      full_time += usec;
+/* Constructors {{{1 */
 
-      datetime->days = full_time / USEC_PER_DAY;
-      datetime->usec = full_time % USEC_PER_DAY;
+/*< internal >
+ * g_date_time_to_instant:
+ * @datetime: a #GDateTime
+ *
+ * Convert a @datetime into an instant.
+ *
+ * An instant is a number that uniquely describes a particular
+ * microsecond in time, taking timezone considerations into account.
+ * (ie: "03:00 -0400" is the same instant as "02:00 -0500").
+ *
+ * An instant is always positive but we use a signed return value to
+ * avoid troubles with C.
+ */
+static gint64
+g_date_time_to_instant (GDateTime *datetime)
+{
+  gint64 offset;
 
-      return 1 <= datetime->days || datetime->days <= 3652059;
-    }
+  offset = g_time_zone_get_offset (datetime->tz, datetime->interval);
+  offset *= USEC_PER_SECOND;
 
-  return TRUE;
+  return datetime->days * USEC_PER_DAY + datetime->usec - offset;
 }
 
 /*< internal >
- * g_date_time_add_ymd:
- * @datetime: a #GDateTime
- * @years: years to add, in the Gregorian calendar
- * @months: months to add, in the Gregorian calendar
- * @days: days to add, in the Gregorian calendar
+ * g_date_time_from_instant:
+ * @tz: a #GTimeZone
+ * @instant: a instant in time
  *
- * Updates @datetime by adding @years, @months and @days to it
+ * Creates a #GDateTime from a timezone and an instant.
  *
- * This function modifies the passed #GDateTime so public accessors
- * should make always pass a copy
+ * This might fail if the time ends up being out of range.
  */
-static gboolean
-g_date_time_add_ymd (GDateTime *datetime,
-                     gint       years,
-                     gint       months,
-                     gint       days)
+static GDateTime *
+g_date_time_from_instant (GTimeZone *tz,
+                          gint64     instant)
 {
-  gint y = g_date_time_get_year (datetime);
-  gint m = g_date_time_get_month (datetime);
-  gint d = g_date_time_get_day_of_month (datetime);
-  gint step, i;
-  const guint16 *max_days;
+  GDateTime *datetime;
+  gint64 offset;
+
+  if (instant < 0 || instant > 1000000000000000000)
+    return NULL;
+
+  datetime = g_date_time_alloc (tz);
+  datetime->interval = g_time_zone_find_interval (tz,
+                                                  G_TIME_TYPE_UNIVERSAL,
+                                                  INSTANT_TO_UNIX (instant));
+  offset = g_time_zone_get_offset (datetime->tz, datetime->interval);
+  offset *= USEC_PER_SECOND;
+
+  instant += offset;
 
-  y += years;
+  datetime->days = instant / USEC_PER_DAY;
+  datetime->usec = instant % USEC_PER_DAY;
 
-  /* subtract one day for leap years */
-  if (GREGORIAN_LEAP (y) && m == 2)
+  if (datetime->days < 1 || 3652059 < datetime->days)
     {
-      if (d == 29)
-        d -= 1;
+      g_date_time_unref (datetime);
+      datetime = NULL;
     }
 
-  /* add months */
-  step = months > 0 ? 1 : -1;
-  for (i = 0; i < ABS (months); i++)
-    {
-      m += step;
+  return datetime;
+}
 
-      if (m < 1)
-        {
-          y -= 1;
-          m = 12;
-        }
-      else if (m > 12)
-        {
-          y += 1;
-          m = 1;
-        }
-    }
+GDateTime *
+g_date_time_new_now (GTimeZone *tz)
+{
+  GTimeVal tv;
 
-  /* clamp the days */
-  max_days = days_in_months[GREGORIAN_LEAP (y) ? 1 : 0];
-  if (max_days[m] < d)
-    d = max_days[m];
+  g_get_current_time (&tv);
 
-  datetime->days = date_to_proleptic_gregorian (y, m, d) + days;
+  return g_date_time_new_from_timeval (tz, &tv);
+}
 
-  return g_date_time_deal_with_date_change (datetime);
+GDateTime *
+g_date_time_new_now_local (void)
+{
+  GDateTime *datetime;
+  GTimeZone *local;
+
+  local = g_time_zone_new_local ();
+  datetime = g_date_time_new_now (local);
+  g_time_zone_unref (local);
+
+  return datetime;
 }
 
-/* Lifecycle {{{1 */
+GDateTime *
+g_date_time_new_now_utc (void)
+{
+  GDateTime *datetime;
+  GTimeZone *utc;
 
-static GDateTime *
-g_date_time_new (void)
+  utc = g_time_zone_new_utc ();
+  datetime = g_date_time_new_now (utc);
+  g_time_zone_unref (utc);
+
+  return datetime;
+}
+
+GDateTime *
+g_date_time_new_from_unix (GTimeZone *tz,
+                           gint64     secs)
+{
+  return g_date_time_from_instant (tz, UNIX_TO_INSTANT (secs));
+}
+
+GDateTime *
+g_date_time_new_from_unix_local (gint64 t)
 {
   GDateTime *datetime;
+  GTimeZone *local;
 
-  datetime = g_slice_new0 (GDateTime);
-  datetime->ref_count = 1;
+  local = g_time_zone_new_local ();
+  datetime = g_date_time_new_from_unix (local, t);
+  g_time_zone_unref (local);
 
   return datetime;
 }
 
-/*< internal >
- * g_date_time_copy:
- * @datetime: a #GDateTime
- *
- * Creates a copy of @datetime.
- *
- * Return value: the newly created #GDateTime which should be freed with
- *   g_date_time_unref().
- */
-static GDateTime *
-g_date_time_copy (const GDateTime *datetime)
+GDateTime *
+g_date_time_new_from_unix_utc (gint64 t)
 {
-  GDateTime *copied;
+  GDateTime *datetime;
+  GTimeZone *utc;
 
-  g_return_val_if_fail (datetime != NULL, NULL);
+  utc = g_time_zone_new_utc ();
+  datetime = g_date_time_new_from_unix (utc, t);
+  g_time_zone_unref (utc);
 
-  copied = g_date_time_new ();
-  copied->days = datetime->days;
-  copied->usec = datetime->usec;
-  copied->tz = g_time_zone_ref (datetime->tz);
-  copied->interval = datetime->interval;
+  return datetime;
+}
 
-  return copied;
+GDateTime *
+g_date_time_new_from_timeval (GTimeZone      *tz,
+                              const GTimeVal *tv)
+{
+  return g_date_time_from_instant (tz, tv->tv_usec +
+                                   UNIX_TO_INSTANT (tv->tv_sec));
 }
 
-/**
- * g_date_time_ref:
- * @datetime: a #GDateTime
- *
- * Atomically increments the reference count of @datetime by one.
- *
- * Return value: the #GDateTime with the reference count increased
- *
- * Since: 2.26
- */
 GDateTime *
-g_date_time_ref (GDateTime *datetime)
+g_date_time_new_from_timeval_local (const GTimeVal *tv)
 {
-  g_return_val_if_fail (datetime != NULL, NULL);
-  g_return_val_if_fail (datetime->ref_count > 0, NULL);
+  GDateTime *datetime;
+  GTimeZone *local;
 
-  g_atomic_int_inc (&datetime->ref_count);
+  local = g_time_zone_new_local ();
+  datetime = g_date_time_new_from_timeval (local, tv);
+  g_time_zone_unref (local);
 
   return datetime;
 }
 
-/**
- * g_date_time_unref:
- * @datetime: a #GDateTime
- *
- * Atomically decrements the reference count of @datetime by one.
- *
- * When the reference count reaches zero, the resources allocated by
- * @datetime are freed
- *
- * Since: 2.26
- */
-void
-g_date_time_unref (GDateTime *datetime)
+GDateTime *
+g_date_time_new_from_timeval_utc (const GTimeVal *tv)
 {
-  g_return_if_fail (datetime != NULL);
-  g_return_if_fail (datetime->ref_count > 0);
+  GDateTime *datetime;
+  GTimeZone *utc;
 
-  if (g_atomic_int_dec_and_test (&datetime->ref_count))
+  utc = g_time_zone_new_utc ();
+  datetime = g_date_time_new_from_timeval (utc, tv);
+  g_time_zone_unref (utc);
+
+  return datetime;
+}
+
+GDateTime *
+g_date_time_new (GTimeZone *tz,
+                 gint       year,
+                 gint       month,
+                 gint       day,
+                 gint       hour,
+                 gint       minute,
+                 gdouble    seconds)
+{
+  GDateTime *datetime;
+  gint64 full_time;
+
+  datetime = g_date_time_alloc (tz);
+  datetime->days = ymd_to_days (year, month, day);
+  datetime->usec = (hour   * USEC_PER_HOUR)
+                 + (minute * USEC_PER_MINUTE)
+                 + (gint64) (seconds * USEC_PER_SECOND);
+
+  full_time = (datetime->days - UNIX_EPOCH_START) * SEC_PER_DAY +
+              datetime->usec / USEC_PER_SECOND;
+
+  datetime->interval = g_time_zone_find_interval (datetime->tz,
+                                                  G_TIME_TYPE_STANDARD,
+                                                  full_time);
+
+  if (datetime->interval == -1)
     {
-      g_time_zone_unref (datetime->tz);
-      g_slice_free (GDateTime, datetime);
+      g_date_time_unref (datetime);
+      datetime = NULL;
     }
+
+  return datetime;
+}
+
+GDateTime *
+g_date_time_new_local (gint    year,
+                       gint    month,
+                       gint    day,
+                       gint    hour,
+                       gint    minute,
+                       gdouble seconds)
+{
+  GDateTime *datetime;
+  GTimeZone *local;
+
+  local = g_time_zone_new_local ();
+  datetime = g_date_time_new (local, year, month, day, hour, minute, seconds);
+  g_time_zone_unref (local);
+
+  return datetime;
+}
+
+GDateTime *
+g_date_time_new_utc (gint    year,
+                     gint    month,
+                     gint    day,
+                     gint    hour,
+                     gint    minute,
+                     gdouble seconds)
+{
+  GDateTime *datetime;
+  GTimeZone *utc;
+
+  utc = g_time_zone_new_utc ();
+  datetime = g_date_time_new (utc, year, month, day, hour, minute, seconds);
+  g_time_zone_unref (utc);
+
+  return datetime;
 }
 
-/* Public API {{{1 */
+GDateTime *
+g_date_time_new_full (GTimeZone *tz,
+                      gint       year,
+                      gint       month,
+                      gint       day,
+                      gint       hour,
+                      gint       minute,
+                      gdouble    seconds,
+                      gboolean   is_dst)
+{
+  GTimeType type = is_dst ? G_TIME_TYPE_DAYLIGHT : G_TIME_TYPE_STANDARD;
+  GDateTime *datetime;
+  gint64 full_time;
+
+  is_dst = !!is_dst;
+  datetime = g_date_time_alloc (tz);
+  datetime->days = ymd_to_days (year, month, day);
+  datetime->usec = (hour   * USEC_PER_HOUR)
+                 + (minute * USEC_PER_MINUTE)
+                 + (gint64) (seconds * USEC_PER_SECOND);
+
+  full_time = (datetime->days - UNIX_EPOCH_START) * SEC_PER_DAY +
+              datetime->usec / USEC_PER_SECOND;
+
+  datetime->interval = g_time_zone_find_interval (datetime->tz,
+                                                  type, full_time);
+
+  if (datetime->interval == -1 ||
+      g_time_zone_is_dst (datetime->tz, datetime->interval) != is_dst)
+    {
+      g_date_time_unref (datetime);
+      datetime = NULL;
+    }
+
+  return datetime;
+}
+
+GDateTime *
+g_date_time_new_local_full (gint     year,
+                            gint     month,
+                            gint     day,
+                            gint     hour,
+                            gint     minute,
+                            gdouble  seconds,
+                            gboolean is_dst)
+{
+  GDateTime *datetime;
+  GTimeZone *local;
+
+  local = g_time_zone_new_local ();
+  datetime = g_date_time_new_full (local,
+                                   year, month, day,
+                                   hour, minute, seconds,
+                                   is_dst);
+  g_time_zone_unref (local);
+
+  return datetime;
+}
+
+/* Adders {{{1 */
 
 static void
-g_date_time_get_week_number (const GDateTime *datetime,
-                             gint            *week_number,
-                             gint            *day_of_week,
-                             gint            *day_of_year)
+g_date_time_get_week_number (GDateTime *datetime,
+                             gint      *week_number,
+                             gint      *day_of_week,
+                             gint      *day_of_year)
 {
   gint a, b, c, d, e, f, g, n, s, month, day, year;
 
-  g_date_time_get_dmy (datetime, &day, &month, &year);
+  g_date_time_get_ymd (datetime, &year, &month, &day);
 
   if (month <= 2)
     {
@@ -688,17 +806,31 @@ g_date_time_get_week_number (const GDateTime *datetime,
  * Since: 2.26
  */
 GDateTime*
-g_date_time_add (const GDateTime *datetime,
-                 GTimeSpan        timespan)
+g_date_time_add (GDateTime *datetime,
+                 GTimeSpan  timespan)
 {
-  GDateTime *dt;
+  return g_date_time_from_instant (datetime->tz, timespan +
+                                   g_date_time_to_instant (datetime));
+}
 
-  g_return_val_if_fail (datetime != NULL, NULL);
+static GDateTime *
+g_date_time_replace_days (GDateTime *datetime,
+                          gint       days)
+{
+  GDateTime *new;
+
+  new = g_date_time_alloc (datetime->tz);
+  new->interval = datetime->interval;
+  new->usec = datetime->usec;
+  new->days = days;
 
-  dt = g_date_time_copy (datetime);
-  g_date_time_add_usec (dt, timespan);
+  if (!g_date_time_deal_with_date_change (new))
+    {
+      g_date_time_unref (new);
+      new = NULL;
+    }
 
-  return dt;
+  return new;
 }
 
 /**
@@ -714,18 +846,26 @@ g_date_time_add (const GDateTime *datetime,
  *
  * Since: 2.26
  */
-GDateTime*
-g_date_time_add_years (const GDateTime *datetime,
-                       gint             years)
+GDateTime *
+g_date_time_add_years (GDateTime *datetime,
+                       gint       years)
 {
-  GDateTime *dt;
+  gint year, month, day;
 
   g_return_val_if_fail (datetime != NULL, NULL);
 
-  dt = g_date_time_copy (datetime);
-  g_date_time_add_ymd (dt, years, 0, 0);
+  if (years < -10000 || years > 10000)
+    return NULL;
+
+  g_date_time_get_ymd (datetime, &year, &month, &day);
+  year += years;
 
-  return dt;
+  /* only possible issue is if we've entered a year with no February 29
+   */
+  if (month == 2 && day == 29 && !GREGORIAN_LEAP (year))
+    day = 28;
+
+  return g_date_time_replace_days (datetime, ymd_to_days (year, month, day));
 }
 
 /**
@@ -742,17 +882,33 @@ g_date_time_add_years (const GDateTime *datetime,
  * Since: 2.26
  */
 GDateTime*
-g_date_time_add_months (const GDateTime *datetime,
-                        gint             months)
+g_date_time_add_months (GDateTime *datetime,
+                        gint       months)
 {
-  GDateTime *dt;
+  gint year, month, day;
 
   g_return_val_if_fail (datetime != NULL, NULL);
+  g_date_time_get_ymd (datetime, &year, &month, &day);
+
+  if (months < -120000 || months > 120000)
+    return NULL;
+
+  year += months / 12;
+  month += months % 12;
+  if (month < 1)
+    {
+      month += 12;
+      year--;
+    }
+  else if (month > 12)
+    {
+      month -= 12;
+      year++;
+    }
 
-  dt = g_date_time_copy (datetime);
-  g_date_time_add_ymd (dt, 0, months, 0);
+  day = MIN (day, days_in_months[GREGORIAN_LEAP (year)][month]);
 
-  return dt;
+  return g_date_time_replace_days (datetime, ymd_to_days (year, month, day));
 }
 
 /**
@@ -769,7 +925,7 @@ g_date_time_add_months (const GDateTime *datetime,
  * Since: 2.26
  */
 GDateTime*
-g_date_time_add_weeks (const GDateTime *datetime,
+g_date_time_add_weeks (GDateTime *datetime,
                        gint             weeks)
 {
   g_return_val_if_fail (datetime != NULL, NULL);
@@ -791,17 +947,15 @@ g_date_time_add_weeks (const GDateTime *datetime,
  * Since: 2.26
  */
 GDateTime*
-g_date_time_add_days (const GDateTime *datetime,
-                      gint             days)
+g_date_time_add_days (GDateTime *datetime,
+                      gint       days)
 {
-  GDateTime *dt;
-
   g_return_val_if_fail (datetime != NULL, NULL);
 
-  dt = g_date_time_copy (datetime);
-  g_date_time_add_ymd (dt, 0, 0, days);
+  if (days < -3660000 || days > 3660000)
+    return NULL;
 
-  return dt;
+  return g_date_time_replace_days (datetime, datetime->days + days);
 }
 
 /**
@@ -817,17 +971,10 @@ g_date_time_add_days (const GDateTime *datetime,
  * Since: 2.26
  */
 GDateTime*
-g_date_time_add_hours (const GDateTime *datetime,
-                       gint             hours)
+g_date_time_add_hours (GDateTime *datetime,
+                       gint       hours)
 {
-  GDateTime *dt;
-
-  g_return_val_if_fail (datetime != NULL, NULL);
-
-  dt = g_date_time_copy (datetime);
-  g_date_time_add_usec (dt, (gint64) hours * USEC_PER_HOUR);
-
-  return dt;
+  return g_date_time_add (datetime, hours * USEC_PER_HOUR);
 }
 
 /**
@@ -843,43 +990,10 @@ g_date_time_add_hours (const GDateTime *datetime,
  * Since: 2.26
  */
 GDateTime*
-g_date_time_add_seconds (const GDateTime *datetime,
-                         gint             seconds)
-{
-  GDateTime *dt;
-
-  g_return_val_if_fail (datetime != NULL, NULL);
-
-  dt = g_date_time_copy (datetime);
-  g_date_time_add_usec (dt, (gint64) seconds * USEC_PER_SECOND);
-
-  return dt;
-}
-
-/**
- * g_date_time_add_milliseconds:
- * @datetime: a #GDateTime
- * @milliseconds: the number of milliseconds to add
- *
- * Creates a copy of @datetime adding the specified number of milliseconds.
- *
- * Return value: the newly created #GDateTime which should be freed with
- *   g_date_time_unref().
- *
- * Since: 2.26
- */
-GDateTime*
-g_date_time_add_milliseconds (const GDateTime *datetime,
-                              gint             milliseconds)
+g_date_time_add_seconds (GDateTime *datetime,
+                         gdouble    seconds)
 {
-  GDateTime *dt;
-
-  g_return_val_if_fail (datetime != NULL, NULL);
-
-  dt = g_date_time_copy (datetime);
-  g_date_time_add_usec (dt, (gint64) milliseconds * USEC_PER_MILLISECOND);
-
-  return dt;
+  return g_date_time_add (datetime, seconds * USEC_PER_SECOND);
 }
 
 /**
@@ -895,17 +1009,10 @@ g_date_time_add_milliseconds (const GDateTime *datetime,
  * Since: 2.26
  */
 GDateTime*
-g_date_time_add_minutes (const GDateTime *datetime,
+g_date_time_add_minutes (GDateTime *datetime,
                          gint             minutes)
 {
-  GDateTime *dt;
-
-  g_return_val_if_fail (datetime != NULL, NULL);
-
-  dt = g_date_time_copy (datetime);
-  g_date_time_add_usec (dt, (gint64) minutes * USEC_PER_MINUTE);
-
-  return dt;
+  return g_date_time_add (datetime, minutes * USEC_PER_MINUTE);
 }
 
 /**
@@ -927,40 +1034,95 @@ g_date_time_add_minutes (const GDateTime *datetime,
  * Since: 2.26
  */
 GDateTime *
-g_date_time_add_full (const GDateTime *datetime,
-                      gint             years,
-                      gint             months,
-                      gint             days,
-                      gint             hours,
-                      gint             minutes,
-                      gint             seconds)
+g_date_time_add_full (GDateTime *datetime,
+                      gint       years,
+                      gint       months,
+                      gint       days,
+                      gint       hours,
+                      gint       minutes,
+                      gdouble    seconds)
 {
-  GDateTime *dt;
-  gint64 usecs;
+  gint year, month, day;
+  gint64 full_time;
+  GDateTime *new;
+  gint interval;
 
   g_return_val_if_fail (datetime != NULL, NULL);
+  g_date_time_get_ymd (datetime, &year, &month, &day);
+
+  months += years * 12;
+
+  if (months < -120000 || months > 120000)
+    return NULL;
+
+  if (days < -3660000 || days > 3660000)
+    return NULL;
+
+  year += months / 12;
+  month += months % 12;
+  if (month < 1)
+    {
+      month += 12;
+      year--;
+    }
+  else if (month > 12)
+    {
+      month -= 12;
+      year++;
+    }
+
+  day = MIN (day, days_in_months[GREGORIAN_LEAP (year)][month]);
+
+  /* full_time is now in unix (local) time */
+  full_time = datetime->usec / USEC_PER_SECOND + SEC_PER_DAY *
+    (ymd_to_days (year, month, day) + days - UNIX_EPOCH_START);
 
-  dt = g_date_time_copy (datetime);
+  interval = g_time_zone_adjust_time (datetime->tz,
+                                      g_time_zone_is_dst (datetime->tz,
+                                                          datetime->interval),
+                                      &full_time);
 
-  /* add date */
-  g_date_time_add_ymd (dt, years, months, days);
+  /* move to UTC unix time */
+  full_time -= g_time_zone_get_offset (datetime->tz, interval);
 
-  /* add time */
-  usecs = (hours   * USEC_PER_HOUR)
-        + (minutes * USEC_PER_MINUTE)
-        + (seconds * USEC_PER_SECOND);
-  g_date_time_add_usec (dt, usecs);
+  /* convert back to an instant, add back fractional seconds */
+  full_time += UNIX_EPOCH_START * SEC_PER_DAY;
+  full_time = full_time * USEC_PER_SECOND +
+              datetime->usec % USEC_PER_SECOND;
+
+  /* do the actual addition now */
+  full_time += (hours * USEC_PER_HOUR) +
+               (minutes * USEC_PER_MINUTE) +
+               (gint64) (seconds * USEC_PER_SECOND);
+
+  /* find the new interval */
+  interval = g_time_zone_find_interval (datetime->tz,
+                                        G_TIME_TYPE_UNIVERSAL,
+                                        INSTANT_TO_UNIX (full_time));
+
+  /* convert back into local time */
+  full_time += USEC_PER_SECOND *
+               g_time_zone_get_offset (datetime->tz, interval);
+
+  /* split into days and usec of a new datetime */
+  new = g_date_time_alloc (datetime->tz);
+  new->interval = interval;
+  new->days = full_time / USEC_PER_DAY;
+  new->usec = full_time % USEC_PER_DAY;
+
+  /* XXX validate */
 
-  return dt;
+  return new;
 }
 
+/* Compare, equal, hash, difference {{{1 */
 /**
  * g_date_time_compare:
  * @dt1: first #GDateTime to compare
  * @dt2: second #GDateTime to compare
  *
- * qsort()-style comparison for #GDateTime<!-- -->'s. Both #GDateTime<-- -->'s
- * must be non-%NULL.
+ * #GCompareFunc-compatible comparison for #GDateTime<!-- -->'s. Both
+ * #GDateTime<-- -->'s must be non-%NULL.
  *
  * Return value: 0 for equal, less than zero if dt1 is less than dt2, greater
  *   than zero if dt2 is greator than dt1.
@@ -971,75 +1133,83 @@ gint
 g_date_time_compare (gconstpointer dt1,
                      gconstpointer dt2)
 {
-  const GDateTime *a, *b;
+  gint64 difference;
 
-  a = dt1;
-  b = dt2;
+  difference = g_date_time_difference ((GDateTime *) dt1, (GDateTime *) dt2);
 
-  if ((a->days == b->days )&&
-      (a->usec == b->usec))
-    {
-      return 0;
-    }
-  else if ((a->days > b->days) ||
-           ((a->days == b->days) && a->usec > b->usec))
-    {
-      return 1;
-    }
-  else
+  if (difference < 0)
     return -1;
+
+  else if (difference > 0)
+    return 1;
+
+  else
+    return 0;
 }
 
 /**
- * g_date_time_day:
- * @datetime: a #GDateTime
+ * g_date_time_difference:
+ * @end: a #GDateTime
+ * @begin: a #GDateTime
  *
- * Creates a new #GDateTime at Midnight on the date represented by @datetime.
+ * Calculates the difference in time between @end and @begin.  The
+ * #GTimeSpan that is returned is effectively @end - @begin (ie:
+ * positive if the first parameter is larger).
  *
- * Return value: the newly created #GDateTime which should be freed with
- *   g_date_time_unref().
+ * Return value: the difference between the two #GDateTime, as a time
+ *   span expressed in microseconds.
  *
  * Since: 2.26
  */
-GDateTime*
-g_date_time_day (const GDateTime *datetime)
+GTimeSpan
+g_date_time_difference (GDateTime *end,
+                        GDateTime *begin)
 {
-  GDateTime *date;
-
-  g_return_val_if_fail (datetime != NULL, NULL);
+  g_return_val_if_fail (begin != NULL, 0);
+  g_return_val_if_fail (end != NULL, 0);
 
-  date = g_date_time_copy (datetime);
-  date->usec = 0;
+  return g_date_time_to_instant (end) -
+         g_date_time_to_instant (begin);
+}
 
-  return date;
+/**
+ * g_date_time_hash:
+ * @datetime: a #GDateTime
+ *
+ * Hashes @datetime into a #guint, suitable for use within #GHashTable.
+ *
+ * Return value: a #guint containing the hash
+ *
+ * Since: 2.26
+ */
+guint
+g_date_time_hash (gconstpointer datetime)
+{
+  return g_date_time_to_instant ((GDateTime *) datetime);
 }
 
 /**
- * g_date_time_difference:
- * @begin: a #GDateTime
- * @end: a #GDateTime
+ * g_date_time_equal:
+ * @dt1: a #GDateTime
+ * @dt2: a #GDateTime
  *
- * Calculates the known difference in time between @begin and @end.
+ * Checks to see if @dt1 and @dt2 are equal.
  *
- * Since the exact precision cannot always be known due to incomplete
- * historic information, an attempt is made to calculate the difference.
+ * Equal here means that they represent the same moment after converting
+ * them to the same timezone.
  *
- * Return value: the difference between the two #GDateTime, as a time
- *   span expressed in microseconds.
+ * Return value: %TRUE if @dt1 and @dt2 are equal
  *
  * Since: 2.26
  */
-GTimeSpan
-g_date_time_difference (const GDateTime *begin,
-                        const GDateTime *end)
+gboolean
+g_date_time_equal (gconstpointer dt1,
+                   gconstpointer dt2)
 {
-  g_return_val_if_fail (begin != NULL, 0);
-  g_return_val_if_fail (end != NULL, 0);
-
-  return (GTimeSpan) (((gint64) end->days - (gint64) begin->days)
-      * USEC_PER_DAY) + ((gint64) end->usec - (gint64) begin->usec);
+  return g_date_time_difference ((GDateTime *) dt1, (GDateTime *) dt2) == 0;
 }
 
+/* Getters {{{1 */
 /**
  * g_date_time_get_day_of_week:
  * @datetime: a #GDateTime
@@ -1052,7 +1222,7 @@ g_date_time_difference (const GDateTime *begin,
  * Since: 2.26
  */
 gint
-g_date_time_get_day_of_week (const GDateTime *datetime)
+g_date_time_get_day_of_week (GDateTime *datetime)
 {
   gint a, y, m,
        year  = 0,
@@ -1067,7 +1237,7 @@ g_date_time_get_day_of_week (const GDateTime *datetime)
    * http://www.tondering.dk/claus/cal/calendar29.txt
    */
 
-  g_date_time_get_dmy (datetime, &day, &month, &year);
+  g_date_time_get_ymd (datetime, &year, &month, &day);
   a = (14 - month) / 12;
   y = year - a;
   m = month + (12 * a) - 2;
@@ -1089,7 +1259,7 @@ g_date_time_get_day_of_week (const GDateTime *datetime)
  * Since: 2.26
  */
 gint
-g_date_time_get_day_of_month (const GDateTime *datetime)
+g_date_time_get_day_of_month (GDateTime *datetime)
 {
   gint           day_of_year,
                  i;
@@ -1098,7 +1268,7 @@ g_date_time_get_day_of_month (const GDateTime *datetime)
 
   g_return_val_if_fail (datetime != NULL, 0);
 
-  days = days_in_year[g_date_time_is_leap_year (datetime) ? 1 : 0];
+  days = days_in_year[GREGORIAN_LEAP (g_date_time_get_year (datetime)) ? 1 : 0];
   g_date_time_get_week_number (datetime, NULL, NULL, &day_of_year);
 
   for (i = 1; i <= 12; i++)
@@ -1124,7 +1294,7 @@ g_date_time_get_day_of_month (const GDateTime *datetime)
  * Since: 2.26
  */
 gint
-g_date_time_get_day_of_year (const GDateTime *datetime)
+g_date_time_get_day_of_year (GDateTime *datetime)
 {
   gint doy = 0;
 
@@ -1135,21 +1305,21 @@ g_date_time_get_day_of_year (const GDateTime *datetime)
 }
 
 /**
- * g_date_time_get_dmy:
+ * g_date_time_get_ymd:
  * @datetime: a #GDateTime.
- * @day: (out): the return location for the day of the month, or %NULL.
- * @month: (out): the return location for the monty of the year, or %NULL.
  * @year: (out): the return location for the gregorian year, or %NULL.
+ * @month: (out): the return location for the monty of the year, or %NULL.
+ * @day: (out): the return location for the day of the month, or %NULL.
  *
  * Retrieves the Gregorian day, month, and year of a given #GDateTime.
  *
  * Since: 2.26
  */
 void
-g_date_time_get_dmy (const GDateTime *datetime,
-                     gint            *day,
-                     gint            *month,
-                     gint            *year)
+g_date_time_get_ymd (GDateTime *datetime,
+                     gint      *year,
+                     gint      *month,
+                     gint      *day)
 {
   gint the_year;
   gint the_month;
@@ -1241,7 +1411,7 @@ end:
  * Since: 2.26
  */
 gint
-g_date_time_get_hour (const GDateTime *datetime)
+g_date_time_get_hour (GDateTime *datetime)
 {
   g_return_val_if_fail (datetime != NULL, 0);
 
@@ -1249,112 +1419,85 @@ g_date_time_get_hour (const GDateTime *datetime)
 }
 
 /**
- * g_date_time_get_julian:
+ * g_date_time_get_microsecond:
  * @datetime: a #GDateTime
- * @period: (out): a location for the Julian period
- * @julian: (out): a location for the day in the Julian period
- * @hour: (out): a location for the hour of the day
- * @minute: (out): a location for the minute of the hour
- * @second: (out): a location for hte second of the minute
  *
- * Retrieves the Julian period, day, hour, minute, and second which @datetime
- * represents in the Julian calendar.
+ * Retrieves the microsecond of the date represented by @datetime
+ *
+ * Return value: the microsecond of the second
  *
  * Since: 2.26
  */
-void
-g_date_time_get_julian (const GDateTime *datetime,
-                        gint            *period,
-                        gint            *julian,
-                        gint            *hour,
-                        gint            *minute,
-                        gint            *second)
+gint
+g_date_time_get_microsecond (GDateTime *datetime)
 {
-  gint y, m, d, a, b, c, e, f, j;
-  g_return_if_fail (datetime != NULL);
-
-  g_date_time_get_dmy (datetime, &d, &m, &y);
-
-  /* FIXME: This is probably not optimal and doesn't handle the fact that the
-   * julian calendar has its 0 hour on midday */
-
-  a = y / 100;
-  b = a / 4;
-  c = 2 - a + b;
-  e = 365.25 * (y + 4716);
-  f = 30.6001 * (m + 1);
-  j = c + d + e + f - 1524;
-
-  if (period)
-    *period = 0;
-
-  if (julian)
-    *julian = j;
-
-  if (hour)
-    *hour = (datetime->usec / USEC_PER_HOUR);
-
-  if (minute)
-    *minute = (datetime->usec % USEC_PER_HOUR) / USEC_PER_MINUTE;
+  g_return_val_if_fail (datetime != NULL, 0);
 
-  if (second)
-    *second = (datetime->usec % USEC_PER_MINUTE) / USEC_PER_SECOND;
+  return (datetime->usec % USEC_PER_SECOND);
 }
 
 /**
- * g_date_time_get_microsecond:
+ * g_date_time_get_minute:
  * @datetime: a #GDateTime
  *
- * Retrieves the microsecond of the date represented by @datetime
+ * Retrieves the minute of the hour represented by @datetime
  *
- * Return value: the microsecond of the second
+ * Return value: the minute of the hour
  *
  * Since: 2.26
  */
 gint
-g_date_time_get_microsecond (const GDateTime *datetime)
+g_date_time_get_minute (GDateTime *datetime)
 {
   g_return_val_if_fail (datetime != NULL, 0);
 
-  return (datetime->usec % USEC_PER_SECOND);
+  return (datetime->usec % USEC_PER_HOUR) / USEC_PER_MINUTE;
 }
 
 /**
- * g_date_time_get_millisecond:
- * @datetime: a #GDateTime
+ * g_date_time_get_week_of_year:
  *
- * Retrieves the millisecond of the date represented by @datetime
+ * Returns the numeric week of the respective year.
  *
- * Return value: the millisecond of the second
+ * Return value: the week of the year
  *
  * Since: 2.26
  */
 gint
-g_date_time_get_millisecond (const GDateTime *datetime)
+g_date_time_get_week_of_year (GDateTime *datetime)
 {
+  gint weeknum;
+
   g_return_val_if_fail (datetime != NULL, 0);
 
-  return (datetime->usec % USEC_PER_SECOND) / USEC_PER_MILLISECOND;
+  g_date_time_get_week_number (datetime, &weeknum, NULL, NULL);
+
+  return weeknum;
 }
 
 /**
- * g_date_time_get_minute:
- * @datetime: a #GDateTime
+ * g_date_time_get_year:
+ * @datetime: A #GDateTime
  *
- * Retrieves the minute of the hour represented by @datetime
+ * Retrieves the year represented by @datetime in the Gregorian calendar.
  *
- * Return value: the minute of the hour
+ * Return value: the year represented by @datetime
  *
  * Since: 2.26
  */
 gint
-g_date_time_get_minute (const GDateTime *datetime)
+g_date_time_get_year (GDateTime *datetime)
 {
+  gint year;
+
   g_return_val_if_fail (datetime != NULL, 0);
 
-  return (datetime->usec % USEC_PER_HOUR) / USEC_PER_MINUTE;
+  g_date_time_get_ymd (datetime, &year, NULL, NULL);
+
+  return year;
 }
 
+
 /**
  * g_date_time_get_month:
  * @datetime: a #GDateTime
@@ -1367,13 +1510,13 @@ g_date_time_get_minute (const GDateTime *datetime)
  * Since: 2.26
  */
 gint
-g_date_time_get_month (const GDateTime *datetime)
+g_date_time_get_month (GDateTime *datetime)
 {
   gint month;
 
   g_return_val_if_fail (datetime != NULL, 0);
 
-  g_date_time_get_dmy (datetime, NULL, &month, NULL);
+  g_date_time_get_ymd (datetime, NULL, &month, NULL);
 
   return month;
 }
@@ -1389,13 +1532,31 @@ g_date_time_get_month (const GDateTime *datetime)
  * Since: 2.26
  */
 gint
-g_date_time_get_second (const GDateTime *datetime)
+g_date_time_get_second (GDateTime *datetime)
 {
   g_return_val_if_fail (datetime != NULL, 0);
 
   return (datetime->usec % USEC_PER_MINUTE) / USEC_PER_SECOND;
 }
 
+/* Exporters {{{1 */
+gint64
+g_date_time_to_unix (GDateTime *datetime)
+{
+  return INSTANT_TO_UNIX (g_date_time_to_instant (datetime));
+}
+
+gboolean
+g_date_time_to_timeval (GDateTime *datetime,
+                        GTimeVal  *tv)
+{
+  tv->tv_sec = INSTANT_TO_UNIX (g_date_time_to_instant (datetime));
+  tv->tv_usec = datetime->usec % USEC_PER_SECOND;
+
+  return TRUE;
+}
+
+/* Timezone queries {{{1 */
 /**
  * g_date_time_get_utc_offset:
  * @datetime: a #GDateTime
@@ -1411,7 +1572,7 @@ g_date_time_get_second (const GDateTime *datetime)
  * Since: 2.26
  */
 GTimeSpan
-g_date_time_get_utc_offset (const GDateTime *datetime)
+g_date_time_get_utc_offset (GDateTime *datetime)
 {
   gint offset;
 
@@ -1434,8 +1595,8 @@ g_date_time_get_utc_offset (const GDateTime *datetime)
  *
  * Since: 2.26
  */
-G_CONST_RETURN gchar *
-g_date_time_get_timezone_abbreviation (const GDateTime *datetime)
+const gchar *
+g_date_time_get_timezone_abbreviation (GDateTime *datetime)
 {
   g_return_val_if_fail (datetime != NULL, NULL);
 
@@ -1443,104 +1604,6 @@ g_date_time_get_timezone_abbreviation (const GDateTime *datetime)
 }
 
 /**
- * g_date_time_get_year:
- * @datetime: A #GDateTime
- *
- * Retrieves the year represented by @datetime in the Gregorian calendar.
- *
- * Return value: the year represented by @datetime
- *
- * Since: 2.26
- */
-gint
-g_date_time_get_year (const GDateTime *datetime)
-{
-  gint year;
-
-  g_return_val_if_fail (datetime != NULL, 0);
-
-  g_date_time_get_dmy (datetime, NULL, NULL, &year);
-
-  return year;
-}
-
-/**
- * g_date_time_hash:
- * @datetime: a #GDateTime
- *
- * Hashes @datetime into a #guint, suitable for use within #GHashTable.
- *
- * Return value: a #guint containing the hash
- *
- * Since: 2.26
- */
-guint
-g_date_time_hash (gconstpointer datetime)
-{
-  GDateTime *dt_utc;
-  gint64 epoch;
-
-  dt_utc = g_date_time_to_utc (datetime);
-  epoch = g_date_time_to_epoch (dt_utc);
-  g_date_time_unref (dt_utc);
-
-  return (guint) epoch;
-}
-
-/**
- * g_date_time_equal:
- * @dt1: a #GDateTime
- * @dt2: a #GDateTime
- *
- * Checks to see if @dt1 and @dt2 are equal.
- *
- * Equal here means that they represent the same moment after converting
- * them to the same timezone.
- *
- * Return value: %TRUE if @dt1 and @dt2 are equal
- *
- * Since: 2.26
- */
-gboolean
-g_date_time_equal (gconstpointer dt1,
-                   gconstpointer dt2)
-{
-  const GDateTime *a, *b;
-  gint64 at, bt;
-
-  a = dt1;
-  b = dt2;
-
-  at = a->days * USEC_PER_DAY + a->usec - g_date_time_get_utc_offset (a);
-  bt = b->days * USEC_PER_DAY + b->usec - g_date_time_get_utc_offset (b);
-
-  return at == bt;
-}
-
-/**
- * g_date_time_is_leap_year:
- * @datetime: a #GDateTime
- *
- * Determines if @datetime represents a date known to fall within
- * a leap year in the Gregorian calendar.
- *
- * Return value: %TRUE if @datetime is a leap year.
- *
- * Since: 2.26
- */
-gboolean
-g_date_time_is_leap_year (const GDateTime *datetime)
-{
-  gint year;
-
-  g_return_val_if_fail (datetime != NULL, FALSE);
-
-  year = g_date_time_get_year (datetime);
-
-  return GREGORIAN_LEAP (year);
-}
-
-/**
  * g_date_time_is_daylight_savings:
  * @datetime: a #GDateTime
  *
@@ -1552,181 +1615,60 @@ g_date_time_is_leap_year (const GDateTime *datetime)
  * Since: 2.26
  */
 gboolean
-g_date_time_is_daylight_savings (const GDateTime *datetime)
+g_date_time_is_daylight_savings (GDateTime *datetime)
 {
   g_return_val_if_fail (datetime != NULL, FALSE);
 
   return g_time_zone_is_dst (datetime->tz, datetime->interval);
 }
 
-/**
- * g_date_time_new_from_date:
- * @year: the Gregorian year
- * @month: the Gregorian month
- * @day: the day in the Gregorian month
- *
- * Creates a new #GDateTime using the specified date within the Gregorian
- * calendar.
- *
- * Return value: the newly created #GDateTime or %NULL if it is outside of
- *   the representable range.
- *
- * Since: 2.26
- */
+/* Timezone convert {{{1 */
 GDateTime *
-g_date_time_new_from_date (gint year,
-                           gint month,
-                           gint day)
+g_date_time_to_timezone (GDateTime *datetime,
+                         GTimeZone *tz)
 {
-  GDateTime *dt;
-
-  g_return_val_if_fail (year > -4712 && year <= 3268, NULL);
-  g_return_val_if_fail (month > 0 && month <= 12, NULL);
-  g_return_val_if_fail (day > 0 && day <= 31, NULL);
-
-  dt = g_date_time_new ();
-
-  dt->days = date_to_proleptic_gregorian (year, month, day);
-  dt->tz = g_time_zone_new_local ();
-
-  g_date_time_deal_with_date_change (dt);
-
-  return dt;
+  return g_date_time_from_instant (tz, g_date_time_to_instant (datetime));
 }
 
-/**
- * g_date_time_new_from_epoch:
- * @t: seconds from the Unix epoch
- *
- * Creates a new #GDateTime using the time since Jan 1, 1970 specified by @t.
- *
- * The timezone of the returned #GDateTime is local time.
- *
- * Return value: the newly created #GDateTime
- *
- * Since: 2.26
- */
-GDateTime*
-g_date_time_new_from_epoch (gint64 t)
-{
-  GDateTime *datetime;
-  gint64 days;
-  gint64 usec;
-
-  t *= 1000000;
-  t += UNIX_EPOCH_START * USEC_PER_DAY;
-
-  if (t < 0)
-    return NULL;
-
-  days = t / USEC_PER_DAY;
-  usec = t % USEC_PER_DAY;
-
-  if (days < 1 || days > 3652059)
-    return NULL;
-
-  datetime = g_date_time_new ();
-  datetime->tz = g_time_zone_new_utc ();
-  datetime->days = days;
-  datetime->usec = usec;
 
-  g_date_time_change_zone (datetime, g_time_zone_new_local ());
-
-  return datetime;
-}
 
 /**
- * g_date_time_new_from_timeval:
- * @tv: #GTimeVal
- *
- * Creates a new #GDateTime using the date and time specified by #GTimeVal.
+ * g_date_time_to_local:
+ * @datetime: a #GDateTime
  *
- * The timezone of the returned #GDateTime is local time.
+ * Creates a new #GDateTime with @datetime converted to local time.
  *
  * Return value: the newly created #GDateTime
  *
  * Since: 2.26
  */
 GDateTime *
-g_date_time_new_from_timeval (GTimeVal *tv)
+g_date_time_to_local (GDateTime *datetime)
 {
-  GDateTime *datetime;
-
-  g_return_val_if_fail (tv != NULL, NULL);
+  GDateTime *new;
+  GTimeZone *local;
 
-  datetime = g_date_time_new_from_epoch (tv->tv_sec);
-  datetime->usec += tv->tv_usec;
+  local = g_time_zone_new_local ();
+  new = g_date_time_to_timezone (datetime, local);
+  g_time_zone_unref (local);
 
-  return datetime;
+  return new;
 }
 
-/**
- * g_date_time_new_full:
- * @year: the Gregorian year
- * @month: the Gregorian month
- * @day: the day of the Gregorian month
- * @hour: the hour of the day
- * @minute: the minute of the hour
- * @second: the second of the minute, with eventual fractionary parts
- * @time_zone: (allow-none): a #GTimeZone, or %NULL for UTC
- *
- * Creates a new #GDateTime using the date and times in the Gregorian
- * calendar.
- *
- * If @time_zone is not %NULL, the #GDateTime will copy the #GTimeZone
- * and sink it, if floating.
- *
- * Return value: the newly created #GDateTime
- *
- * Since: 2.26
- */
 GDateTime *
-g_date_time_new_full (gint             year,
-                      gint             month,
-                      gint             day,
-                      gint             hour,
-                      gint             minute,
-                      gdouble          second,
-                      const gchar     *time_zone)
+g_date_time_to_utc (GDateTime *datetime)
 {
-  GDateTime *dt;
-
-  g_return_val_if_fail (hour >= 0 && hour < 24, NULL);
-  g_return_val_if_fail (minute >= 0 && minute < 60, NULL);
-  g_return_val_if_fail (second >= 0.0 && second <= 60.0, NULL);
-
-  dt = g_date_time_new ();
-  dt->days = date_to_proleptic_gregorian (year, month, day);
-  dt->usec = (hour   * USEC_PER_HOUR)
-           + (minute * USEC_PER_MINUTE)
-           + (second * USEC_PER_SECOND);
-
-  dt->tz = g_time_zone_new (time_zone);
-  g_date_time_deal_with_date_change (dt);
-
-  return dt;
-}
-
-/**
- * g_date_time_new_now:
- *
- * Creates a new #GDateTime representing the current date and time.
- *
- * Return value: the newly created #GDateTime which should be freed with
- *   g_date_time_unref().
- *
- * Since: 2.26
- */
-GDateTime*
-g_date_time_new_now (void)
-{
-  GTimeVal tv;
+  GDateTime *new;
+  GTimeZone *utc;
 
-  g_get_current_time (&tv);
+  utc = g_time_zone_new_utc ();
+  new = g_date_time_to_timezone (datetime, utc);
+  g_time_zone_unref (utc);
 
-  return g_date_time_new_from_timeval (&tv);
+  return new;
 }
 
+/* Format {{{1 */
 /**
  * g_date_time_format:
  * @datetime: A #GDateTime
@@ -1784,7 +1726,7 @@ g_date_time_new_now (void)
  * Since: 2.26
  */
 gchar *
-g_date_time_format (const GDateTime *datetime,
+g_date_time_format (GDateTime *datetime,
                     const gchar     *format)
 {
   GString  *outstr;
@@ -1900,7 +1842,7 @@ g_date_time_format (const GDateTime *datetime,
                                           g_date_time_get_minute (datetime));
                   break;
                 case 's':
-                  g_string_append_printf (outstr, "%" G_GINT64_FORMAT, g_date_time_to_epoch (datetime));
+                  g_string_append_printf (outstr, "%" G_GINT64_FORMAT, g_date_time_to_unix (datetime));
                   break;
                 case 'S':
                   g_string_append_printf (outstr, "%02d", g_date_time_get_second (datetime));
@@ -1974,179 +1916,6 @@ bad_format:
   return NULL;
 }
 
-/**
- * g_date_time_to_local:
- * @datetime: a #GDateTime
- *
- * Creates a new #GDateTime with @datetime converted to local time.
- *
- * Return value: the newly created #GDateTime
- *
- * Since: 2.26
- */
-GDateTime *
-g_date_time_to_local (const GDateTime *datetime)
-{
-  GDateTime *dt;
-  GTimeZone *local;
-
-  local = g_time_zone_new_local ();
-
-  dt = g_date_time_copy (datetime);
-  if (!g_date_time_change_zone (dt, local))
-    {
-      g_date_time_unref (dt);
-      dt = NULL;
-    }
-  g_time_zone_unref (local);
-
-  return dt;
-}
-
-/**
- * g_date_time_to_epoch:
- * @datetime: a #GDateTime
- *
- * Converts @datetime into an integer representing seconds since the
- * Unix epoch
- *
- * Return value: @datetime as seconds since the Unix epoch
- *
- * Since: 2.26
- */
-gint64
-g_date_time_to_epoch (const GDateTime *datetime)
-{
-  gint64 result;
-
-  g_return_val_if_fail (datetime != NULL, 0);
-
-  if (datetime->days <= 0)
-    return G_MININT64;
-
-  result = (datetime->days - UNIX_EPOCH_START) * SEC_PER_DAY
-         + datetime->usec / USEC_PER_SECOND
-         - g_date_time_get_utc_offset (datetime) / USEC_PER_SECOND;
-
-  return result;
-}
-
-/**
- * g_date_time_to_timeval:
- * @datetime: a #GDateTime
- * @tv: A #GTimeVal
- *
- * Converts @datetime into a #GTimeVal and stores the result into @timeval.
- *
- * Since: 2.26
- */
-void
-g_date_time_to_timeval (const GDateTime *datetime,
-                        GTimeVal        *tv)
-{
-  g_return_if_fail (datetime != NULL);
-  g_return_if_fail (tv != NULL);
-
-  tv->tv_sec = g_date_time_to_epoch (datetime);
-  tv->tv_usec = datetime->usec % USEC_PER_SECOND;
-}
-
-/**
- * g_date_time_to_utc:
- * @datetime: a #GDateTime
- *
- * Creates a new #GDateTime that reprents @datetime in Universal coordinated
- * time.
- *
- * Return value: the newly created #GDateTime which should be freed with
- *   g_date_time_unref().
- *
- * Since: 2.26
- */
-GDateTime *
-g_date_time_to_utc (const GDateTime *datetime)
-{
-  GDateTime *dt;
-  GTimeZone *utc;
-
-  g_return_val_if_fail (datetime != NULL, NULL);
-
-  utc = g_time_zone_new_utc ();
-  dt = g_date_time_copy (datetime);
-  if (!g_date_time_change_zone (dt, utc))
-    {
-      g_date_time_unref (dt);
-      dt = NULL;
-    }
-  g_time_zone_unref (utc);
-
-  return dt;
-}
-
-/**
- * g_date_time_new_today:
- *
- * Createsa new #GDateTime that represents Midnight on the current day.
- *
- * Return value: the newly created #GDateTime which should be freed with
- *   g_date_time_unref().
- *
- * Since: 2.26
- */
-GDateTime*
-g_date_time_new_today (void)
-{
-  GDateTime *dt;
-
-  dt = g_date_time_new_now ();
-  dt->usec = 0;
-
-  return dt;
-}
-
-/**
- * g_date_time_new_utc_now:
- *
- * Creates a new #GDateTime that represents the current instant in Universal
- * Coordinated Time (UTC).
- *
- * Return value: the newly created #GDateTime which should be freed with
- *   g_date_time_unref().
- *
- * Since: 2.26
- */
-GDateTime *
-g_date_time_new_utc_now (void)
-{
-  GDateTime *utc, *now;
-
-  now = g_date_time_new_now ();
-  utc = g_date_time_to_utc (now);
-  g_date_time_unref (now);
-
-  return utc;
-}
-
-/**
- * g_date_time_get_week_of_year:
- *
- * Returns the numeric week of the respective year.
- *
- * Return value: the week of the year
- *
- * Since: 2.26
- */
-gint
-g_date_time_get_week_of_year (const GDateTime *datetime)
-{
-  gint weeknum;
-
-  g_return_val_if_fail (datetime != NULL, 0);
-
-  g_date_time_get_week_number (datetime, &weeknum, NULL, NULL);
-
-  return weeknum;
-}
 
 /* Epilogue {{{1 */
 /* vim:set foldmethod=marker: */
diff --git a/glib/gdatetime.h b/glib/gdatetime.h
index 0e276e5..210f13a 100644
--- a/glib/gdatetime.h
+++ b/glib/gdatetime.h
@@ -1,20 +1,26 @@
-/* gdatetime.h
- *
+/*
  * Copyright (C) 2009-2010 Christian Hergert <chris dronelabs com>
+ * Copyright © 2010 Codethink Limited
  *
- * This is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * licence, or (at your option) any later version.
  *
- * This is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
+ * This is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ * License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
+ * USA.
+ *
+ * Authors: Christian Hergert <chris dronelabs com>
+ *          Thiago Santos <thiago sousa santos collabora co uk>
+ *          Emmanuele Bassi <ebassi linux intel com>
+ *          Ryan Lortie <desrt desrt ca>
  */
 
 #if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
@@ -24,8 +30,7 @@
 #ifndef __G_DATE_TIME_H__
 #define __G_DATE_TIME_H__
 
-#include <time.h>
-#include <glib/gtypes.h>
+#include <glib/gtimezone.h>
 
 G_BEGIN_DECLS
 
@@ -93,97 +98,123 @@ typedef gint64 GTimeSpan;
  */
 typedef struct _GDateTime GDateTime;
 
-GDateTime *           g_date_time_new_now                (void);
-GDateTime *           g_date_time_new_today              (void);
-GDateTime *           g_date_time_new_utc_now            (void);
-GDateTime *           g_date_time_new_from_date          (gint             year,
-                                                          gint             month,
-                                                          gint             day);
-GDateTime *           g_date_time_new_from_epoch         (gint64           secs);
-GDateTime *           g_date_time_new_from_timeval       (GTimeVal        *tv);
-GDateTime *           g_date_time_new_full               (gint             year,
-                                                          gint             month,
-                                                          gint             day,
-                                                          gint             hour,
-                                                          gint             minute,
-                                                          gdouble          second,
-                                                          const gchar     *time_zone);
-
-GDateTime *           g_date_time_ref                    (GDateTime       *datetime);
-void                  g_date_time_unref                  (GDateTime       *datetime);
-
-GDateTime *           g_date_time_add                    (const GDateTime *datetime,
-                                                          GTimeSpan        timespan);
-GDateTime *           g_date_time_add_days               (const GDateTime *datetime,
-                                                          gint             days);
-GDateTime *           g_date_time_add_hours              (const GDateTime *datetime,
-                                                          gint             hours);
-GDateTime *           g_date_time_add_milliseconds       (const GDateTime *datetime,
-                                                          gint             milliseconds);
-GDateTime *           g_date_time_add_minutes            (const GDateTime *datetime,
-                                                          gint             minutes);
-GDateTime *           g_date_time_add_months             (const GDateTime *datetime,
-                                                          gint             months);
-GDateTime *           g_date_time_add_seconds            (const GDateTime *datetime,
-                                                          gint             seconds);
-GDateTime *           g_date_time_add_weeks              (const GDateTime *datetime,
-                                                          gint             weeks);
-GDateTime *           g_date_time_add_years              (const GDateTime *datetime,
-                                                          gint             years);
-GDateTime *           g_date_time_add_full               (const GDateTime *datetime,
-                                                          gint             years,
-                                                          gint             months,
-                                                          gint             days,
-                                                          gint             hours,
-                                                          gint             minutes,
-                                                          gint             seconds);
-
-GDateTime *           g_date_time_day                    (const GDateTime  *datetime);
-
-gint                  g_date_time_compare                (gconstpointer   dt1,
-                                                          gconstpointer   dt2);
-gboolean              g_date_time_equal                  (gconstpointer   dt1,
-                                                          gconstpointer   dt2);
-guint                 g_date_time_hash                   (gconstpointer   datetime);
-
-GTimeSpan             g_date_time_difference             (const GDateTime *begin,
-                                                          const GDateTime *end);
-
-void                  g_date_time_get_julian             (const GDateTime *datetime,
-                                                          gint            *period,
-                                                          gint            *julian,
-                                                          gint            *hour,
-                                                          gint            *minute,
-                                                          gint            *second);
-gint                  g_date_time_get_hour               (const GDateTime *datetime);
-gint                  g_date_time_get_minute             (const GDateTime *datetime);
-gint                  g_date_time_get_second             (const GDateTime *datetime);
-gint                  g_date_time_get_millisecond        (const GDateTime *datetime);
-gint                  g_date_time_get_microsecond        (const GDateTime *datetime);
-gint                  g_date_time_get_day_of_week        (const GDateTime *datetime);
-gint                  g_date_time_get_day_of_month       (const GDateTime *datetime);
-gint                  g_date_time_get_week_of_year       (const GDateTime *datetime);
-gint                  g_date_time_get_day_of_year        (const GDateTime *datetime);
-gint                  g_date_time_get_month              (const GDateTime *datetime);
-gint                  g_date_time_get_year               (const GDateTime *datetime);
-void                  g_date_time_get_dmy                (const GDateTime *datetime,
-                                                          gint            *day,
-                                                          gint            *month,
-                                                          gint            *year);
-
-GTimeSpan             g_date_time_get_utc_offset         (const GDateTime *datetime);
-G_CONST_RETURN gchar *g_date_time_get_timezone_abbreviation (const GDateTime *datetime);
-gboolean              g_date_time_is_daylight_savings    (const GDateTime *datetime);
-
-gboolean              g_date_time_is_leap_year           (const GDateTime *datetime);
-
-GDateTime *           g_date_time_to_local               (const GDateTime *datetime);
-gint64                g_date_time_to_epoch               (const GDateTime *datetime);
-void                  g_date_time_to_timeval             (const GDateTime *datetime,
-                                                          GTimeVal        *tv);
-GDateTime *           g_date_time_to_utc                 (const GDateTime *datetime);
-gchar *               g_date_time_format                 (const GDateTime *datetime,
-                                                          const gchar     *format) G_GNUC_MALLOC;
+GDateTime *             g_date_time_ref                                 (GDateTime      *datetime);
+void                    g_date_time_unref                               (GDateTime      *datetime);
+
+GDateTime *             g_date_time_new_now_local                       (void);
+GDateTime *             g_date_time_new_now_utc                         (void);
+GDateTime *             g_date_time_new_now                             (GTimeZone      *tz);
+
+GDateTime *             g_date_time_new_from_unix_local                 (gint64          secs);
+GDateTime *             g_date_time_new_from_unix_utc                   (gint64          secs);
+GDateTime *             g_date_time_new_from_unix                       (GTimeZone      *timezone,
+                                                                         gint64          secs);
+GDateTime *             g_date_time_new_from_timeval_local              (const GTimeVal *tv);
+GDateTime *             g_date_time_new_from_timeval_utc                (const GTimeVal *tv);
+GDateTime *             g_date_time_new_from_timeval                    (GTimeZone      *timezone,
+                                                                         const GTimeVal *tv);
+
+GDateTime *             g_date_time_new_local                           (gint            year,
+                                                                         gint            month,
+                                                                         gint            day,
+                                                                         gint            hour,
+                                                                         gint            minute,
+                                                                         gdouble         second);
+GDateTime *             g_date_time_new_local_full                      (gint            year,
+                                                                         gint            month,
+                                                                         gint            day,
+                                                                         gint            hour,
+                                                                         gint            minute,
+                                                                         gdouble         second,
+                                                                         gboolean        is_dst);
+GDateTime *             g_date_time_new_utc                             (gint            year,
+                                                                         gint            month,
+                                                                         gint            day,
+                                                                         gint            hour,
+                                                                         gint            minute,
+                                                                         gdouble         second);
+GDateTime *             g_date_time_new                                 (GTimeZone      *tz,
+                                                                         gint            year,
+                                                                         gint            month,
+                                                                         gint            day,
+                                                                         gint            hour,
+                                                                         gint            minute,
+                                                                         gdouble         second);
+GDateTime *             g_date_time_new_full                            (GTimeZone      *tz,
+                                                                         gint            year,
+                                                                         gint            month,
+                                                                         gint            day,
+                                                                         gint            hour,
+                                                                         gint            minute,
+                                                                         gdouble         second,
+                                                                         gboolean        is_dst);
+
+GDateTime *             g_date_time_add                                 (GDateTime      *datetime,
+                                                                         GTimeSpan       timespan);
+GDateTime *             g_date_time_add_days                            (GDateTime      *datetime,
+                                                                         gint            days);
+GDateTime *             g_date_time_add_hours                           (GDateTime      *datetime,
+                                                                         gint            hours);
+GDateTime *             g_date_time_add_minutes                         (GDateTime      *datetime,
+                                                                         gint            minutes);
+GDateTime *             g_date_time_add_months                          (GDateTime      *datetime,
+                                                                         gint            months);
+GDateTime *             g_date_time_add_seconds                         (GDateTime      *datetime,
+                                                                         gdouble         seconds);
+GDateTime *             g_date_time_add_weeks                           (GDateTime      *datetime,
+                                                                         gint            weeks);
+GDateTime *             g_date_time_add_years                           (GDateTime      *datetime,
+                                                                         gint            years);
+GDateTime *             g_date_time_add_full                            (GDateTime      *datetime,
+                                                                         gint            years,
+                                                                         gint            months,
+                                                                         gint            days,
+                                                                         gint            hours,
+                                                                         gint            minutes,
+                                                                         gdouble         seconds);
+
+gint                    g_date_time_compare                             (gconstpointer   dt1,
+                                                                         gconstpointer   dt2);
+gboolean                g_date_time_equal                               (gconstpointer   dt1,
+                                                                         gconstpointer   dt2);
+guint                   g_date_time_hash                                (gconstpointer   datetime);
+
+GTimeSpan               g_date_time_difference                          (GDateTime      *begin,
+                                                                         GDateTime      *end);
+
+gint                    g_date_time_get_hour                            (GDateTime      *datetime);
+gint                    g_date_time_get_minute                          (GDateTime      *datetime);
+gint                    g_date_time_get_second                          (GDateTime      *datetime);
+gint                    g_date_time_get_microsecond                     (GDateTime      *datetime);
+gdouble                 g_date_time_get_seconds                         (GDateTime      *datetime);
+gint                    g_date_time_get_day_of_week                     (GDateTime      *datetime);
+gint                    g_date_time_get_day_of_month                    (GDateTime      *datetime);
+gint                    g_date_time_get_week_of_year                    (GDateTime      *datetime);
+gint                    g_date_time_get_day_of_year                     (GDateTime      *datetime);
+gint                    g_date_time_get_month                           (GDateTime      *datetime);
+gint                    g_date_time_get_year                            (GDateTime      *datetime);
+void                    g_date_time_get_ymd                             (GDateTime      *datetime,
+                                                                         gint           *year,
+                                                                         gint           *month,
+                                                                         gint           *day);
+
+gint64                  g_date_time_to_unix                             (GDateTime      *datetime);
+gboolean                g_date_time_to_timeval                          (GDateTime      *datetime,
+                                                                         GTimeVal       *tv);
+
+GTimeSpan               g_date_time_get_utc_offset                      (GDateTime      *datetime);
+const gchar *           g_date_time_get_timezone_abbreviation           (GDateTime      *datetime);
+gboolean                g_date_time_is_daylight_savings                 (GDateTime      *datetime);
+
+gboolean                g_date_time_is_leap_year                        (GDateTime      *datetime);
+
+GDateTime *             g_date_time_to_local                            (GDateTime      *datetime);
+GDateTime *             g_date_time_to_utc                              (GDateTime      *datetime);
+GDateTime *             g_date_time_to_timezone                         (GDateTime      *datetime,
+                                                                         GTimeZone      *tz);
+
+gchar *                 g_date_time_format                              (GDateTime      *datetime,
+                                                                         const gchar    *format) G_GNUC_MALLOC;
 
 G_END_DECLS
 
diff --git a/glib/glib.symbols b/glib/glib.symbols
index a0e0911..ec8763f 100644
--- a/glib/glib.symbols
+++ b/glib/glib.symbols
@@ -329,24 +329,20 @@ g_date_time_add
 g_date_time_add_days
 g_date_time_add_full
 g_date_time_add_hours
-g_date_time_add_milliseconds
 g_date_time_add_minutes
 g_date_time_add_months
 g_date_time_add_seconds
 g_date_time_add_weeks
 g_date_time_add_years
 g_date_time_compare
-g_date_time_day
 g_date_time_difference
 g_date_time_equal
+g_date_time_format G_GNUC_MALLOC
 g_date_time_get_day_of_month
 g_date_time_get_day_of_week
 g_date_time_get_day_of_year
-g_date_time_get_dmy
 g_date_time_get_hour
-g_date_time_get_julian
 g_date_time_get_microsecond
-g_date_time_get_millisecond
 g_date_time_get_minute
 g_date_time_get_month
 g_date_time_get_second
@@ -354,21 +350,28 @@ g_date_time_get_timezone_abbreviation
 g_date_time_get_utc_offset
 g_date_time_get_week_of_year
 g_date_time_get_year
+g_date_time_get_ymd
 g_date_time_hash
 g_date_time_is_daylight_savings
-g_date_time_is_leap_year
-g_date_time_new_from_date
-g_date_time_new_from_epoch
+g_date_time_new
 g_date_time_new_from_timeval
+g_date_time_new_from_timeval_local
+g_date_time_new_from_timeval_utc
+g_date_time_new_from_unix
+g_date_time_new_from_unix_local
+g_date_time_new_from_unix_utc
 g_date_time_new_full
+g_date_time_new_local
+g_date_time_new_local_full
 g_date_time_new_now
-g_date_time_new_today
-g_date_time_new_utc_now
-g_date_time_format G_GNUC_MALLOC
+g_date_time_new_now_local
+g_date_time_new_now_utc
+g_date_time_new_utc
 g_date_time_ref
 g_date_time_to_local
-g_date_time_to_epoch
 g_date_time_to_timeval
+g_date_time_to_timezone
+g_date_time_to_unix
 g_date_time_to_utc
 g_date_time_unref
 #endif
diff --git a/glib/gtimezone.c b/glib/gtimezone.c
index 6d71d9c..ce42f50 100644
--- a/glib/gtimezone.c
+++ b/glib/gtimezone.c
@@ -490,7 +490,7 @@ interval_end (GTimeZone *tz,
               gint       interval)
 {
   if (interval < tz->timecnt)
-    return gint64_from_be (tz->trans[interval]);
+    return gint64_from_be (tz->trans[interval]) - 1;
 
   return G_MAXINT64;
 }
@@ -520,14 +520,20 @@ inline static gint64
 interval_local_start (GTimeZone *tz,
                       gint       interval)
 {
-  return interval_start (tz, interval) + interval_offset (tz, interval);
+  if (interval)
+    return interval_start (tz, interval) + interval_offset (tz, interval);
+
+  return G_MININT64;
 }
 
 inline static gint64
 interval_local_end (GTimeZone *tz,
                     gint       interval)
 {
-  return interval_end (tz, interval) + interval_offset (tz, interval) - 1;
+  if (interval < tz->timecnt)
+    return interval_end (tz, interval) + interval_offset (tz, interval);
+
+  return G_MAXINT64;
 }
 
 static gboolean
@@ -556,16 +562,7 @@ interval_valid (GTimeZone *tz,
  * In any of the cases where g_time_zone_find_interval() succeeds then
  * this function returns the same value, without modifying @time.
  *
- * In order to succeed, this function treats @type merely as a hint.
- * The distinction between %G_TIME_TYPE_STANDARD and
- * %G_TIME_TYPE_DAYLIGHT is ignored except in the case that the given
- * @time is ambiguous.  In Toronto, for example, 01:30 on November 7th
- * 2010 occured twice (once inside of daylight savings time and the
- * next, an hour later, outside of daylight savings time).  In this
- * case, the different value of @type would result in a different
- * interval being returned.
- *
- * This function may also modify @time in order to deal with
+ * This function may, however, modify @time in order to deal with
  * non-existent times.  If the non-existent local @time of 02:30 were
  * requested on March 13th 2010 in Toronto then this function would
  * adjust @time to be 03:00 and return the interval containing the
@@ -647,18 +644,19 @@ g_time_zone_adjust_time (GTimeZone *tz,
  *
  * If @type is %G_TIME_TYPE_UNIVERSAL then this function will always
  * succeed (since universal time is monotonic and continuous).
- * Otherwise, there are two situations for which this function could
- * fail.
  *
- * First, it's possible to pick a local time that simply does not exist.
- * In Toronto, for example, 02:00 on March 14th 2010 does not exist (due
- * to the leap forward to begin daylight savings time).
+ * Otherwise @time is treated is local time.  The distinction between
+ * %G_TIME_TYPE_STANDARD and %G_TIME_TYPE_DAYLIGHT is ignored except in
+ * the case that the given @time is ambiguous.  In Toronto, for example,
+ * 01:30 on November 7th 2010 occured twice (once inside of daylight
+ * savings time and the next, an hour later, outside of daylight savings
+ * time).  In this case, the different value of @type would result in a
+ * different interval being returned.
  *
- * Second, it's possible that the given @type was not a match for the
- * type of time in effect at the given local time (ie:
- * %G_TIME_TYPE_STANDARD was specified during an interval of daylight
- * savings time or %G_TIME_TYPE_DAYLIGHT was specified during an
- * interval of standard time).
+ * It is still possible for this function to fail.  In Toronto, for
+ * example, 02:00 on March 14th 2010 does not exist (due to the leap
+ * forward to begin daylight savings time).  -1 is returned in that
+ * case.
  *
  * Returns: the interval containing @time, or -1 in case of failure
  *
@@ -700,9 +698,6 @@ g_time_zone_find_interval (GTimeZone *tz,
 
       else if (i < tz->timecnt && time >= interval_local_start (tz, i + 1))
         i++;
-
-      else
-        return -1;
     }
 
   return i;
diff --git a/glib/gtimezone.h b/glib/gtimezone.h
index afcb292..8bc6684 100644
--- a/glib/gtimezone.h
+++ b/glib/gtimezone.h
@@ -1,20 +1,20 @@
 /*
  * Copyright © 2010 Codethink Limited
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the licence, or (at your option) any later version.
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * licence, or (at your option) any later version.
  *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
  *
  * Author: Ryan Lortie <desrt desrt ca>
  */
diff --git a/glib/tests/gdatetime.c b/glib/tests/gdatetime.c
index 4253053..846fbc8 100644
--- a/glib/tests/gdatetime.c
+++ b/glib/tests/gdatetime.c
@@ -73,7 +73,7 @@ test_GDateTime_now (void)
   memset (&tm, 0, sizeof (tm));
   get_localtime_tm (time (NULL), &tm);
 
-  dt = g_date_time_new_now ();
+  dt = g_date_time_new_now_local ();
 
   g_assert_cmpint (g_date_time_get_year (dt), ==, 1900 + tm.tm_year);
   g_assert_cmpint (g_date_time_get_month (dt), ==, 1 + tm.tm_mon);
@@ -87,27 +87,7 @@ test_GDateTime_now (void)
 }
 
 static void
-test_GDateTime_today (void)
-{
-  GDateTime *dt;
-  struct tm tm;
-
-  memset (&tm, 0, sizeof (tm));
-  get_localtime_tm (time (NULL), &tm);
-
-  dt = g_date_time_new_today ();
-  g_assert_cmpint (g_date_time_get_year (dt), ==, 1900 + tm.tm_year);
-  g_assert_cmpint (g_date_time_get_month (dt), ==, 1 + tm.tm_mon);
-  g_assert_cmpint (g_date_time_get_day_of_month (dt), ==, tm.tm_mday);
-  g_assert_cmpint (g_date_time_get_hour (dt), ==, 0);
-  g_assert_cmpint (g_date_time_get_minute (dt), ==, 0);
-  g_assert_cmpint (g_date_time_get_second (dt), ==, 0);
-  g_assert_cmpint (g_date_time_get_millisecond (dt), ==, 0);
-  g_date_time_unref (dt);
-}
-
-static void
-test_GDateTime_new_from_epoch (void)
+test_GDateTime_new_from_unix (void)
 {
   GDateTime *dt;
   struct tm  tm;
@@ -117,7 +97,7 @@ test_GDateTime_new_from_epoch (void)
   t = time (NULL);
   get_localtime_tm (t, &tm);
 
-  dt = g_date_time_new_from_epoch (t);
+  dt = g_date_time_new_from_unix_local (t);
   g_assert_cmpint (g_date_time_get_year (dt), ==, 1900 + tm.tm_year);
   g_assert_cmpint (g_date_time_get_month (dt), ==, 1 + tm.tm_mon);
   g_assert_cmpint (g_date_time_get_day_of_month (dt), ==, tm.tm_mday);
@@ -135,7 +115,7 @@ test_GDateTime_new_from_epoch (void)
   tm.tm_sec = 0;
   t = mktime (&tm);
 
-  dt = g_date_time_new_from_epoch (t);
+  dt = g_date_time_new_from_unix_local (t);
   g_assert_cmpint (g_date_time_get_year (dt), ==, 1970);
   g_assert_cmpint (g_date_time_get_month (dt), ==, 1);
   g_assert_cmpint (g_date_time_get_day_of_month (dt), ==, 1);
@@ -146,99 +126,68 @@ test_GDateTime_new_from_epoch (void)
 }
 
 static void
-test_GDateTime_is_leap_year (void)
-{
-  GDateTime *dt;
-  gint       i;
-
-  for (i = 1; i <= 3000; i++)
-    {
-      dt = g_date_time_new_from_date (i, 1, 1);
-      if ((((i % 4) == 0) && ((i % 100) != 0)) || ((i % 400) == 0))
-        g_assert (g_date_time_is_leap_year (dt));
-      else
-        g_assert (!g_date_time_is_leap_year (dt));
-      g_date_time_unref (dt);
-    }
-}
-
-static void
 test_GDateTime_compare (void)
 {
   GDateTime *dt1, *dt2;
   gint       i;
 
-  dt1 = g_date_time_new_from_date (2000, 1, 1);
+  dt1 = g_date_time_new_utc (2000, 1, 1, 0, 0, 0);
 
   for (i = 1; i < 2000; i++)
     {
-      dt2 = g_date_time_new_from_date (i, 12, 31);
+      dt2 = g_date_time_new_utc (i, 12, 31, 0, 0, 0);
       g_assert_cmpint (1, ==, g_date_time_compare (dt1, dt2));
       g_date_time_unref (dt2);
     }
 
-  dt2 = g_date_time_new_full (1999, 12, 31, 23, 59, 59, "Z");
+  dt2 = g_date_time_new_utc (1999, 12, 31, 23, 59, 59);
   g_assert_cmpint (1, ==, g_date_time_compare (dt1, dt2));
   g_date_time_unref (dt2);
 
-  dt2 = g_date_time_new_full (2000, 1, 1, 0, 0, 1, "Z");
+  dt2 = g_date_time_new_utc (2000, 1, 1, 0, 0, 1);
   g_assert_cmpint (-1, ==, g_date_time_compare (dt1, dt2));
   g_date_time_unref (dt2);
 
-  dt2 = g_date_time_new_full (2000, 1, 1, 0, 0, 0, "Z");
+  dt2 = g_date_time_new_utc (2000, 1, 1, 0, 0, 0);
   g_assert_cmpint (0, ==, g_date_time_compare (dt1, dt2));
   g_date_time_unref (dt2);
   g_date_time_unref (dt1);
 }
 
 static void
-test_GDateTime_date (void)
-{
-  GDateTime *dt1, *dt2;
-
-  dt1 = g_date_time_new_full (2009, 10, 19, 13, 0, 55, "Z");
-  dt2 = g_date_time_day (dt1);
-  g_assert (dt1 != NULL);
-  g_assert (dt2 != NULL);
-  g_assert_cmpint (2009, ==, g_date_time_get_year (dt2));
-  g_assert_cmpint (10, ==, g_date_time_get_month (dt2));
-  g_assert_cmpint (19, ==, g_date_time_get_day_of_month (dt2));
-  g_assert_cmpint (0, ==, g_date_time_get_hour (dt2));
-  g_assert_cmpint (0, ==, g_date_time_get_minute (dt2));
-  g_assert_cmpint (0, ==, g_date_time_get_second (dt2));
-  g_date_time_unref (dt1);
-  g_date_time_unref (dt2);
-}
-
-static void
 test_GDateTime_equal (void)
 {
   GDateTime *dt1, *dt2;
+  GTimeZone *tz;
 
-  dt1 = g_date_time_new_from_date (2009, 10, 19);
-  dt2 = g_date_time_new_from_date (2009, 10, 19);
+  dt1 = g_date_time_new_local (2009, 10, 19, 0, 0, 0);
+  dt2 = g_date_time_new_local (2009, 10, 19, 0, 0, 0);
   g_assert (g_date_time_equal (dt1, dt2));
   g_date_time_unref (dt1);
   g_date_time_unref (dt2);
 
-  dt1 = g_date_time_new_from_date (2009, 10, 18);
-  dt2 = g_date_time_new_from_date (2009, 10, 19);
+  dt1 = g_date_time_new_local (2009, 10, 18, 0, 0, 0);
+  dt2 = g_date_time_new_local (2009, 10, 19, 0, 0, 0);
   g_assert (!g_date_time_equal (dt1, dt2));
   g_date_time_unref (dt1);
   g_date_time_unref (dt2);
 
   /* UTC-0300 and not in DST */
-  dt1 = g_date_time_new_full (2010, 5, 24,  8, 0, 0, "-03:00");
+  tz = g_time_zone_new ("-03:00");
+  dt1 = g_date_time_new (tz, 2010, 5, 24,  8, 0, 0);
+  g_time_zone_unref (tz);
   g_assert_cmpint (g_date_time_get_utc_offset (dt1) / G_USEC_PER_SEC, ==, (-3 * 3600));
   /* UTC */
-  dt2 = g_date_time_new_full (2010, 5, 24, 11, 0, 0, "Z");
+  dt2 = g_date_time_new_utc (2010, 5, 24, 11, 0, 0);
   g_assert_cmpint (g_date_time_get_utc_offset (dt2), ==, 0);
 
   g_assert (g_date_time_equal (dt1, dt2));
   g_date_time_unref (dt1);
 
   /* America/Recife is in UTC-0300 */
-  dt1 = g_date_time_new_full (2010, 5, 24,  8, 0, 0, "America/Recife");
+  tz = g_time_zone_new ("America/Recife");
+  dt1 = g_date_time_new (tz, 2010, 5, 24,  8, 0, 0);
+  g_time_zone_unref (tz);
   g_assert_cmpint (g_date_time_get_utc_offset (dt1) / G_USEC_PER_SEC, ==, (-3 * 3600));
   g_assert (g_date_time_equal (dt1, dt2));
   g_date_time_unref (dt1);
@@ -250,11 +199,11 @@ test_GDateTime_get_day_of_week (void)
 {
   GDateTime *dt;
 
-  dt = g_date_time_new_from_date (2009, 10, 19);
+  dt = g_date_time_new_local (2009, 10, 19, 0, 0, 0);
   g_assert_cmpint (1, ==, g_date_time_get_day_of_week (dt));
   g_date_time_unref (dt);
 
-  dt = g_date_time_new_from_date (2000, 10, 1);
+  dt = g_date_time_new_local (2000, 10, 1, 0, 0, 0);
   g_assert_cmpint (7, ==, g_date_time_get_day_of_week (dt));
   g_date_time_unref (dt);
 }
@@ -264,25 +213,25 @@ test_GDateTime_get_day_of_month (void)
 {
   GDateTime *dt;
 
-  dt = g_date_time_new_from_date (2009, 10, 19);
+  dt = g_date_time_new_local (2009, 10, 19, 0, 0, 0);
   g_assert_cmpint (g_date_time_get_day_of_month (dt), ==, 19);
   g_date_time_unref (dt);
 
-  dt = g_date_time_new_from_date (1400, 3, 12);
+  dt = g_date_time_new_local (1400, 3, 12, 0, 0, 0);
   g_assert_cmpint (g_date_time_get_day_of_month (dt), ==, 12);
   g_date_time_unref (dt);
 
-  dt = g_date_time_new_from_date (1800, 12, 31);
+  dt = g_date_time_new_local (1800, 12, 31, 0, 0, 0);
   g_assert_cmpint (g_date_time_get_day_of_month (dt), ==, 31);
   g_date_time_unref (dt);
 
-  dt = g_date_time_new_from_date (1000, 1, 1);
+  dt = g_date_time_new_local (1000, 1, 1, 0, 0, 0);
   g_assert_cmpint (g_date_time_get_day_of_month (dt), ==, 1);
   g_date_time_unref (dt);
 }
 
 static void
-test_GDateTime_get_dmy (void)
+test_GDateTime_get_ymd (void)
 {
    GDateTime *dt;
    struct tm tm;
@@ -296,8 +245,8 @@ test_GDateTime_get_dmy (void)
    memset (&tm, 0, sizeof (struct tm));
    get_localtime_tm (t, &tm);
 
-   dt = g_date_time_new_from_epoch (t);
-   g_date_time_get_dmy(dt, &d, &m, &y);
+   dt = g_date_time_new_from_unix_utc (t);
+   g_date_time_get_ymd(dt, &y, &m, &d);
    g_assert_cmpint(y, ==, tm.tm_year + 1900);
    g_assert_cmpint(m, ==, tm.tm_mon + 1);
    g_assert_cmpint(d, ==, tm.tm_mday);
@@ -313,9 +262,9 @@ test_GDateTime_get_dmy (void)
          {
            for (d = 1; d <= days[leap][m]; d++)
              {
-               GDateTime *dt1 = g_date_time_new_from_date (y, m, d);
+               GDateTime *dt1 = g_date_time_new_utc (y, m, d, 0, 0, 0);
 
-               g_date_time_get_dmy (dt1, &d2, &m2, &y2);
+               g_date_time_get_ymd (dt1, &y2, &m2, &d2);
                g_assert_cmpint (y, ==, y2);
                g_assert_cmpint (m, ==, m2);
                g_assert_cmpint (d, ==, d2);
@@ -330,86 +279,53 @@ test_GDateTime_get_hour (void)
 {
   GDateTime *dt;
 
-  dt = g_date_time_new_full (2009, 10, 19, 15, 13, 11, "Z");
+  dt = g_date_time_new_utc (2009, 10, 19, 15, 13, 11);
   g_assert_cmpint (15, ==, g_date_time_get_hour (dt));
   g_date_time_unref (dt);
 
-  dt = g_date_time_new_full (100, 10, 19, 1, 0, 0, "Z");
+  dt = g_date_time_new_utc (100, 10, 19, 1, 0, 0);
   g_assert_cmpint (1, ==, g_date_time_get_hour (dt));
   g_date_time_unref (dt);
 
-  dt = g_date_time_new_full (100, 10, 19, 0, 0, 0, "Z");
+  dt = g_date_time_new_utc (100, 10, 19, 0, 0, 0);
   g_assert_cmpint (0, ==, g_date_time_get_hour (dt));
   g_date_time_unref (dt);
 
-  dt = g_date_time_new_full (100, 10, 1, 23, 59, 59, "Z");
+  dt = g_date_time_new_utc (100, 10, 1, 23, 59, 59);
   g_assert_cmpint (23, ==, g_date_time_get_hour (dt));
   g_date_time_unref (dt);
 }
 
 static void
-test_GDateTime_get_julian (void)
-{
-  GDateTime *dt;
-  gint period, julian, hour = 1, min = 1, sec = 1;
-
-  dt = g_date_time_new_from_date (1984, 8, 16);
-  g_date_time_get_julian (dt, &period, &julian, &hour, &min, &sec);
-  g_assert_cmpint (period, ==, 0);
-  g_assert_cmpint (julian, ==, 2445929);
-  g_assert_cmpint (hour, ==, 0);
-  g_assert_cmpint (min, ==, 0);
-  g_assert_cmpint (sec, ==, 0);
-  g_date_time_unref (dt);
-}
-
-static void
 test_GDateTime_get_microsecond (void)
 {
   GTimeVal   tv;
   GDateTime *dt;
 
   g_get_current_time (&tv);
-  dt = g_date_time_new_from_timeval (&tv);
+  dt = g_date_time_new_from_timeval_local (&tv);
   g_assert_cmpint (tv.tv_usec, ==, g_date_time_get_microsecond (dt));
   g_date_time_unref (dt);
 }
 
 static void
-test_GDateTime_get_millisecond (void)
-{
-  GTimeVal   tv;
-  GDateTime *dt;
-
-  g_get_current_time (&tv);
-  dt = g_date_time_new_from_timeval (&tv);
-  g_assert_cmpint ((tv.tv_usec / 1000), ==, g_date_time_get_millisecond (dt));
-  g_date_time_unref (dt);
-
-  dt = g_date_time_new_full (2010, 9, 15, 12, 0, 0.1234, "Z");
-  g_assert_cmpint (123, ==, g_date_time_get_millisecond (dt));
-  g_assert_cmpint (123400, ==, g_date_time_get_microsecond (dt));
-  g_date_time_unref (dt);
-}
-
-static void
 test_GDateTime_get_year (void)
 {
   GDateTime *dt;
 
-  dt = g_date_time_new_from_date (2009, 1, 1);
+  dt = g_date_time_new_local (2009, 1, 1, 0, 0, 0);
   g_assert_cmpint (2009, ==, g_date_time_get_year (dt));
   g_date_time_unref (dt);
 
-  dt = g_date_time_new_from_date (1, 1, 1);
+  dt = g_date_time_new_local (1, 1, 1, 0, 0, 0);
   g_assert_cmpint (1, ==, g_date_time_get_year (dt));
   g_date_time_unref (dt);
 
-  dt = g_date_time_new_from_date (13, 1, 1);
+  dt = g_date_time_new_local (13, 1, 1, 0, 0, 0);
   g_assert_cmpint (13, ==, g_date_time_get_year (dt));
   g_date_time_unref (dt);
 
-  dt = g_date_time_new_from_date (3000, 1, 1);
+  dt = g_date_time_new_local (3000, 1, 1, 0, 0, 0);
   g_assert_cmpint (3000, ==, g_date_time_get_year (dt));
   g_date_time_unref (dt);
 }
@@ -422,7 +338,7 @@ test_GDateTime_hash (void)
   h = g_hash_table_new_full (g_date_time_hash, g_date_time_equal,
                              (GDestroyNotify)g_date_time_unref,
                              NULL);
-  g_hash_table_insert (h, g_date_time_new_now (), NULL);
+  g_hash_table_insert (h, g_date_time_new_now_local (), NULL);
   g_hash_table_remove_all (h);
   g_hash_table_destroy (h);
 }
@@ -434,7 +350,7 @@ test_GDateTime_new_from_timeval (void)
   GTimeVal   tv, tv2;
 
   g_get_current_time (&tv);
-  dt = g_date_time_new_from_timeval (&tv);
+  dt = g_date_time_new_from_timeval_local (&tv);
 
   if (g_test_verbose ())
     g_print ("\nDT%04d-%02d-%02dT%02d:%02d:%02d%s\n",
@@ -453,14 +369,14 @@ test_GDateTime_new_from_timeval (void)
 }
 
 static void
-test_GDateTime_to_epoch (void)
+test_GDateTime_to_unix (void)
 {
   GDateTime *dt;
   time_t     t;
 
   t = time (NULL);
-  dt = g_date_time_new_from_epoch (t);
-  g_assert_cmpint (g_date_time_to_epoch (dt), ==, t);
+  dt = g_date_time_new_from_unix_local (t);
+  g_assert_cmpint (g_date_time_to_unix (dt), ==, t);
   g_date_time_unref (dt);
 }
 
@@ -469,7 +385,7 @@ test_GDateTime_add_years (void)
 {
   GDateTime *dt, *dt2;
 
-  dt = g_date_time_new_from_date (2009, 10, 19);
+  dt = g_date_time_new_local (2009, 10, 19, 0, 0, 0);
   dt2 = g_date_time_add_years (dt, 1);
   g_assert_cmpint (2010, ==, g_date_time_get_year (dt2));
   g_date_time_unref (dt);
@@ -481,7 +397,7 @@ test_GDateTime_add_months (void)
 {
 #define TEST_ADD_MONTHS(y,m,d,a,ny,nm,nd) G_STMT_START { \
   GDateTime *dt, *dt2; \
-  dt = g_date_time_new_full (y, m, d, 0, 0, 0, "Z"); \
+  dt = g_date_time_new_utc (y, m, d, 0, 0, 0); \
   dt2 = g_date_time_add_months (dt, a); \
   ASSERT_DATE (dt2, ny, nm, nd); \
   g_date_time_unref (dt); \
@@ -506,7 +422,7 @@ test_GDateTime_add_days (void)
 {
 #define TEST_ADD_DAYS(y,m,d,a,ny,nm,nd) G_STMT_START { \
   GDateTime *dt, *dt2; \
-  dt = g_date_time_new_from_date (y, m, d); \
+  dt = g_date_time_new_local (y, m, d, 0, 0, 0); \
   dt2 = g_date_time_add_days (dt, a); \
   g_assert_cmpint (ny, ==, g_date_time_get_year (dt2)); \
   g_assert_cmpint (nm, ==, g_date_time_get_month (dt2)); \
@@ -529,7 +445,7 @@ test_GDateTime_add_weeks (void)
 {
 #define TEST_ADD_WEEKS(y,m,d,a,ny,nm,nd) G_STMT_START { \
   GDateTime *dt, *dt2; \
-  dt = g_date_time_new_from_date (y, m, d); \
+  dt = g_date_time_new_local (y, m, d, 0, 0, 0); \
   dt2 = g_date_time_add_weeks (dt, a); \
   g_assert_cmpint (ny, ==, g_date_time_get_year (dt2)); \
   g_assert_cmpint (nm, ==, g_date_time_get_month (dt2)); \
@@ -549,7 +465,7 @@ test_GDateTime_add_hours (void)
 {
 #define TEST_ADD_HOURS(y,m,d,h,mi,s,a,ny,nm,nd,nh,nmi,ns) G_STMT_START { \
   GDateTime *dt, *dt2; \
-  dt = g_date_time_new_full (y, m, d, h, mi, s, "Z"); \
+  dt = g_date_time_new_utc (y, m, d, h, mi, s); \
   dt2 = g_date_time_add_hours (dt, a); \
   g_assert_cmpint (ny, ==, g_date_time_get_year (dt2)); \
   g_assert_cmpint (nm, ==, g_date_time_get_month (dt2)); \
@@ -570,7 +486,7 @@ test_GDateTime_add_full (void)
 {
 #define TEST_ADD_FULL(y,m,d,h,mi,s,ay,am,ad,ah,ami,as,ny,nm,nd,nh,nmi,ns) G_STMT_START { \
   GDateTime *dt, *dt2; \
-  dt = g_date_time_new_full (y, m, d, h, mi, s, "Z"); \
+  dt = g_date_time_new_utc (y, m, d, h, mi, s); \
   dt2 = g_date_time_add_full (dt, ay, am, ad, ah, ami, as); \
   g_assert_cmpint (ny, ==, g_date_time_get_year (dt2)); \
   g_assert_cmpint (nm, ==, g_date_time_get_month (dt2)); \
@@ -600,29 +516,11 @@ test_GDateTime_add_full (void)
 }
 
 static void
-test_GDateTime_add_milliseconds (void)
-{
-#define TEST_ADD_MILLISECOND(i,o) G_STMT_START { \
-  GDateTime *dt, *dt2; \
-  dt = g_date_time_new_from_date (2000, 1, 1); \
-  dt2 = g_date_time_add_milliseconds (dt, i); \
-  g_assert_cmpint (o, ==, g_date_time_get_millisecond (dt2)); \
-  g_date_time_unref (dt); \
-  g_date_time_unref (dt2); \
-} G_STMT_END
-
-  TEST_ADD_MILLISECOND (199, 199);
-  TEST_ADD_MILLISECOND (10001, 1);
-  TEST_ADD_MILLISECOND (22201, 201);
-  TEST_ADD_MILLISECOND (-1000, 0);
-}
-
-static void
 test_GDateTime_add_minutes (void)
 {
 #define TEST_ADD_MINUTES(i,o) G_STMT_START { \
   GDateTime *dt, *dt2; \
-  dt = g_date_time_new_from_date (2000, 1, 1); \
+  dt = g_date_time_new_local (2000, 1, 1, 0, 0, 0); \
   dt2 = g_date_time_add_minutes (dt, i); \
   g_assert_cmpint (o, ==, g_date_time_get_minute (dt2)); \
   g_date_time_unref (dt); \
@@ -641,7 +539,7 @@ test_GDateTime_add_seconds (void)
 {
 #define TEST_ADD_SECONDS(i,o) G_STMT_START { \
   GDateTime *dt, *dt2; \
-  dt = g_date_time_new_from_date (2000, 1, 1); \
+  dt = g_date_time_new_local (2000, 1, 1, 0, 0, 0); \
   dt2 = g_date_time_add_seconds (dt, i); \
   g_assert_cmpint (o, ==, g_date_time_get_second (dt2)); \
   g_date_time_unref (dt); \
@@ -665,9 +563,9 @@ test_GDateTime_diff (void)
 #define TEST_DIFF(y,m,d,y2,m2,d2,u) G_STMT_START { \
   GDateTime *dt1, *dt2; \
   GTimeSpan  ts = 0; \
-  dt1 = g_date_time_new_from_date (y, m, d); \
-  dt2 = g_date_time_new_from_date (y2, m2, d2); \
-  ts = g_date_time_difference (dt1, dt2); \
+  dt1 = g_date_time_new_local (y, m, d, 0, 0, 0); \
+  dt2 = g_date_time_new_local (y2, m2, d2, 0, 0, 0); \
+  ts = g_date_time_difference (dt2, dt1); \
   g_assert_cmpint (ts, ==, u); \
   g_date_time_unref (dt1); \
   g_date_time_unref (dt2); \
@@ -686,7 +584,7 @@ test_GDateTime_get_minute (void)
 {
   GDateTime *dt;
 
-  dt = g_date_time_new_full (2009, 12, 1, 1, 31, 0, "Z");
+  dt = g_date_time_new_utc (2009, 12, 1, 1, 31, 0);
   g_assert_cmpint (31, ==, g_date_time_get_minute (dt));
   g_date_time_unref (dt);
 }
@@ -696,7 +594,7 @@ test_GDateTime_get_month (void)
 {
   GDateTime *dt;
 
-  dt = g_date_time_new_full (2009, 12, 1, 1, 31, 0, "Z");
+  dt = g_date_time_new_utc (2009, 12, 1, 1, 31, 0);
   g_assert_cmpint (12, ==, g_date_time_get_month (dt));
   g_date_time_unref (dt);
 }
@@ -706,29 +604,18 @@ test_GDateTime_get_second (void)
 {
   GDateTime *dt;
 
-  dt = g_date_time_new_full (2009, 12, 1, 1, 31, 44, "Z");
+  dt = g_date_time_new_utc (2009, 12, 1, 1, 31, 44);
   g_assert_cmpint (44, ==, g_date_time_get_second (dt));
   g_date_time_unref (dt);
 }
 
 static void
-test_GDateTime_new_from_date (void)
-{
-  GDateTime *dt;
-
-  dt = g_date_time_new_from_date (2009, 12, 11);
-  g_assert_cmpint (2009, ==, g_date_time_get_year (dt));
-  g_assert_cmpint (12, ==, g_date_time_get_month (dt));
-  g_assert_cmpint (11, ==, g_date_time_get_day_of_month (dt));
-  g_date_time_unref (dt);
-}
-
-static void
 test_GDateTime_new_full (void)
 {
+  GTimeZone *tz;
   GDateTime *dt;
 
-  dt = g_date_time_new_full (2009, 12, 11, 12, 11, 10, "Z");
+  dt = g_date_time_new_utc (2009, 12, 11, 12, 11, 10);
   g_assert_cmpint (2009, ==, g_date_time_get_year (dt));
   g_assert_cmpint (12, ==, g_date_time_get_month (dt));
   g_assert_cmpint (11, ==, g_date_time_get_day_of_month (dt));
@@ -737,7 +624,9 @@ test_GDateTime_new_full (void)
   g_assert_cmpint (10, ==, g_date_time_get_second (dt));
   g_date_time_unref (dt);
 
-  dt = g_date_time_new_full (2010, 5, 24, 8, 4, 0, "America/Recife");
+  tz = g_time_zone_new ("America/Recife");
+  dt = g_date_time_new (tz, 2010, 5, 24, 8, 4, 0);
+  g_time_zone_unref (tz);
   g_assert_cmpint (2010, ==, g_date_time_get_year (dt));
   g_assert_cmpint (5, ==, g_date_time_get_month (dt));
   g_assert_cmpint (24, ==, g_date_time_get_day_of_month (dt));
@@ -750,7 +639,7 @@ test_GDateTime_new_full (void)
 }
 
 static void
-test_GDateTime_utc_now (void)
+test_GDateTime_now_utc (void)
 {
   GDateTime *dt;
   time_t     t;
@@ -769,7 +658,7 @@ test_GDateTime_utc_now (void)
     memcpy (&tm, tmp, sizeof (struct tm));
   }
 #endif
-  dt = g_date_time_new_utc_now ();
+  dt = g_date_time_new_now_utc ();
   g_assert_cmpint (tm.tm_year + 1900, ==, g_date_time_get_year (dt));
   g_assert_cmpint (tm.tm_mon + 1, ==, g_date_time_get_month (dt));
   g_assert_cmpint (tm.tm_mday, ==, g_date_time_get_day_of_month (dt));
@@ -789,7 +678,7 @@ test_GDateTime_get_utc_offset (void)
   memset (&tm, 0, sizeof (tm));
   get_localtime_tm (time (NULL), &tm);
 
-  dt = g_date_time_new_now ();
+  dt = g_date_time_new_now_local ();
   ts = g_date_time_get_utc_offset (dt);
 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
   g_assert_cmpint (ts, ==, (tm.tm_gmtoff * G_TIME_SPAN_SECOND));
@@ -807,7 +696,7 @@ test_GDateTime_to_timeval (void)
   memset (&tv2, 0, sizeof (tv2));
 
   g_get_current_time (&tv1);
-  dt = g_date_time_new_from_timeval (&tv1);
+  dt = g_date_time_new_from_timeval_local (&tv1);
   g_date_time_to_timeval (dt, &tv2);
   g_assert_cmpint (tv1.tv_sec, ==, tv2.tv_sec);
   g_assert_cmpint (tv1.tv_usec, ==, tv2.tv_usec);
@@ -819,8 +708,8 @@ test_GDateTime_to_local (void)
 {
   GDateTime *utc, *now, *dt;
 
-  utc = g_date_time_new_utc_now ();
-  now = g_date_time_new_now ();
+  utc = g_date_time_new_now_utc ();
+  now = g_date_time_new_now_local ();
   dt = g_date_time_to_local (utc);
 
   g_assert_cmpint (g_date_time_get_year (now), ==, g_date_time_get_year (dt));
@@ -851,7 +740,7 @@ test_GDateTime_to_utc (void)
     memcpy (&tm, tmp, sizeof (struct tm));
   }
 #endif
-  dt2 = g_date_time_new_now ();
+  dt2 = g_date_time_new_now_local ();
   dt = g_date_time_to_utc (dt2);
   g_assert_cmpint (tm.tm_year + 1900, ==, g_date_time_get_year (dt));
   g_assert_cmpint (tm.tm_mon + 1, ==, g_date_time_get_month (dt));
@@ -867,7 +756,7 @@ static void
 test_GDateTime_get_day_of_year (void)
 {
 #define TEST_DAY_OF_YEAR(y,m,d,o)                       G_STMT_START {  \
-  GDateTime *__dt = g_date_time_new_from_date ((y), (m), (d));          \
+  GDateTime *__dt = g_date_time_new_local ((y), (m), (d), 0, 0, 0);     \
   g_assert_cmpint ((o), ==, g_date_time_get_day_of_year (__dt));        \
   g_date_time_unref (__dt);                             } G_STMT_END
 
@@ -886,21 +775,21 @@ test_GDateTime_printf (void)
   gchar t_str[16];
 
 #define TEST_PRINTF(f,o)                        G_STMT_START {  \
-GDateTime *__dt = g_date_time_new_from_date (2009, 10, 24);     \
+GDateTime *__dt = g_date_time_new_local (2009, 10, 24, 0, 0, 0);\
   gchar *__p = g_date_time_format (__dt, (f));                  \
   g_assert_cmpstr (__p, ==, (o));                               \
   g_date_time_unref (__dt);                                     \
   g_free (__p);                                 } G_STMT_END
 
 #define TEST_PRINTF_DATE(y,m,d,f,o)             G_STMT_START {  \
-  GDateTime *dt = g_date_time_new_from_date ((y), (m), (d));    \
+  GDateTime *dt = g_date_time_new_local (y, m, d, 0, 0, 0);     \
   gchar *p = g_date_time_format (dt, (f));                      \
   g_assert_cmpstr (p, ==, (o));                                 \
   g_date_time_unref (dt);                                       \
   g_free (p);                                   } G_STMT_END
 
 #define TEST_PRINTF_TIME(h,m,s,f,o)             G_STMT_START { \
-  GDateTime *dt = g_date_time_new_full (2009, 10, 24, (h), (m), (s), "Z"); \
+  GDateTime *dt = g_date_time_new_local (2009, 10, 24, (h), (m), (s)); \
   gchar *p = g_date_time_format (dt, (f));                      \
   g_assert_cmpstr (p, ==, (o));                                 \
   g_date_time_unref (dt);                                       \
@@ -977,9 +866,11 @@ static void
 test_GDateTime_dst (void)
 {
   GDateTime *dt1, *dt2;
+  GTimeZone *tz;
 
   /* this date has the DST state set for Europe/London */
-  dt1 = g_date_time_new_full (2009, 8, 15, 3, 0, 1, "Europe/London");
+  tz = g_time_zone_new ("Europe/London");
+  dt1 = g_date_time_new (tz, 2009, 8, 15, 3, 0, 1);
   g_assert (g_date_time_is_daylight_savings (dt1));
   g_assert_cmpint (g_date_time_get_utc_offset (dt1) / G_USEC_PER_SEC, ==, 3600);
   g_assert_cmpint (g_date_time_get_hour (dt1), ==, 3);
@@ -994,7 +885,7 @@ test_GDateTime_dst (void)
   g_date_time_unref (dt1);
 
   /* now do the reverse: start with a non-DST state and move to DST */
-  dt1 = g_date_time_new_full (2009, 2, 15, 2, 0, 1, "Europe/London");
+  dt1 = g_date_time_new (tz, 2009, 2, 15, 2, 0, 1);
   g_assert (!g_date_time_is_daylight_savings (dt1));
   g_assert_cmpint (g_date_time_get_hour (dt1), ==, 2);
 
@@ -1004,6 +895,7 @@ test_GDateTime_dst (void)
 
   g_date_time_unref (dt2);
   g_date_time_unref (dt1);
+  g_time_zone_unref (tz);
 }
 
 gint
@@ -1017,43 +909,36 @@ main (gint   argc,
   g_test_add_func ("/GDateTime/add_days", test_GDateTime_add_days);
   g_test_add_func ("/GDateTime/add_full", test_GDateTime_add_full);
   g_test_add_func ("/GDateTime/add_hours", test_GDateTime_add_hours);
-  g_test_add_func ("/GDateTime/add_milliseconds", test_GDateTime_add_milliseconds);
   g_test_add_func ("/GDateTime/add_minutes", test_GDateTime_add_minutes);
   g_test_add_func ("/GDateTime/add_months", test_GDateTime_add_months);
   g_test_add_func ("/GDateTime/add_seconds", test_GDateTime_add_seconds);
   g_test_add_func ("/GDateTime/add_weeks", test_GDateTime_add_weeks);
   g_test_add_func ("/GDateTime/add_years", test_GDateTime_add_years);
   g_test_add_func ("/GDateTime/compare", test_GDateTime_compare);
-  g_test_add_func ("/GDateTime/date", test_GDateTime_date);
   g_test_add_func ("/GDateTime/diff", test_GDateTime_diff);
   g_test_add_func ("/GDateTime/equal", test_GDateTime_equal);
   g_test_add_func ("/GDateTime/get_day_of_week", test_GDateTime_get_day_of_week);
   g_test_add_func ("/GDateTime/get_day_of_month", test_GDateTime_get_day_of_month);
   g_test_add_func ("/GDateTime/get_day_of_year", test_GDateTime_get_day_of_year);
-  g_test_add_func ("/GDateTime/get_dmy", test_GDateTime_get_dmy);
+  g_test_add_func ("/GDateTime/get_ymd", test_GDateTime_get_ymd);
   g_test_add_func ("/GDateTime/get_hour", test_GDateTime_get_hour);
-  g_test_add_func ("/GDateTime/get_julian", test_GDateTime_get_julian);
   g_test_add_func ("/GDateTime/get_microsecond", test_GDateTime_get_microsecond);
-  g_test_add_func ("/GDateTime/get_millisecond", test_GDateTime_get_millisecond);
   g_test_add_func ("/GDateTime/get_minute", test_GDateTime_get_minute);
   g_test_add_func ("/GDateTime/get_month", test_GDateTime_get_month);
   g_test_add_func ("/GDateTime/get_second", test_GDateTime_get_second);
   g_test_add_func ("/GDateTime/get_utc_offset", test_GDateTime_get_utc_offset);
   g_test_add_func ("/GDateTime/get_year", test_GDateTime_get_year);
   g_test_add_func ("/GDateTime/hash", test_GDateTime_hash);
-  g_test_add_func ("/GDateTime/is_leap_year", test_GDateTime_is_leap_year);
-  g_test_add_func ("/GDateTime/new_from_date", test_GDateTime_new_from_date);
-  g_test_add_func ("/GDateTime/new_from_epoch", test_GDateTime_new_from_epoch);
+  g_test_add_func ("/GDateTime/new_from_unix", test_GDateTime_new_from_unix);
   g_test_add_func ("/GDateTime/new_from_timeval", test_GDateTime_new_from_timeval);
   g_test_add_func ("/GDateTime/new_full", test_GDateTime_new_full);
   g_test_add_func ("/GDateTime/now", test_GDateTime_now);
   g_test_add_func ("/GDateTime/printf", test_GDateTime_printf);
   g_test_add_func ("/GDateTime/to_local", test_GDateTime_to_local);
-  g_test_add_func ("/GDateTime/to_epoch", test_GDateTime_to_epoch);
+  g_test_add_func ("/GDateTime/to_unix", test_GDateTime_to_unix);
   g_test_add_func ("/GDateTime/to_timeval", test_GDateTime_to_timeval);
   g_test_add_func ("/GDateTime/to_utc", test_GDateTime_to_utc);
-  g_test_add_func ("/GDateTime/today", test_GDateTime_today);
-  g_test_add_func ("/GDateTime/utc_now", test_GDateTime_utc_now);
+  g_test_add_func ("/GDateTime/now_utc", test_GDateTime_now_utc);
   g_test_add_func ("/GDateTime/dst", test_GDateTime_dst);
 
   return g_test_run ();



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