mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-04 02:06:18 +01:00
gdatetime: fix floating-point conversion
Conversion from floating point to integer requires special care. https://bugzilla.gnome.org/show_bug.cgi?id=697715
This commit is contained in:
parent
b5733ecc76
commit
3cfac71d09
@ -1295,6 +1295,7 @@ g_date_time_new (GTimeZone *tz,
|
||||
{
|
||||
GDateTime *datetime;
|
||||
gint64 full_time;
|
||||
gint64 usec;
|
||||
|
||||
g_return_val_if_fail (tz != NULL, NULL);
|
||||
|
||||
@ -1322,10 +1323,20 @@ g_date_time_new (GTimeZone *tz,
|
||||
G_TIME_TYPE_STANDARD,
|
||||
&full_time);
|
||||
|
||||
/* This is the correct way to convert a scaled FP value to integer.
|
||||
* If this surprises you, please observe that (int)(1.000001 * 1e6)
|
||||
* is 1000000. This is not a problem with precision, it's just how
|
||||
* FP numbers work.
|
||||
* See https://bugzilla.gnome.org/show_bug.cgi?id=697715. */
|
||||
usec = seconds * USEC_PER_SECOND;
|
||||
if ((usec + 1) * 1e-6 <= seconds) {
|
||||
usec++;
|
||||
}
|
||||
|
||||
full_time += UNIX_EPOCH_START * SEC_PER_DAY;
|
||||
datetime->days = full_time / SEC_PER_DAY;
|
||||
datetime->usec = (full_time % SEC_PER_DAY) * USEC_PER_SECOND;
|
||||
datetime->usec += ((int) (seconds * USEC_PER_SECOND)) % USEC_PER_SECOND;
|
||||
datetime->usec += usec % USEC_PER_SECOND;
|
||||
|
||||
return datetime;
|
||||
}
|
||||
|
@ -2083,6 +2083,21 @@ test_posix_parse (void)
|
||||
g_time_zone_unref (tz);
|
||||
}
|
||||
|
||||
static void
|
||||
test_GDateTime_floating_point (void)
|
||||
{
|
||||
GDateTime *dt;
|
||||
GTimeZone *tz;
|
||||
|
||||
g_test_bug ("697715");
|
||||
|
||||
tz = g_time_zone_new ("-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);
|
||||
}
|
||||
|
||||
gint
|
||||
main (gint argc,
|
||||
gchar *argv[])
|
||||
@ -2140,6 +2155,7 @@ main (gint argc,
|
||||
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/posix-parse", test_posix_parse);
|
||||
g_test_add_func ("/GTimeZone/floating-point", test_GDateTime_floating_point);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user