@@ -719,6 +719,7 @@ type formulaFuncs struct {
719
719
// VDB
720
720
// VLOOKUP
721
721
// WEEKDAY
722
+ // WEEKNUM
722
723
// WEIBULL
723
724
// WEIBULL.DIST
724
725
// XIRR
@@ -12803,6 +12804,86 @@ func (fn *formulaFuncs) WEEKDAY(argsList *list.List) formulaArg {
12803
12804
return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
12804
12805
}
12805
12806
12807
+ // weeknum is an implementation of the formula function WEEKNUM.
12808
+ func (fn *formulaFuncs) weeknum(snTime time.Time, returnType int) formulaArg {
12809
+ days := snTime.YearDay()
12810
+ weekMod, weekNum := days%7, math.Ceil(float64(days)/7)
12811
+ if weekMod == 0 {
12812
+ weekMod = 7
12813
+ }
12814
+ year := snTime.Year()
12815
+ firstWeekday := int(time.Date(year, time.January, 1, 0, 0, 0, 0, time.UTC).Weekday())
12816
+ var offset int
12817
+ switch returnType {
12818
+ case 1, 17:
12819
+ offset = 0
12820
+ case 2, 11, 21:
12821
+ offset = 1
12822
+ case 12, 13, 14, 15, 16:
12823
+ offset = returnType - 10
12824
+ default:
12825
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
12826
+ }
12827
+ padding := offset + 7 - firstWeekday
12828
+ if padding > 7 {
12829
+ padding -= 7
12830
+ }
12831
+ if weekMod > padding {
12832
+ weekNum++
12833
+ }
12834
+ if returnType == 21 && (firstWeekday == 0 || firstWeekday > 4) {
12835
+ if weekNum--; weekNum < 1 {
12836
+ if weekNum = 52; int(time.Date(year-1, time.January, 1, 0, 0, 0, 0, time.UTC).Weekday()) < 4 {
12837
+ weekNum++
12838
+ }
12839
+ }
12840
+ }
12841
+ return newNumberFormulaArg(weekNum)
12842
+ }
12843
+
12844
+ // WEEKNUM function returns an integer representing the week number (from 1 to
12845
+ // 53) of the year. The syntax of the function is:
12846
+ //
12847
+ // WEEKNUM(serial_number,[return_type])
12848
+ //
12849
+ func (fn *formulaFuncs) WEEKNUM(argsList *list.List) formulaArg {
12850
+ if argsList.Len() < 1 {
12851
+ return newErrorFormulaArg(formulaErrorVALUE, "WEEKNUM requires at least 1 argument")
12852
+ }
12853
+ if argsList.Len() > 2 {
12854
+ return newErrorFormulaArg(formulaErrorVALUE, "WEEKNUM allows at most 2 arguments")
12855
+ }
12856
+ sn := argsList.Front().Value.(formulaArg)
12857
+ num, returnType := sn.ToNumber(), 1
12858
+ var snTime time.Time
12859
+ if num.Type != ArgNumber {
12860
+ dateString := strings.ToLower(sn.Value())
12861
+ if !isDateOnlyFmt(dateString) {
12862
+ if _, _, _, _, _, err := strToTime(dateString); err.Type == ArgError {
12863
+ return err
12864
+ }
12865
+ }
12866
+ y, m, d, _, err := strToDate(dateString)
12867
+ if err.Type == ArgError {
12868
+ return err
12869
+ }
12870
+ snTime = time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.Now().Location())
12871
+ } else {
12872
+ if num.Number < 0 {
12873
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
12874
+ }
12875
+ snTime = timeFromExcelTime(num.Number, false)
12876
+ }
12877
+ if argsList.Len() == 2 {
12878
+ returnTypeArg := argsList.Back().Value.(formulaArg).ToNumber()
12879
+ if returnTypeArg.Type != ArgNumber {
12880
+ return returnTypeArg
12881
+ }
12882
+ returnType = int(returnTypeArg.Number)
12883
+ }
12884
+ return fn.weeknum(snTime, returnType)
12885
+ }
12886
+
12806
12887
// Text Functions
12807
12888
12808
12889
// CHAR function returns the character relating to a supplied character set
0 commit comments