gnumeric r16675 - in trunk: . plugins/fn-date src src/tools



Author: mortenw
Date: Fri Jun 27 13:59:06 2008
New Revision: 16675
URL: http://svn.gnome.org/viewvc/gnumeric?rev=16675&view=rev

Log:
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.



Modified:
   trunk/ChangeLog
   trunk/plugins/fn-date/ChangeLog
   trunk/plugins/fn-date/functions.c
   trunk/src/gnm-datetime.c
   trunk/src/gnm-datetime.h
   trunk/src/sheet-autofill.c
   trunk/src/tools/ChangeLog
   trunk/src/tools/fill-series.c

Modified: trunk/plugins/fn-date/functions.c
==============================================================================
--- trunk/plugins/fn-date/functions.c	(original)
+++ trunk/plugins/fn-date/functions.c	Fri Jun 27 13:59:06 2008
@@ -126,7 +126,6 @@
 	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 @@
 
         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 @@
 
 	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 @@
 
 	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 @@
 		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 @@
 	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 @@
                   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 @@
 	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 @@
 	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)

Modified: trunk/src/gnm-datetime.c
==============================================================================
--- trunk/src/gnm-datetime.c	(original)
+++ trunk/src/gnm-datetime.c	Fri Jun 27 13:59:06 2008
@@ -135,7 +135,7 @@
 		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 @@
 
 	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);
+}

Modified: trunk/src/gnm-datetime.h
==============================================================================
--- trunk/src/gnm-datetime.h	(original)
+++ trunk/src/gnm-datetime.h	Fri Jun 27 13:59:06 2008
@@ -19,6 +19,9 @@
 			    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
 

Modified: trunk/src/sheet-autofill.c
==============================================================================
--- trunk/src/sheet-autofill.c	(original)
+++ trunk/src/sheet-autofill.c	Fri Jun 27 13:59:06 2008
@@ -590,10 +590,7 @@
 	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;

Modified: trunk/src/tools/fill-series.c
==============================================================================
--- trunk/src/tools/fill-series.c	(original)
+++ trunk/src/tools/fill-series.c	Fri Jun 27 13:59:06 2008
@@ -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 @@
 		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 @@
 		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 @@
 	
 	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 @@
 	
 	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 @@
 	
 	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 @@
 	
 	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));



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]