From f5d3d59d8c65d9396893ae0156fef21592f6f425 Mon Sep 17 00:00:00 2001 From: xuri Date: Sat, 11 Jun 2022 14:08:21 +0800 Subject: ref #65: new formula function EOMONTH --- calc.go | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) (limited to 'calc.go') diff --git a/calc.go b/calc.go index fc983e9..35b9d74 100644 --- a/calc.go +++ b/calc.go @@ -435,6 +435,7 @@ type formulaFuncs struct { // EFFECT // EDATE // ENCODEURL +// EOMONTH // ERF // ERF.PRECISE // ERFC @@ -12394,7 +12395,9 @@ func (fn *formulaFuncs) EDATE(argsList *list.List) formulaArg { if month.Number > 11 { y += int(math.Floor(float64(m) / 12)) } - m = int(math.Mod(float64(m), 12)) + if m = m % 12; m < 0 { + m += 12 + } if d > 28 { if days := getDaysInMonth(y, m); d > days { d = days @@ -12404,6 +12407,55 @@ func (fn *formulaFuncs) EDATE(argsList *list.List) formulaArg { return newNumberFormulaArg(result) } +// EOMONTH function returns the last day of the month, that is a specified +// number of months before or after an initial supplied start date. The syntax +// of the function is: +// +// EOMONTH(start_date,months) +// +func (fn *formulaFuncs) EOMONTH(argsList *list.List) formulaArg { + if argsList.Len() != 2 { + return newErrorFormulaArg(formulaErrorVALUE, "EOMONTH requires 2 arguments") + } + date := argsList.Front().Value.(formulaArg) + num := date.ToNumber() + var dateTime time.Time + if num.Type != ArgNumber { + dateString := strings.ToLower(date.Value()) + if !isDateOnlyFmt(dateString) { + if _, _, _, _, _, err := strToTime(dateString); err.Type == ArgError { + return err + } + } + y, m, d, _, err := strToDate(dateString) + if err.Type == ArgError { + return err + } + dateTime = time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.Now().Location()) + } else { + if num.Number < 0 { + return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM) + } + dateTime = timeFromExcelTime(num.Number, false) + } + months := argsList.Back().Value.(formulaArg).ToNumber() + if months.Type != ArgNumber { + return months + } + y, m := dateTime.Year(), int(dateTime.Month())+int(months.Number)-1 + if m < 0 { + y -= int(math.Ceil(-1 * float64(m) / 12)) + } + if m > 11 { + y += int(math.Floor(float64(m) / 12)) + } + if m = m % 12; m < 0 { + m += 12 + } + result, _ := timeToExcelTime(time.Date(y, time.Month(m+1), getDaysInMonth(y, m+1), 0, 0, 0, 0, time.UTC), false) + return newNumberFormulaArg(result) +} + // HOUR function returns an integer representing the hour component of a // supplied Excel time. The syntax of the function is: // -- cgit v1.2.1