diff --git a/glib/gdatetime.c b/glib/gdatetime.c index 81518cd70..4b1811fd6 100644 --- a/glib/gdatetime.c +++ b/glib/gdatetime.c @@ -1033,15 +1033,41 @@ g_date_time_new_now_utc (void) GDateTime * g_date_time_new_from_unix_local (gint64 t) { - GDateTime *datetime; - GTimeZone *local; - if (t > G_MAXINT64 / USEC_PER_SECOND || t < G_MININT64 / USEC_PER_SECOND) return NULL; + return g_date_time_new_from_unix_local_usec (t * USEC_PER_SECOND); +} + +/** + * g_date_time_new_from_unix_local_usec: (constructor) + * @usecs: the Unix time in microseconds + * + * Creates a [struct@GLib.DateTime] corresponding to the given Unix time @t in the + * local time zone. + * + * Unix time is the number of microseconds that have elapsed since 1970-01-01 + * 00:00:00 UTC, regardless of the local time offset. + * + * This call can fail (returning `NULL`) if @t represents a time outside + * of the supported range of #GDateTime. + * + * You should release the return value by calling [method@GLib.DateTime.unref] + * when you are done with it. + * + * Returns: (transfer full) (nullable): a new [struct@GLib.DateTime], or `NULL` + * + * Since: 2.80 + **/ +GDateTime * +g_date_time_new_from_unix_local_usec (gint64 usecs) +{ + GDateTime *datetime; + GTimeZone *local; + local = g_time_zone_new_local (); - datetime = g_date_time_new_from_unix (local, t * USEC_PER_SECOND); + datetime = g_date_time_new_from_unix (local, usecs); g_time_zone_unref (local); return datetime; @@ -1069,15 +1095,40 @@ g_date_time_new_from_unix_local (gint64 t) GDateTime * g_date_time_new_from_unix_utc (gint64 t) { - GDateTime *datetime; - GTimeZone *utc; - if (t > G_MAXINT64 / USEC_PER_SECOND || t < G_MININT64 / USEC_PER_SECOND) return NULL; + return g_date_time_new_from_unix_utc_usec (t * USEC_PER_SECOND); +} + +/** + * g_date_time_new_from_unix_utc: (constructor) + * @usecs: the Unix time in microseconds + * + * Creates a [struct@GLib.DateTime] corresponding to the given Unix time @t in UTC. + * + * Unix time is the number of microseconds that have elapsed since 1970-01-01 + * 00:00:00 UTC. + * + * This call can fail (returning `NULL`) if @t represents a time outside + * of the supported range of #GDateTime. + * + * You should release the return value by calling [method@GLib.DateTime.unref] + * when you are done with it. + * + * Returns: (transfer full) (nullable): a new [struct@GLib.DateTime], or `NULL` + * + * Since: 2.80 + **/ +GDateTime * +g_date_time_new_from_unix_utc_usec (gint64 usecs) +{ + GDateTime *datetime; + GTimeZone *utc; + utc = g_time_zone_new_utc (); - datetime = g_date_time_new_from_unix (utc, t * USEC_PER_SECOND); + datetime = g_date_time_new_from_unix (utc, usecs); g_time_zone_unref (utc); return datetime; @@ -2566,6 +2617,27 @@ g_date_time_to_unix (GDateTime *datetime) return INSTANT_TO_UNIX (g_date_time_to_instant (datetime)); } +/** + * g_date_time_to_unix_usec: + * @datetime: a #GDateTime + * + * Gives the Unix time corresponding to @datetime, in microseconds. + * + * Unix time is the number of microseconds that have elapsed since 1970-01-01 + * 00:00:00 UTC, regardless of the time zone associated with @datetime. + * + * Returns: the Unix time corresponding to @datetime + * + * Since: 2.80 + **/ +gint64 +g_date_time_to_unix_usec (GDateTime *datetime) +{ + g_return_val_if_fail (datetime != NULL, 0); + + return INSTANT_TO_UNIX_USECS (g_date_time_to_instant (datetime)); +} + /** * g_date_time_to_timeval: * @datetime: a #GDateTime diff --git a/glib/gdatetime.h b/glib/gdatetime.h index 95614f50c..846d22ca3 100644 --- a/glib/gdatetime.h +++ b/glib/gdatetime.h @@ -138,6 +138,11 @@ GDateTime * g_date_time_new_from_unix_local (gint64 GLIB_AVAILABLE_IN_ALL GDateTime * g_date_time_new_from_unix_utc (gint64 t); +GLIB_AVAILABLE_IN_2_80 +GDateTime * g_date_time_new_from_unix_local_usec (gint64 usecs); +GLIB_AVAILABLE_IN_2_80 +GDateTime * g_date_time_new_from_unix_utc_usec (gint64 usecs); + G_GNUC_BEGIN_IGNORE_DEPRECATIONS GLIB_DEPRECATED_IN_2_62_FOR(g_date_time_new_from_unix_local) GDateTime * g_date_time_new_from_timeval_local (const GTimeVal *tv); @@ -265,6 +270,9 @@ gdouble g_date_time_get_seconds (GDateTi GLIB_AVAILABLE_IN_ALL gint64 g_date_time_to_unix (GDateTime *datetime); +GLIB_AVAILABLE_IN_2_80 +gint64 g_date_time_to_unix_usec (GDateTime *datetime); + G_GNUC_BEGIN_IGNORE_DEPRECATIONS GLIB_DEPRECATED_IN_2_62_FOR(g_date_time_to_unix) gboolean g_date_time_to_timeval (GDateTime *datetime, diff --git a/glib/tests/gdatetime.c b/glib/tests/gdatetime.c index 0dc82c68b..f60368d14 100644 --- a/glib/tests/gdatetime.c +++ b/glib/tests/gdatetime.c @@ -3392,6 +3392,38 @@ test_time_zone_caching (void) g_assert_true (tz1 == tz2); } +static void +test_date_time_unix_usec (void) +{ + gint64 usecs = g_get_real_time (); + gint64 secs = usecs / G_USEC_PER_SEC; + GDateTime *dt; + GDateTime *local; + + dt = g_date_time_new_from_unix_utc (secs); + g_assert_cmpint (g_date_time_to_unix_usec (dt), ==, secs * G_USEC_PER_SEC); + g_assert_cmpint (g_date_time_to_unix (dt), ==, secs); + g_date_time_unref (dt); + + dt = g_date_time_new_from_unix_utc_usec (usecs); + g_assert_cmpint (g_date_time_to_unix_usec (dt), ==, usecs); + g_assert_cmpint (g_date_time_to_unix (dt), ==, secs); + g_date_time_unref (dt); + + local = g_date_time_new_from_unix_local (secs); + dt = g_date_time_to_utc (local); + g_assert_cmpint (g_date_time_to_unix_usec (dt), ==, secs * G_USEC_PER_SEC); + g_assert_cmpint (g_date_time_to_unix (dt), ==, secs); + g_date_time_unref (dt); + g_date_time_unref (local); + + local = g_date_time_new_from_unix_local_usec (usecs); + dt = g_date_time_to_utc (local); + g_assert_cmpint (g_date_time_to_unix_usec (dt), ==, usecs); + g_assert_cmpint (g_date_time_to_unix (dt), ==, secs); + g_date_time_unref (dt); + g_date_time_unref (local); +} gint main (gint argc, @@ -3476,6 +3508,7 @@ main (gint argc, g_test_add_func ("/GDateTime/eras/japan", test_date_time_eras_japan); g_test_add_func ("/GDateTime/eras/thailand", test_date_time_eras_thailand); g_test_add_func ("/GDateTime/eras/parsing", test_date_time_eras_parsing); + g_test_add_func ("/GDateTime/unix_usec", test_date_time_unix_usec); g_test_add_func ("/GTimeZone/find-interval", test_find_interval); g_test_add_func ("/GTimeZone/adjust-time", test_adjust_time);