如何在 C# 中使用 csvHelper 将两个单独列中的日期和时间合并到一个新的日期时间列中

Posted

技术标签:

【中文标题】如何在 C# 中使用 csvHelper 将两个单独列中的日期和时间合并到一个新的日期时间列中【英文标题】:How to merge date and time from two separate columns into a new datetime column using csvHelper in C# 【发布时间】:2021-10-28 21:58:22 【问题描述】:

我有以下格式的 CSV 文件。

在以下代码sn-p中使用csvHelper(使用Visual Studio 2019),我可以成功读取文件。

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);
        

从调试窗口我可以看到数据记录(从那里你可以看到日期和时间的单独列)。

但是,我需要得到一个日期时间格式的单列,如下所示。

我已经调查过了,但没能解决。 :(

【问题讨论】:

【参考方案1】:

可以在ClassMap中使用Convert方法

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; 

【讨论】:

在 LINQPad6 中测试您的代码,它运行良好。然后按照您的建议使用 VS2019 在 ClassMap 中更新我的方法,但是在读取我的 CSV 文件时,它会引发以下异常: System.FormatException: String '16 .07.2021 0:00:00 ' was not Recognized as a valid DateTime。跨度> 在 VS2019 中使用 .NET5 按照您的建议更新我在 ClassMap 中的方法,但是在读取我的 CSV 文件时会引发以下异常: System.FormatException: String '16 .07.2021 0:00:00 '未被识别为有效的日期时间。 看起来问题出在时间格式上。 HH 是“小时,使用从 00 到 23 的 24 小时制”。 H 是“小时,使用从 0 到 23 的 24 小时制”。 HH 不喜欢“0:00:00”时间。我将字符串时间格式更改为“dd.MM.yyyy H:mm:ss”。 非常感谢。现在它可以 100% 工作。感谢所有的帮助和解释。 :)【参考方案2】:

如果要将结果转换为 POCO,则编写一个 getter 方法,在该方法中连接日期和时间字段并将其转换并作为 DateTime 属性返回。

(或)

使用此功能

DateTime GetDateTime(string date, string time)

    return DateTime.ParseExact(date + " " + time, "dd.MM.yyyy HH:mm:ss", CultureInfo.InvariantCulture);

并将结果附加到返回列表中。

【讨论】:

【参考方案3】:

尝试将项目添加到您的列表 records 并连接日期字段和时间字段,如下所示:

...
using (var csv = new CsvReader(Reader, config))

    csv.Context.RegisterClassMap<CsvLineClassMap>();
    var records = csv.GetRecords<CsvLine>().ToList();

    var newDateTime = new DateTime();
    newDateTime = Convert.ToDateTime(records[2] + " " + records[2]);
    records.Add(newDateTime);

...

此外,您可以将以下内容用于日期转换部分并格式化日期和时间:

DateTime dt1 = DateTime.ParseExact(records[2] + " " + records[2], "dd/MM/yy h:mm:ss tt", CultureInfo.InvariantCulture);

【讨论】:

我不需要在我的记录列表中添加另一列。当我阅读 CSV 文件时,我需要它只显示一个带有日期时间的列,我不想要两个带有日期和时间的单独列。 我不想使用新方法将日期和时间放在一起,然后将其连接起来。我想在使用 Csvhelper 库时直接这样做。

以上是关于如何在 C# 中使用 csvHelper 将两个单独列中的日期和时间合并到一个新的日期时间列中的主要内容,如果未能解决你的问题,请参考以下文章

使用 CSVhelper 将单个列更新为先前编写的 CSV 文件。我有 Java 代码,但无法将其翻译成 C#

C# CSVhelper 无法使用自定义映射编写

在 vb.net 中使用带有 shouldquote 的 csvhelper writer

使用 CsvHelper 读取多头 CSV 文件

如何将 EnumConverter 与 CsvHelper 一起使用

C# CsvHelper:WriteRecord 抛出“ConfigurationException:不能自动映射继承 IEnumerable 的类型”