代码之家  ›  专栏  ›  技术社区  ›  ash

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

  •  2
  • ash  · 技术社区  · 8 年前

    下面是我如何通过扩展 默认类型转换器

    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();
     }
    
    3 回复  |  直到 4 年前
        1
  •  4
  •   Panagiotis Kanavos    8 年前

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

    一个选项是设置 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指定为TypeConverter选项:

        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 更不用说类型转换器选项了。我是从 this Github issue 应作为文件。

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

        2
  •  0
  •   Patrick Artner    8 年前
    public override object ConvertFromString(TypeConverterOptions options, string text)
    {
        if (string.IsNullOrEmpty(text)) return null;
    
        return Convert.ToDateTime(text);
    }
    

        3
  •  -1
  •   Robert    8 年前

    Convert.ToDateTime(text);
    

    有一个重载,其格式必须在此处指定。试试看。

    enter image description here

    编辑:

    在ConvertFromString方法中添加以下内容:

    public override object ConvertFromString(TypeConverterOptions options, string text)
    {
        if (string.IsNullOrEmpty(text)) return null;
    
        DateTimeFormatInfo info = new DateTimeFormatInfo() { FullDateTimePattern = DateStringFormat };
    
        return Convert.ToDateTime(text, info);
    }