Ich habe eine CSV-Datei, die (neben anderen Feldern) (nullable) DateTime-Werte enthält, die wie „2021-11-20 14:16:52.255421" formatiert sind. Ich möchte die Millisekunden oder was auch immer loswerden.
Ich habe es so versucht, aber irgendwie bleibt das Datumsformat gleich:
var csvConfiguration = new CsvConfiguration(CultureInfo.InvariantCulture);
csvConfiguration.HasHeaderRecord = true;
csvConfiguration.Delimiter = ";";
csvConfiguration.TrimOptions = TrimOptions.Trim;
Record[] records;
using (var reader = new StreamReader(CsvPath, Encoding.UTF8))
using (var csv = new CsvReader(reader, csvConfiguration))
{
records = csv.GetRecords<Record>().ToArray();
}
using (var writer = new StreamWriter($@"reformatted.csv"))
using (var csv = new CsvWriter(writer, CultureInfo.CurrentCulture))
{
//I have also tried with these options, but it doesn't help either
//var options = new TypeConverterOptions { Formats = new[] { "yyyy-MM-dd HH:mm:ss" } };
//csv.Context.TypeConverterOptionsCache.AddOptions<DateTime>(options);
csv.WriteRecords(records.Where(x => x.Memo!= null));
}
// "mbox_id";"email_address";"created";"updated";"created_by";"memo";
class Record
{
[Name("mbox_id")]
public string MailboxId { get; set; }
[Name("email_address")]
public string EmailAddress { get; set;}
[Name("created")]
public DateTime? Created { get; set; }
[Name("updated")]
public DateTime? Updated { get; set; }
[Name("created_by")]
public string CreatedBy { get; set;}
[Name("memo")]
public string Memo { get; set; }
}
Was mache ich falsch? Ich verstehe wirklich nicht, wie der CsvWriter überhaupt über das Eingabeformat Bescheid wissen sollte...
Lösung des Problems
Ihr Problem ist, dass Sie, da Ihre Eigenschaften vom Typ DateTime?
sind, explizit einen Typkonverter für DateTime?
sowie registrieren müssen DateTime
:
csv.Context.TypeConverterOptionsCache.AddOptions<DateTime?>(options);
csv.Context.TypeConverterOptionsCache.AddOptions<DateTime>(options);
Demo-Geige Nr. 1 hier.
Wenn diese Situation häufig auftritt, können Sie eine Erweiterungsmethode TypeConverterOptionsCache
wie folgt erstellen:
public static class TypeConverterOptionsCacheExtensions
{
public static void AddOptionsForTypeAndNullable(this TypeConverterOptionsCache cache, Type type, TypeConverterOptions options)
{
if (type == null || cache == null)
throw new ArgumentNullException();
if (!type.IsValueType)
{
cache.AddOptions(type, options);
}
else
{
var underlying = Nullable.GetUnderlyingType(type)?? type;
var nullable = typeof(Nullable<>).MakeGenericType(underlying);
cache.AddOptions(underlying, options);
cache.AddOptions(nullable, options);
}
}
public static void AddOptionsForTypeAndNullable<T>(this TypeConverterOptionsCache cache, TypeConverterOptions options) where T: struct
=> cache.AddOptionsForTypeAndNullable(typeof(T), options);
}
Und dann mach:
csv.Context.TypeConverterOptionsCache.AddOptionsForTypeAndNullable<DateTime>(options);
Demo-Geige Nr. 2 hier.
Keine Kommentare:
Kommentar veröffentlichen