@@ -433,6 +433,7 @@ type formulaFuncs struct {
433
433
// DOLLARFR
434
434
// DURATION
435
435
// EFFECT
436
+ // EDATE
436
437
// ENCODEURL
437
438
// ERF
438
439
// ERF.PRECISE
@@ -1544,7 +1545,7 @@ func formulaCriteriaParser(exp string) (fc *formulaCriteria) {
1544
1545
if exp == "" {
1545
1546
return
1546
1547
}
1547
- if match := regexp.MustCompile(`^([0-9] +)$`).FindStringSubmatch(exp); len(match) > 1 {
1548
+ if match := regexp.MustCompile(`^(\d +)$`).FindStringSubmatch(exp); len(match) > 1 {
1548
1549
fc.Type, fc.Condition = criteriaEq, match[1]
1549
1550
return
1550
1551
}
@@ -10862,7 +10863,7 @@ func (fn *formulaFuncs) TREND(argsList *list.List) formulaArg {
10862
10863
}
10863
10864
10864
10865
// 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) {
10866
10867
var cnt1, cnt2, sum1, sumSqr1, sum2, sumSqr2 float64
10867
10868
var fVal formulaArg
10868
10869
for i := 0; i < c1; i++ {
@@ -10935,9 +10936,9 @@ func (fn *formulaFuncs) tTest(mtx1, mtx2 [][]formulaArg, fTails, fTyp float64) f
10935
10936
fT = math.Abs(sumD) * math.Sqrt((cnt-1)/divider)
10936
10937
fF = cnt - 1
10937
10938
} 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)
10939
10940
} 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)
10941
10942
}
10942
10943
if !ok {
10943
10944
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
@@ -12351,6 +12352,58 @@ func (fn *formulaFuncs) ISOWEEKNUM(argsList *list.List) formulaArg {
12351
12352
return newNumberFormulaArg(float64(weekNum))
12352
12353
}
12353
12354
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
+
12354
12407
// HOUR function returns an integer representing the hour component of a
12355
12408
// supplied Excel time. The syntax of the function is:
12356
12409
//
0 commit comments