我有以下代码:
require 'date'
f = File.open(filepath)
f.each_with_index do |line, i|
a, b = line.split("\t")
d = DateTime.strptime(a, '%m/%d/%Y %I:%M %p')
puts "#{a} --- #{b}"
break unless i < 100
end
我收到以下错误:
c_reader.rb:10:in `strptime': invalid date (ArgumentError)
from c_reader.rb:10:in `block in <main>'
from c_reader.rb:6:in `each'
from c_reader.rb:6:in `each_with_index'
from c_reader.rb:6:in `<main>'
文件内容:
1/30/2014 1:00 AM 1251.6 1/30/2014 2:00 AM 1248 1/30/2014 3:00 AM 1246.32 1/30/2014 4:00 AM 1242.96 1/30/2014 5:00 AM 1282.08 1/30/2014 6:00 AM 1293.84 1/30/2014 7:00 AM 1307.04 1/30/2014 8:00 AM 1337.76 1/30/2014 9:00 AM 1357.92
如果我将其输入IRB,它可以完美运行:
DateTime.strptime("1/30/2014 2:00 PM", '%m/%d/%Y %I:%M %p')
有人可以告诉我这里发生了什么吗?
答案 0 :(得分:2)
您的示例数据与您的代码尝试处理的内容不匹配,所以我为此进行了调整。此外,它需要一些东西来表明AM / PM正在受到尊重。
通过对数据的这些调整,您的代码可以正常工作。 strptime
返回有效的DateTime对象。
require 'date'
[
"1/30/2014 1:00 AM\t1251.6",
"1/30/2014 2:00 AM\t1248",
"1/30/2014 3:00 PM\t1246.32",
"1/30/2014 4:00 PM\t1242.96",
].each do |line|
a, b = line.split("\t")
puts DateTime.strptime(a, '%m/%d/%Y %I:%M %p')
end
# >> 2014-01-30T01:00:00+00:00
# >> 2014-01-30T02:00:00+00:00
# >> 2014-01-30T15:00:00+00:00
# >> 2014-01-30T16:00:00+00:00
您的数据文件有BOM(&#34;字节顺序标记&#34;)。前两个字节表示文件中字节顺序的"endianness"。另外,每个字符实际占用两个字节。这是一个UTF-16LE文件,因为fffe
缺少一个位(0xfe
== 0b11111110
),表示字节对的结尾小于第一个字节。如果是feff
它是&#34; big-endian&#34;:
0000000: fffe 3100 2f00 3300 3000 2f00 3200 3000 ..1./.3.0./.2.0.
Ruby并不知道如何处理这些因为它预期默认的UTF-8。要解决这个问题,你需要告诉Ruby如何解释它。查看IO.new
的文档,了解如何定义编码。 Ruby假定数据将是UTF-8,因此传入的数据必须从UTF-16LE转换为UTF-8。这是一种方法:
require 'date'
File.open(
"test.csv",
"rb:BOM|UTF-16LE:UTF-8"
) do |fi|
fi.each_with_index do |line, i|
a, b = line.split("\t")
d = DateTime.strptime(a, '%m/%d/%Y %I:%M %p')
puts "#{ 1 + i } #{a} --- #{b}"
break unless i < 100
end
end
运行输出:
1 1/30/2014 1:00 AM --- 1251.6 2 1/30/2014 2:00 AM --- 1248 3 1/30/2014 3:00 AM --- 1246.32 4 1/30/2014 4:00 AM --- 1242.96 5 1/30/2014 5:00 AM --- 1282.08 6 1/30/2014 6:00 AM --- 1293.84 7 1/30/2014 7:00 AM --- 1307.04 8 1/30/2014 8:00 AM --- 1337.76 9 1/30/2014 9:00 AM --- 1357.92