基于 WeihanLi.Npoi 实现excel导入时纯汉字的日期转换

基于 WeihanLi.Npoi 实现excel导入时纯汉字的日期转换

Intro

前段时间有位小伙伴在 Github 上提了一个 “不能识别纯汉字的日期格式” issue

二〇二二年一月一日 格式的日期单元格识别不出来会变成,0001/1/1 0:00:00 如何让它能够识别出来呢,基于 InputFormatter 的强大扩展性支持,我们只需要实现一个从纯汉字的日期转换成标准日期的一个转换即可,详细参考后面的实现

Implement

首先去网上找了一个将支持将汉字日期转换的方法,实现来自于 http://luoma.pro/Content/Detail/671?parentId=1,(代码有点长,这里只是截出来一部分只是作为示例,有需要的小伙伴也可以自己写一个

// http://luoma.pro/Content/Detail/671?parentId=1
public static class DateTimeUtils
{
    public static bool TransStrToDateTime(string? str, out DateTime dt)
    {
        dt = default;
        if (str.IsNullOrEmpty())
            return false;

        //第一次转换
        if (DateTime.TryParse(str, out dt))
        {
            return true;
        }
        //第二次转换
        string[] format = new string[]
        {
            "yyyyMMdd",
            "yyyyMdHHmmss",
            "yyyyMMddHHmmss",
            "yyyy-M-d",
            "yyyy-MM-dd",
            "yyyy-MM-dd HH:mm:ss",
            "yyyy/M/d",
            "yyyy/MM/dd",
            "yyyy/MM/dd HH:mm:ss",
            "yyyy.M.d",
            "yyyy.MM.dd",
            "yyyy.MM.dd HH:mm:ss",
            "yyyy年M月d日",
            "yyyy年MM月dd日",
            "yyyy年MM月dd日HH:mm:ss",
            "yyyy年MM月dd日 HH时mm分ss秒"
        };
        if (DateTime.TryParseExact(str, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out dt))
        {
            return true;
        }
        //第三次转换
        try
        {
            if (Regex.IsMatch(str, "^(零|〇|一|二|三|四|五|六|七|八|九|十){2,4}年((正|一|二|三|四|五|六|七|八|九|十|十一|十二)月((一|二|三|四|五|六|七|八|九|十){1,3}(日)?)?)?$"))
            {
                var match = Regex.Match(str, @"^(.+)年(.+)月(.+)日$");
                if (match.Success)
                {
                    int year = GetYear(match.Groups[1].Value);
                    int month = GetMonth(match.Groups[2].Value);
                    long dayL = ParseCnToInt(match.Groups[3].Value);
                    dt = new DateTime(year, month, int.Parse(dayL.ToString()));
                    return true;
                }
            }
        }
        catch
        {
            return false;
        }
        return false;
    }
}

接下来来准备一个测试方法和 model:

private sealed class ChineseDateFormatter
{
    public sealed class ChineDateTestModel
    {
        public DateTime Date { get; set; }
    }

    public static DateTime FormatInput(string? input)
    {
        if (DateTimeUtils.TransStrToDateTime(input, out var dt))
        {
            return dt;
        }
        throw new ArgumentException("Invalid date input");
    }
}

最终配置和导入实现代码如下:

FluentSettings.For<ChineseDateFormatter.ChineDateTestModel>()
            .Property(x => x.Date)
            .HasColumnInputFormatter(ChineseDateFormatter.FormatInput);

var excelPath = "<excelPath>"; 
var list = ExcelHelper.ToEntityList<ChineseDateFormatter.ChineDateTestModel>(excelPath);
var item = list[0];
Guard.NotNull(item);
Assert.Equal(DateTime.Parse("2022-01-01"), item.Date);

这里我们导入一个纯汉字的日期来测试一下,excel 内容示例如下:

0e472c53a9902ae404216d1485f1dfb6.png

导入结果如下:

7822a607a9962d8ceb685ff284dce69b.png

可以看到我们导入的时间此时已经不再是默认值了,可以正常读取出来了

More

其他类似的需求也可以通过这种方式来实现,InputFormatter 主要是针对导入的处理,OutputFormatter 主要针对导出的处理,更多示例可以参考介绍:https://weihanli.github.io/WeihanLi.Npoi/docs/articles/zh/InputOutputFormatter.html(也支持 CSV 的处理)

目前觉得这种纯汉字的日期比较少,我们基本不会用到,也不建议使用,因为大部分库应该都是不支持的e9ec1735bb8e5a34c605eb5980e4cc0e.png

所以目前建议自己实现一个 formatter

如果用到的朋友比较多的话,也可以考虑集成在 package 里这样大家使用起来会更方便,欢迎需要的朋友进行反馈

References

  • https://github.com/WeihanLi/WeihanLi.Npoi/commit/f98f624dfc2b2adf56ccd34a7f8964dde53ec291

  • https://github.com/WeihanLi/WeihanLi.Npoi

  • https://www.nuget.org/packages/WeihanLi.Npoi/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值