Unable to set datetime format for reading csv data
rupesh-kachhi opened this issue · comments
Problem-
I am trying to read this type of data from CSV-
DATE,grain
1/1/1992,grain
2/1/1992,grain
here date is in the format dd/MM/yyyy.
here is the necessary code -
//To read
var records = csv.GetRecords().ToList();
//to write
csvOutput.Context.RegisterClassMap();
// Write the header record.
csvOutput.WriteHeader();
csvOutput.NextRecord();
// Write the updated data records.
csvOutput.WriteRecords(records);
// Classes used
public class CsvRecord
{
public string Grain { get; set; }
[Name("DATE")]
public DateTime Date { get; set; }
}
public class CsvRecordMap : ClassMap
{
public CsvRecordMap()
{
Map(m => m.Grain);
Map(m => m.Date).TypeConverterOption.Format("yyyy/MM/dd");
}
}
After execution everything is working fine
after writecsv, I am getting date format as "yyyy/dd/MM"
if we add one record like this
13/1/1992,grain
it will give error taking default format as MM/dd/yyyy
If you are using CultureInfo.InvariantCulture
, the default date format is MM/dd/yyyy
. (Which I think is silly, since the majority of countries have dd/MM/yyyy
as their default).
So you need to either use a CultureInfo
that uses dd/MM/yyyy
for your CsvReader
using (var csv = new CsvReader(reader, new CultureInfo("en-IN")))
Or use another ClassMap<CsvRecord>
for your CsvReader
that sets the correct format.
Map(m => m.Date).TypeConverterOption.Format("dd/MM/yyyy");
Thank you for your fast response.
But I don't want to use another class map also I was not able to parse the string to date. I was getting this error -
System.FormatException: 'String '13/1/1992' was not recognized as a valid DateTime.'
so I tried with the format "d/M/yyyy" and it worked but the mapping format was different.
So I discovered an alternative way to do the same using Custom Type Converter. and without much code change.
Here is some code snippet -
[TypeConverter(typeof(CustomDateConverter))]
public DateTime Date { get; set; }
// This is CustomDateConverter class
public class CustomDateConverter : DefaultTypeConverter
{
public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
{
string[] dateFormats = { "dd/MM/yyyy", "d/M/yyyy"};
foreach (var format in dateFormats)
{
if (DateTime.TryParseExact(text, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out var parsedDate))
{
return parsedDate;
}
}
throw new FormatException($"Unable to parse date: {text}");
}
}
used this and no other code changes.
I just remembered. There is another way to do it.
var options = new TypeConverterOptions { Formats = new[] { "dd/MM/yyyy", "d/M/yyyy" } };
csvReader.Context.TypeConverterOptionsCache.AddOptions<DateTime>(options);