我有一个具有 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/