c# - 自定义日期时间转换器返回 null?

标签 c# datetime csvhelper

我有一个具有 DateTime 类型属性的模型。通过此属性,我希望在写入 CSV 文件以及通过 CsvHelper 读取 CSV 文件时在字符串中包含秒和微秒。

这就是我如何通过扩展DefaultTypeConverter来想出解决方案

public class CsvDateTimeConverter : DefaultTypeConverter
{
    private const string DateStringFormat = "MM/dd/yyyy HH:mm:ss.fff";

    public override object ConvertFromString(TypeConverterOptions options, string text)
    {
        if (string.IsNullOrEmpty(text)) return null;

        return Convert.ToDateTime(text);
    }

    public override string ConvertToString(TypeConverterOptions options, object value)
    {
        if (value == null) return "";

        var dateTime = (DateTime) value;

        return dateTime.ToString(DateStringFormat);
    }
}

模型看起来像这样

public class MyModel
{
    // ..... removed other properties
    public DateTime MyDateTime {get; set};
}

CsvClassMapper 看起来像这样

public sealed class CsvMap : CsvClassMap<MyModel>
{
    public CsvMap()
    {
        Map(m => m.MyDateTime).TypeConverter<CsvDateTimeConverter>();
    }
}

我向读者和作者注册了类映射。但问题是:

我可以使用转换器成功写入 CSV 文件,但是当我尝试从 CSV 文件读取时,它可以读取其他属性,但为 DateTime 属性返回 null。

那么..我错过了什么?

编辑:

如果有帮助:

这是从 csv 文件读取的代码:

using (TextReader reader = new StreamReader(filePath))
{
     var csv = new CsvReader(reader);
     csv.Configuration.RegisterClassMap<CsvMap>();

     csv.Configuration.Encoding = Encoding.UTF8;

     return csv.GetRecords<MyModel>().ToList();
 }

最佳答案

您不需要指定自定义类型转换器。这是美国风格的日期时间格式,添加了毫秒。您所需要的只是指定正确的区域性以及可能使用的格式。

一种选择是将 Configuration.CultureInfo 属性设置为美国文化:

reader.Configuration.CultureInfo = CultureInfo.GetCultureInfo("en-US");

以下代码将生成并读取美国日期,没有毫秒:

        using (var file = new StreamWriter("test.csv"))
        {
            var writer = new CsvWriter(file);
            writer.Configuration.CultureInfo = CultureInfo.GetCultureInfo("en-US");
            writer.WriteRecords(items);
        }

        using (var file = new StreamReader("test.csv"))
        {
            var reader= new CsvReader(file);
            reader.Configuration.CultureInfo = CultureInfo.GetCultureInfo("en-US");
            var models=reader.GetRecords<MyModel>().ToArray();
            Console.WriteLine(models[0]);                
        }

您可以通过类映射中的 TypeConverterOptions 方法为字段指定不同的格式:

public sealed class CsvMap : CsvHelper.Configuration.CsvClassMap<MyModel>
{
    public CsvMap()
    {
        Map(m => m.Date).TypeConverterOption("MM/dd/yyyy HH:mm:ss.fff");
        Map(m => m.ID);
    }
}

以下代码仅添加类映射,将生成以毫秒为单位的美国日期:

        using (var file = new StreamWriter("test.csv"))
        {
            var writer = new CsvWriter(file);
            writer.Configuration.CultureInfo = CultureInfo.GetCultureInfo("en-US");
            writer.Configuration.RegisterClassMap<CsvMap>();
            writer.WriteRecords(items);
        }

        using (var file = new StreamReader("test.csv"))
        {
            var reader= new CsvReader(file);
            reader.Configuration.CultureInfo = CultureInfo.GetCultureInfo("en-US");
            reader.Configuration.RegisterClassMap<CsvMap>();                
            var models=reader.GetRecords<MyModel>().ToArray();
            Console.WriteLine(models[0]);                
        }

Date,ID
10/12/2017 11:56:11.016,1
10/11/2017 11:56:11.021,2

如果您不想设置整个文件的区域性,也可以将 CultureInfo 指定为 TypeConverterOption:

    public CsvMap()
    {
        Map(m => m.Date).TypeConverterOption("MM/dd/yyyy HH:mm:ss.fff")
                        .TypeConverterOption(CultureInfo.GetCultureInfo("en-US"));
        Map(m => m.ID);
    }

注意

CsvHelper 最近(本周)发布了重大更新 (3.0)。上周还没有呢!当前版本是3.2.0。

在此版本中,CsvClassMap 变为 CsvMap,并且 TypeConverterOptions 方法变为具有返回 MapMember 的方法的对象:

    public CsvMap()
    {
        string format="MM/dd/yyyy HH:mm:ss.fff";
        var enUS=CultureInfo.GetCultureInfo("en-US");

        Map(m => m.Date).TypeConverterOption.Format(format)
                        .TypeConverterOption.CultureInfo(enUS);
        Map(m => m.ID);
    }

仍然没有 Type Converters 的文档更不用说 TypeConverterOptions 了。我从this Github issue找到了方法它应该作为文档。

另一个选项是检查 the source code本身。

关于c# - 自定义日期时间转换器返回 null?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46704523/

相关文章:

c# - 使用 CsvHelper 生成带有动态 header 的 CSV

c# - 使用与主程序存储在不同文件夹中的引用库 (dll)?

c# - OtpSharp 无法与 google 身份验证器配合使用

Javascript日期时间时间只给出 "Uncaught TypeError: undefined is not a function"

php - 将一周添加到以 YYYYMMDD 格式存储的 SQL 值

c# - 将验证添加到 CsvHelper.Configuration.ClassMap 对象(字符串)

Csvhelper 和 excel 操作

c# - 如何从 asp.net 中的代码后面调用确认消息?

c# - 如何更改已经加载的内容的纹理?

c# - DateTime.today() 在管理员中运行不同