mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-05-22 05:22:10 +02: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;
|
GDateTime *datetime;
|
||||||
gint64 full_time;
|
gint64 full_time;
|
||||||
|
gint64 usec;
|
||||||
|
|
||||||
g_return_val_if_fail (tz != NULL, NULL);
|
g_return_val_if_fail (tz != NULL, NULL);
|
||||||
|
|
||||||
@ -1322,10 +1323,20 @@ g_date_time_new (GTimeZone *tz,
|
|||||||
G_TIME_TYPE_STANDARD,
|
G_TIME_TYPE_STANDARD,
|
||||||
&full_time);
|
&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;
|
full_time += UNIX_EPOCH_START * SEC_PER_DAY;
|
||||||
datetime->days = full_time / SEC_PER_DAY;
|
datetime->days = full_time / SEC_PER_DAY;
|
||||||
datetime->usec = (full_time % SEC_PER_DAY) * USEC_PER_SECOND;
|
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;
|
return datetime;
|
||||||
}
|
}
|
||||||
|
@ -2083,6 +2083,21 @@ test_posix_parse (void)
|
|||||||
g_time_zone_unref (tz);
|
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
|
gint
|
||||||
main (gint argc,
|
main (gint argc,
|
||||||
gchar *argv[])
|
gchar *argv[])
|
||||||
@ -2140,6 +2155,7 @@ main (gint argc,
|
|||||||
g_test_add_func ("/GTimeZone/adjust-time", test_adjust_time);
|
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", test_no_header);
|
||||||
g_test_add_func ("/GTimeZone/posix-parse", test_posix_parse);
|
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 ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user