【问题标题】:How can I serialize DateTime with miliseconds in CsvHelper如何在 CsvHelper 中以毫秒为单位序列化 DateTime
【发布时间】:2021-10-05 13:32:50
【问题描述】:

我想用毫秒将带有DateTime 字段的对象序列化为csv。我该怎么做?

我正在用这段代码写 csv:

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

_checksums 是这个类的Dictionary

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

【问题讨论】:

  • CsvPropertyMap 包含一个 TypeConverterOption 方法来指定此类内容

标签: c# csv datetime


【解决方案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();
    }
}

【讨论】:

    【解决方案2】:

    谢谢,但我用这个主题制作了自己的转换器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());
                }
    

    【讨论】:

    • 在最新版本中,你必须使用csv.Context.TypeConverterCache而不是csv.Configuration.TypeConverterCache
    【解决方案3】:

    如果您正在使用此CsvHelper,似乎有一种方法可以使用ClassMap 对其进行配置:

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

    【讨论】:

    • 答案中的链接有问题....Http.StatusCode == 404 ...找不到页面。
    • 是的,他的文档似乎消失了。有一个类似的问题显示了如何在更新的版本中进行日期格式化:stackoverflow.com/questions/56779725/…
    猜你喜欢
    • 1970-01-01
    • 2019-08-08
    • 1970-01-01
    • 2011-08-22
    • 1970-01-01
    • 1970-01-01
    • 2019-02-24
    • 2015-09-16
    • 1970-01-01
    相关资源
    最近更新 更多