Search code examples
csvhelper

How to parse datetime from a specific timezone into UTC?


I want to assume a specific timezone (EST) when reading datetime, and convert to UTC.

I tried this:

csvPropertyMap.TypeConverterOption(DateTimeStyles.AssumeLocal | DateTimeStyles.AdjustToUniversal);

But it won't work as my code is running in the cloud, where the local is UTC.

Is there a way to configure a TimeZoneInfo in the column mapping ?


Solution

  • This should work if you want to assume DateTime values are in a specific timezone and then convert them to UTC.

    static void Main(string[] args)
    {
        using (MemoryStream stream = new MemoryStream())
        using (StreamWriter writer = new StreamWriter(stream))
        using (StreamReader reader = new StreamReader(stream))
        using (CsvReader csv = new CsvReader(reader))
        {
            writer.WriteLine("Id,Name,FooDate");
            writer.WriteLine("1,Test,04/19/2019 05:42:00");
            writer.Flush();
            stream.Position = 0;
    
            var easternStandardTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
            csv.Configuration.TypeConverterCache.RemoveConverter<DateTime>();
            csv.Configuration.TypeConverterCache.AddConverter<DateTime>(new TimeZonetoUtcConverter(easternStandardTimeZone));
    
            var records = csv.GetRecords<Foo>().ToList();
    
            Console.ReadKey();
        }
    
    }
    
    public class Foo
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public DateTime FooDate { get; set; }
    }
    
    public class TimeZonetoUtcConverter: DateTimeConverter
    {
        private readonly TimeZoneInfo timeZoneInfo;
    
        public TimeZonetoUtcConverter(TimeZoneInfo timeZoneInfo)
        {
            this.timeZoneInfo = timeZoneInfo;
        }
    
        public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
        {
            var parsedDate = base.ConvertFromString(text, row, memberMapData);
    
            return TimeZoneInfo.ConvertTimeToUtc((DateTime)parsedDate, timeZoneInfo);
        }
    }