diff --git a/date.go b/date.go index b8c26e008a..c4acd6d575 100644 --- a/date.go +++ b/date.go @@ -20,6 +20,7 @@ const ( nanosInADay = float64((24 * time.Hour) / time.Nanosecond) dayNanoseconds = 24 * time.Hour maxDuration = 290 * 364 * dayNanoseconds + roundEpsilon = 1e-9 ) var ( @@ -151,14 +152,14 @@ func timeFromExcelTime(excelTime float64, date1904 bool) time.Time { } return date } - var floatPart = excelTime - float64(wholeDaysPart) + var floatPart = excelTime - float64(wholeDaysPart) + roundEpsilon if date1904 { date = excel1904Epoc } else { date = excel1900Epoc } durationPart := time.Duration(nanosInADay * floatPart) - return date.AddDate(0, 0, wholeDaysPart).Add(durationPart) + return date.AddDate(0, 0, wholeDaysPart).Add(durationPart).Truncate(time.Second) } // ExcelDateToTime converts a float-based excel date representation to a time.Time. diff --git a/date_test.go b/date_test.go index 2addc4ab99..cc516d572a 100644 --- a/date_test.go +++ b/date_test.go @@ -33,6 +33,7 @@ var excelTimeInputList = []dateTest{ {60.0, time.Date(1900, 2, 28, 0, 0, 0, 0, time.UTC)}, {61.0, time.Date(1900, 3, 1, 0, 0, 0, 0, time.UTC)}, {41275.0, time.Date(2013, 1, 1, 0, 0, 0, 0, time.UTC)}, + {44450.3333333333, time.Date(2021, time.September, 11, 8, 0, 0, 0, time.UTC)}, {401769.0, time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC)}, } @@ -66,6 +67,19 @@ func TestTimeFromExcelTime(t *testing.T) { assert.Equal(t, test.GoValue, timeFromExcelTime(test.ExcelValue, false)) }) } + for hour := 0; hour < 24; hour++ { + for min := 0; min < 60; min++ { + for sec := 0; sec < 60; sec++ { + date := time.Date(2021, time.December, 30, hour, min, sec, 0, time.UTC) + excelTime, err := timeToExcelTime(date) + assert.NoError(t, err) + dateOut := timeFromExcelTime(excelTime, false) + assert.EqualValues(t, hour, dateOut.Hour()) + assert.EqualValues(t, min, dateOut.Minute()) + assert.EqualValues(t, sec, dateOut.Second()) + } + } + } } func TestTimeFromExcelTime_1904(t *testing.T) {