【问题标题】:How to specify datetime format in C# Deedle when reading and writing CSV?读写CSV时如何在C#Deedle中指定日期时间格式?
【发布时间】:2020-04-16 17:43:07
【问题描述】:

假设我有以下data.csv 文件。

Timestamp,DoubleCol,BooleanCol,StringCol
04/15/2020 06:45:02.085-07:00,1.52,True,Some String
04/15/2020 06:45:03.057-07:00,2.32,False,Some String
04/15/2020 06:45:04.058-07:00,4.55,True,Some String
04/15/2020 06:45:05.057-07:00,1.52,False,Some String
04/15/2020 06:45:06.057-07:00,2.32,True,Some String
04/15/2020 06:45:07.057-07:00,4.55,False,Some String
04/15/2020 06:45:08.057-07:00,1.52,True,Some String
04/15/2020 06:45:09.058-07:00,2.32,False,Some String
04/15/2020 06:45:10.057-07:00,4.55,True,Some String
04/15/2020 06:45:11.057-07:00,1.02,False,Some String

我需要将此 CSV 读入 Frame,对 Timestamp 列进行一些过滤,然后写入一个 CSV,但 Timestamp 列是 ISO 8601 字符串。

如果我只是这样做,第一列是字符串类型,而不是 DateTimeOffset。

filePath = "data.csv";
timestampFormat = "MM/dd/yyyy HH:mm:ss:fffK"; // This is sent along with the CSV file.
var frame = Frame.ReadCsv(filePath);

另外,如果我试试这个:

var tsFrame = frame.IndexRows<DateTime>("Timestamp");

我明白了

FormatException: String '04/15/2020 06:45:02.085-07:00' was not recognized as a valid DateTime.

那么如何指定解析第一列时使用的 DateTime 格式呢?

然后,如何在写出 CSV 时指定使用 ISO 8601?

注意

这是一个简化的场景。实际上,我事先并不知道架构。除了第一列是时间戳(我也收到了格式)。其余的列可以是任何东西。所以我需要一个不依赖于编译时模式的解决方案。

【问题讨论】:

  • 使用 zzz 代替 K : "MM/dd/yyyy HH:mm:ss.fffzzz";
  • 我无法控制格式。我刚收到。但是,是的,我总是可以用zzz 替换K
  • 修改后能否读取数据?编写时使用 tsFrame.ToStroing(""MM/dd/yyyy HH:mm:ss:fffzzz"")

标签: c# csv datetime datetime-format deedle


【解决方案1】:

首先,您的时间戳格式不正确。您的格式为"MM/dd/yyyy HH:mm:ss:fffK":fffK 之前,但您的样本数据在毫秒之前有.,即04/15/2020 06:45:10.057-07:00

现在,在调用ReadCsv 时没有简单的方法来指定确切的日期时间解析格式,但是您可以使用Select 操作和ReplaceColumn 将数据读取为string,然后解析日期明确:

df.ReplaceColumn("Timestamp",
  df.GetColumn<string>("Timestamp").Select(kvp => 
    DateTime.ParseExact(kvp.Value, timestampFormat, 
      CultureInfo.InvariantCulture, DateTimeStyles.None)));

【讨论】:

  • 谢谢,这很好用。我已添加 .ToUniversalTime() 以使它们采用 UTC。现在,ReplaceColumn似乎删除了原来的并附加了新的,所以现在时间戳在最后。无论如何要把它放回第一列?
  • 嗯,我不确定是否有简单的方法来切换顺序。对于任何实际的运行时操作都无关紧要,但我想最好先让该列进行预览。您也许可以使用SortColumnsByKey 对列进行排序,但这将进行字母排序。否则,您可能需要通过将所有列一一添加来创建一个新框架(这实际上可以并且应该足够高效)。
【解决方案2】:

我不熟悉 Deedle,但您可以尝试使用我的库 Sylvan.Data.Csv,(以 nuget package 的形式提供),它允许使用架构读取 CSV 数据。查看 Deedle API:Frame 也有一个 ReadReader 方法,允许提供一个 IDataReader,所以我的库应该很容易集成。

using var tr = File.OpenText("data.csv");

var schema = new TypedCsvSchema();
schema.Add(0, typeof(DateTime));
schema.Add(1, typeof(double));
schema.Add(2, typeof(bool));
schema.Add(3, typeof(string));

var options = new CsvDataReaderOptions { Schema = schema };
DbDataReader dr = CsvDataReader.Create(tr, options);


var frame = Frame.ReadReader(dr);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-14
    • 2021-06-30
    • 1970-01-01
    • 2017-12-23
    • 1970-01-01
    相关资源
    最近更新 更多