Search code examples
c#datetimefilehelpers

FileHelpers will only parse datetime if date string matches universal time format


My datetime field will only parse if the formatter is set to the universal time format and the date time is already in that format. Is this an expected behavior, or should it be able to take any proper date string and format it to a different format? If so, how does this get resolved?

This works if the date input is already in universal format:

[FieldTrim(TrimMode.Both)]
[FieldConverter(ConverterKind.Date, "yyyy-MM-dd hh:mm")]
public DateTime Transaction_date; //where Transaction_date CSV value = "2019-01-02 6:00"

These don't work:

[FieldTrim(TrimMode.Both)]
[FieldConverter(ConverterKind.Date, "yyyy-MM-dd hh:mm")]
public DateTime Transaction_date; //where Transaction_date = "01-02-2019 6:00"

This is the exception for the above code:

"Message": "An error has occurred.", "ExceptionMessage": "Error Converting '01-02-2009 06:00' to type: 'DateTime'. Using the format: 'yyyy-MM-dd hh:mm'", "ExceptionType": "FileHelpers.ConvertException", "StackTrace": " at FileHelpers.ConvertHelpers.DateTimeConverter.StringToField(String from)\r\n at FileHelpers.FieldBase.AssignFromString(ExtractedInfo fieldString, LineInfo line)\r\n at FileHelpers.FieldBase.ExtractFieldValue(LineInfo line)\r\n at FileHelpers.RecordOperations.StringToRecord(Object record, LineInfo line, Object[] values)\r\n at FileHelpers.FileHelperEngine1.ReadStreamAsList(TextReader reader, Int32 maxRecords, DataTable dt)\r\n at FileHelpers.FileHelperEngine1.ReadStream(TextReader reader, Int32 maxRecords)\r\n at FileHelpers.FileHelperEngine`1.ReadString(String source, Int32 maxRecords)...

[FieldTrim(TrimMode.Both)]
[FieldConverter(ConverterKind.Date, "MM-dd-yyyy hh:mm")]
public DateTime Transaction_date; //where Transaction_date CSV value = "2019-01-02 6:00" Note that formatter is not universal date format

This is the exception for the above snippet:

"Message": "An error has occurred.", "ExceptionMessage": "Error Converting '2009-01-02 06:00' to type: 'DateTime'. Using the format: 'MM-dd-yyyy hh:mm'", "ExceptionType": "FileHelpers.ConvertException", "StackTrace": " at FileHelpers.ConvertHelpers.DateTimeConverter.StringToField(String from)\r\n at FileHelpers.FieldBase.AssignFromString(ExtractedInfo fieldString, LineInfo line)\r\n at FileHelpers.FieldBase.ExtractFieldValue(LineInfo line)\r\n at FileHelpers.RecordOperations.StringToRecord(Object record, LineInfo line, Object[] values)\r\n at FileHelpers.FileHelperEngine1.ReadStreamAsList(TextReader reader, Int32 maxRecords, DataTable dt)\r\n at FileHelpers.FileHelperEngine1.ReadStream(TextReader reader, Int32 maxRecords)\r\n at FileHelpers.FileHelperEngine`1.ReadString(String source, Int32 maxRecords)...


Solution

  • According to these docs, you can use ConverterKind.DateMultiFormat to allow for up to three formats.

    [FieldConverter(ConverterKind.DateMultiFormat, "yyyy-MM-dd HH:mm", "MM-dd-yyyy HH:mm")]
    

    Note you had hh in your code. That is for hours of a 12-hour clock ranging 01 to 12. It's not very useful without also specifying the tt for the am/pm meridiem indicator. You probably meant HH, which is for hours of a 24-hour clock ranging 00 to 23. Formatting tokens are case sensitive.

    Ultimately, the formats you specify are passed to DateTime.TryParseExact in the source code here. Thus, any of the .NET date and time format strings can be used.

    Regarding your question:

    ... should it be able to take any proper date string ...

    No. It will accept only the formats you provide.

    Keep in mind that date strings can be ambiguous when culture is unclear. For example, 01/02/2019 would be January 2nd in the US, but would be interpreted as February 1st in much of the rest of the world.