You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Go语言excelize包读取Excel日期格式不匹配问题求助

解决Go中使用excelize解析Excel日期格式不一致的问题

问题核心

Excel中日期列显示为23/03/2018,但通过excelize读取时部分行返回03-23-18,用time.Parse("02/01/2006")解析报错month out of range,且前5行正常、其余行异常,将列改为General格式后显示为数值。

根本原因

Excel的日期本质是浮点数(从基准日期开始的累计天数),单元格显示的日期格式只是渲染效果。异常原因通常是:

  • 部分单元格实际存储为文本格式的日期,而非数值型日期
  • 不同单元格的日期格式样式不一致,导致excelize返回不同格式的字符串
  • excelize默认根据系统区域设置格式化日期字符串,与Excel显示格式不匹配

解决方案

1. 读取原始单元格数值,手动转换日期

优先读取Excel日期的原始数值,再通过excelize内置工具转换为time.Time,这是最可靠的方式:

package main

import (
    "fmt"
    "strconv"
    "time"
    "log"
    
    "github.com/xuri/excelize/v2"
)

func main() {
    excelFile, err := excelize.OpenFile("your_file.xlsx")
    if err != nil {
        log.Panic(err)
    }
    defer excelFile.Close()

    rows, err := excelFile.Rows("Asset Data")
    if err != nil {
        log.Panic(err)
    }

    // 构建列名到索引的映射
    cm := make(map[string]int)
    if rows.Next() {
        headers, err := rows.Columns()
        if err != nil {
            log.Panic(err)
        }
        for idx, h := range headers {
            cm[h] = idx
        }
    }

    rowNum := 2 // 从第2行开始读数据行
    for rows.Next() {
        // 获取日期列的单元格坐标(Excel列从1开始)
        colName, err := excelize.ColumnNumberToName(cm["date of inspection"] + 1)
        if err != nil {
            log.Panic(err)
        }
        cell := fmt.Sprintf("%s%d", colName, rowNum)

        // 读取原始单元格值(跳过自动格式化)
        rawValue, err := excelFile.GetCellValue("Asset Data", cell, excelize.Options{RawCellValue: true})
        if err != nil {
            log.Panic(err)
        }

        var dateOfInspection time.Time
        // 尝试解析为Excel日期数值
        excelDate, err := strconv.ParseFloat(rawValue, 64)
        if err == nil {
            // 转换为time.Time,false对应Windows默认的1900年基准
            dateOfInspection, err = excelize.ExcelDateToTime(excelDate, false)
            if err != nil {
                log.Panic(err)
            }
        } else {
            // 若为文本格式,尝试多种常见日期格式解析
            formats := []string{"02/01/2006", "01-02-06", "02-01-2006", "01/02/06"}
            var parseErr error
            for _, f := range formats {
                dateOfInspection, parseErr = time.Parse(f, rawValue)
                if parseErr == nil {
                    break
                }
            }
            if parseErr != nil {
                log.Printf("无法解析日期: %s", rawValue)
                rowNum++
                continue
            }
        }

        fmt.Printf("第%d行日期: %s\n", rowNum, dateOfInspection.Format("02/01/2006"))
        rowNum++
    }
}

2. 处理已读取的不一致字符串

如果必须使用Rows().Columns()读取格式化后的字符串,可以尝试多种格式依次解析:

// 替换原解析逻辑
dateStr := row[cm["date of inspection"]]
formats := []string{"02/01/2006", "01-02-06"}
var dateOfInspection time.Time
var err error
for _, f := range formats {
    dateOfInspection, err = time.Parse(f, dateStr)
    if err == nil {
        break
    }
}
if err != nil {
    log.Printf("解析日期失败: %s", dateStr)
}

关键说明

  • 使用RawCellValue: true读取原始值,避免excelize自动格式化带来的格式差异
  • excelize.ExcelDateToTime可处理Excel日期数值,第二个参数:false对应Windows的1900基准,true对应Mac的1904基准
  • 若存在文本格式的日期,需覆盖可能的所有格式,确保兼容性

内容的提问来源于stack exchange,提问作者erwin-lovecraft

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 12:50:16