如何将unix时间戳(自纪元以来的秒数)转换为Ruby DateTime?

Tro*_*han 350 ruby datetime timestamp

如何将Unix时间戳(自纪元以来的秒数)转换为Ruby DateTime?

Ada*_*lin 612

对不起,短暂的突触失败时刻.这是真正的答案.

require 'date'

Time.at(seconds_since_epoch_integer).to_datetime
Run Code Online (Sandbox Code Playgroud)

简要示例(这考虑了当前系统时区):

$ date +%s
1318996912

$ irb

ruby-1.9.2-p180 :001 > require 'date'
 => true 

ruby-1.9.2-p180 :002 > Time.at(1318996912).to_datetime
 => #<DateTime: 2011-10-18T23:01:52-05:00 (13261609807/5400,-5/24,2299161)> 
Run Code Online (Sandbox Code Playgroud)

进一步更新(适用于UTC):

ruby-1.9.2-p180 :003 > Time.at(1318996912).utc.to_datetime
 => #<DateTime: 2011-10-19T04:01:52+00:00 (13261609807/5400,0/1,2299161)>
Run Code Online (Sandbox Code Playgroud)

最新更新:我在一周或两周前在HA服务上工作时对此线程中的顶级解决方案进行了基准测试,并且惊讶地发现其Time.at(..)表现优于DateTime.strptime(..)(更新:添加了更多基准测试).

# ~ % ruby -v
#  => ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-darwin13.0]

irb(main):038:0> Benchmark.measure do
irb(main):039:1*   ["1318996912", "1318496912"].each do |s|
irb(main):040:2*     DateTime.strptime(s, '%s')
irb(main):041:2>   end
irb(main):042:1> end

=> #<Benchmark ... @real=2.9e-05 ... @total=0.0>

irb(main):044:0> Benchmark.measure do
irb(main):045:1>   [1318996912, 1318496912].each do |i|
irb(main):046:2>     DateTime.strptime(i.to_s, '%s')
irb(main):047:2>   end
irb(main):048:1> end

=> #<Benchmark ... @real=2.0e-05 ... @total=0.0>

irb(main):050:0* Benchmark.measure do
irb(main):051:1*   ["1318996912", "1318496912"].each do |s|
irb(main):052:2*     Time.at(s.to_i).to_datetime
irb(main):053:2>   end
irb(main):054:1> end

=> #<Benchmark ... @real=1.5e-05 ... @total=0.0>

irb(main):056:0* Benchmark.measure do
irb(main):057:1*   [1318996912, 1318496912].each do |i|
irb(main):058:2*     Time.at(i).to_datetime
irb(main):059:2>   end
irb(main):060:1> end

=> #<Benchmark ... @real=2.0e-05 ... @total=0.0>
Run Code Online (Sandbox Code Playgroud)

  • 这与上面的anser不同,Time.at假设当前时区,其中DateTime.strptime使用UTC. (32认同)
  • 这很有趣但Time.at().to_datetime似乎比DateTime.strptime()更令人愉快,因为它的可读性......至少对我而言 (27认同)
  • "Time.at"优于"DateTime.strptime"并不令人惊讶.后者必须解析一个字符串,这通常比直接接收一个数字慢得多. (5认同)
  • @VitalyBabiy希望我的更新能为您解决这个问题. (4认同)
  • 您的基准测试并不完全测试`DateTime.strptime`,因为它每次迭代都会创建两个新的字符串,这非常昂贵.这不仅仅是@claw所说的字符串解析 (2认同)

ste*_*lag 338

DateTime.strptime自纪元以来可以处理几秒钟.必须将该数字转换为字符串:

require 'date'
DateTime.strptime("1318996912",'%s')
Run Code Online (Sandbox Code Playgroud)

  • 它确实用'%Q` tho处理毫秒. (39认同)
  • 这不处理小数秒 (4认同)
  • 跟进@ TheMiniJohn的回答.看起来像`Time`而不是`DateTime`.所以使用`Time.strptime("1318996912345",'%Q').to_f`你将看到保留的毫秒数,而`DateTime.strptime("1318996912345",'%Q').to_f`不保留​​它. (3认同)

Wat*_*Box 64

时区处理

我只是想澄清一下,尽管这已经被评论过,所以未来的人们不要错过这个非常重要的区别.

DateTime.strptime("1318996912",'%s') # => Wed, 19 Oct 2011 04:01:52 +0000
Run Code Online (Sandbox Code Playgroud)

以UTC显示返回值,并要求秒为字符串并输出UTC时间对象,而

Time.at(1318996912) # => 2011-10-19 00:01:52 -0400
Run Code Online (Sandbox Code Playgroud)

在LOCAL时区中显示返回值,通常需要一个FixNum参数,但即使显示不是,Time对象本身仍然是UTC.

因此即使我将相同的整数传递给两个方法,我看起来有两个不同的结果,因为类的#to_s方法是如何工作的.但是,正如@Eero不得不提醒我两次:

Time.at(1318996912) == DateTime.strptime("1318996912",'%s') # => true
Run Code Online (Sandbox Code Playgroud)

两个返回值之间的相等比较仍然返回true.同样,这是因为值基本相同(虽然不同的类,#==方法会为您处理),但该#to_s方法会打印截然不同的字符串.虽然,如果我们看一下琴弦,我们可以看到它们确实是同一时间,只是印在不同的时区.

方法论证澄清

文档还说"如果给出了数字参数,则结果是在本地时间." 这是有道理的,但对我来说有点混乱,因为他们没有在文档中给出任何非整数参数的例子.因此,对于一些非整数参数示例:

Time.at("1318996912")
TypeError: can't convert String into an exact number
Run Code Online (Sandbox Code Playgroud)

您不能使用String参数,但可以使用Time参数Time.at,它将在参数的时区中返回结果:

Time.at(Time.new(2007,11,1,15,25,0, "+09:00"))
=> 2007-11-01 15:25:00 +0900
Run Code Online (Sandbox Code Playgroud)

****编辑在各方面都不完全和完全错误****

  • 对不起,但你纠正的还是错的!:-)运行`Time.use_zone"Samoa"do Time.at(1318996912)== DateTime.strptime("1318996912",'%s')end`来验证时间是否相等,没有LOCAL时间戳,并且在这两种情况下,Unix时间戳都被解释为UTC.`Time.at`*在本地时区显示*生成的Time对象,`DateTime.strptime`*以UTC表示*生成的DateTime对象,但无论它们是否相同,因为它们是等效的时刻. (4认同)
  • 看似合理,我已经投票(现在不能撤销),但在进一步检查你对UTC的主张是不真实的.生成的DateTime/Time对象将以UTC与本地对比,是,但在两种情况下原始时间戳都被解释为UTC格式!所以无论方法如何,时刻都是平等的.在非UTC时区尝试`Time.at(1318996912)== DateTime.strptime("1318996912",'%s')`你会看到! (3认同)

小智 8

一个命令将日期时间转换为Unix格式,然后转换为字符串

    DateTime.strptime(Time.now.utc.to_i.to_s,'%s').strftime("%d %m %y")

    Time.now.utc.to_i #Converts time from Unix format
    DateTime.strptime(Time.now.utc.to_i.to_s,'%s') #Converts date and time from unix format to DateTime
Run Code Online (Sandbox Code Playgroud)

最后strftime用于格式化日期

例:

    irb(main):034:0> DateTime.strptime("1410321600",'%s').strftime("%d %m %y")
    "10 09 14"
Run Code Online (Sandbox Code Playgroud)