Commit e9c648f5 authored by Morten Welinder's avatar Morten Welinder Committed by Morten Welinder

Improve rounding precision and avoid overflow. Also, round before doing

2000-01-10  Morten Welinder  <terra@diku.dk>

	* src/format.c (split_time): Improve rounding precision and avoid
 	overflow.  Also, round before doing date part.

	* src/functions/fn-date.c (gnumeric_hour, gnumeric_minute,
 	gnumeric_second): Don't do the 0.5 second rounding here.
	(get_serial_date, get_serial_time): Do it here.
parent 340eebca
2000-01-10 Morten Welinder <terra@diku.dk>
* src/format.c (split_time): Improve rounding precision and avoid
overflow. Also, round before doing date part.
* src/functions/fn-date.c (gnumeric_hour, gnumeric_minute,
gnumeric_second): Don't do the 0.5 second rounding here.
(get_serial_date, get_serial_time): Do it here.
2000-01-10 Jody Goldberg <jgoldberg@home.com>
* src/application.c (application_clipboard_cut) : Typo.
......
2000-01-10 Morten Welinder <terra@diku.dk>
* src/format.c (split_time): Improve rounding precision and avoid
overflow. Also, round before doing date part.
* src/functions/fn-date.c (gnumeric_hour, gnumeric_minute,
gnumeric_second): Don't do the 0.5 second rounding here.
(get_serial_date, get_serial_time): Do it here.
2000-01-10 Jody Goldberg <jgoldberg@home.com>
* src/application.c (application_clipboard_cut) : Typo.
......
......@@ -30,6 +30,10 @@ get_serial_date (const Value *v)
} else
serial = 0;
}
/* Add half a second. Yes, Excel rounds up the date too. */
serial += 0.5 / DAY_SECONDS;
return floor (serial);
}
......@@ -59,6 +63,10 @@ get_serial_time (Value *v)
serial = 0;
g_free (str);
}
/* Add half a second. Yes, Excel rounds up the date too. */
serial += 0.5 / DAY_SECONDS;
return serial - floor (serial);
}
......@@ -328,7 +336,7 @@ gnumeric_hour (FunctionEvalInfo *ei, Value **argv)
{
int secs;
secs = (int)(get_serial_time (argv[0]) * DAY_SECONDS + 0.5);
secs = (int)(get_serial_time (argv[0]) * DAY_SECONDS);
return value_new_int (secs / 3600);
}
......@@ -356,7 +364,7 @@ gnumeric_minute (FunctionEvalInfo *ei, Value **argv)
{
int secs;
secs = (int)(get_serial_time (argv[0]) * DAY_SECONDS + 0.5);
secs = (int)(get_serial_time (argv[0]) * DAY_SECONDS);
return value_new_int ((secs / 60) % 60);
}
......@@ -384,7 +392,7 @@ gnumeric_second (FunctionEvalInfo *ei, Value **argv)
{
int secs;
secs = (int)(get_serial_time (argv[0]) * DAY_SECONDS + 0.5);
secs = (int)(get_serial_time (argv[0]) * DAY_SECONDS);
return value_new_int (secs % 60);
}
......
......@@ -688,19 +688,24 @@ split_time (gdouble number)
{
static struct tm tm;
guint secs;
GDate* date;
GDate* date = g_date_new_serial (number);
/* Excel compatible rounding, I think. -- MW. */
number += 0.5 / 86400;
date = g_date_new_serial (number);
g_date_to_struct_tm (date, &tm);
/*
* WARNING : Be very careful about rounding here
* 86400 is not a great number to multiply by and one can easily
* loose a second, and hence an entire minute.
* We first round the seconds, then do integer calculations
* for the rest.
* This code used to be
* secs = ((number * 86400. + .5)) - (((int)number) * 86400);
* but that does not work on Sparc's. (I don't think it really works
* anywhere else, but that is just a guess. Think overflow.
*
* (And that was before the += 0.5 above).
*/
secs = ((number * 86400. + .5)) - (((int)number) * 86400);
secs = (int)((number - (int)number) * 86400);
tm.tm_hour = secs / 3600;
secs -= tm.tm_hour * 3600;
......
......@@ -30,6 +30,10 @@ get_serial_date (const Value *v)
} else
serial = 0;
}
/* Add half a second. Yes, Excel rounds up the date too. */
serial += 0.5 / DAY_SECONDS;
return floor (serial);
}
......@@ -59,6 +63,10 @@ get_serial_time (Value *v)
serial = 0;
g_free (str);
}
/* Add half a second. Yes, Excel rounds up the date too. */
serial += 0.5 / DAY_SECONDS;
return serial - floor (serial);
}
......@@ -328,7 +336,7 @@ gnumeric_hour (FunctionEvalInfo *ei, Value **argv)
{
int secs;
secs = (int)(get_serial_time (argv[0]) * DAY_SECONDS + 0.5);
secs = (int)(get_serial_time (argv[0]) * DAY_SECONDS);
return value_new_int (secs / 3600);
}
......@@ -356,7 +364,7 @@ gnumeric_minute (FunctionEvalInfo *ei, Value **argv)
{
int secs;
secs = (int)(get_serial_time (argv[0]) * DAY_SECONDS + 0.5);
secs = (int)(get_serial_time (argv[0]) * DAY_SECONDS);
return value_new_int ((secs / 60) % 60);
}
......@@ -384,7 +392,7 @@ gnumeric_second (FunctionEvalInfo *ei, Value **argv)
{
int secs;
secs = (int)(get_serial_time (argv[0]) * DAY_SECONDS + 0.5);
secs = (int)(get_serial_time (argv[0]) * DAY_SECONDS);
return value_new_int (secs % 60);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment