Open tdjastrzebski opened 7 months ago
Easiest way is to use DateTimeOffset
instead.
Another option would be to use a custom type converter.
public class UtcDateTimeConverter : DateTimeConverter
{
public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
{
var o = base.ConvertFromString(text, row, memberMapData);
return (o as DateTime?)?.ToUniversalTime() ?? o;
}
}
// Register the converter.
csv.Context.TypeConverterCache.AddConverter<DateTime>(new UtcDateTimeConverter());
Thank you, @JoshClose
Does this solve your problem?
@JoshClose Yes, it solves the problem.
One just needs to be careful to call AddConverter<DateTime>(..)
before RegisterClassMap<MyMap<T>>()
is called.
This is one of the reasons why I still believe some CsvConfiguration
option would be a better solution, but my problem is solved.
@JoshClose, just one question: I realized that I do not know why your UtcDateTimeConverter
seems to work.
ToUniversalTime()
method does not just change DateTimeKind
to Utc, it also applies the required time offset and that is exactly what I try to avoid.
Looking at this code
var date = DateTime.Parse("2023-10-26T14:50:11.365+00:00", CultureInfo.InvariantCulture);
var dateU = date.ToUniversalTime();
date.Kind.Dump();
dateU.Kind.Dump();
date.Dump();
dateU.Dump();
with output
Local
Utc
10/26/2023 9:50:11 AM
10/26/2023 2:50:11 PM
It seems that since the time zone is included in the date string, it's smart enough to figure out creating it as local actually converts to 9:50 AM. Then you change to universal and get 2:40 PM, which is what the string shows. If you don't have the +00:00
as part of the date string, it comes out as Unspecified and the universal conversion doesn't work properly. In this case, you would want to use DateTimeStyles.AssumLocal
or DateTimeStyles.AssumeUniversal
.
The problem: in server-side running code (e.g. Azure Function) I always want date/time strings to be deserialized as UTC DateTime. In my test environment string like "2023-10-26T14:50:11.365+00:00" is deserialized with time part value 16:50:11 (local). I know the TypeConverterOption for individual fields can be defined like this
Map( m => m.DateTimeProperty ).TypeConverterOption( DateTimeStyles.AssumeUniversal );
or class property attribute can be added, but I would like to turn time conversion off globally, preferably usingCsvConfiguration
and just forget about it since in server-side software I never want conversion to local time. The necessity to implement such conversion everywhere is VERY error-prone as I recently learned. For the same reason I would like to avoid any post-fixing e.g. by callingToUniversalTime()
. After deserialization, in server-side/cloud-running code I ALWAYS want DateTime to be UTC, not local.I am not suggesting change of the default behavior, but adding some option to change it - unless it is already available, but I could not find any.