假设我有以下内容 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中,对时间戳列做一些过滤,然后写一个CSV,但时间戳列是ISO 8601字符串。
如果我简单地这样做,第一列的类型是String,而不是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?
注意
这是一个简化的方案。在现实中,我事先并不知道模式。除了第一列是时间戳(我也收到格式)。其余的列可以是任何东西。所以我需要一个不依赖编译时模式的解决方案。
首先,你的时间戳格式不正确。你的格式是 "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)));
我对Deedle不熟悉,但你可以试试用我的库。Sylvan.Data.Csv
(可作为 套餐),可以读取带有模式的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);