已验证 提交 d3227393 编写于 作者: xurime's avatar xurime

#65 fn: DATEDIF

上级 9af00b9b
......@@ -256,6 +256,7 @@ var tokenPriority = map[string]int{
// CSC
// CSCH
// DATE
// DATEDIF
// DEC2BIN
// DEC2HEX
// DEC2OCT
......@@ -4634,22 +4635,89 @@ func (fn *formulaFuncs) DATE(argsList *list.List) formulaArg {
if argsList.Len() != 3 {
return newErrorFormulaArg(formulaErrorVALUE, "DATE requires 3 number arguments")
}
var year, month, day int
var err error
if year, err = strconv.Atoi(argsList.Front().Value.(formulaArg).String); err != nil {
return newErrorFormulaArg(formulaErrorVALUE, "DATE requires 3 number arguments")
}
if month, err = strconv.Atoi(argsList.Front().Next().Value.(formulaArg).String); err != nil {
return newErrorFormulaArg(formulaErrorVALUE, "DATE requires 3 number arguments")
}
if day, err = strconv.Atoi(argsList.Back().Value.(formulaArg).String); err != nil {
year := argsList.Front().Value.(formulaArg).ToNumber()
month := argsList.Front().Next().Value.(formulaArg).ToNumber()
day := argsList.Back().Value.(formulaArg).ToNumber()
if year.Type != ArgNumber || month.Type != ArgNumber || day.Type != ArgNumber {
return newErrorFormulaArg(formulaErrorVALUE, "DATE requires 3 number arguments")
}
d := makeDate(year, time.Month(month), day)
d := makeDate(int(year.Number), time.Month(month.Number), int(day.Number))
return newStringFormulaArg(timeFromExcelTime(daysBetween(excelMinTime1900.Unix(), d)+1, false).String())
}
// NOW function returns the current date and time. The function receives no arguments and therefore. The syntax of the function is:
// DATEDIF function calculates the number of days, months, or years between
// two dates. The syntax of the function is:
//
// DATEDIF(start_date,end_date,unit)
//
func (fn *formulaFuncs) DATEDIF(argsList *list.List) formulaArg {
if argsList.Len() != 3 {
return newErrorFormulaArg(formulaErrorVALUE, "DATEDIF requires 3 number arguments")
}
startArg, endArg := argsList.Front().Value.(formulaArg).ToNumber(), argsList.Front().Next().Value.(formulaArg).ToNumber()
if startArg.Type != ArgNumber || endArg.Type != ArgNumber {
return startArg
}
if startArg.Number > endArg.Number {
return newErrorFormulaArg(formulaErrorNUM, "start_date > end_date")
}
if startArg.Number == endArg.Number {
return newNumberFormulaArg(0)
}
unit := strings.ToLower(argsList.Back().Value.(formulaArg).Value())
startDate, endDate := timeFromExcelTime(startArg.Number, false), timeFromExcelTime(endArg.Number, false)
sy, smm, sd := startDate.Date()
ey, emm, ed := endDate.Date()
sm, em, diff := int(smm), int(emm), 0.0
switch unit {
case "d":
return newNumberFormulaArg(endArg.Number - startArg.Number)
case "y":
diff = float64(ey - sy)
if em < sm || (em == sm && ed < sd) {
diff--
}
case "m":
ydiff := ey - sy
mdiff := em - sm
if ed < sd {
mdiff--
}
if mdiff < 0 {
ydiff--
mdiff += 12
}
diff = float64(ydiff*12 + mdiff)
case "md":
smMD := em
if ed < sd {
smMD--
}
diff = endArg.Number - daysBetween(excelMinTime1900.Unix(), makeDate(ey, time.Month(smMD), sd)) - 1
case "ym":
diff = float64(em - sm)
if ed < sd {
diff--
}
if diff < 0 {
diff += 12
}
case "yd":
syYD := sy
if em < sm || (em == sm && ed < sd) {
syYD++
}
s := daysBetween(excelMinTime1900.Unix(), makeDate(syYD, time.Month(em), ed))
e := daysBetween(excelMinTime1900.Unix(), makeDate(sy, time.Month(sm), sd))
diff = s - e
default:
return newErrorFormulaArg(formulaErrorVALUE, "DATEDIF has invalid unit")
}
return newNumberFormulaArg(diff)
}
// NOW function returns the current date and time. The function receives no
// arguments and therefore. The syntax of the function is:
//
// NOW()
//
......
......@@ -722,6 +722,20 @@ func TestCalcCellValue(t *testing.T) {
// DATE
"=DATE(2020,10,21)": "2020-10-21 00:00:00 +0000 UTC",
"=DATE(1900,1,1)": "1899-12-31 00:00:00 +0000 UTC",
// DATEDIF
"=DATEDIF(43101,43101,\"D\")": "0",
"=DATEDIF(43101,43891,\"d\")": "790",
"=DATEDIF(43101,43891,\"Y\")": "2",
"=DATEDIF(42156,44242,\"y\")": "5",
"=DATEDIF(43101,43891,\"M\")": "26",
"=DATEDIF(42171,44242,\"m\")": "67",
"=DATEDIF(42156,44454,\"MD\")": "14",
"=DATEDIF(42171,44242,\"md\")": "30",
"=DATEDIF(43101,43891,\"YM\")": "2",
"=DATEDIF(42171,44242,\"ym\")": "7",
"=DATEDIF(43101,43891,\"YD\")": "59",
"=DATEDIF(36526,73110,\"YD\")": "60",
"=DATEDIF(42171,44242,\"yd\")": "244",
// Text Functions
// CHAR
"=CHAR(65)": "A",
......@@ -1436,6 +1450,11 @@ func TestCalcCellValue(t *testing.T) {
`=DATE("text",10,21)`: "DATE requires 3 number arguments",
`=DATE(2020,"text",21)`: "DATE requires 3 number arguments",
`=DATE(2020,10,"text")`: "DATE requires 3 number arguments",
// DATEDIF
"=DATEDIF()": "DATEDIF requires 3 number arguments",
"=DATEDIF(\"\",\"\",\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
"=DATEDIF(43891,43101,\"Y\")": "start_date > end_date",
"=DATEDIF(43101,43891,\"x\")": "DATEDIF has invalid unit",
// NOW
"=NOW(A1)": "NOW accepts no arguments",
// TODAY
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册