简短的回答
Excel 时间戳对时区一无所知。如果要导出一个值并以当地时间显示,则需要在将其utc_offset
发送到 Axlsx 之前将其添加到时间。
t = ...
excel_time = Time.at(t.to_f + t.utc_offset)
sheet.add_row ["Time:", excel_time]
长答案
在 Ruby(和许多其他编程语言)中,时间戳表示为自 1970 年 1 月 1 日 00:00:00 UTC(纪元)以来的秒数。RubyTime
对象还保留了一个时区,因此当您将其打印出来时,它可以显示本地时间。如果更改时区,时间会以不同的方式打印出来,但底层数字保持不变。
在 Excel 中,时间戳表示为自 1900 年 1 月 1 日(或 1904 年,取决于工作簿设置)以来的天数;时间表示为一天的一小部分。如果今天的日期是 41262,那么上午 12 点是 41262.0,中午是 41262.5。此方案中没有时区,时间只是您从手表上读出的数字。
当 Axlsx 将 Ruby Time 对象导出到 Excel 时,它会调用to_f
以获取自纪元以来的时间值(以秒为单位),然后进行一些数学运算以将其转换为 Excel 喜欢的序列号。伟大的!但它抛弃了utc_offset
,这就是为什么时间在 Excel 中显示为 UTC 的原因。
解决方案是简单地将 UTC 偏移量添加到代码中的时间,然后再将它们交给 Axlsx。例如,如果您使用的是东部标准时间,则必须减去五个小时。从技术上讲,就 Ruby 而言,您创建的新时间对象是不正确的,但我们这样做只是为了取悦 Excel。