Go语言使用excelize读取Excel日期解析错误的问题求助
解决Go中Excel日期解析的年份偏差问题
问题原因
你遇到的核心问题有两个:
- Excel日期的存储与显示差异:Excel的日期默认以**序列号(浮点数)**存储,显示的
27/06/1905是格式化后的文本;而excelize读取时如果直接获取列文本,会按Excel的显示格式返回短年份版本27-06-05。 - Go time包的两位年份解析规则:
time.Parse中,两位年份格式06的默认映射规则是:00-69对应2000-2069,70-99对应1970-1999。因此05会被解析为2005,而非目标的1905。
最优解决方案:读取Excel日期原始序列号(推荐)
直接读取Excel日期的原始序列号,再转换为Go的time.Time对象,这是最准确的方式,完全避免格式解析的歧义。
代码示例
package main import ( "fmt" "strconv" "time" "github.com/xuri/excelize/v2" ) func excelSerialToTime(serial float64) time.Time { // Excel的起始日期是1899-12-30(兼容1900闰年bug) excelEpoch := time.Date(1899, time.December, 30, 0, 0, 0, 0, time.UTC) // 拆分整数(天数)和小数(时分秒)部分 days := int(serial) hours := (serial - float64(days)) * 24 minutes := (hours - float64(int(hours))) * 60 seconds := (minutes - float64(int(minutes))) * 60 return excelEpoch.AddDate(0, 0, days).Add( time.Duration(int(hours))*time.Hour + time.Duration(int(minutes))*time.Minute + time.Duration(int(seconds))*time.Second, ) } func main() { excelFile, err := excelize.OpenFile("your_file.xlsx") if err != nil { fmt.Println(err) return } defer excelFile.Close() // 读取日期单元格的原始数值(替换为你的单元格位置,比如"B2") cellValue, err := excelFile.GetCellValue("Asset Data", "B2") if err != nil { fmt.Println(err) return } // 转换为Excel日期序列号 serial, err := strconv.ParseFloat(cellValue, 64) if err != nil { fmt.Println("单元格为文本格式,切换到文本解析逻辑") // 可插入下方备用方案的代码 return } // 转换为Go时间对象 date := excelSerialToTime(serial) fmt.Println(date.Format("02/01/2006")) // 输出:27/06/1905 }
备用方案:处理文本格式的日期
如果Excel日期是以纯文本存储的,可以手动修正年份解析逻辑:
代码示例
package main import ( "fmt" "time" ) func parseExcelShortDate(dateStr string) (time.Time, error) { // 先按默认规则解析 t, err := time.Parse("02-01-06", dateStr) if err != nil { return time.Time{}, err } // 修正年份:若解析结果为2000-2069区间,调整为1900-1969 year := t.Year() if year >= 2000 && year <= 2069 { t = t.AddDate(-100, 0, 0) } return t, nil } func main() { // 模拟excelize读取到的短日期字符串 dateStr := "27-06-05" date, err := parseExcelShortDate(dateStr) if err != nil { fmt.Println(err) return } fmt.Println(date.Format("02/01/2006")) // 输出:27/06/1905 }
注意事项
- 优先使用序列号解析方案,文本格式的日期可能存在格式变体,稳定性远不如读取原始序列号。
- Excel的1900闰年bug:Excel错误地将1900年视为闰年,上述
excelSerialToTime函数已兼容此问题。
内容的提问来源于stack exchange,提问作者erwin-lovecraft
相关产品推荐
相关产品推荐

