Search code examples
c#asp.net-corecsvhelper

How to merge date and time from two separate columns into a new datetime column using csvHelper in C#


I have the following CSV file with the following format. enter image description here

Using csvHelper in the following code snippet (using Visual Studio 2019), I can successfully read the file.

public ActionResult UploadCsvFile(IFormFile file)
        {
            if (file != null)
            {
                try
                {
                    var basePath = Path.Combine(_hostEnvironment.WebRootPath, "uploads/");
                    if (!Directory.Exists(basePath))
                        Directory.CreateDirectory(basePath);    
                    var filePath = Path.Combine(basePath, file.FileName);
                    using (var stream = new FileStream(filePath, FileMode.Create))
                    {
                        file.CopyTo(stream);
                    }   
                    var config = new CsvConfiguration(CultureInfo.CurrentCulture)
                    {
                        Delimiter = ";",
                        HasHeaderRecord = true
                    };
                    using (var Reader = new StreamReader(filePath))  
                    using (var csv = new CsvReader(Reader, config))
                    {
                        csv.Context.RegisterClassMap<CsvLineClassMap>();
                        var records = csv.GetRecords<CsvLine>().ToList();   
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }
            return Json(null);
        }

From the debugging window I can see the data records (From there you can see the separate columns of date and time). enter image description here

But, I need to get as a result in a single column with datetime format, As the following recreated. enter image description here

I have investigated, but have not been able to solve it. :(


Solution

  • You can use the Convert method in the ClassMap

    void Main()
    {
        System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture("es");
    
        var data = new StringBuilder();
        data.AppendLine("Code;Date;Time;Level;Flow;Volumen");
        data.AppendLine("OB-0100-99;16.07.2021;19:00:00;125,53;38,8;1621770");
        data.AppendLine(";16.07.2021;20:00:00;138,6;69,4;1621780");
    
        var config = new CsvConfiguration(CultureInfo.CurrentCulture)
        {
            Delimiter = ";"
        };
        
        using (var streamReader = new StringReader(data.ToString()))
        using (var csv = new CsvReader(streamReader, config))
        {
            csv.Context.RegisterClassMap<CsvLineClassMap>();
            var records = csv.GetRecords<CsvLine>().ToList().Dump();
        }
        
    }
    
    public class CsvLineClassMap : ClassMap<CsvLine>
    {
        public CsvLineClassMap()
        {
            Map(x => x.Flow);
            Map(x => x.Code);
            Map(x => x.DateTime).Convert(x => 
            { 
                return DateTime.ParseExact(
                    x.Row.GetField("Date") + " " + x.Row.GetField("Time"),
                    "dd.MM.yyyy H:mm:ss",
                    CultureInfo.InvariantCulture);
            });
            Map(x => x.Level);
            Map(x => x.Volumen);
        }
    }
    
    public class CsvLine
    {
        public double Flow { get; set; }
        public string Code { get; set; }
        public DateTime DateTime { get; set; }
        public double Level { get; set; }
        public double Volumen { get; set; }
    }