如何在Ruby中将MS excel日期从float格式转换为日期格式?

kon*_*ung 9 ruby excel ruby-on-rails date activesupport

尝试在ruby脚本中使用roo gem解析和XLSX文件.

在Excel中,日期以DDDDD.ttttt格式存储为浮点数或整数,从中计数1900-01-00 (00 no 01).因此,为了转换40396这样的日期 - 你会采取1900-01-00 + 40396,你应该得到2010-10-15,但我得到2010-08-08.

我正在使用active_support/time进行计算,如下所示:

Time.new("1900-01-01") + 40396.days
Run Code Online (Sandbox Code Playgroud)

我的计算错误还是有积极支持的错误?

我在Windows 7上运行ruby 1.9.3-mri +最新的active_support gem(3.2.1)

编辑

我正在使用错误的数据查看Excel中的旧文件 - 我的脚本/控制台正在提取正确的数据 - 因此我的困惑 - 我做的一切正常,除了使用正确的文件!该死的全能者!

感谢大家的回复,我会在这里保留问题,以防有人需要有关如何使用ruby从excel转换日期的信息.

对于遇到此问题的其他人 - 电子表格宝石也不支持此时正确读取XLSX文件(v 0.7.1) - 因此我使用roo进行读取,使用axlsx进行写入.

Mar*_*eed 27

您的日期编号中有一个错误的错误 - 由于Lotus 1-2-3中的错误,Excel和其他电子表格程序已经仔细维护了30多年的兼容性.

最初,第1天的目的是在1900年1月1日(正如你所说,这将使第0天等于1899年12月31日).但莲花错误地认为1900年是闰年,所以如果你现在使用莲花数并向后计数,正确地使1900年成为常年,那么1900年3月1日之前所有东西的数字都太高了.第1天变为1899年12月31日,第0天变回第30天.因此,基于Lotus的电子表格中日期算术的时代实际上是1899年12月30日星期六.(现代Excel和其他一些电子表格扩展了Lotus bug兼容性足以显示1900年2月实际上有第29天,所以他们将标记日0"12月31日",同意这是一个星期六!但其他基于Lotus的电子表格不这样做,而且Ruby当然也没有.)

但是,即使考虑到这个错误,你所陈述的例子也是错误的:莲花日号码40,396是2010年8月6日,而不是10月15日.我已在Excel,LibreOffice和Google表格中确认了此通信,所有这些都是一致的.你必须在某处有交叉的例子.

这是进行转换的一种方法:

Time.utc(1899,12,30) + 40396.days #=> 2010-08-06 00:00:00 UTC
Run Code Online (Sandbox Code Playgroud)

或者,您可以利用另一个已知的通信.Ruby(以及一般POSIX系统)的时间零点是1970年1月1日格林威治标准时间午夜.1970年1月1日是莲花日25,569.只要您记得在UTC中进行计算,您也可以这样做:

Time.at( (40396 - 25569).days ).utc # => 2010-08-06 00:00:00 UTC
Run Code Online (Sandbox Code Playgroud)

在任何一种情况下,您可能希望为纪元日期声明符号常量(Time代表1899-12-30 的对象或POSIX"day 0"值25,569).

.days如果您不需要active_support/core_ext/integer/time其他任何东西,可以将这些调用替换为乘法86400(每天秒数),并且不想仅为此加载它.


kgx*_*kgx 6

“Excel 将日期和时间存储为一个数字,表示自 1900 年 1 月 0 日以来的天数,加上 24 小时制的小数部分: ddddd.tttttt 。这称为序列日期或序列日期时间。” ( http://www.cpearson.com/excel/datetime.htm )

如果您的列包含日期时间,而不仅仅是日期,则以下代码很有用:

 dt = DateTime.new(1899, 12, 30) + excel_value.to_f
Run Code Online (Sandbox Code Playgroud)

还要记住,excel 工作表中有 2 种日期模式,基于 1900 和基于 1904,通常默认情况下为在 Mac 上创建的电子表格启用。如果您始终发现日期相差 4 年,则应使用不同的基准日期:

 dt = DateTime.new(1904, 1, 1) + excel_value.to_f
Run Code Online (Sandbox Code Playgroud)

您可以为任何电子表格启用/禁用 1904 日期模式,但如果您在添加数据后更改设置,则日期将在电子表格中显示 4 年。一般来说,您应该始终使用 1900 日期模式,因为大多数 excel 用户都是基于 Windows 的。

注意:此方法的一个问题是四舍五入可能发生在 +/- 1 秒内。对我来说,我导入的日期“足够接近”,但需要记住。更好的解决方案可能会在小数秒内使用舍入来解决此问题。