Skip to content

Commit 518e02a

Browse files
committed
ref qax-os#65: new formula function EDATE
1 parent 964af19 commit 518e02a

File tree

2 files changed

+67
-4
lines changed

2 files changed

+67
-4
lines changed

calc.go

+57-4
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ type formulaFuncs struct {
433433
// DOLLARFR
434434
// DURATION
435435
// EFFECT
436+
// EDATE
436437
// ENCODEURL
437438
// ERF
438439
// ERF.PRECISE
@@ -1544,7 +1545,7 @@ func formulaCriteriaParser(exp string) (fc *formulaCriteria) {
15441545
if exp == "" {
15451546
return
15461547
}
1547-
if match := regexp.MustCompile(`^([0-9]+)$`).FindStringSubmatch(exp); len(match) > 1 {
1548+
if match := regexp.MustCompile(`^(\d+)$`).FindStringSubmatch(exp); len(match) > 1 {
15481549
fc.Type, fc.Condition = criteriaEq, match[1]
15491550
return
15501551
}
@@ -10862,7 +10863,7 @@ func (fn *formulaFuncs) TREND(argsList *list.List) formulaArg {
1086210863
}
1086310864

1086410865
// tTest calculates the probability associated with the Student's T Test.
10865-
func tTest(bTemplin bool, mtx1, mtx2 [][]formulaArg, c1, c2, r1, r2 int, fT, fF float64) (float64, float64, bool) {
10866+
func tTest(bTemplin bool, mtx1, mtx2 [][]formulaArg, c1, c2, r1, r2 int) (float64, float64, bool) {
1086610867
var cnt1, cnt2, sum1, sumSqr1, sum2, sumSqr2 float64
1086710868
var fVal formulaArg
1086810869
for i := 0; i < c1; i++ {
@@ -10935,9 +10936,9 @@ func (fn *formulaFuncs) tTest(mtx1, mtx2 [][]formulaArg, fTails, fTyp float64) f
1093510936
fT = math.Abs(sumD) * math.Sqrt((cnt-1)/divider)
1093610937
fF = cnt - 1
1093710938
} else if fTyp == 2 {
10938-
fT, fF, ok = tTest(false, mtx1, mtx2, c1, c2, r1, r2, fT, fF)
10939+
fT, fF, ok = tTest(false, mtx1, mtx2, c1, c2, r1, r2)
1093910940
} else {
10940-
fT, fF, ok = tTest(true, mtx1, mtx2, c1, c2, r1, r2, fT, fF)
10941+
fT, fF, ok = tTest(true, mtx1, mtx2, c1, c2, r1, r2)
1094110942
}
1094210943
if !ok {
1094310944
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
@@ -12351,6 +12352,58 @@ func (fn *formulaFuncs) ISOWEEKNUM(argsList *list.List) formulaArg {
1235112352
return newNumberFormulaArg(float64(weekNum))
1235212353
}
1235312354

12355+
// EDATE function returns a date that is a specified number of months before or
12356+
// after a supplied start date. The syntax of function is:
12357+
//
12358+
// EDATE(start_date,months)
12359+
//
12360+
func (fn *formulaFuncs) EDATE(argsList *list.List) formulaArg {
12361+
if argsList.Len() != 2 {
12362+
return newErrorFormulaArg(formulaErrorVALUE, "EDATE requires 2 arguments")
12363+
}
12364+
date := argsList.Front().Value.(formulaArg)
12365+
num := date.ToNumber()
12366+
var dateTime time.Time
12367+
if num.Type != ArgNumber {
12368+
dateString := strings.ToLower(date.Value())
12369+
if !isDateOnlyFmt(dateString) {
12370+
if _, _, _, _, _, err := strToTime(dateString); err.Type == ArgError {
12371+
return err
12372+
}
12373+
}
12374+
y, m, d, _, err := strToDate(dateString)
12375+
if err.Type == ArgError {
12376+
return err
12377+
}
12378+
dateTime = time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.Now().Location())
12379+
} else {
12380+
if num.Number < 0 {
12381+
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
12382+
}
12383+
dateTime = timeFromExcelTime(num.Number, false)
12384+
}
12385+
month := argsList.Back().Value.(formulaArg).ToNumber()
12386+
if month.Type != ArgNumber {
12387+
return month
12388+
}
12389+
y, d := dateTime.Year(), dateTime.Day()
12390+
m := int(dateTime.Month()) + int(month.Number)
12391+
if month.Number < 0 {
12392+
y -= int(math.Ceil(-1 * float64(m) / 12))
12393+
}
12394+
if month.Number > 11 {
12395+
y += int(math.Floor(float64(m) / 12))
12396+
}
12397+
m = int(math.Mod(float64(m), 12))
12398+
if d > 28 {
12399+
if days := getDaysInMonth(y, m); d > days {
12400+
d = days
12401+
}
12402+
}
12403+
result, _ := timeToExcelTime(time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.UTC), false)
12404+
return newNumberFormulaArg(result)
12405+
}
12406+
1235412407
// HOUR function returns an integer representing the hour component of a
1235512408
// supplied Excel time. The syntax of the function is:
1235612409
//

calc_test.go

+10
Original file line numberDiff line numberDiff line change
@@ -1475,6 +1475,10 @@ func TestCalcCellValue(t *testing.T) {
14751475
"=DAYS(2,1)": "1",
14761476
"=DAYS(INT(2),INT(1))": "1",
14771477
"=DAYS(\"02/02/2015\",\"01/01/2015\")": "32",
1478+
// EDATE
1479+
"=EDATE(\"01/01/2021\",-1)": "44166",
1480+
"=EDATE(\"01/31/2020\",1)": "43890",
1481+
"=EDATE(\"01/29/2020\",12)": "44225",
14781482
// HOUR
14791483
"=HOUR(1)": "0",
14801484
"=HOUR(43543.5032060185)": "12",
@@ -3437,6 +3441,12 @@ func TestCalcCellValue(t *testing.T) {
34373441
"=DAYS(0,\"\")": "#VALUE!",
34383442
"=DAYS(NA(),0)": "#VALUE!",
34393443
"=DAYS(0,NA())": "#VALUE!",
3444+
// EDATE
3445+
"=EDATE()": "EDATE requires 2 arguments",
3446+
"=EDATE(0,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
3447+
"=EDATE(-1,0)": "#NUM!",
3448+
"=EDATE(\"\",0)": "#VALUE!",
3449+
"=EDATE(\"January 25, 100\",0)": "#VALUE!",
34403450
// HOUR
34413451
"=HOUR()": "HOUR requires exactly 1 argument",
34423452
"=HOUR(-1)": "HOUR only accepts positive argument",

0 commit comments

Comments
 (0)