* 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
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
+#include <math.h>
#include <string.h>
#include <time.h>
+#include <gi18n.h>
#include <glib.h>
#include <glib/gstdio.h>
#include <locale.h>
+#ifdef G_OS_WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#ifndef NAN
+#define NAN HUGE_VAL * 0.0f
+#endif
+#endif
+
#define ASSERT_DATE(dt,y,m,d) G_STMT_START { \
+ g_assert_nonnull ((dt)); \
g_assert_cmpint ((y), ==, g_date_time_get_year ((dt))); \
g_assert_cmpint ((m), ==, g_date_time_get_month ((dt))); \
g_assert_cmpint ((d), ==, g_date_time_get_day_of_month ((dt))); \
} G_STMT_END
-#define ASSERT_TIME(dt,H,M,S) G_STMT_START { \
+#define ASSERT_TIME(dt,H,M,S,U) G_STMT_START { \
+ g_assert_nonnull ((dt)); \
g_assert_cmpint ((H), ==, g_date_time_get_hour ((dt))); \
g_assert_cmpint ((M), ==, g_date_time_get_minute ((dt))); \
g_assert_cmpint ((S), ==, g_date_time_get_second ((dt))); \
+ g_assert_cmpint ((U), ==, g_date_time_get_microsecond ((dt))); \
} G_STMT_END
static void
{
GDateTime *dt;
struct tm tm;
+ time_t before;
+ time_t after;
+
+ /* before <= dt.to_unix() <= after, but the inequalities might not be
+ * equality if we're close to the boundary between seconds.
+ * We loop until before == after (and hence dt.to_unix() should equal both)
+ * to guard against that. */
+ do
+ {
+ before = g_get_real_time () / G_TIME_SPAN_SECOND;
- memset (&tm, 0, sizeof (tm));
- get_localtime_tm (time (NULL), &tm);
+ memset (&tm, 0, sizeof (tm));
+ get_localtime_tm (before, &tm);
- dt = g_date_time_new_now_local ();
+ dt = g_date_time_new_now_local ();
+
+ after = g_get_real_time () / G_TIME_SPAN_SECOND;
+ }
+ while (before != after);
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), ==, tm.tm_hour);
g_assert_cmpint (g_date_time_get_minute (dt), ==, tm.tm_min);
- /* XXX we need some fuzzyness here */
- g_assert_cmpint (g_date_time_get_second (dt), >=, tm.tm_sec);
+ g_assert_cmpint (g_date_time_get_second (dt), ==, tm.tm_sec);
g_date_time_unref (dt);
}
memset (&tm, 0, sizeof (tm));
t = time (NULL);
+ g_assert_cmpint (t, !=, (time_t) -1);
get_localtime_tm (t, &tm);
dt = g_date_time_new_from_unix_local (t);
g_assert_cmpint (g_date_time_get_second (dt), ==, tm.tm_sec);
g_date_time_unref (dt);
+ /* Choose 1990-01-01 04:00:00 because no DST leaps happened then. The more
+ * obvious 1990-01-01 00:00:00 was a DST leap in America/Lima (which has,
+ * confusingly, since stopped using DST). */
memset (&tm, 0, sizeof (tm));
tm.tm_year = 90;
tm.tm_mday = 1;
tm.tm_mon = 0;
- tm.tm_hour = 0;
+ tm.tm_hour = 4;
tm.tm_min = 0;
tm.tm_sec = 0;
tm.tm_isdst = -1;
g_assert_cmpint (g_date_time_get_year (dt), ==, 1990);
g_assert_cmpint (g_date_time_get_month (dt), ==, 1);
g_assert_cmpint (g_date_time_get_day_of_month (dt), ==, 1);
- g_assert_cmpint (g_date_time_get_hour (dt), ==, 0);
+ g_assert_cmpint (g_date_time_get_hour (dt), ==, 4);
g_assert_cmpint (g_date_time_get_minute (dt), ==, 0);
g_assert_cmpint (g_date_time_get_second (dt), ==, 0);
g_date_time_unref (dt);
}
+/* Check that trying to create a #GDateTime too far in the future (or past) reliably
+ * fails. Previously, the checks for this overflowed and it silently returned
+ * an incorrect #GDateTime. */
+static void
+test_GDateTime_new_from_unix_overflow (void)
+{
+ GDateTime *dt;
+
+ g_test_bug ("http://bugzilla.gnome.org/782089");
+
+ dt = g_date_time_new_from_unix_utc (G_MAXINT64);
+ g_assert_null (dt);
+
+ dt = g_date_time_new_from_unix_local (G_MAXINT64);
+ g_assert_null (dt);
+
+ dt = g_date_time_new_from_unix_utc (G_MININT64);
+ g_assert_null (dt);
+
+ dt = g_date_time_new_from_unix_local (G_MININT64);
+ g_assert_null (dt);
+}
+
static void
test_GDateTime_invalid (void)
{
GDateTime *dt;
- g_test_bug ("702674");
+ g_test_bug ("http://bugzilla.gnome.org/702674");
dt = g_date_time_new_utc (2013, -2147483647, 31, 17, 15, 48);
g_assert (dt == NULL);
g_date_time_unref (dt2);
/* UTC-0300 and not in DST */
- tz = g_time_zone_new ("-03:00");
+ tz = g_time_zone_new_identifier ("-03:00");
+ g_assert_nonnull (tz);
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));
/* America/Recife is in UTC-0300 */
#ifdef G_OS_UNIX
- tz = g_time_zone_new ("America/Recife");
+ tz = g_time_zone_new_identifier ("America/Recife");
#elif defined G_OS_WIN32
- tz = g_time_zone_new ("E. South America Standard Time");
+ tz = g_time_zone_new_identifier ("E. South America Standard Time");
#endif
+ g_assert_nonnull (tz);
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_date_time_unref (dt);
}
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
static void
test_GDateTime_get_microsecond (void)
{
g_assert_cmpint (tv.tv_usec, ==, g_date_time_get_microsecond (dt));
g_date_time_unref (dt);
}
+G_GNUC_END_IGNORE_DEPRECATIONS
static void
test_GDateTime_get_year (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_local (), NULL);
+ g_hash_table_add (h, g_date_time_new_now_local ());
g_hash_table_remove_all (h);
g_hash_table_destroy (h);
}
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
static void
test_GDateTime_new_from_timeval (void)
{
dt = g_date_time_new_from_timeval_local (&tv);
if (g_test_verbose ())
- g_print ("\nDT%04d-%02d-%02dT%02d:%02d:%02d%s\n",
+ g_printerr ("\nDT%04d-%02d-%02dT%02d:%02d:%02d%s\n",
g_date_time_get_year (dt),
g_date_time_get_month (dt),
g_date_time_get_day_of_month (dt),
g_date_time_unref (dt);
}
+static glong
+find_maximum_supported_tv_sec (void)
+{
+ glong highest_success = 0, lowest_failure = G_MAXLONG;
+ GTimeVal tv;
+ GDateTime *dt = NULL;
+
+ tv.tv_usec = 0;
+
+ /* Corner case of all glong values being valid. */
+ tv.tv_sec = G_MAXLONG;
+ dt = g_date_time_new_from_timeval_utc (&tv);
+ if (dt != NULL)
+ {
+ highest_success = tv.tv_sec;
+ g_date_time_unref (dt);
+ }
+
+ while (highest_success < lowest_failure - 1)
+ {
+ tv.tv_sec = highest_success + (lowest_failure - highest_success) / 2;
+ dt = g_date_time_new_from_timeval_utc (&tv);
+
+ if (dt != NULL)
+ {
+ highest_success = tv.tv_sec;
+ g_date_time_unref (dt);
+ }
+ else
+ {
+ lowest_failure = tv.tv_sec;
+ }
+ }
+
+ return highest_success;
+}
+
+/* Check that trying to create a #GDateTime too far in the future reliably
+ * fails. With a #GTimeVal, this is subtle, as the tv_usec are added into the
+ * calculation part-way through.
+ *
+ * This varies a bit between 32- and 64-bit architectures, due to the
+ * differences in the size of glong (tv.tv_sec). */
+static void
+test_GDateTime_new_from_timeval_overflow (void)
+{
+ GDateTime *dt;
+ GTimeVal tv;
+
+ g_test_bug ("http://bugzilla.gnome.org/782089");
+
+ tv.tv_sec = find_maximum_supported_tv_sec ();
+ tv.tv_usec = G_USEC_PER_SEC - 1;
+
+ g_test_message ("Maximum supported GTimeVal.tv_sec = %lu", tv.tv_sec);
+
+ /* Sanity check: do we support the year 2000? */
+ g_assert_cmpint (tv.tv_sec, >=, 946684800);
+
+ dt = g_date_time_new_from_timeval_utc (&tv);
+ g_assert_nonnull (dt);
+ g_date_time_unref (dt);
+
+ if (tv.tv_sec < G_MAXLONG)
+ {
+ tv.tv_sec++;
+ tv.tv_usec = 0;
+
+ dt = g_date_time_new_from_timeval_utc (&tv);
+ g_assert_null (dt);
+ }
+}
+
static void
test_GDateTime_new_from_timeval_utc (void)
{
dt = g_date_time_new_from_timeval_utc (&tv);
if (g_test_verbose ())
- g_print ("\nDT%04d-%02d-%02dT%02d:%02d:%02d%s\n",
+ g_printerr ("\nDT%04d-%02d-%02dT%02d:%02d:%02d%s\n",
g_date_time_get_year (dt),
g_date_time_get_month (dt),
g_date_time_get_day_of_month (dt),
g_assert_cmpint (tv.tv_usec, ==, tv2.tv_usec);
g_date_time_unref (dt);
}
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+static void
+test_GDateTime_new_from_iso8601 (void)
+{
+ GDateTime *dt;
+ GTimeZone *tz;
+
+ /* Need non-empty string */
+ dt = g_date_time_new_from_iso8601 ("", NULL);
+ g_assert_null (dt);
+
+ /* Needs to be correctly formatted */
+ dt = g_date_time_new_from_iso8601 ("not a date", NULL);
+ g_assert_null (dt);
+
+ dt = g_date_time_new_from_iso8601 (" +55", NULL);
+ g_assert_null (dt);
+
+ /* Check common case */
+ dt = g_date_time_new_from_iso8601 ("2016-08-24T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 8, 24);
+ ASSERT_TIME (dt, 22, 10, 42, 0);
+ g_date_time_unref (dt);
+
+ /* Timezone is required in text or passed as arg */
+ tz = g_time_zone_new_utc ();
+ dt = g_date_time_new_from_iso8601 ("2016-08-24T22:10:42", tz);
+ ASSERT_DATE (dt, 2016, 8, 24);
+ g_date_time_unref (dt);
+ g_time_zone_unref (tz);
+ dt = g_date_time_new_from_iso8601 ("2016-08-24T22:10:42", NULL);
+ g_assert_null (dt);
+
+ /* Can't have whitespace */
+ dt = g_date_time_new_from_iso8601 ("2016 08 24T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-08-24T22:10:42Z ", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 (" 2016-08-24T22:10:42Z", NULL);
+ g_assert_null (dt);
+
+ /* Check lowercase time separator or space allowed */
+ dt = g_date_time_new_from_iso8601 ("2016-08-24t22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 8, 24);
+ ASSERT_TIME (dt, 22, 10, 42, 0);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-08-24 22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 8, 24);
+ ASSERT_TIME (dt, 22, 10, 42, 0);
+ g_date_time_unref (dt);
+
+ /* Check dates without separators allowed */
+ dt = g_date_time_new_from_iso8601 ("20160824T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 8, 24);
+ ASSERT_TIME (dt, 22, 10, 42, 0);
+ g_date_time_unref (dt);
+
+ /* Months are two digits */
+ dt = g_date_time_new_from_iso8601 ("2016-1-01T22:10:42Z", NULL);
+ g_assert_null (dt);
+
+ /* Days are two digits */
+ dt = g_date_time_new_from_iso8601 ("2016-01-1T22:10:42Z", NULL);
+ g_assert_null (dt);
+
+ /* Need consistent usage of separators */
+ dt = g_date_time_new_from_iso8601 ("2016-0824T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("201608-24T22:10:42Z", NULL);
+ g_assert_null (dt);
+
+ /* Check month within valid range */
+ dt = g_date_time_new_from_iso8601 ("2016-00-13T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-13-13T22:10:42Z", NULL);
+ g_assert_null (dt);
+
+ /* Check day within valid range */
+ dt = g_date_time_new_from_iso8601 ("2016-01-00T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-01-31T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 1, 31);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-01-32T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-02-29T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 2, 29);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-02-30T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2017-02-28T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2017, 2, 28);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2017-02-29T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-03-31T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 3, 31);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-03-32T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-04-30T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 4, 30);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-04-31T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-05-31T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 5, 31);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-05-32T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-06-30T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 6, 30);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-06-31T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-07-31T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 7, 31);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-07-32T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-08-31T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 8, 31);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-08-32T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-09-30T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 9, 30);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-09-31T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-10-31T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 10, 31);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-10-32T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-11-30T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 11, 30);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-11-31T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-12-31T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 12, 31);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-12-32T22:10:42Z", NULL);
+ g_assert_null (dt);
+
+ /* Check ordinal days work */
+ dt = g_date_time_new_from_iso8601 ("2016-237T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 8, 24);
+ ASSERT_TIME (dt, 22, 10, 42, 0);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016237T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 8, 24);
+ ASSERT_TIME (dt, 22, 10, 42, 0);
+ g_date_time_unref (dt);
+
+ /* Check ordinal leap days */
+ dt = g_date_time_new_from_iso8601 ("2016-366T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 12, 31);
+ ASSERT_TIME (dt, 22, 10, 42, 0);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2017-365T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2017, 12, 31);
+ ASSERT_TIME (dt, 22, 10, 42, 0);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2017-366T22:10:42Z", NULL);
+ g_assert_null (dt);
+
+ /* Days start at 1 */
+ dt = g_date_time_new_from_iso8601 ("2016-000T22:10:42Z", NULL);
+ g_assert_null (dt);
+
+ /* Limited to number of days in the year (2016 is a leap year) */
+ dt = g_date_time_new_from_iso8601 ("2016-367T22:10:42Z", NULL);
+ g_assert_null (dt);
+
+ /* Days are two digits */
+ dt = g_date_time_new_from_iso8601 ("2016-1T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-12T22:10:42Z", NULL);
+ g_assert_null (dt);
+
+ /* Check week days work */
+ dt = g_date_time_new_from_iso8601 ("2016-W34-3T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 8, 24);
+ ASSERT_TIME (dt, 22, 10, 42, 0);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016W343T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 8, 24);
+ ASSERT_TIME (dt, 22, 10, 42, 0);
+ g_date_time_unref (dt);
+
+ /* We don't support weeks without weekdays (valid ISO 8601) */
+ dt = g_date_time_new_from_iso8601 ("2016-W34T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016W34T22:10:42Z", NULL);
+ g_assert_null (dt);
+
+ /* Weeks are two digits */
+ dt = g_date_time_new_from_iso8601 ("2016-W3-1T22:10:42Z", NULL);
+ g_assert_null (dt);
+
+ /* Weeks start at 1 */
+ dt = g_date_time_new_from_iso8601 ("2016-W00-1T22:10:42Z", NULL);
+ g_assert_null (dt);
+
+ /* Week one might be in the previous year */
+ dt = g_date_time_new_from_iso8601 ("2015-W01-1T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2014, 12, 29);
+ g_date_time_unref (dt);
+
+ /* Last week might be in next year */
+ dt = g_date_time_new_from_iso8601 ("2015-W53-7T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 1, 3);
+ g_date_time_unref (dt);
+
+ /* Week 53 doesn't always exist */
+ dt = g_date_time_new_from_iso8601 ("2016-W53-1T22:10:42Z", NULL);
+ g_assert_null (dt);
+
+ /* Limited to number of days in the week */
+ dt = g_date_time_new_from_iso8601 ("2016-W34-0T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-W34-8T22:10:42Z", NULL);
+ g_assert_null (dt);
+
+ /* Days are one digit */
+ dt = g_date_time_new_from_iso8601 ("2016-W34-99T22:10:42Z", NULL);
+ g_assert_null (dt);
+
+ /* Check week day changes depending on year */
+ dt = g_date_time_new_from_iso8601 ("2017-W34-1T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2017, 8, 21);
+ g_date_time_unref (dt);
+
+ /* Check week day changes depending on leap years */
+ dt = g_date_time_new_from_iso8601 ("1900-W01-1T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 1900, 1, 1);
+ g_date_time_unref (dt);
+
+ /* YYYY-MM not allowed (NOT valid ISO 8601) */
+ dt = g_date_time_new_from_iso8601 ("2016-08T22:10:42Z", NULL);
+ g_assert_null (dt);
+
+ /* We don't support omitted year (valid ISO 8601) */
+ dt = g_date_time_new_from_iso8601 ("--08-24T22:10:42Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("--0824T22:10:42Z", NULL);
+ g_assert_null (dt);
+
+ /* Seconds must be two digits. */
+ dt = g_date_time_new_from_iso8601 ("2016-08-10T22:10:4Z", NULL);
+ g_assert_null (dt);
+
+ /* Seconds must all be digits. */
+ dt = g_date_time_new_from_iso8601 ("2016-08-10T22:10:4aZ", NULL);
+ g_assert_null (dt);
+
+ /* Check subseconds work */
+ dt = g_date_time_new_from_iso8601 ("2016-08-24T22:10:42.123456Z", NULL);
+ ASSERT_DATE (dt, 2016, 8, 24);
+ ASSERT_TIME (dt, 22, 10, 42, 123456);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-08-24T22:10:42,123456Z", NULL);
+ ASSERT_DATE (dt, 2016, 8, 24);
+ ASSERT_TIME (dt, 22, 10, 42, 123456);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-08-24T22:10:42.Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-08-24T221042.123456Z", NULL);
+ ASSERT_DATE (dt, 2016, 8, 24);
+ ASSERT_TIME (dt, 22, 10, 42, 123456);
+ g_date_time_unref (dt);
+
+ /* Subseconds must all be digits. */
+ dt = g_date_time_new_from_iso8601 ("2016-08-10T22:10:42.5aZ", NULL);
+ g_assert_null (dt);
+
+ /* Subseconds can be an arbitrary length, but must not overflow.
+ * The ASSERT_TIME() comparisons are constrained by only comparing up to
+ * microsecond granularity. */
+ dt = g_date_time_new_from_iso8601 ("2016-08-10T22:10:09.222222222222222222Z", NULL);
+ ASSERT_DATE (dt, 2016, 8, 10);
+ ASSERT_TIME (dt, 22, 10, 9, 222222);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-08-10T22:10:09.2222222222222222222Z", NULL);
+ g_assert_null (dt);
+
+ /* Small numerator, large divisor when parsing the subseconds. */
+ dt = g_date_time_new_from_iso8601 ("2016-08-10T22:10:00.0000000000000000001Z", NULL);
+ ASSERT_DATE (dt, 2016, 8, 10);
+ ASSERT_TIME (dt, 22, 10, 0, 0);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-08-10T22:10:00.00000000000000000001Z", NULL);
+ g_assert_null (dt);
+
+ /* We don't support times without minutes / seconds (valid ISO 8601) */
+ dt = g_date_time_new_from_iso8601 ("2016-08-24T22Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-08-24T22:10Z", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-08-24T2210Z", NULL);
+ g_assert_null (dt);
+
+ /* UTC time uses 'Z' */
+ dt = g_date_time_new_from_iso8601 ("2016-08-24T22:10:42Z", NULL);
+ ASSERT_DATE (dt, 2016, 8, 24);
+ ASSERT_TIME (dt, 22, 10, 42, 0);
+ g_assert_cmpint (g_date_time_get_utc_offset (dt), ==, 0);
+ g_date_time_unref (dt);
+
+ /* Check timezone works */
+ dt = g_date_time_new_from_iso8601 ("2016-08-24T22:10:42+12:00", NULL);
+ ASSERT_DATE (dt, 2016, 8, 24);
+ ASSERT_TIME (dt, 22, 10, 42, 0);
+ g_assert_cmpint (g_date_time_get_utc_offset (dt), ==, 12 * G_TIME_SPAN_HOUR);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-08-24T22:10:42+12", NULL);
+ ASSERT_DATE (dt, 2016, 8, 24);
+ ASSERT_TIME (dt, 22, 10, 42, 0);
+ g_assert_cmpint (g_date_time_get_utc_offset (dt), ==, 12 * G_TIME_SPAN_HOUR);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-08-24T22:10:42-02", NULL);
+ ASSERT_DATE (dt, 2016, 8, 24);
+ ASSERT_TIME (dt, 22, 10, 42, 0);
+ g_assert_cmpint (g_date_time_get_utc_offset (dt), ==, -2 * G_TIME_SPAN_HOUR);
+ g_date_time_unref (dt);
+
+ /* Timezone seconds not allowed */
+ dt = g_date_time_new_from_iso8601 ("2016-08-24T22-12:00:00", NULL);
+ g_assert_null (dt);
+ dt = g_date_time_new_from_iso8601 ("2016-08-24T22-12:00:00.000", NULL);
+ g_assert_null (dt);
+
+ /* Timezone hours two digits */
+ dt = g_date_time_new_from_iso8601 ("2016-08-24T22-2Z", NULL);
+ g_assert_null (dt);
+
+ /* Ordinal date (YYYYDDD), space separator, and then time as HHMMSS,SSS
+ * The interesting bit is that the seconds field is so long as to parse as
+ * NaN */
+ dt = g_date_time_new_from_iso8601 ("0005306 000001,666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666600080000-00", NULL);
+ g_assert_null (dt);
+}
+
+typedef struct {
+ gboolean success;
+ const gchar *in;
+
+ /* Expected result: */
+ guint year;
+ guint month;
+ guint day;
+ guint hour;
+ guint minute;
+ guint second;
+ guint microsecond;
+ GTimeSpan utc_offset;
+} Iso8601ParseTest;
+
+static void
+test_GDateTime_new_from_iso8601_2 (void)
+{
+ const Iso8601ParseTest tests[] = {
+ { TRUE, "1990-11-01T10:21:17Z", 1990, 11, 1, 10, 21, 17, 0, 0 },
+ { TRUE, "19901101T102117Z", 1990, 11, 1, 10, 21, 17, 0, 0 },
+ { TRUE, "1970-01-01T00:00:17.12Z", 1970, 1, 1, 0, 0, 17, 120000, 0 },
+ { TRUE, "1970-01-01T00:00:17.1234Z", 1970, 1, 1, 0, 0, 17, 123400, 0 },
+ { TRUE, "1970-01-01T00:00:17.123456Z", 1970, 1, 1, 0, 0, 17, 123456, 0 },
+ { TRUE, "1980-02-22T12:36:00+02:00", 1980, 2, 22, 12, 36, 0, 0, 2 * G_TIME_SPAN_HOUR },
+ { TRUE, "1990-12-31T15:59:60-08:00", 1990, 12, 31, 15, 59, 59, 0, -8 * G_TIME_SPAN_HOUR },
+ { FALSE, " ", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "x", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "123x", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "2001-10+x", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "1980-02-22T", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "2001-10-08Tx", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "2001-10-08T10:11x", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "Wed Dec 19 17:20:20 GMT 2007", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "1980-02-22T10:36:00Zulu", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "2T0+819855292164632335", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { TRUE, "2018-08-03T14:08:05.446178377+01:00", 2018, 8, 3, 14, 8, 5, 446178, 1 * G_TIME_SPAN_HOUR },
+ { FALSE, "2147483648-08-03T14:08:05.446178377+01:00", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "2018-13-03T14:08:05.446178377+01:00", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "2018-00-03T14:08:05.446178377+01:00", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "2018-08-00T14:08:05.446178377+01:00", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "2018-08-32T14:08:05.446178377+01:00", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "2018-08-03T24:08:05.446178377+01:00", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "2018-08-03T14:60:05.446178377+01:00", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "2018-08-03T14:08:63.446178377+01:00", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "2018-08-03T14:08:05.446178377+100:00", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { TRUE, "20180803T140805.446178377+0100", 2018, 8, 3, 14, 8, 5, 446178, 1 * G_TIME_SPAN_HOUR },
+ { FALSE, "21474836480803T140805.446178377+0100", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "20181303T140805.446178377+0100", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "20180003T140805.446178377+0100", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "20180800T140805.446178377+0100", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "20180832T140805.446178377+0100", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "20180803T240805.446178377+0100", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "20180803T146005.446178377+0100", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "20180803T140863.446178377+0100", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "20180803T140805.446178377+10000", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "-0005-01-01T00:00:00Z", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "2018-08-06", 0, 0, 0, 0, 0, 0, 0, 0 },
+ /* This is not accepted by g_time_val_from_iso8601(), but is accepted by g_date_time_new_from_iso8601():
+ { FALSE, "2018-08-06 13:51:00Z", 0, 0, 0, 0, 0, 0, 0, 0 },
+ * */
+ { TRUE, "20180803T140805,446178377+0100", 2018, 8, 3, 14, 8, 5, 446178, 1 * G_TIME_SPAN_HOUR },
+ { TRUE, "2018-08-03T14:08:05.446178377-01:00", 2018, 8, 3, 14, 8, 5, 446178, -1 * G_TIME_SPAN_HOUR },
+ { FALSE, "2018-08-03T14:08:05.446178377 01:00", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { TRUE, "1990-11-01T10:21:17", 1990, 11, 1, 10, 21, 17, 0, 0 },
+ /* These are accepted by g_time_val_from_iso8601(), but not by g_date_time_new_from_iso8601():
+ { TRUE, "19901101T102117+5", 1990, 11, 1, 10, 21, 17, 0, 5 * G_TIME_SPAN_HOUR },
+ { TRUE, "19901101T102117+3:15", 1990, 11, 1, 10, 21, 17, 0, 3 * G_TIME_SPAN_HOUR + 15 * G_TIME_SPAN_MINUTE },
+ { TRUE, " 1990-11-01T10:21:17Z ", 1990, 11, 1, 10, 21, 17, 0, 0 },
+ { FALSE, "2018-08-03T14:08:05.446178377+01:60", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "20180803T140805.446178377+0160", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { TRUE, "+1980-02-22T12:36:00+02:00", 1980, 2, 22, 12, 36, 0, 0, 2 * G_TIME_SPAN_HOUR },
+ { TRUE, "1990-11-01T10:21:17 ", 1990, 11, 1, 10, 21, 17, 0, 0 },
+ */
+ { FALSE, "1719W462 407777-07", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "4011090 260528Z", 0, 0, 0, 0, 0, 0, 0, 0 },
+ { FALSE, "0000W011 228214-22", 0, 0, 0, 0, 0, 0, 0, 0 },
+ };
+ GTimeZone *tz = NULL;
+ GDateTime *dt = NULL;
+ gsize i;
+
+ g_test_summary ("Further parser tests for g_date_time_new_from_iso8601(), "
+ "checking success and failure using test vectors.");
+
+ tz = g_time_zone_new_utc ();
+
+ for (i = 0; i < G_N_ELEMENTS (tests); i++)
+ {
+ g_test_message ("Vector %" G_GSIZE_FORMAT ": %s", i, tests[i].in);
+
+ dt = g_date_time_new_from_iso8601 (tests[i].in, tz);
+ if (tests[i].success)
+ {
+ g_assert_nonnull (dt);
+ ASSERT_DATE (dt, tests[i].year, tests[i].month, tests[i].day);
+ ASSERT_TIME (dt, tests[i].hour, tests[i].minute, tests[i].second, tests[i].microsecond);
+ g_assert_cmpint (g_date_time_get_utc_offset (dt), ==, tests[i].utc_offset);
+ }
+ else
+ {
+ g_assert_null (dt);
+ }
+
+ g_clear_pointer (&dt, g_date_time_unref);
+ }
+
+ g_time_zone_unref (tz);
+}
static void
test_GDateTime_to_unix (void)
time_t t;
t = time (NULL);
+ g_assert_cmpint (t, !=, (time_t) -1);
dt = g_date_time_new_from_unix_local (t);
g_assert_cmpint (g_date_time_to_unix (dt), ==, t);
g_date_time_unref (dt);
static void
test_GDateTime_new_full (void)
{
- GTimeZone *tz;
+ GTimeZone *tz, *dt_tz;
GDateTime *dt;
+#ifdef G_OS_WIN32
+ LCID currLcid = GetThreadLocale ();
+ LANGID currLangId = LANGIDFROMLCID (currLcid);
+ LANGID en = MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US);
+ SetThreadUILanguage (en);
+#endif
+
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_date_time_unref (dt);
#ifdef G_OS_UNIX
- tz = g_time_zone_new ("America/Recife");
+ tz = g_time_zone_new_identifier ("America/Tijuana");
#elif defined G_OS_WIN32
- tz = g_time_zone_new ("E. South America Standard Time");
+ tz = g_time_zone_new_identifier ("Pacific Standard Time");
#endif
- dt = g_date_time_new (tz, 2010, 5, 24, 8, 4, 0);
- g_time_zone_unref (tz);
+ g_assert_nonnull (tz);
+ dt = g_date_time_new (tz, 2010, 11, 24, 8, 4, 0);
+
+ dt_tz = g_date_time_get_timezone (dt);
+ g_assert_cmpstr (g_time_zone_get_identifier (dt_tz), ==,
+ g_time_zone_get_identifier (tz));
+
g_assert_cmpint (2010, ==, g_date_time_get_year (dt));
- g_assert_cmpint (5, ==, g_date_time_get_month (dt));
+ g_assert_cmpint (11, ==, g_date_time_get_month (dt));
g_assert_cmpint (24, ==, g_date_time_get_day_of_month (dt));
g_assert_cmpint (8, ==, g_date_time_get_hour (dt));
g_assert_cmpint (4, ==, g_date_time_get_minute (dt));
g_assert_cmpint (0, ==, g_date_time_get_second (dt));
#ifdef G_OS_UNIX
- g_assert_cmpstr ("BRT", ==, g_date_time_get_timezone_abbreviation (dt));
+ g_assert_cmpstr ("PST", ==, g_date_time_get_timezone_abbreviation (dt));
+ g_assert_cmpstr ("America/Tijuana", ==, g_time_zone_get_identifier (dt_tz));
#elif defined G_OS_WIN32
- g_assert_cmpstr ("E. South America Standard Time", ==,
+ g_assert_cmpstr ("Pacific Standard Time", ==,
g_date_time_get_timezone_abbreviation (dt));
+ g_assert_cmpstr ("Pacific Standard Time", ==,
+ g_time_zone_get_identifier (dt_tz));
+ SetThreadUILanguage (currLangId);
#endif
g_assert (!g_date_time_is_daylight_savings (dt));
g_date_time_unref (dt);
+ g_time_zone_unref (tz);
+
+ /* Check month limits */
+ dt = g_date_time_new_utc (2016, 1, 31, 22, 10, 42);
+ ASSERT_DATE (dt, 2016, 1, 31);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_utc (2016, 1, 32, 22, 10, 42);
+ g_assert_null (dt);
+ dt = g_date_time_new_utc (2016, 2, 29, 22, 10, 42);
+ ASSERT_DATE (dt, 2016, 2, 29);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_utc (2016, 2, 30, 22, 10, 42);
+ g_assert_null (dt);
+ dt = g_date_time_new_utc (2017, 2, 28, 22, 10, 42);
+ ASSERT_DATE (dt, 2017, 2, 28);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_utc (2017, 2, 29, 22, 10, 42);
+ g_assert_null (dt);
+ dt = g_date_time_new_utc (2016, 3, 31, 22, 10, 42);
+ ASSERT_DATE (dt, 2016, 3, 31);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_utc (2016, 3, 32, 22, 10, 42);
+ g_assert_null (dt);
+ dt = g_date_time_new_utc (2016, 4, 30, 22, 10, 42);
+ ASSERT_DATE (dt, 2016, 4, 30);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_utc (2016, 4, 31, 22, 10, 42);
+ g_assert_null (dt);
+ dt = g_date_time_new_utc (2016, 5, 31, 22, 10, 42);
+ ASSERT_DATE (dt, 2016, 5, 31);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_utc (2016, 5, 32, 22, 10, 42);
+ g_assert_null (dt);
+ dt = g_date_time_new_utc (2016, 6, 30, 22, 10, 42);
+ ASSERT_DATE (dt, 2016, 6, 30);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_utc (2016, 6, 31, 22, 10, 42);
+ g_assert_null (dt);
+ dt = g_date_time_new_utc (2016, 7, 31, 22, 10, 42);
+ ASSERT_DATE (dt, 2016, 7, 31);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_utc (2016, 7, 32, 22, 10, 42);
+ g_assert_null (dt);
+ dt = g_date_time_new_utc (2016, 8, 31, 22, 10, 42);
+ ASSERT_DATE (dt, 2016, 8, 31);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_utc (2016, 8, 32, 22, 10, 42);
+ g_assert_null (dt);
+ dt = g_date_time_new_utc (2016, 9, 30, 22, 10, 42);
+ ASSERT_DATE (dt, 2016, 9, 30);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_utc (2016, 9, 31, 22, 10, 42);
+ g_assert_null (dt);
+ dt = g_date_time_new_utc (2016, 10, 31, 22, 10, 42);
+ ASSERT_DATE (dt, 2016, 10, 31);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_utc (2016, 10, 32, 22, 10, 42);
+ g_assert_null (dt);
+ dt = g_date_time_new_utc (2016, 11, 30, 22, 10, 42);
+ ASSERT_DATE (dt, 2016, 11, 30);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_utc (2016, 11, 31, 22, 10, 42);
+ g_assert_null (dt);
+ dt = g_date_time_new_utc (2016, 12, 31, 22, 10, 42);
+ ASSERT_DATE (dt, 2016, 12, 31);
+ g_date_time_unref (dt);
+ dt = g_date_time_new_utc (2016, 12, 32, 22, 10, 42);
+ g_assert_null (dt);
+
+ /* Seconds limits. */
+ dt = g_date_time_new_utc (2020, 12, 9, 14, 49, NAN);
+ g_assert_null (dt);
+ dt = g_date_time_new_utc (2020, 12, 9, 14, 49, -0.1);
+ g_assert_null (dt);
+ dt = g_date_time_new_utc (2020, 12, 9, 14, 49, 60.0);
+ g_assert_null (dt);
+
+ /* Year limits */
+ dt = g_date_time_new_utc (10000, 1, 1, 0, 0, 0);
+ dt = g_date_time_new_utc (0, 1, 1, 0, 0, 0);
}
static void
test_GDateTime_now_utc (void)
{
GDateTime *dt;
- time_t t;
struct tm tm;
+ time_t t;
+ time_t after;
- t = time (NULL);
+ /* t <= dt.to_unix() <= after, but the inequalities might not be
+ * equality if we're close to the boundary between seconds.
+ * We loop until t == after (and hence dt.to_unix() should equal both)
+ * to guard against that. */
+ do
+ {
+ t = g_get_real_time () / G_TIME_SPAN_SECOND;
#ifdef HAVE_GMTIME_R
- gmtime_r (&t, &tm);
+ gmtime_r (&t, &tm);
#else
- {
- struct tm *tmp = gmtime (&t);
- /* Assume gmtime() can't fail as we got t from time(NULL). (Note
- * that on Windows, gmtime() *is* MT-safe, it uses a thread-local
- * buffer.)
- */
- memcpy (&tm, tmp, sizeof (struct tm));
- }
+ {
+ struct tm *tmp = gmtime (&t);
+ /* Assume gmtime() can't fail as we got t from time(NULL). (Note
+ * that on Windows, gmtime() *is* MT-safe, it uses a thread-local
+ * buffer.)
+ */
+ memcpy (&tm, tmp, sizeof (struct tm));
+ }
#endif
- dt = g_date_time_new_now_utc ();
+ dt = g_date_time_new_now_utc ();
+
+ after = g_get_real_time () / G_TIME_SPAN_SECOND;
+ }
+ while (t != after);
+
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));
struct tm tm;
memset (&tm, 0, sizeof (tm));
- get_localtime_tm (time (NULL), &tm);
+ get_localtime_tm (g_get_real_time () / G_TIME_SPAN_SECOND, &tm);
dt = g_date_time_new_now_local ();
ts = g_date_time_get_utc_offset (dt);
#endif
}
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
static void
test_GDateTime_to_timeval (void)
{
g_assert_cmpint (tv1.tv_usec, ==, tv2.tv_usec);
g_date_time_unref (dt);
}
+G_GNUC_END_IGNORE_DEPRECATIONS
static void
test_GDateTime_to_local (void)
{
- GDateTime *utc, *now, *dt;
+ GDateTime *utc = NULL, *now = NULL, *dt;
+ time_t before, after;
+
+ /* before <= utc.to_unix() <= now.to_unix() <= after, but the inequalities
+ * might not be equality if we're close to the boundary between seconds.
+ * We loop until before == after (and hence the GDateTimes should match)
+ * to guard against that. */
+ do
+ {
+ before = g_get_real_time () / G_TIME_SPAN_SECOND;
+ g_clear_pointer (&utc, g_date_time_unref);
+ g_clear_pointer (&now, g_date_time_unref);
+ utc = g_date_time_new_now_utc ();
+ now = g_date_time_new_now_local ();
+ after = g_get_real_time () / G_TIME_SPAN_SECOND;
+ }
+ while (before != after);
- 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));
struct tm tm;
t = time (NULL);
+ g_assert_cmpint (t, !=, (time_t) -1);
#ifdef HAVE_GMTIME_R
gmtime_r (&t, &tm);
#else
* that long, and it will cause the test to fail if dst isn't big
* enough.
*/
+ gchar *old_lc_all;
+ gchar *old_lc_messages;
gchar dst[64];
struct tm tt;
time_t t;
+#ifdef G_OS_WIN32
+ gchar *current_tz = NULL;
+ DYNAMIC_TIME_ZONE_INFORMATION dtz_info;
+#endif
+
#define TEST_PRINTF(f,o) G_STMT_START { \
GDateTime *__dt = g_date_time_new_local (2009, 10, 24, 0, 0, 0);\
gchar *__p = g_date_time_format (__dt, (f)); \
#define TEST_PRINTF_DATE(y,m,d,f,o) G_STMT_START { \
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)); \
+ gchar *o_casefold = g_utf8_casefold (o, -1); \
+ gchar *p_casefold = g_utf8_casefold (p, -1); \
+ g_assert_cmpstr (p_casefold, ==, (o_casefold)); \
g_date_time_unref (dt); \
+ g_free (p_casefold); \
+ g_free (o_casefold); \
g_free (p); } G_STMT_END
#define TEST_PRINTF_TIME(h,m,s,f,o) G_STMT_START { \
g_date_time_unref (dt); \
g_free (p); } G_STMT_END
+ old_lc_all = g_strdup (g_getenv ("LC_ALL"));
+ g_unsetenv ("LC_ALL");
+
+ old_lc_messages = g_strdup (g_getenv ("LC_MESSAGES"));
+ g_setenv ("LC_MESSAGES", "C", TRUE);
+
/*
* This is a little helper to make sure we can compare timezones to
* that of the generated timezone.
*/
t = time (NULL);
+ g_assert_cmpint (t, !=, (time_t) -1);
memset (&tt, 0, sizeof(tt));
get_localtime_tm (t, &tt);
tt.tm_year = 2009 - 1900;
get_localtime_tm (t, &tt);
strftime (dst, sizeof(dst), "%Z", &tt);
- /* get current time_t for 20090924 in the local timezone */
- tt.tm_sec = 0;
- tt.tm_min = 0;
- tt.tm_hour = 0;
- t = mktime (&tt);
-
TEST_PRINTF ("%a", "Sat");
TEST_PRINTF ("%A", "Saturday");
TEST_PRINTF ("%b", "Oct");
TEST_PRINTF ("%d", "24");
TEST_PRINTF_DATE (2009, 1, 1, "%d", "01");
TEST_PRINTF ("%e", "24"); // fixme
+ TEST_PRINTF_TIME (10, 10, 1.001, "%f", "001000");
TEST_PRINTF ("%h", "Oct");
TEST_PRINTF ("%H", "00");
TEST_PRINTF_TIME (15, 0, 0, "%H", "15");
#ifdef G_OS_UNIX
TEST_PRINTF ("%Z", dst);
#elif defined G_OS_WIN32
- TEST_PRINTF ("%Z", "Pacific Standard Time");
+ g_assert (GetDynamicTimeZoneInformation (&dtz_info) != TIME_ZONE_ID_INVALID);
+ if (wcscmp (dtz_info.StandardName, L"") != 0)
+ current_tz = g_utf16_to_utf8 (dtz_info.StandardName, -1, NULL, NULL, NULL);
+ else
+ current_tz = g_utf16_to_utf8 (dtz_info.DaylightName, -1, NULL, NULL, NULL);
+
+ TEST_PRINTF ("%Z", current_tz);
+ g_free (current_tz);
#endif
+
+ if (old_lc_messages != NULL)
+ g_setenv ("LC_MESSAGES", old_lc_messages, TRUE);
+ else
+ g_unsetenv ("LC_MESSAGES");
+ g_free (old_lc_messages);
+
+ if (old_lc_all != NULL)
+ g_setenv ("LC_ALL", old_lc_all, TRUE);
+ g_free (old_lc_all);
}
static void
{
gchar *oldlocale;
+ /* If running uninstalled (G_TEST_BUILDDIR is set), skip this test, since we
+ * need the translations to be installed. We can’t mess around with
+ * bindtextdomain() here, as the compiled .gmo files in po/ are not in the
+ * right installed directory hierarchy to be successfully loaded by gettext. */
+ if (g_getenv ("G_TEST_BUILDDIR") != NULL)
+ {
+ g_test_skip ("Skipping due to running uninstalled. "
+ "This test can only be run when the translations are installed.");
+ return;
+ }
+
oldlocale = g_strdup (setlocale (LC_ALL, NULL));
setlocale (LC_ALL, "ja_JP.eucjp");
if (strstr (setlocale (LC_ALL, NULL), "ja_JP") == NULL)
{
- g_test_message ("locale ja_JP.eucjp not available, skipping non-UTF8 tests");
+ g_test_skip ("locale ja_JP.eucjp not available, skipping non-UTF8 tests");
g_free (oldlocale);
return;
}
if (g_get_charset (NULL))
{
- g_test_message ("locale ja_JP.eucjp may be available, but glib seems to think that it's equivalent to UTF-8, skipping non-UTF-8 tests.");
- g_test_message ("This is a known issue on Darwin");
+ g_test_skip ("locale ja_JP.eucjp may be available, but glib seems to think that it's equivalent to UTF-8, skipping non-UTF-8 tests. This is a known issue on Darwin");
setlocale (LC_ALL, oldlocale);
g_free (oldlocale);
return;
*/
TEST_PRINTF ("%a", "\345\234\237");
TEST_PRINTF ("%A", "\345\234\237\346\233\234\346\227\245");
-#ifndef HAVE_CARBON /* OSX just returns the number */
+#ifndef __APPLE__ /* OSX just returns the number */
TEST_PRINTF ("%b", "10\346\234\210");
#endif
TEST_PRINTF ("%B", "10\346\234\210");
TEST_PRINTF ("%d", "24");
TEST_PRINTF_DATE (2009, 1, 1, "%d", "01");
TEST_PRINTF ("%e", "24"); // fixme
-#ifndef HAVE_CARBON /* OSX just returns the number */
+#ifndef __APPLE__ /* OSX just returns the number */
TEST_PRINTF ("%h", "10\346\234\210");
#endif
TEST_PRINTF ("%H", "00");
TEST_PRINTF_TIME (10, 13, 13, "%l", "10");
TEST_PRINTF ("%m", "10");
TEST_PRINTF ("%M", "00");
-#ifndef HAVE_CARBON /* OSX returns latin "AM", not japanese */
+#ifndef __APPLE__ /* OSX returns latin "AM", not japanese */
TEST_PRINTF ("%p", "\345\215\210\345\211\215");
TEST_PRINTF_TIME (13, 13, 13, "%p", "\345\215\210\345\276\214");
TEST_PRINTF ("%P", "\345\215\210\345\211\215");
TEST_PRINTF ("%S", "00");
TEST_PRINTF ("%t", " ");
TEST_PRINTF ("%u", "6");
-#ifndef HAVE_CARBON /* OSX returns YYYY/MM/DD in ASCII */
+#ifndef __APPLE__ /* OSX returns YYYY/MM/DD in ASCII */
TEST_PRINTF ("%x", "2009\345\271\26410\346\234\21024\346\227\245");
#endif
TEST_PRINTF ("%X", "00\346\231\20200\345\210\20600\347\247\222");
g_free (oldlocale);
}
+/* Checks that it is possible to use format string that
+ * is unrepresentable in current locale charset. */
+static void
+test_format_unrepresentable (void)
+{
+ gchar *oldlocale = g_strdup (setlocale (LC_ALL, NULL));
+ setlocale (LC_ALL, "POSIX");
+
+ TEST_PRINTF ("ąśćł", "ąśćł");
+
+ /* We are using Unicode ratio symbol here, which is outside ASCII. */
+ TEST_PRINTF_TIME (23, 15, 0, "%H∶%M", "23∶15");
+
+ /* Test again, this time in locale with non ASCII charset. */
+ if (setlocale (LC_ALL, "pl_PL.ISO-8859-2") != NULL)
+ TEST_PRINTF_TIME (23, 15, 0, "%H∶%M", "23∶15");
+ else
+ g_test_skip ("locale pl_PL.ISO-8859-2 not available, skipping test");
+
+ setlocale (LC_ALL, oldlocale);
+ g_free (oldlocale);
+}
+
static void
test_modifiers (void)
{
TEST_PRINTF_DATE (2011, 7, 1, "%_Om", " \333\267"); /* ' 7' */
}
else
- g_test_message ("locale fa_IR not available, skipping O modifier tests");
+ g_test_skip ("locale fa_IR not available, skipping O modifier tests");
+ setlocale (LC_ALL, oldlocale);
+ g_free (oldlocale);
+}
+
+/* Test that the `O` modifier for g_date_time_format() works with %B, %b and %h;
+ * i.e. whether genitive month names are supported. */
+static void
+test_month_names (void)
+{
+ gchar *oldlocale;
+
+ g_test_bug ("http://bugzilla.gnome.org/749206");
+
+ /* If running uninstalled (G_TEST_BUILDDIR is set), skip this test, since we
+ * need the translations to be installed. We can’t mess around with
+ * bindtextdomain() here, as the compiled .gmo files in po/ are not in the
+ * right installed directory hierarchy to be successfully loaded by gettext. */
+ if (g_getenv ("G_TEST_BUILDDIR") != NULL)
+ {
+ g_test_skip ("Skipping due to running uninstalled. "
+ "This test can only be run when the translations are installed.");
+ return;
+ }
+
+ oldlocale = g_strdup (setlocale (LC_ALL, NULL));
+
+ /* Make sure that nothing has been changed in western European languages. */
+ setlocale (LC_ALL, "en_GB.utf-8");
+ if (strstr (setlocale (LC_ALL, NULL), "en_GB") != NULL)
+ {
+ TEST_PRINTF_DATE (2018, 1, 1, "%B", "January");
+ TEST_PRINTF_DATE (2018, 2, 1, "%OB", "February");
+ TEST_PRINTF_DATE (2018, 3, 1, "%b", "Mar");
+ TEST_PRINTF_DATE (2018, 4, 1, "%Ob", "Apr");
+ TEST_PRINTF_DATE (2018, 5, 1, "%h", "May");
+ TEST_PRINTF_DATE (2018, 6, 1, "%Oh", "Jun");
+ }
+ else
+ g_test_skip ("locale en_GB not available, skipping English month names test");
+
+ setlocale (LC_ALL, "de_DE.utf-8");
+ if (strstr (setlocale (LC_ALL, NULL), "de_DE") != NULL)
+ {
+ TEST_PRINTF_DATE (2018, 7, 1, "%B", "Juli");
+ TEST_PRINTF_DATE (2018, 8, 1, "%OB", "August");
+ TEST_PRINTF_DATE (2018, 9, 1, "%b", "Sep");
+ TEST_PRINTF_DATE (2018, 10, 1, "%Ob", "Okt");
+ TEST_PRINTF_DATE (2018, 11, 1, "%h", "Nov");
+ TEST_PRINTF_DATE (2018, 12, 1, "%Oh", "Dez");
+ }
+ else
+ g_test_skip ("locale de_DE not available, skipping German month names test");
+
+ setlocale (LC_ALL, "es_ES.utf-8");
+ if (strstr (setlocale (LC_ALL, NULL), "es_ES") != NULL)
+ {
+ TEST_PRINTF_DATE (2018, 1, 1, "%B", "enero");
+ TEST_PRINTF_DATE (2018, 2, 1, "%OB", "febrero");
+ TEST_PRINTF_DATE (2018, 3, 1, "%b", "mar");
+ TEST_PRINTF_DATE (2018, 4, 1, "%Ob", "abr");
+ TEST_PRINTF_DATE (2018, 5, 1, "%h", "may");
+ TEST_PRINTF_DATE (2018, 6, 1, "%Oh", "jun");
+ }
+ else
+ g_test_skip ("locale es_ES not available, skipping Spanish month names test");
+
+ setlocale (LC_ALL, "fr_FR.utf-8");
+ if (strstr (setlocale (LC_ALL, NULL), "fr_FR") != NULL)
+ {
+ TEST_PRINTF_DATE (2018, 7, 1, "%B", "juillet");
+ TEST_PRINTF_DATE (2018, 8, 1, "%OB", "août");
+ TEST_PRINTF_DATE (2018, 9, 1, "%b", "sept.");
+ TEST_PRINTF_DATE (2018, 10, 1, "%Ob", "oct.");
+ TEST_PRINTF_DATE (2018, 11, 1, "%h", "nov.");
+ TEST_PRINTF_DATE (2018, 12, 1, "%Oh", "déc.");
+ }
+ else
+ g_test_skip ("locale fr_FR not available, skipping French month names test");
+
+ /* Make sure that there are visible changes in some European languages. */
+ setlocale (LC_ALL, "el_GR.utf-8");
+ if (strstr (setlocale (LC_ALL, NULL), "el_GR") != NULL)
+ {
+ TEST_PRINTF_DATE (2018, 1, 1, "%B", "Ιανουαρίου");
+ TEST_PRINTF_DATE (2018, 2, 1, "%B", "Φεβρουαρίου");
+ TEST_PRINTF_DATE (2018, 3, 1, "%B", "Μαρτίου");
+ TEST_PRINTF_DATE (2018, 4, 1, "%OB", "Απρίλιος");
+ TEST_PRINTF_DATE (2018, 5, 1, "%OB", "Μάιος");
+ TEST_PRINTF_DATE (2018, 6, 1, "%OB", "Ιούνιος");
+ TEST_PRINTF_DATE (2018, 7, 1, "%b", "Ιουλ");
+ TEST_PRINTF_DATE (2018, 8, 1, "%Ob", "Αύγ");
+ }
+ else
+ g_test_skip ("locale el_GR not available, skipping Greek month names test");
+
+ setlocale (LC_ALL, "hr_HR.utf-8");
+ if (strstr (setlocale (LC_ALL, NULL), "hr_HR") != NULL)
+ {
+ TEST_PRINTF_DATE (2018, 5, 1, "%B", "svibnja");
+ TEST_PRINTF_DATE (2018, 6, 1, "%B", "lipnja");
+ TEST_PRINTF_DATE (2018, 7, 1, "%B", "srpnja");
+ TEST_PRINTF_DATE (2018, 8, 1, "%OB", "Kolovoz");
+ TEST_PRINTF_DATE (2018, 9, 1, "%OB", "Rujan");
+ TEST_PRINTF_DATE (2018, 10, 1, "%OB", "Listopad");
+ TEST_PRINTF_DATE (2018, 11, 1, "%b", "Stu");
+ TEST_PRINTF_DATE (2018, 12, 1, "%Ob", "Pro");
+ }
+ else
+ g_test_skip ("locale hr_HR not available, skipping Croatian month names test");
+
+ setlocale (LC_ALL, "lt_LT.utf-8");
+ if (strstr (setlocale (LC_ALL, NULL), "lt_LT") != NULL)
+ {
+ TEST_PRINTF_DATE (2018, 1, 1, "%B", "sausio");
+ TEST_PRINTF_DATE (2018, 2, 1, "%B", "vasario");
+ TEST_PRINTF_DATE (2018, 3, 1, "%B", "kovo");
+ TEST_PRINTF_DATE (2018, 4, 1, "%OB", "balandis");
+ TEST_PRINTF_DATE (2018, 5, 1, "%OB", "gegužė");
+ TEST_PRINTF_DATE (2018, 6, 1, "%OB", "birželis");
+ TEST_PRINTF_DATE (2018, 7, 1, "%b", "liep.");
+ TEST_PRINTF_DATE (2018, 8, 1, "%Ob", "rugp.");
+ }
+ else
+ g_test_skip ("locale lt_LT not available, skipping Lithuanian month names test");
+
+ setlocale (LC_ALL, "pl_PL.utf-8");
+ if (strstr (setlocale (LC_ALL, NULL), "pl_PL") != NULL)
+ {
+ TEST_PRINTF_DATE (2018, 5, 1, "%B", "maja");
+ TEST_PRINTF_DATE (2018, 6, 1, "%B", "czerwca");
+ TEST_PRINTF_DATE (2018, 7, 1, "%B", "lipca");
+ TEST_PRINTF_DATE (2018, 8, 1, "%OB", "sierpień");
+ TEST_PRINTF_DATE (2018, 9, 1, "%OB", "wrzesień");
+ TEST_PRINTF_DATE (2018, 10, 1, "%OB", "październik");
+ TEST_PRINTF_DATE (2018, 11, 1, "%b", "lis");
+ TEST_PRINTF_DATE (2018, 12, 1, "%Ob", "gru");
+ }
+ else
+ g_test_skip ("locale pl_PL not available, skipping Polish month names test");
+
+ setlocale (LC_ALL, "ru_RU.utf-8");
+ if (strstr (setlocale (LC_ALL, NULL), "ru_RU") != NULL)
+ {
+ TEST_PRINTF_DATE (2018, 1, 1, "%B", "января");
+ TEST_PRINTF_DATE (2018, 2, 1, "%B", "февраля");
+ TEST_PRINTF_DATE (2018, 3, 1, "%B", "марта");
+ TEST_PRINTF_DATE (2018, 4, 1, "%OB", "Апрель");
+ TEST_PRINTF_DATE (2018, 5, 1, "%OB", "Май");
+ TEST_PRINTF_DATE (2018, 6, 1, "%OB", "Июнь");
+ TEST_PRINTF_DATE (2018, 7, 1, "%b", "июл");
+ TEST_PRINTF_DATE (2018, 8, 1, "%Ob", "авг");
+ /* This difference is very important in Russian: */
+ TEST_PRINTF_DATE (2018, 5, 1, "%b", "мая");
+ TEST_PRINTF_DATE (2018, 5, 1, "%Ob", "май");
+ }
+ else
+ g_test_skip ("locale ru_RU not available, skipping Russian month names test");
+
setlocale (LC_ALL, oldlocale);
g_free (oldlocale);
}
/* this date has the DST state set for Europe/London */
#ifdef G_OS_UNIX
- tz = g_time_zone_new ("Europe/London");
+ tz = g_time_zone_new_identifier ("Europe/London");
#elif defined G_OS_WIN32
- tz = g_time_zone_new ("GMT Standard Time");
+ tz = g_time_zone_new_identifier ("GMT Standard Time");
#endif
+ g_assert_nonnull (tz);
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);
dt = g_date_time_new (timezone, year, month, day, 0, 0, 0);
#if 0
- g_print ("%04d-%02d-%02d = %04d-W%02d-%d = %04d-%03d\n",
+ g_printerr ("%04d-%02d-%02d = %04d-W%02d-%d = %04d-%03d\n",
year, month, day,
week_year, week_num, weekday,
year, day_of_year);
GDateTime *dt;
gchar *p;
- g_test_bug ("642935");
+ g_test_bug ("http://bugzilla.gnome.org/642935");
- tz = g_time_zone_new ("-08:00");
+ tz = g_time_zone_new_identifier ("-08:00");
+ g_assert_nonnull (tz);
dt = g_date_time_new (tz, 1, 1, 1, 0, 0, 0);
p = g_date_time_format (dt, "%z");
g_date_time_unref (dt);
g_time_zone_unref (tz);
- tz = g_time_zone_new ("+00:00");
+ tz = g_time_zone_new_identifier ("+00:00");
+ g_assert_nonnull (tz);
dt = g_date_time_new (tz, 1, 1, 1, 0, 0, 0);
p = g_date_time_format (dt, "%:::z");
g_assert_cmpstr (p, ==, "+00");
g_date_time_unref (dt);
g_time_zone_unref (tz);
- tz = g_time_zone_new ("+08:23");
+ tz = g_time_zone_new_identifier ("+08:23");
+ g_assert_nonnull (tz);
dt = g_date_time_new (tz, 1, 1, 1, 0, 0, 0);
p = g_date_time_format (dt, "%:::z");
g_assert_cmpstr (p, ==, "+08:23");
g_date_time_unref (dt);
g_time_zone_unref (tz);
- tz = g_time_zone_new ("+08:23:45");
+ tz = g_time_zone_new_identifier ("+08:23:45");
+ g_assert_nonnull (tz);
dt = g_date_time_new (tz, 1, 1, 1, 0, 0, 0);
p = g_date_time_format (dt, "%:::z");
g_assert_cmpstr (p, ==, "+08:23:45");
g_free (p);
g_date_time_unref (dt);
g_time_zone_unref (tz);
+
+ tz = g_time_zone_new_identifier ("-00:15");
+ g_assert_nonnull (tz);
+ dt = g_date_time_new (tz, 1, 1, 1, 0, 0, 0);
+
+ p = g_date_time_format (dt, "%z");
+ g_assert_cmpstr (p, ==, "-0015");
+ g_free (p);
+
+ p = g_date_time_format (dt, "%:z");
+ g_assert_cmpstr (p, ==, "-00:15");
+ g_free (p);
+
+ p = g_date_time_format (dt, "%::z");
+ g_assert_cmpstr (p, ==, "-00:15:00");
+ g_free (p);
+
+ p = g_date_time_format (dt, "%:::z");
+ g_assert_cmpstr (p, ==, "-00:15");
+ g_free (p);
+
+ g_date_time_unref (dt);
+ g_time_zone_unref (tz);
+}
+
+static void
+test_6_days_until_end_of_the_month (void)
+{
+ GTimeZone *tz;
+ GDateTime *dt;
+ gchar *p;
+
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2215");
+
+#ifdef G_OS_UNIX
+ /* This is the footertz string from `Europe/Paris` from tzdata 2020b. It’s
+ * used by GLib when the tzdata file was compiled with `zic -b slim`, which is
+ * the default in tzcode ≥2020b.
+ *
+ * The `M10.5.0` part indicates that the summer time end transition happens on
+ * the Sunday (`0`) in the last week (`5`) of October (`10`). That’s 6 days
+ * before the end of the month, and hence was triggering issue #2215.
+ *
+ * References:
+ * - https://tools.ietf.org/id/draft-murchison-tzdist-tzif-15.html#rfc.section.3.3
+ * - https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03
+ */
+ tz = g_time_zone_new_identifier ("CET-1CEST,M3.5.0,M10.5.0/3");
+#elif defined (G_OS_WIN32)
+ tz = g_time_zone_new_identifier ("Romance Standard Time");
+#endif
+ g_assert_nonnull (tz);
+ dt = g_date_time_new (tz, 2020, 10, 5, 1, 1, 1);
+
+ p = g_date_time_format (dt, "%Y-%m-%d %H:%M:%S%z");
+ /* Incorrect output is "2020-10-05 01:01:01+0100" */
+ g_assert_cmpstr (p, ==, "2020-10-05 01:01:01+0200");
+ g_free (p);
+
+ g_date_time_unref (dt);
+ g_time_zone_unref (tz);
}
static void
+test_format_iso8601 (void)
+{
+ GTimeZone *tz = NULL;
+ GDateTime *dt = NULL;
+ gchar *p = NULL;
+
+ tz = g_time_zone_new_utc ();
+ dt = g_date_time_new (tz, 2019, 6, 26, 15, 1, 5);
+ p = g_date_time_format_iso8601 (dt);
+ g_assert_cmpstr (p, ==, "2019-06-26T15:01:05Z");
+ g_free (p);
+ g_date_time_unref (dt);
+ g_time_zone_unref (tz);
+
+ tz = g_time_zone_new_offset (-60 * 60);
+ dt = g_date_time_new (tz, 2019, 6, 26, 15, 1, 5);
+ p = g_date_time_format_iso8601 (dt);
+ g_assert_cmpstr (p, ==, "2019-06-26T15:01:05-01");
+ g_free (p);
+ g_date_time_unref (dt);
+ g_time_zone_unref (tz);
+
+ tz = g_time_zone_new_utc ();
+ dt = g_date_time_new (tz, 2020, 8, 5, 12, 30, 55.000001);
+ p = g_date_time_format_iso8601 (dt);
+ g_assert_cmpstr (p, ==, "2020-08-05T12:30:55.000001Z");
+ g_free (p);
+ g_date_time_unref (dt);
+ g_time_zone_unref (tz);
+}
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-y2k"
+static void
test_strftime (void)
{
#ifdef __linux__
}
#endif
}
+#pragma GCC diagnostic pop
+
+/* Check that g_date_time_format() correctly returns %NULL for format
+ * placeholders which are not supported in the current locale. */
+static void
+test_GDateTime_strftime_error_handling (void)
+{
+ gchar *oldlocale;
+
+ oldlocale = g_strdup (setlocale (LC_ALL, NULL));
+ setlocale (LC_ALL, "de_DE.utf-8");
+ if (strstr (setlocale (LC_ALL, NULL), "de_DE") != NULL)
+ {
+ /* de_DE doesn’t ever write time in 12-hour notation, so %r is
+ * unsupported for it. */
+ TEST_PRINTF_TIME (23, 0, 0, "%r", NULL);
+ }
+ else
+ g_test_skip ("locale de_DE not available, skipping error handling tests");
+ setlocale (LC_ALL, oldlocale);
+ g_free (oldlocale);
+}
static void
test_find_interval (void)
gint i1, i2;
#ifdef G_OS_UNIX
- tz = g_time_zone_new ("Canada/Eastern");
+ tz = g_time_zone_new_identifier ("America/Toronto");
#elif defined G_OS_WIN32
- tz = g_time_zone_new ("Eastern Standard Time");
+ tz = g_time_zone_new_identifier ("Eastern Standard Time");
#endif
+ g_assert_nonnull (tz);
dt = g_date_time_new_utc (2010, 11, 7, 1, 30, 0);
u = g_date_time_to_unix (dt);
gint i1, i2;
#ifdef G_OS_UNIX
- tz = g_time_zone_new ("Canada/Eastern");
+ tz = g_time_zone_new_identifier ("America/Toronto");
#elif defined G_OS_WIN32
- tz = g_time_zone_new ("Eastern Standard Time");
+ tz = g_time_zone_new_identifier ("Eastern Standard Time");
#endif
+ g_assert_nonnull (tz);
dt = g_date_time_new_utc (2010, 11, 7, 1, 30, 0);
u = g_date_time_to_unix (dt);
u2 = u;
g_date_time_unref (dt);
i1 = g_time_zone_adjust_time (tz, G_TIME_TYPE_DAYLIGHT, &u2);
+ g_assert_cmpint (i1, >=, 0);
g_assert (u == u2);
g_time_zone_unref (tz);
{
GTimeZone *tz;
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
tz = g_time_zone_new ("blabla");
+ G_GNUC_END_IGNORE_DEPRECATIONS
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "UTC");
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "UTC");
g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, 0);
g_assert (!g_time_zone_is_dst (tz, 0));
}
static void
+test_no_header_identifier (void)
+{
+ GTimeZone *tz;
+
+ tz = g_time_zone_new_identifier ("blabla");
+
+ g_assert_null (tz);
+}
+
+static void
test_posix_parse (void)
{
GTimeZone *tz;
GDateTime *gdt1, *gdt2;
- tz = g_time_zone_new ("PST");
+ /* Check that an unknown zone name falls back to UTC. */
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ tz = g_time_zone_new ("nonexistent");
+ G_GNUC_END_IGNORE_DEPRECATIONS
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "UTC");
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "UTC");
g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, 0);
g_assert (!g_time_zone_is_dst (tz, 0));
g_time_zone_unref (tz);
+ /* An existent zone name should not fall back to UTC. */
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
tz = g_time_zone_new ("PST8");
+ G_GNUC_END_IGNORE_DEPRECATIONS
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "PST8");
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "PST");
g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, - 8 * 3600);
g_assert (!g_time_zone_is_dst (tz, 0));
/* This fails rules_from_identifier on Unix (though not on Windows)
* but passes anyway because PST8PDT is a zone name.
*/
- tz = g_time_zone_new ("PST8PDT");
+ tz = g_time_zone_new_identifier ("PST8PDT");
+ g_assert_nonnull (tz);
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "PST8PDT");
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "PST");
g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, - 8 * 3600);
g_assert (!g_time_zone_is_dst (tz, 0));
g_assert (g_time_zone_is_dst (tz, 1));
g_time_zone_unref (tz);
- tz = g_time_zone_new ("PST8PDT6:32:15");
+ tz = g_time_zone_new_identifier ("PST8PDT6:32:15");
#ifdef G_OS_WIN32
+ g_assert_nonnull (tz);
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "PST8PDT6:32:15");
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "PST");
g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, - 8 * 3600);
g_assert (!g_time_zone_is_dst (tz, 0));
g_date_time_unref (gdt1);
g_date_time_unref (gdt2);
#else
- g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "UTC");
- g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, 0);
- g_assert (!g_time_zone_is_dst (tz, 0));
+ g_assert_null (tz);
#endif
- g_time_zone_unref (tz);
+ g_clear_pointer (&tz, g_time_zone_unref);
- tz = g_time_zone_new ("NZST-12:00:00NZDT-13:00:00,M10.1.0,M3.3.0");
+ tz = g_time_zone_new_identifier ("NZST-12:00:00NZDT-13:00:00,M10.1.0,M3.3.0");
+ g_assert_nonnull (tz);
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "NZST-12:00:00NZDT-13:00:00,M10.1.0,M3.3.0");
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "NZST");
g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, 12 * 3600);
g_assert (!g_time_zone_is_dst (tz, 0));
g_date_time_unref (gdt2);
g_time_zone_unref (tz);
- tz = g_time_zone_new ("NZST-12:00:00NZDT-13:00:00,280,77");
+ tz = g_time_zone_new_identifier ("NZST-12:00:00NZDT-13:00:00,279,76");
+ g_assert_nonnull (tz);
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "NZST-12:00:00NZDT-13:00:00,279,76");
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "NZST");
g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, 12 * 3600);
g_assert (!g_time_zone_is_dst (tz, 0));
g_date_time_unref (gdt2);
g_time_zone_unref (tz);
- tz = g_time_zone_new ("NZST-12:00:00NZDT-13:00:00,J279,J76");
+ tz = g_time_zone_new_identifier ("NZST-12:00:00NZDT-13:00:00,J279,J76");
+ g_assert_nonnull (tz);
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "NZST-12:00:00NZDT-13:00:00,J279,J76");
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "NZST");
g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, 12 * 3600);
g_assert (!g_time_zone_is_dst (tz, 0));
g_date_time_unref (gdt2);
g_time_zone_unref (tz);
- tz = g_time_zone_new ("NZST-12:00:00NZDT-13:00:00,M10.1.0/07:00,M3.3.0/07:00");
+ tz = g_time_zone_new_identifier ("NZST-12:00:00NZDT-13:00:00,M10.1.0/07:00,M3.3.0/07:00");
+ g_assert_nonnull (tz);
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "NZST-12:00:00NZDT-13:00:00,M10.1.0/07:00,M3.3.0/07:00");
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "NZST");
g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, 12 * 3600);
g_assert (!g_time_zone_is_dst (tz, 0));
g_date_time_unref (gdt1);
g_date_time_unref (gdt2);
g_time_zone_unref (tz);
+
+ tz = g_time_zone_new_identifier ("VIR-00:30");
+ g_assert_nonnull (tz);
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "VIR-00:30");
+ g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "VIR");
+ g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, (30 * 60));
+ g_assert_false (g_time_zone_is_dst (tz, 0));
+
+ tz = g_time_zone_new_identifier ("VIR-00:30VID,0/00:00:00,365/23:59:59");
+ g_assert_nonnull (tz);
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "VIR-00:30VID,0/00:00:00,365/23:59:59");
+ g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "VIR");
+ g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, (30 * 60));
+ g_assert_false (g_time_zone_is_dst (tz, 0));
+ g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 1), ==, "VID");
+ g_assert_cmpint (g_time_zone_get_offset (tz, 1), ==, (90 * 60));
+ g_assert_true (g_time_zone_is_dst (tz, 1));
+
+ tz = g_time_zone_new_identifier ("VIR-02:30VID,0/00:00:00,365/23:59:59");
+ g_assert_nonnull (tz);
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "VIR-02:30VID,0/00:00:00,365/23:59:59");
+ g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "VIR");
+ g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, (150 * 60));
+ g_assert_false (g_time_zone_is_dst (tz, 0));
+ g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 1), ==, "VID");
+ g_assert_cmpint (g_time_zone_get_offset (tz, 1), ==, (210 * 60));
+ g_assert_true (g_time_zone_is_dst (tz, 1));
+
+ tz = g_time_zone_new_identifier ("VIR-02:30VID-04:30,0/00:00:00,365/23:59:59");
+ g_assert_nonnull (tz);
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "VIR-02:30VID-04:30,0/00:00:00,365/23:59:59");
+ g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "VIR");
+ g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, (150 * 60));
+ g_assert_false (g_time_zone_is_dst (tz, 0));
+ g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 1), ==, "VID");
+ g_assert_cmpint (g_time_zone_get_offset (tz, 1), ==, (270 * 60));
+ g_assert_true (g_time_zone_is_dst (tz, 1));
+
+ tz = g_time_zone_new_identifier ("VIR-12:00VID-13:00,0/00:00:00,365/23:59:59");
+ g_assert_nonnull (tz);
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "VIR-12:00VID-13:00,0/00:00:00,365/23:59:59");
+ g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "VIR");
+ g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, (720 * 60));
+ g_assert_false (g_time_zone_is_dst (tz, 0));
+ g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 1), ==, "VID");
+ g_assert_cmpint (g_time_zone_get_offset (tz, 1), ==, (780 * 60));
+ g_assert_true (g_time_zone_is_dst (tz, 1));
+}
+
+static void
+test_GDateTime_floating_point (void)
+{
+ GDateTime *dt;
+ GTimeZone *tz;
+
+ g_test_bug ("http://bugzilla.gnome.org/697715");
+
+ tz = g_time_zone_new_identifier ("-03:00");
+ g_assert_nonnull (tz);
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "-03:00");
+ dt = g_date_time_new (tz, 2010, 5, 24, 8, 0, 1.000001);
+ g_time_zone_unref (tz);
+ g_assert_cmpint (g_date_time_get_microsecond (dt), ==, 1);
+ g_date_time_unref (dt);
+}
+
+/* Check that g_time_zone_get_identifier() returns the identifier given to
+ * g_time_zone_new(), or "UTC" if loading the timezone failed. */
+static void
+test_identifier (void)
+{
+ GTimeZone *tz;
+ gchar *old_tz = g_strdup (g_getenv ("TZ"));
+
+#ifdef G_OS_WIN32
+ const char *recife_tz = "SA Eastern Standard Time";
+#else
+ const char *recife_tz = "America/Recife";
+#endif
+
+ tz = g_time_zone_new_identifier ("UTC");
+ g_assert_nonnull (tz);
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "UTC");
+ g_time_zone_unref (tz);
+
+ tz = g_time_zone_new_utc ();
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "UTC");
+ g_time_zone_unref (tz);
+
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ tz = g_time_zone_new ("some rubbish");
+ G_GNUC_END_IGNORE_DEPRECATIONS
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "UTC");
+ g_time_zone_unref (tz);
+
+ tz = g_time_zone_new_identifier ("Z");
+ g_assert_nonnull (tz);
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "Z");
+ g_time_zone_unref (tz);
+
+ tz = g_time_zone_new_identifier ("+03:15");
+ g_assert_nonnull (tz);
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "+03:15");
+ g_time_zone_unref (tz);
+
+ /* System timezone. We can’t change this, but we can at least assert that
+ * the identifier is non-NULL and non-empty. */
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ tz = g_time_zone_new (NULL);
+ G_GNUC_END_IGNORE_DEPRECATIONS
+ g_test_message ("System time zone identifier: %s", g_time_zone_get_identifier (tz));
+ g_assert_nonnull (g_time_zone_get_identifier (tz));
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), !=, "");
+ g_time_zone_unref (tz);
+
+ /* Local timezone tests. */
+ if (g_setenv ("TZ", recife_tz, TRUE))
+ {
+ tz = g_time_zone_new_local ();
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, recife_tz);
+ g_time_zone_unref (tz);
+ }
+
+ if (g_setenv ("TZ", "some rubbish", TRUE))
+ {
+ tz = g_time_zone_new_local ();
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "UTC");
+ g_time_zone_unref (tz);
+ }
+
+ if (old_tz != NULL)
+ g_assert_true (g_setenv ("TZ", old_tz, TRUE));
+ else
+ g_unsetenv ("TZ");
+
+ g_free (old_tz);
+}
+
+/* Test various calls to g_time_zone_new_offset(). */
+static void
+test_new_offset (void)
+{
+ const gint32 vectors[] =
+ {
+ -10000,
+ -3600,
+ -61,
+ -60,
+ -59,
+ 0,
+ 59,
+ 60,
+ 61,
+ 3600,
+ 10000,
+ };
+ gsize i;
+
+ for (i = 0; i < G_N_ELEMENTS (vectors); i++)
+ {
+ GTimeZone *tz = NULL;
+
+ g_test_message ("Vector %" G_GSIZE_FORMAT ": %d", i, vectors[i]);
+
+ tz = g_time_zone_new_offset (vectors[i]);
+ g_assert_nonnull (tz);
+ g_assert_cmpstr (g_time_zone_get_identifier (tz), !=, "UTC");
+ g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, vectors[i]);
+ g_time_zone_unref (tz);
+ }
+}
+
+static void
+test_time_zone_parse_rfc8536 (void)
+{
+ const gchar *test_files[] =
+ {
+ /* Generated with `zic -b slim`; see
+ * https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1533#note_842235 */
+ "Amsterdam-slim",
+ /* Generated with `zic -b fat` */
+ "Amsterdam-fat",
+ };
+ gsize i;
+
+ g_test_summary ("Test parsing time zone files in RFC 8536 version 3 format");
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2129");
+
+ for (i = 0; i < G_N_ELEMENTS (test_files); i++)
+ {
+ gchar *path = NULL;
+ GTimeZone *tz = NULL;
+
+ path = g_test_build_filename (G_TEST_DIST, "time-zones", test_files[i], NULL);
+ g_assert_true (g_path_is_absolute (path));
+ tz = g_time_zone_new_identifier (path);
+ g_assert_nonnull (tz);
+ g_time_zone_unref (tz);
+ g_free (path);
+ }
}
+/* Check GTimeZone instances are cached. */
+static void
+test_time_zone_caching (void)
+{
+ GTimeZone *tz1 = NULL, *tz2 = NULL;
+
+ g_test_summary ("GTimeZone instances are cached");
+
+ /* Check a specific (arbitrary) timezone. These are only cached while third
+ * party code holds a ref to at least one instance. */
+#ifdef G_OS_UNIX
+ tz1 = g_time_zone_new_identifier ("Europe/London");
+ g_assert_nonnull (tz1);
+ tz2 = g_time_zone_new_identifier ("Europe/London");
+ g_assert_nonnull (tz2);
+ g_time_zone_unref (tz1);
+ g_time_zone_unref (tz2);
+#elif defined G_OS_WIN32
+ tz1 = g_time_zone_new_identifier ("GMT Standard Time");
+ g_assert_nonnull (tz1);
+ tz2 = g_time_zone_new_identifier ("GMT Standard Time");
+ g_assert_nonnull (tz2);
+ g_time_zone_unref (tz1);
+ g_time_zone_unref (tz2);
+#endif
+
+ /* Only compare pointers */
+ g_assert_true (tz1 == tz2);
+
+ /* Check the default timezone, local and UTC. These are cached internally in
+ * GLib, so should persist even after the last third party reference is
+ * dropped.
+ *
+ * The default timezone could be NULL on some platforms (FreeBSD) if
+ * `/etc/localtime` is not set correctly. */
+ tz1 = g_time_zone_new_identifier (NULL);
+ if (tz1 != NULL)
+ {
+ g_assert_nonnull (tz1);
+ g_time_zone_unref (tz1);
+ tz2 = g_time_zone_new_identifier (NULL);
+ g_assert_nonnull (tz2);
+ g_time_zone_unref (tz2);
+
+ g_assert_true (tz1 == tz2);
+ }
+
+ tz1 = g_time_zone_new_utc ();
+ g_time_zone_unref (tz1);
+ tz2 = g_time_zone_new_utc ();
+ g_time_zone_unref (tz2);
+
+ g_assert_true (tz1 == tz2);
+
+ tz1 = g_time_zone_new_local ();
+ g_time_zone_unref (tz1);
+ tz2 = g_time_zone_new_local ();
+ g_time_zone_unref (tz2);
+
+ g_assert_true (tz1 == tz2);
+}
+
+
gint
main (gint argc,
gchar *argv[])
{
+ /* In glibc, LANGUAGE is used as highest priority guess for category value.
+ * Unset it to avoid interference with tests using setlocale and translation. */
+ g_unsetenv ("LANGUAGE");
+
g_test_init (&argc, &argv, NULL);
- g_test_bug_base ("http://bugzilla.gnome.org/");
/* GDateTime Tests */
+ bind_textdomain_codeset ("glib20", "UTF-8");
g_test_add_func ("/GDateTime/invalid", test_GDateTime_invalid);
g_test_add_func ("/GDateTime/add_days", test_GDateTime_add_days);
g_test_add_func ("/GDateTime/hash", test_GDateTime_hash);
g_test_add_func ("/GDateTime/new_from_unix", test_GDateTime_new_from_unix);
g_test_add_func ("/GDateTime/new_from_unix_utc", test_GDateTime_new_from_unix_utc);
+ g_test_add_func ("/GDateTime/new_from_unix/overflow", test_GDateTime_new_from_unix_overflow);
g_test_add_func ("/GDateTime/new_from_timeval", test_GDateTime_new_from_timeval);
g_test_add_func ("/GDateTime/new_from_timeval_utc", test_GDateTime_new_from_timeval_utc);
+ g_test_add_func ("/GDateTime/new_from_timeval/overflow", test_GDateTime_new_from_timeval_overflow);
+ g_test_add_func ("/GDateTime/new_from_iso8601", test_GDateTime_new_from_iso8601);
+ g_test_add_func ("/GDateTime/new_from_iso8601/2", test_GDateTime_new_from_iso8601_2);
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/test-6-days-until-end-of-the-month", test_6_days_until_end_of_the_month);
g_test_add_func ("/GDateTime/printf", test_GDateTime_printf);
g_test_add_func ("/GDateTime/non_utf8_printf", test_non_utf8_printf);
+ g_test_add_func ("/GDateTime/format_unrepresentable", test_format_unrepresentable);
+ g_test_add_func ("/GDateTime/format_iso8601", test_format_iso8601);
g_test_add_func ("/GDateTime/strftime", test_strftime);
+ g_test_add_func ("/GDateTime/strftime/error_handling", test_GDateTime_strftime_error_handling);
g_test_add_func ("/GDateTime/modifiers", test_modifiers);
+ g_test_add_func ("/GDateTime/month_names", test_month_names);
g_test_add_func ("/GDateTime/to_local", test_GDateTime_to_local);
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 ("/GTimeZone/find-interval", test_find_interval);
g_test_add_func ("/GTimeZone/adjust-time", test_adjust_time);
g_test_add_func ("/GTimeZone/no-header", test_no_header);
+ g_test_add_func ("/GTimeZone/no-header-identifier", test_no_header_identifier);
g_test_add_func ("/GTimeZone/posix-parse", test_posix_parse);
+ g_test_add_func ("/GTimeZone/floating-point", test_GDateTime_floating_point);
+ g_test_add_func ("/GTimeZone/identifier", test_identifier);
+ g_test_add_func ("/GTimeZone/new-offset", test_new_offset);
+ g_test_add_func ("/GTimeZone/parse-rfc8536", test_time_zone_parse_rfc8536);
+ g_test_add_func ("/GTimeZone/caching", test_time_zone_caching);
return g_test_run ();
}