Commit 234c66fa authored by Andreas J. Guelzow's avatar Andreas J. Guelzow Committed by Andreas J. Guelzow

change oem to eom, don't release null maturity or settlement. Implement

2002-01-16  Andreas J. Guelzow <aguelzow@taliesin.ca>

	* fn-financial.c : change oem to eom, don't release null maturity
	  or settlement. Implement `xl' selector
	(coupdaybs) : fix documentation
	(coupncd) : fix documentation
	(couppcd) : fix documentation
	(coupdayscd) : fix documentation
	(coupdays) :  fix documentation

2002-01-16  Andreas J. Guelzow <aguelzow@taliesin.ca>

	* src/datetime.c : change oem to eom
	(days_between_dep_basis) : fix basis == 0, add `in_order' flag
	(adjust_dates_basis) : fix basis == 0
	(coupdays) : fix basis == 2, 3 and partially fix to
	  basis == 1
parent e3c16e5c
......@@ -167,6 +167,7 @@ Dialogs
: Editing nested functions. How best to express this.
: Switching between multiple function at the same level.
: Don't ask to fill arguments for functions without arguments.
: Selecting a function with more than one optional arg shows only the first.
- Import Dialog
: Rewrite main page preview (see Bug #66393)
......
2002-01-16 Andreas J. Guelzow <aguelzow@taliesin.ca>
* src/datetime.c : change oem to eom
(days_between_dep_basis) : fix basis == 0, add `in_order' flag
(adjust_dates_basis) : fix basis == 0
(coupdays) : fix basis == 2, 3 and partially fix to
basis == 1
2002-01-15 Morten Welinder <terra@diku.dk>
* src/GNOME_Gnumeric.xml, src/workbook-control-gui.c: support
......
2002-01-16 Andreas J. Guelzow <aguelzow@taliesin.ca>
* src/datetime.c : change oem to eom
(days_between_dep_basis) : fix basis == 0, add `in_order' flag
(adjust_dates_basis) : fix basis == 0
(coupdays) : fix basis == 2, 3 and partially fix to
basis == 1
2002-01-15 Morten Welinder <terra@diku.dk>
* src/GNOME_Gnumeric.xml, src/workbook-control-gui.c: support
......
2002-01-16 Andreas J. Guelzow <aguelzow@taliesin.ca>
* src/datetime.c : change oem to eom
(days_between_dep_basis) : fix basis == 0, add `in_order' flag
(adjust_dates_basis) : fix basis == 0
(coupdays) : fix basis == 2, 3 and partially fix to
basis == 1
2002-01-15 Morten Welinder <terra@diku.dk>
* src/GNOME_Gnumeric.xml, src/workbook-control-gui.c: support
......
2002-01-16 Andreas J. Guelzow <aguelzow@taliesin.ca>
* src/datetime.c : change oem to eom
(days_between_dep_basis) : fix basis == 0, add `in_order' flag
(adjust_dates_basis) : fix basis == 0
(coupdays) : fix basis == 2, 3 and partially fix to
basis == 1
2002-01-15 Morten Welinder <terra@diku.dk>
* src/GNOME_Gnumeric.xml, src/workbook-control-gui.c: support
......
......@@ -5,8 +5,8 @@
* Jukka-Pekka Iivonen (jiivonen@hutcs.cs.hut.fi)
* Morten Welinder (terra@diku.dk)
* Vladimir Vuksan (vuksan@veus.hr)
* Andreas J. Guelzow (aguelzow@taliesin.ca)
*
*/
#include <gnumeric-config.h>
#include <gnumeric.h>
......@@ -308,14 +308,14 @@ func_coup_cd (FunctionEvalInfo *ei, Value **argv, gboolean next)
GDate *maturity;
GDate *date;
int freq, basis;
gboolean oem, xl, err = FALSE;
gboolean eom, xl, err = FALSE;
Value *result;
settlement = datetime_value_to_g (argv[0]);
maturity = datetime_value_to_g (argv[1]);
freq = value_get_as_int (argv[2]);
basis = argv[3] ? value_get_as_int (argv[3]) : 0;
oem = argv[4] ? value_get_as_bool (argv[4], &err) : TRUE;
eom = argv[4] ? value_get_as_bool (argv[4], &err) : TRUE;
xl = argv[4] ? FALSE : TRUE;
if (!maturity || !settlement || err) {
......@@ -323,20 +323,30 @@ func_coup_cd (FunctionEvalInfo *ei, Value **argv, gboolean next)
goto out;
}
if (basis < 0 || basis > 5 || ((12/freq) * freq != 12)
|| g_date_compare (settlement, maturity) >= 0) {
result = value_new_error (ei->pos, gnumeric_err_NUM);
goto out;
if (xl) {
if (basis < 0 || basis > 4 || (freq != 1 && freq != 2 && freq != 4)
|| g_date_compare (settlement, maturity) >= 0) {
result = value_new_error (ei->pos, gnumeric_err_NUM);
goto out;
}
}
else
if (basis < 0 || basis > 5 || (freq == 0) || (12 % freq != 0)
|| g_date_compare (settlement, maturity) > (next ? -1 : 0)) {
result = value_new_error (ei->pos, gnumeric_err_NUM);
goto out;
}
date = xl ? coup_cd_xl (settlement, maturity, freq, next) :
coup_cd (settlement, maturity, freq, oem, next);
coup_cd (settlement, maturity, freq, eom, next);
result = value_new_int (datetime_g_to_serial (date));
g_date_free (date);
out:
g_date_free (settlement);
g_date_free (maturity);
if (settlement != NULL)
g_date_free (settlement);
if (maturity != NULL)
g_date_free (maturity);
return result;
}
......@@ -2793,25 +2803,34 @@ static char *help_coupdaybs = {
"@SYNTAX=COUPDAYBS(settlement,maturity,frequency[,basis])\n"
"@DESCRIPTION="
"COUPDAYBS returns the number of days from the beginning of the "
"coupon period to the settlement date. "
"@settlement is the settlement date of the security. "
"@maturity is the maturity date of the security. "
"@frequency is the number of coupon payments per year. "
"Allowed frequencies are: 1 = annual, 2 = semi, 4 = quarterly. "
"coupon period to the settlement date.\n"
"@settlement is the settlement date of the security.\n"
"@maturity is the maturity date of the security.\n"
"@frequency is the number of coupon payments per year.\n"
"@eom = TRUE handles end of month maturity dates special.\n"
"Allowed frequencies are: 1 = annual, 2 = semi, 4 = quarterly and "
"if eom is given: 6 = bimonthly, 12 = monthly.\n"
"@basis is the type of day counting system you want to use:\n"
"\n"
"0 US 30/360\n"
"0 30/360\n"
"1 actual days/actual days\n"
"2 actual days/360\n"
"3 actual days/365\n"
"4 European 30/360\n"
"5 US 30/360 (available only if eom is given)\n"
"(see the gnumeric manual for a detailed description of these bases)\n"
"\n"
"If @frequency is other than 1, 2, or 4, COUPDAYBS returns #NUM! "
"error. "
"If @basis is omitted, US 30/360 is applied. "
"If @basis is not in between 0 and 4, #NUM! error is returned. "
"If @frequency is invalid, COUPDAYBS returns #NUM! "
"error.\n"
"If @basis is omitted, 30/360 is applied.\n"
"If @basis is invalid, #NUM! error is returned.\n"
"\n"
"If COUPDAYBS is called with 3 or 4 arguments, it is XL compatible."
"\n"
"@EXAMPLES=\n"
"COUPDAYBS(""8-Oct-2001"",""29-Nov-2002"",4,0) = 40"
"COUPDAYBS(""8-Oct-2001"",""29-Nov-2002"",4,0,TRUE) = 39"
"COUPDAYBS(""8-Oct-2001"",""29-Nov-2002"",4,0,FALSE) = 39"
"\n"
"@SEEALSO=")
};
......@@ -2823,14 +2842,14 @@ gnumeric_coupdaybs (FunctionEvalInfo *ei, Value **argv)
GDate *maturity;
int freq, basis;
Value *result;
gboolean oem, err = FALSE;
gboolean eom, err = FALSE;
gboolean xl;
settlement = datetime_value_to_g (argv[0]);
maturity = datetime_value_to_g (argv[1]);
freq = value_get_as_int (argv[2]);
basis = argv[3] ? value_get_as_int (argv[3]) : 0;
oem = argv[4] ? value_get_as_bool (argv[4], &err) : 0;
eom = argv[4] ? value_get_as_bool (argv[4], &err) : 0;
xl = argv[4] ? FALSE : TRUE;
if (!maturity || !settlement || err) {
......@@ -2838,17 +2857,27 @@ gnumeric_coupdaybs (FunctionEvalInfo *ei, Value **argv)
goto out;
}
if (basis < 0 || basis > 4 || (freq != 1 && freq != 2 && freq != 4)
|| g_date_compare (settlement, maturity) > 0) {
result = value_new_error (ei->pos, gnumeric_err_NUM);
goto out;
if (xl) {
if (basis < 0 || basis > 4 || (freq != 1 && freq != 2 && freq != 4)
|| g_date_compare (settlement, maturity) >= 0) {
result = value_new_error (ei->pos, gnumeric_err_NUM);
goto out;
}
}
else
if (basis < 0 || basis > 5 || (freq == 0) || (12 % freq != 0)
|| g_date_compare (settlement, maturity) > 0) {
result = value_new_error (ei->pos, gnumeric_err_NUM);
goto out;
}
result = value_new_float (coupdaybs (settlement, maturity, freq, basis, oem, xl));
result = value_new_int (coupdaybs (settlement, maturity, freq, basis, eom, xl));
out:
g_date_free (settlement);
g_date_free (maturity);
if (settlement != NULL)
g_date_free (settlement);
if (maturity != NULL)
g_date_free (maturity);
return result;
}
......@@ -2857,26 +2886,33 @@ gnumeric_coupdaybs (FunctionEvalInfo *ei, Value **argv)
static char *help_coupdays = {
N_("@FUNCTION=COUPDAYS\n"
"@SYNTAX=COUPDAYS(settlement,maturity,frequency[,basis])\n"
"@SYNTAX=COUPDAYS(settlement,maturity,frequency[,basis,eom])\n"
"@DESCRIPTION="
"COUPDAYS returns the number of days in the coupon period of the "
"settlement date."
"@settlement is the settlement date of the security. "
"@maturity is the maturity date of the security. "
"@frequency is the number of coupon payments per year. "
"Allowed frequencies are: 1 = annual, 2 = semi, 4 = quarterly. "
"settlement date.\n"
"@settlement is the settlement date of the security.\n"
"@maturity is the maturity date of the security.\n"
"@frequency is the number of coupon payments per year.\n"
"@eom = TRUE handles end of month maturity dates special.\n"
"Allowed frequencies are: 1 = annual, 2 = semi, 4 = quarterly and "
"if eom is given: 6 = bimonthly, 12 = monthly.\n"
"@basis is the type of day counting system you want to use:\n"
"\n"
"0 US 30/360\n"
"0 30/360\n"
"1 actual days/actual days\n"
"2 actual days/360\n"
"3 actual days/365\n"
"4 European 30/360\n"
"5 US 30/360 (available only if eom is given)\n"
"(see the gnumeric manual for a detailed description of these bases)\n"
"\n"
"If @frequency is other than 1, 2, or 4, COUPDAYS returns #NUM! "
"error. "
"If @basis is omitted, US 30/360 is applied. "
"If @basis is not in between 0 and 4, #NUM! error is returned. "
"If @frequency is invalid, COUPDAYS returns #NUM! "
"error.\n"
"If @basis is omitted, 30/360 is applied.\n"
"If @basis is invalid, #NUM! error is returned.\n"
"\n"
"If COUPDAYS is called with 3 or 4 arguments and basis other than 1, "
"it is XL compatible."
"\n"
"@EXAMPLES=\n"
"\n"
......@@ -2890,14 +2926,14 @@ gnumeric_coupdays (FunctionEvalInfo *ei, Value **argv)
GDate *maturity;
int freq, basis;
Value *result;
gboolean oem, err = FALSE;
gboolean eom, err = FALSE;
gboolean xl;
settlement = datetime_value_to_g (argv[0]);
maturity = datetime_value_to_g (argv[1]);
freq = value_get_as_int (argv[2]);
basis = argv[3] ? value_get_as_int (argv[3]) : 0;
oem = argv[4] ? value_get_as_bool (argv[4], &err) : 0;
eom = argv[4] ? value_get_as_bool (argv[4], &err) : 0;
xl = argv[4] ? FALSE : TRUE;
if (!maturity || !settlement || err) {
......@@ -2905,17 +2941,27 @@ gnumeric_coupdays (FunctionEvalInfo *ei, Value **argv)
goto out;
}
if (basis < 0 || basis > 4 || (freq != 1 && freq != 2 && freq != 4)
|| g_date_compare (settlement, maturity) > 0) {
result = value_new_error (ei->pos, gnumeric_err_NUM);
goto out;
if (xl) {
if (basis < 0 || basis > 4 || (freq != 1 && freq != 2 && freq != 4)
|| g_date_compare (settlement, maturity) >= 0) {
result = value_new_error (ei->pos, gnumeric_err_NUM);
goto out;
}
}
else
if (basis < 0 || basis > 5 || (freq == 0) || (12 % freq != 0)
|| g_date_compare (settlement, maturity) > 0) {
result = value_new_error (ei->pos, gnumeric_err_NUM);
goto out;
}
result = value_new_int (coupdays (settlement, maturity, freq, basis, oem, xl));
result = value_new_float (coupdays (settlement, maturity, freq, basis, eom, xl));
out:
g_date_free (settlement);
g_date_free (maturity);
if (settlement != NULL)
g_date_free (settlement);
if (maturity != NULL)
g_date_free (maturity);
return result;
}
......@@ -2924,28 +2970,37 @@ gnumeric_coupdays (FunctionEvalInfo *ei, Value **argv)
static char *help_coupdaysnc = {
N_("@FUNCTION=COUPDAYSNC\n"
"@SYNTAX=COUPDAYSNC(settlement,maturity,frequency[,basis])\n"
"@SYNTAX=COUPDAYSNC(settlement,maturity,frequency[,basis,eom])\n"
"@DESCRIPTION="
"COUPDAYSNC returns the number of days from the settlement date "
"to the next coupon date. "
"@settlement is the settlement date of the security. "
"@maturity is the maturity date of the security. "
"@frequency is the number of coupon payments per year. "
"Allowed frequencies are: 1 = annual, 2 = semi, 4 = quarterly. "
"to the next coupon date.\n"
"@settlement is the settlement date of the security.\n"
"@maturity is the maturity date of the security.\n"
"@frequency is the number of coupon payments per year.\n"
"@eom = TRUE handles end of month maturity dates special.\n"
"Allowed frequencies are: 1 = annual, 2 = semi, 4 = quarterly and "
"if eom is given: 6 = bimonthly, 12 = monthly.\n"
"@basis is the type of day counting system you want to use:\n"
"\n"
"0 US 30/360\n"
"0 30/360\n"
"1 actual days/actual days\n"
"2 actual days/360\n"
"3 actual days/365\n"
"4 European 30/360\n"
"5 US 30/360 (available only if eom is given)\n"
"(see the gnumeric manual for a detailed description of these bases)\n"
"\n"
"If @frequency is other than 1, 2, or 4, COUPDAYSNC returns #NUM! "
"error. "
"If @basis is omitted, US 30/360 is applied. "
"If @basis is not in between 0 and 4, #NUM! error is returned. "
"If @frequency is invalid, COUPDAYSNC returns #NUM! "
"error.\n"
"If @basis is omitted, 30/360 is applied.\n"
"If @basis is invalid, #NUM! error is returned.\n"
"\n"
"If COUPDAYSNC is called with 3 or 4 arguments, it is XL compatible."
"\n"
"@EXAMPLES=\n"
"COUPDAYSNC(""8-Oct-2001"",""29-Nov-2002"",4,0) = 50"
"COUPDAYSNC(""8-Oct-2001"",""29-Nov-2002"",4,0,TRUE) = 51"
"COUPDAYSNC(""8-Oct-2001"",""29-Nov-2002"",4,0,FALSE) = 51"
"\n"
"@SEEALSO=")
};
......@@ -2957,14 +3012,14 @@ gnumeric_coupdaysnc (FunctionEvalInfo *ei, Value **argv)
GDate *maturity;
int freq, basis;
Value *result;
gboolean oem, err = FALSE;
gboolean eom, err = FALSE;
gboolean xl;
settlement = datetime_value_to_g (argv[0]);
maturity = datetime_value_to_g (argv[1]);
freq = value_get_as_int (argv[2]);
basis = argv[3] ? value_get_as_int (argv[3]) : 0;
oem = argv[4] ? value_get_as_bool (argv[4], &err) : 0;
eom = argv[4] ? value_get_as_bool (argv[4], &err) : 0;
xl = argv[4] ? FALSE : TRUE;
if (!maturity || !settlement || err) {
......@@ -2972,17 +3027,27 @@ gnumeric_coupdaysnc (FunctionEvalInfo *ei, Value **argv)
goto out;
}
if (basis < 0 || basis > 4 || (freq != 1 && freq != 2 && freq != 4)
|| g_date_compare (settlement, maturity) > 0) {
result = value_new_error (ei->pos, gnumeric_err_NUM);
goto out;
if (xl) {
if (basis < 0 || basis > 4 || (freq != 1 && freq != 2 && freq != 4)
|| g_date_compare (settlement, maturity) >= 0) {
result = value_new_error (ei->pos, gnumeric_err_NUM);
goto out;
}
}
else
if (basis < 0 || basis > 5 || (freq == 0) || (12 % freq != 0)
|| g_date_compare (settlement, maturity) > 0) {
result = value_new_error (ei->pos, gnumeric_err_NUM);
goto out;
}
result = value_new_float (coupdaysnc (settlement, maturity, freq, basis, oem, xl));
result = value_new_int (coupdaysnc (settlement, maturity, freq, basis, eom, xl));
out:
g_date_free (settlement);
g_date_free (maturity);
if (settlement != NULL)
g_date_free (settlement);
if (maturity != NULL)
g_date_free (maturity);
return result;
}
......@@ -2991,27 +3056,36 @@ gnumeric_coupdaysnc (FunctionEvalInfo *ei, Value **argv)
static char *help_coupncd = {
N_("@FUNCTION=COUPNCD\n"
"@SYNTAX=COUPNCD(settlement,maturity,frequency[,basis])\n"
"@SYNTAX=COUPNCD(settlement,maturity,frequency[,basis,eom])\n"
"@DESCRIPTION="
"COUPNCD returns the coupon date following settlement."
"@settlement is the settlement date of the security. "
"@maturity is the maturity date of the security. "
"@frequency is the number of coupon payments per year. "
"Allowed frequencies are: 1 = annual, 2 = semi, 4 = quarterly. "
"COUPNCD returns the coupon date following settlement.\n"
"@settlement is the settlement date of the security.\n"
"@maturity is the maturity date of the security.\n"
"@frequency is the number of coupon payments per year.\n"
"@eom = TRUE handles end of month maturity dates special.\n"
"Allowed frequencies are: 1 = annual, 2 = semi, 4 = quarterly and "
"if eom is given: 6 = bimonthly, 12 = monthly.\n"
"@basis is the type of day counting system you want to use:\n"
"\n"
"0 US 30/360\n"
"0 30/360\n"
"1 actual days/actual days\n"
"2 actual days/360\n"
"3 actual days/365\n"
"4 European 30/360\n"
"5 US 30/360 (available only if eom is given)\n"
"(see the gnumeric manual for a detailed description of these bases)\n"
"\n"
"If @frequency is other than 1, 2, or 4, COUPNCD returns #NUM! "
"error. "
"If @basis is omitted, US 30/360 is applied. "
"If @basis is not in between 0 and 4, #NUM! error is returned. "
"If @frequency is invalid, COUPNCD returns #NUM! "
"error.\n"
"If @basis is omitted, 30/360 is applied.\n"
"If @basis is invalid, #NUM! error is returned.\n"
"\n"
"If COUPNCD is called with 3 or 4 arguments, it is XL compatible."
"\n"
"@EXAMPLES=\n"
"COUPNCD(""8-Oct-2001"",""29-Nov-2002"",4,0) = 28-Nov-2001"
"COUPNCD(""8-Oct-2001"",""29-Nov-2002"",4,0,TRUE) = 29-Nov-2001"
"COUPNCD(""8-Oct-2001"",""29-Nov-2002"",4,0,FALSE) = 29-Nov-2001"
"\n"
"@SEEALSO=")
};
......@@ -3026,27 +3100,38 @@ gnumeric_coupncd (FunctionEvalInfo *ei, Value **argv)
static char *help_couppcd = {
N_("@FUNCTION=COUPPCD\n"
"@SYNTAX=COUPPCD(settlement,maturity,frequency[,basis])\n"
"@SYNTAX=COUPPCD(settlement,maturity,frequency[,basis,eom])\n"
"@DESCRIPTION="
"COUPPCD returns the coupon date preceeding settlement."
"@settlement is the settlement date of the security. "
"@maturity is the maturity date of the security. "
"@frequency is the number of coupon payments per year. "
"Allowed frequencies are: 1 = annual, 2 = semi, 4 = quarterly. "
"COUPPCD returns the coupon date preceeding settlement.\n"
"@settlement is the settlement date of the security.\n"
"@maturity is the maturity date of the security.\n"
"@frequency is the number of coupon payments per year.\n"
"@eom = TRUE handles end of month maturity dates special.\n"
"Allowed frequencies are: 1 = annual, 2 = semi, 4 = quarterly and "
"if eom is given: 6 = bimonthly, 12 = monthly.\n"
"@basis is the type of day counting system you want to use:\n"
"\n"
"0 US 30/360\n"
"0 30/360\n"
"1 actual days/actual days\n"
"2 actual days/360\n"
"3 actual days/365\n"
"4 European 30/360\n"
"5 US 30/360 (available only if eom is given)\n"
"(see the gnumeric manual for a detailed description of these bases)\n"
"\n"
"If @frequency is other than 1, 2, or 4, COUPPCD returns #NUM! "
"error. "
"If @basis is omitted, US 30/360 is applied. "
"If @basis is not in between 0 and 4, #NUM! error is returned. "
"If @frequency is invalid, COUPPCD returns #NUM! "
"error.\n"
"If @basis is omitted, 30/360 is applied.\n"
"If @basis is invalid, #NUM! error is returned.\n"
"\n"
"If COUPPCD is called with 3 or 4 arguments, it is XL compatible."
"\n"
"@EXAMPLES=\n"
"COUPPCD(""8-Oct-2001"",""29-Nov-2002"",4,0) = 28-Aug-2001"
"COUPPCD(""8-Oct-2001"",""29-Nov-2002"",4,0,TRUE) = 29-Aug-2001"
"COUPPCD(""8-Oct-2001"",""29-Nov-2002"",4,0,FALSE) = 29-Aug-2001"
"COUPPCD(""8-Oct-2001"",""30-Nov-2002"",4,0,FALSE) = 30-Aug-2001"
"COUPPCD(""8-Oct-2001"",""30-Nov-2002"",4,0,TRUE) = 31-Aug-2001"
"\n"
"@SEEALSO=")
};
......@@ -3239,19 +3324,19 @@ finance_functions_init (void)
auto_format_function_result (def, AF_MONETARY);
def = function_add_args (cat, "coupdaybs", "fff|fb",
"settlement,maturity,frequency[,basis,oem]",
"settlement,maturity,frequency[,basis,eom]",
&help_coupdaybs, gnumeric_coupdaybs);
def = function_add_args (cat, "coupdays", "fff|fb",
"settlement,maturity,frequency[,basis,oem]",
"settlement,maturity,frequency[,basis,eom]",
&help_coupdays, gnumeric_coupdays);
def = function_add_args (cat, "coupdaysnc", "fff|fb",
"settlement,maturity,frequency[,basis,oem]",
"settlement,maturity,frequency[,basis,eom]",
&help_coupdaysnc, gnumeric_coupdaysnc);
def = function_add_args (cat, "coupncd", "fff|fb",
"settlement,maturity,frequency[,basis,oem]",
"settlement,maturity,frequency[,basis,eom]",
&help_coupncd, gnumeric_coupncd);
auto_format_function_result (def, AF_DATE);
......@@ -3260,7 +3345,7 @@ finance_functions_init (void)
&help_coupnum, gnumeric_coupnum);
def = function_add_args (cat, "couppcd", "fff|fb",
"settlement,maturity,frequency[,basis,oem]",
"settlement,maturity,frequency[,basis,eom]",
&help_couppcd, gnumeric_couppcd);
auto_format_function_result (def, AF_DATE);
......
......@@ -5,6 +5,7 @@
* Miguel de Icaza (miguel@gnu.org)
* Morten Welinder <terra@diku.dk>
* Jukka-Pekka Iivonen <iivonen@iki.fi>
* Andreas J. Guelzow <aguelzow@taliesin.ca>
*/
#include <gnumeric-config.h>
......@@ -329,8 +330,11 @@ adjust_dates_basis (GDate *from, GDate *to, int basis)
{
switch (basis) {
case BASIS_30Ep360:
if (g_date_day(to) == 31)
if (g_date_day (to) >= 30) {
g_date_set_day (to, 30);
if (g_date_day (from) == 31)
g_date_set_day (from, 30);
}
break;
case BASIS_30_360:
if (g_date_day(from) >= 30) {
......@@ -364,15 +368,14 @@ adjust_dates_basis (GDate *from, GDate *to, int basis)
* "2 actual days/360\n"
* "3 actual days/365\n"
* "4 European 30/360\n"
* @in_order : dates are considered in order
*
* returns : Number of days strictly between from and to +1
*
* Note: before calling this function adjust_dates_basis _must_
* have been called.
*/
gint32
days_between_dep_basis (GDate *from, GDate *to, int basis)
days_between_dep_basis (GDate *from, GDate *to, int basis, gboolean in_order)
{
GDate from_date;
gint32 days;
......@@ -380,13 +383,18 @@ days_between_dep_basis (GDate *from, GDate *to, int basis)
switch (g_date_compare (from, to)) {
case 1:
return (- days_between_dep_basis (to, from, basis));
return (- days_between_dep_basis (to, from, basis, !in_order));
case 0:
return 0;
default:
break;
}
if (in_order)
adjust_dates_basis (from, to, basis);
else
adjust_dates_basis (to, from, basis);
if (basis == BASIS_ACTACT)
return (g_date_julian (to) - g_date_julian (from));
......@@ -415,8 +423,15 @@ days_between_dep_basis (GDate *from, GDate *to, int basis)
case BASIS_ACT360:
case BASIS_ACT365:
return days + g_date_julian (to) - g_date_julian (&from_date);
case BASIS_30Ep360:
return days += (30 * (g_date_month(to) - g_date_month(&from_date))
+ ((in_order && g_date_is_last_of_month (to)) ? 30
: g_date_day (to))
- ((!in_order && g_date_is_last_of_month (from)) ? 30
: g_date_day (&from_date)));
default:
return (days + 30 * (g_date_month(to) - g_date_month(&from_date))
return days += (30 * (g_date_month(to) - g_date_month(&from_date))
+ g_date_day(to) - g_date_day(&from_date));
}
}
......@@ -429,7 +444,7 @@ days_between_dep_basis (GDate *from, GDate *to, int basis)
* @settlement: GDate *
* @maturity : GDate * must follow settlement strictly
* @freq : int divides 12 evenly
* @oem : gboolean whether to do special end of month
* @eom : gboolean whether to do special end of month
* handling
* @next : gboolean whether next or previous date
*
......@@ -439,13 +454,13 @@ days_between_dep_basis (GDate *from, GDate *to, int basis)
*/
GDate *
coup_cd (GDate *settlement, GDate *maturity, int freq, gboolean oem, gboolean next)
coup_cd (GDate *settlement, GDate *maturity, int freq, gboolean eom, gboolean next)
{
int months, periods;
GDate *result;
gboolean is_oem_special;
gboolean is_eom_special;
is_oem_special = oem && g_date_is_last_of_month (maturity);
is_eom_special = eom && g_date_is_last_of_month (maturity);
months = 12 / freq;
periods = (g_date_year(maturity) - g_date_year(settlement));
......@@ -458,7 +473,7 @@ coup_cd (GDate *settlement, GDate *maturity, int freq, gboolean oem, gboolean ne
g_date_set_julian (result, g_date_julian (maturity));
periods++;
g_date_subtract_months (result, periods * months);
if (is_oem_special)
if (is_eom_special)
while (!g_date_is_last_of_month (result))
g_date_add_days (result, 1);
} while (g_date_compare (settlement, result) < 0 );
......@@ -467,7 +482,7 @@ coup_cd (GDate *settlement, GDate *maturity, int freq, gboolean oem, gboolean ne
g_date_set_julian (result, g_date_julian (maturity));
periods--;
g_date_subtract_months (result, periods * months);
if (is_oem_special)
if (is_eom_special)
while (!g_date_is_last_of_month (result))
g_date_add_days (result, 1);
}
......@@ -483,7 +498,7 @@ coup_cd (GDate *settlement, GDate *maturity, int freq, gboolean oem, gboolean ne
* @settlement: GDate *
* @maturity : GDate * must follow settlement strictly
* @freq : int divides 12 evenly
* @oem : gboolean whether to do special end of month
* @eom : gboolean whether to do special end of month
* handling
* @next : gboolean whether next or previous date
*
......@@ -497,10 +512,10 @@ coup_cd_xl (GDate *settlement, GDate *maturity, int freq, gboolean next)
{
GDate *result;
GDate coupon;
gboolean is_oem_special;
gboolean is_eom_special;
int months = 12 / freq;
is_oem_special = g_date_is_last_of_month (maturity);
is_eom_special = g_date_is_last_of_month (maturity);
result = g_date_new();
......@@ -510,7 +525,7 @@ coup_cd_xl (GDate *settlement, GDate *maturity, int freq, gboolean next)
do {
g_date_set_julian (result, g_date_julian (&coupon));
g_date_subtract_months (&coupon, months);
if (is_oem_special)
if (is_eom_special)
while (!g_date_is_last_of_month (&coupon))
g_date_add_days (&coupon, 1);
} while (g_date_compare (settlement, &coupon) < 0 );
......@@ -529,8 +544,8 @@ coup_cd_xl (GDate *settlement, GDate *maturity, int freq, gboolean next)
* Returns the number of days in the coupon period of the settlement date.
* Currently, returns negative numbers if the branch is not implemented.
*/
int
coupdays (GDate *settlement, GDate *maturity, int freq, int basis, gboolean oem,
gnum_float
coupdays (GDate *settlement, GDate *maturity, int freq, int basis, gboolean eom,
gboolean xl)
{
GDate *prev;
......@@ -542,21 +557,21 @@ coupdays (GDate *settlement, GDate *maturity, int freq, int basis, gboolean oem,
case BASIS_30E360:
case BASIS_30_360:
return (12 / freq) * 30;
case BASIS_ACT360:
return 360 / freq;
case BASIS_ACT365:
return 365.0 / freq;
case BASIS_ACTACT:
default:
break;
next = xl ? coup_cd_xl (settlement, maturity, freq, TRUE) :
coup_cd (settlement, maturity, freq, eom, TRUE);
prev = xl ? coup_cd_xl (settlement, next, freq, FALSE) :
coup_cd (settlement, maturity, freq, eom, FALSE);
days = days_between_dep_basis (prev, next, basis, TRUE);
g_date_free (prev);
g_date_free (next);
return days;
}
/* Now we need to look at the real coupon dates */
prev = xl ? coup_cd_xl (settlement, maturity, freq, FALSE) :
coup_cd (settlement, maturity, freq, oem, FALSE);
next = xl ? coup_cd_xl (settlement, maturity, freq, TRUE) :
coup_cd (settlement, maturity, freq, oem, TRUE);
adjust_dates_basis (prev, next, basis);
days = days_between_dep_basis (prev, next, basis);
g_date_free (prev);
g_date_free (next);
return days;