Commit 07f3acad authored by Morten Welinder's avatar Morten Welinder Committed by Morten Welinder

New functions.

2008-06-27  Morten Welinder  <terra@gnome.org>

	* src/gnm-datetime.c (gnm_date_add_days, gnm_date_add_months): New
	functions.

	* src/sheet-autofill.c (afm_compute): Simplify using
	gnm_date_add_months.

2008-06-27  Morten Welinder  <terra@gnome.org>

	* functions.c (gnumeric_date, datedif_opt_md, gnumeric_edate,
	gnumeric_eomonth): Simplify using gnm_date_add_months and
	gnm_date_add_days.

2008-06-27  Morten Welinder  <terra@gnome.org>

	* fill-series.c (do_row_filling_wday, do_column_filling_wday):
	Simplify using gnm_date_add_days.
	(do_row_filling_month, do_column_filling_month): Simplify using
	gnm_date_add_months.


svn path=/trunk/; revision=16675
parent 5b3db7aa
2008-06-27 Morten Welinder <terra@gnome.org>
* src/gnm-datetime.c (gnm_date_add_days, gnm_date_add_months): New
functions.
* src/sheet-autofill.c (afm_compute): Simplify using
gnm_date_add_months.
2008-06-25 Morten Welinder <terra@gnome.org>
* src/mathfunc.c (phyper): Short-circuit x>=NR case. Fixes
......
2008-06-27 Morten Welinder <terra@gnome.org>
* functions.c (gnumeric_date, datedif_opt_md, gnumeric_edate,
gnumeric_eomonth): Simplify using gnm_date_add_months and
gnm_date_add_days.
2008-06-25 Morten Welinder <terra@gnome.org>
* functions.c (gnumeric_eomonth): Work around glib problem. Fixes
......
......@@ -126,7 +126,6 @@ gnumeric_date (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
gnm_float day = value_get_as_float (argv [2]);
GDate date;
GODateConventions const *conv = DATE_CONV (ei->pos);
int y, m, d;
if (year < 0 || year >= 10000)
goto error;
......@@ -145,32 +144,12 @@ gnumeric_date (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
g_date_clear (&date, 1);
y = (int)year;
g_date_set_dmy (&date, 1, 1, y);
if (!g_date_valid (&date))
goto error;
g_date_set_dmy (&date, 1, 1, (int)year);
gnm_date_add_months (&date, (int)month);
gnm_date_add_days (&date, (int)day);
m = (int)month;
if (y + m / 12 < gnm_date_convention_base (conv))
goto error;
else if (m > 0)
g_date_add_months (&date, m - 1);
else if (m < 0)
g_date_subtract_months (&date, 1 - m);
if (!g_date_valid (&date))
goto error;
d = (int)day;
if (d < 0 && g_date_get_julian (&date) < (unsigned)-d)
goto error;
else if (d > 0)
g_date_add_days (&date, d - 1);
else if (d < 0)
g_date_subtract_days (&date, 1 - d);
if (!g_date_valid (&date))
goto error;
if (g_date_get_year (&date) < gnm_date_convention_base (conv) ||
if (!g_date_valid (&date) ||
g_date_get_year (&date) < gnm_date_convention_base (conv) ||
g_date_get_year (&date) >= 11900)
goto error;
......@@ -329,8 +308,8 @@ datedif_opt_yd (GDate *gdate1, GDate *gdate2, int excel_compat)
day = g_date_get_day (gdate1);
g_date_add_years (gdate1,
datetime_g_years_between (gdate1, gdate2));
gnm_date_add_years (gdate1,
datetime_g_years_between (gdate1, gdate2));
/* according to glib.h, feb 29 turns to feb 28 if necessary */
if (excel_compat) {
......@@ -368,8 +347,8 @@ datedif_opt_md (GDate *gdate1, GDate *gdate2, gboolean excel_compat)
day = g_date_get_day (gdate1);
g_date_add_months (gdate1,
datetime_g_months_between (gdate1, gdate2));
gnm_date_add_months (gdate1,
datetime_g_months_between (gdate1, gdate2));
/* according to glib.h, days>28 decrease if necessary */
if (excel_compat) {
......@@ -385,11 +364,11 @@ datedif_opt_md (GDate *gdate1, GDate *gdate2, gboolean excel_compat)
g_date_set_year (gdate2, new_year2);
/* add back the days if they were decreased by
g_date_add_months */
gnm_date_add_months */
/* ( i feel this is inferior because it reports e.g.:
datedif(1/31/95,3/1/95,"d") == -2 ) */
g_date_add_days (gdate1,
day - g_date_get_day (gdate1));
gnm_date_add_days (gdate1,
day - g_date_get_day (gdate1));
}
return g_date_days_between (gdate1, gdate2);
......@@ -463,7 +442,6 @@ gnumeric_edate (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
gnm_float serial = value_get_as_float (argv[0]);
gnm_float months = value_get_as_float (argv[1]);
GDate date;
int m, y;
if (serial < 0 || serial > INT_MAX)
return value_new_error_NUM (ei->pos);
......@@ -471,19 +449,7 @@ gnumeric_edate (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
return value_new_error_NUM (ei->pos);
datetime_serial_to_g (&date, (int)serial, conv);
if (!g_date_valid (&date))
return value_new_error_VALUE (ei->pos);
m = (int)months;
y = g_date_get_year (&date) + m / 12;
/* Pretest for the benefit of #539868 */
if (y > 9999 || y < 1900)
g_date_clear (&date, 1);
else if (m > 0)
g_date_add_months (&date, m);
else if (m < 0)
g_date_subtract_months (&date, -m);
gnm_date_add_months (&date, (int)months);
if (!g_date_valid (&date) ||
g_date_get_year (&date) < 1900 ||
......@@ -969,7 +935,6 @@ gnumeric_eomonth (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
gnm_float months = argv[1] ? value_get_as_float (argv[1]) : 0;
GDate date;
GODateConventions const *conv = DATE_CONV (ei->pos);
int m, y;
datetime_value_to_g (&date, argv[0], conv);
if (!g_date_valid (&date))
......@@ -978,17 +943,7 @@ gnumeric_eomonth (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
if (months > INT_MAX / 2 || -months > INT_MAX / 2)
return value_new_error_NUM (ei->pos);
m = (int)months;
y = g_date_get_year (&date) + m / 12;
/* Pretest for the benefit of #539868 */
if (y > 9999 || y < 1900)
g_date_clear (&date, 1);
else if (m > 0)
g_date_add_months (&date, m);
else if (m < 0)
g_date_subtract_months (&date, -m);
gnm_date_add_months (&date, (int)months);
if (!g_date_valid (&date) ||
g_date_get_year (&date) < 1900 ||
g_date_get_year (&date) > 9999)
......
......@@ -135,7 +135,7 @@ yearfrac (GDate const *from, GDate const *to, basis_t basis)
int feb29s, years;
d1 = *from;
g_date_add_years (&d1, 1);
gnm_date_add_years (&d1, 1);
if (g_date_compare (to, &d1) > 0) {
/* More than one year. */
years = y2 + 1 - y1;
......@@ -171,3 +171,107 @@ yearfrac (GDate const *from, GDate const *to, basis_t basis)
return days / peryear;
}
/* ------------------------------------------------------------------------- */
/* Like g_date_add_days, but...
*
* 1. Do not spew criticals.
* 2. Number of days is signed.
*/
void
gnm_date_add_days (GDate *d, int n)
{
if (!g_date_valid (d))
return;
if (n >= 0) {
guint32 lim = 23936166; /* 31-Dec-65535 */
guint32 j = g_date_get_julian (d);
if (j > lim || (unsigned)n > lim - j)
goto bad;
g_date_add_days (d, n);
} else {
int m = g_date_get_julian (d) - 1;
if (m + n <= 0)
goto bad;
g_date_subtract_days (d, -n);
}
return;
bad:
g_date_clear (d, 1);
}
/* Like g_date_add_months, but...
*
* 1. Do not spew criticals.
* 2. Number of months is signed.
*/
void
gnm_date_add_months (GDate *d, int n)
{
if (!g_date_valid (d))
return;
if (n >= 0) {
int m = (65535 - g_date_get_year (d)) * 12 +
(12 - g_date_get_month (d));
if (n > m)
goto bad;
g_date_add_months (d, n);
} else {
int m = (g_date_get_year (d) - 1) * 12 +
(g_date_get_month (d) - 1);
if (m + n <= 0)
goto bad;
g_date_subtract_months (d, -n);
}
return;
bad:
g_date_clear (d, 1);
}
/* Like g_date_add_years, but...
*
* 1. Do not spew criticals.
* 2. Number of years is signed.
*/
void
gnm_date_add_years (GDate *d, int n)
{
if (!g_date_valid (d))
return;
if (n >= 0) {
int m = 65535 - g_date_get_year (d);
if (n > m)
goto bad;
g_date_add_years (d, n);
} else {
int m = g_date_get_year (d) - 1;
if (m + n <= 0)
goto bad;
g_date_subtract_years (d, -n);
}
return;
bad:
g_date_clear (d, 1);
}
......@@ -19,6 +19,9 @@ int annual_year_basis (GnmValue const *value_date, basis_t basis,
GODateConventions const *date_conv);
gnm_float yearfrac (GDate const *from, GDate const *to, basis_t basis);
void gnm_date_add_days (GDate *d, int n);
void gnm_date_add_months (GDate *d, int n);
void gnm_date_add_years (GDate *d, int n);
G_END_DECLS
......
......@@ -590,10 +590,7 @@ afm_compute (AutoFillerMonth *afm, int n)
GDate d = afm->base;
GnmValue *v;
if (afm->nmonths >= 0)
g_date_add_months (&d, n * afm->nmonths);
else
g_date_subtract_months (&d, n * -afm->nmonths);
gnm_date_add_months (&d, n * afm->nmonths);
if (!g_date_valid (&d) || g_date_get_year (&d) > 9999)
return NULL;
......
2008-06-27 Morten Welinder <terra@gnome.org>
* fill-series.c (do_row_filling_wday, do_column_filling_wday):
Simplify using gnm_date_add_days.
(do_row_filling_month, do_column_filling_month): Simplify using
gnm_date_add_months.
2008-06-25 Jody Goldberg <jody@gnome.org>
* Release 1.9.1
......
......@@ -37,6 +37,7 @@
#include "workbook.h"
#include "tools.h"
#include "numbers.h"
#include "gnm-datetime.h"
#include "mathfunc.h"
#include "fill-series.h"
......@@ -62,10 +63,7 @@ do_row_filling_wday (data_analysis_output_t *dao, fill_series_t *info)
wd = g_date_get_weekday (&date);
if (wd + (steps % 5) > G_DATE_FRIDAY)
days += 2;
if (days > 0)
g_date_add_days (&date, days);
else
g_date_subtract_days (&date, - days);
gnm_date_add_days (&date, days);
dao_set_cell_float (dao, i, 0,
datetime_g_to_serial (&date, conv));
......@@ -92,10 +90,7 @@ do_column_filling_wday (data_analysis_output_t *dao, fill_series_t *info)
wd = g_date_get_weekday (&date);
if (wd + (steps % 5) > G_DATE_FRIDAY)
days += 2;
if (days > 0)
g_date_add_days (&date, days);
else
g_date_subtract_days (&date, - days);
gnm_date_add_days (&date, days);
dao_set_cell_float (dao, 0,i,
datetime_g_to_serial (&date, conv));
......@@ -116,10 +111,7 @@ do_row_filling_month (data_analysis_output_t *dao, fill_series_t *info)
for (i = 0; i < info->n; i++) {
datetime_serial_to_g (&date, start, conv);
if (info->step_value > 0)
g_date_add_months (&date, i * info->step_value);
else
g_date_subtract_months (&date,- i * info->step_value);
gnm_date_add_months (&date, i * info->step_value);
dao_set_cell_float (dao, i, 0,
datetime_g_to_serial (&date, conv));
......@@ -138,10 +130,7 @@ do_column_filling_month (data_analysis_output_t *dao, fill_series_t *info)
for (i = 0; i < info->n; i++) {
datetime_serial_to_g (&date, start, conv);
if (info->step_value > 0)
g_date_add_months (&date, i * info->step_value);
else
g_date_subtract_months (&date,- i * info->step_value);
gnm_date_add_months (&date, i * info->step_value);
dao_set_cell_float (dao, 0, i,
datetime_g_to_serial (&date, conv));
......@@ -160,10 +149,7 @@ do_row_filling_year (data_analysis_output_t *dao, fill_series_t *info)
for (i = 0; i < info->n; i++) {
datetime_serial_to_g (&date, start, conv);
if (info->step_value > 0)
g_date_add_years (&date, i * info->step_value);
else
g_date_subtract_years (&date,- i * info->step_value);
gnm_date_add_years (&date, i * info->step_value);
dao_set_cell_float (dao, i, 0,
datetime_g_to_serial (&date, conv));
......@@ -182,10 +168,7 @@ do_column_filling_year (data_analysis_output_t *dao, fill_series_t *info)
for (i = 0; i < info->n; i++) {
datetime_serial_to_g (&date, start, conv);
if (info->step_value > 0)
g_date_add_years (&date, i * info->step_value);
else
g_date_subtract_years (&date,- i * info->step_value);
gnm_date_add_years (&date, i * info->step_value);
dao_set_cell_float (dao, 0, i,
datetime_g_to_serial (&date, conv));
......
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