如何在CsvHelper中以毫秒为单位序列化DateTime

时间:2019-05-29 14:26:23

标签: c# csv datetime

我想以毫秒为单位将带有DateTime字段的对象序列化为csv。我怎样才能做到这一点?

我正在通过以下代码编写csv:

using (var writer = new StreamWriter(_checksumsFilePath))
using (var csv = new CsvWriter(writer))
{
   csv.WriteRecords(_checksums.Values.ToList());
}

而_checksums是此类的字典:

public class SomeClass
{
    public string Name { get; set; }

    public string val{ get; set; }

    public DateTime lastTime{ get; set; }
}

当我写的时候,我从调试器看到-在DateTime中有几毫秒,但是对csv文件只写:

Name;val;lastTime
someName;49BC20DF15E412A64472421E13FE86FF1C5165E18B2AFCCF160D4DC19FE68A14;29.05.2019 16:13:08

3 个答案:

答案 0 :(得分:1)

我通过使用基类的功能对您的答案进行了改进。 假设您只编写 csv 文件,这应该可以解决问题。 类 DefaultTypeConverter (GitHub) 从 memberMapData.TypeConverterOptions.Formats 中获取所需的格式。 由于此参数是为类 CsvWriter 中的所有转换器设置的,您可能不希望这样,您可以按照我的方式编辑此函数,以使用自定义格式。 此函数现在不使用类 CsvWriter 中设置的格式,而是使用您自己的格式。

public class DateConverter : DateTimeConverter
{
    private readonly string dateFormat;

    /// <summary>
    /// Initializes a new instance of the <see cref="DateConverter"/> class.
    /// </summary>
    /// <param name="dateFormat">Format in which the data should be formatted.</param>
    public DateConverter(string dateFormat)
        : base()
    {
        this.dateFormat = dateFormat;
    }

    /// <inheritdoc/>
    public override string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
    {
        if (value == null)
        {
            if (memberMapData.TypeConverterOptions.NullValues.Count > 0)
            {
                return memberMapData.TypeConverterOptions.NullValues.First();
            }

            return string.Empty;
        }

        if (value is IFormattable formattable)
        {
            var format = this.dateFormat;
            return formattable.ToString(format, memberMapData.TypeConverterOptions.CultureInfo);
        }

        return value.ToString();
    }
}

答案 1 :(得分:0)

如果您正在使用此CsvHelper,似乎可以通过ClassMap对其进行配置:

https://joshclose.github.io/CsvHelper/api/CsvHelper.Configuration

答案 2 :(得分:0)

谢谢,但是我根据这个主题CsvHelper set default custom TypeConverter

创建了自己的转换器

我做了一些小改动

    public class DateConverter : ITypeConverter
    {
        private readonly string _dateFormat;

        public DateConverter(string dateFormat)
        {
            _dateFormat = dateFormat;
        }

        public object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
        {
            if (!string.IsNullOrEmpty(text))
            {
                DateTime dt;
                DateTime.TryParseExact(text, _dateFormat,
                                       CultureInfo.InvariantCulture,
                                       DateTimeStyles.None,
                                       out dt);
                if (IsValidSqlDateTime(dt))
                {
                    return dt;
                }

            }

            return null;
        }
        public string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
        {
            return ObjectToDateString(value, _dateFormat);
        }

        public string ObjectToDateString(object o, string dateFormat)
        {
            if (o == null) return string.Empty;

            DateTime dt;
            if (o is DateTime)
            {
                dt = (DateTime)o;
                return dt.ToString(dateFormat);
            }
            else
                return string.Empty;
        }
        public bool IsValidSqlDateTime(DateTime? dateTime)
        {
            if (dateTime == null) return true;

            DateTime minValue = DateTime.Parse(System.Data.SqlTypes.SqlDateTime.MinValue.ToString());
            DateTime maxValue = DateTime.Parse(System.Data.SqlTypes.SqlDateTime.MaxValue.ToString());

            if (minValue > dateTime.Value || maxValue < dateTime.Value)
                return false;

            return true;
        }
    }

并使用:

using (var writer = new StreamWriter(_checksumsFilePath))
            using (var csv = new CsvWriter(writer))
            {
                csv.Configuration.TypeConverterCache.RemoveConverter<DateTime>();
                csv.Configuration.TypeConverterCache.RemoveConverter<DateTime?>();
                csv.Configuration.TypeConverterCache.AddConverter<DateTime?>(new DateConverter("MM/dd/yyyy hh:mm:ss.fff"));
                csv.Configuration.TypeConverterCache.AddConverter<DateTime>(new DateConverter("MM/dd/yyyy hh:mm:ss.fff"));
                csv.WriteRecords(_checksums.Values.ToList());
            }