Я хочу сериализовать объект с полем 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
Если вы используете этот CsvHelper
, кажется, есть способ настроить его с помощью ClassMap
:
https://joshclose.github.io/CsvHelper/api/CsvHelper.Configuration
ПРОБЛЕМА со ссылками в ответе.... Http.StatusCode == 404
... страница не найдена.
Да, его документация, кажется, исчезла. Есть аналогичный вопрос, который показывает, как форматировать дату в более поздней версии: stackoverflow.com/questions/56779725/…
Спасибо, но я делаю свой собственный конвертер из этой темы CsvHelper устанавливает пользовательский 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
Я улучшил ваш ответ, используя функции базовых классов.
Предполагая, что вы пишете только файлы csv, это должно помочь.
Класс DefaultTypeConverter
(Гитхаб) получает требуемый формат из 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();
}
}
CsvPropertyMap включает метод
TypeConverterOption
для указания таких вещей.