如何将Unix时间戳(从epoch开始的秒数)转换为Ruby DateTime?
抱歉,是短暂的突触故障。这才是真正的答案。
require 'date' Time.at(seconds_since_epoch_integer).to_datetime
简单的例子(这将考虑当前系统时区):
$ 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)>
进一步的更新(用于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)>
最近的更新:我在一两个星期前在HA服务上工作时对这个线程中的顶级解决方案进行了基准测试,并惊讶地发现Time.at(..)优于DateTime.strptime(..)(更新:添加了更多的基准测试)。
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>
DateTime.strptime可以处理自epoch以来的秒数。该数字必须转换为字符串:
DateTime.strptime
require 'date' DateTime.strptime("1318996912",'%s')
如果你只想要一个日期,你可以执行Date.strptime(invoice.date.to_s, '%s'),其中invoice.date以__abc2的形式出现,然后转换为String。
Date.strptime(invoice.date.to_s, '%s')
invoice.date
String
时区处理
我只是想澄清一下,尽管这已经被评论过了所以以后的人不会错过这个非常重要的区别。
DateTime.strptime("1318996912",'%s') # => Wed, 19 Oct 2011 04:01:52 +0000
显示一个UTC返回值,要求秒为字符串,并输出一个UTC时间对象,而
Time.at(1318996912) # => 2011-10-19 00:01:52 -0400
显示一个本地时区的返回值,通常需要一个FixNum参数,但time对象本身仍然是UTC,即使显示不是。
因此,尽管我向两个方法传递了相同的整数,但由于类的#to_s方法的工作方式,我似乎得到了两个不同的结果。然而,正如@Eero两次提醒我的那样:
#to_s
Time.at(1318996912) == DateTime.strptime("1318996912",'%s') # => true
两个返回值之间的相等比较仍然返回true。同样,这是因为值基本上是相同的(尽管不同的类,#==方法会为你处理这个问题),但#to_s方法打印的字符串完全不同。虽然,如果我们看一下字符串,我们可以看到它们确实是相同的时间,只是打印在不同的时区。
#==
方法参数澄清
文档还说“如果给出了一个数字参数,结果是本地时间”,这很有意义,但让我有点困惑,因为文档中没有给出任何非整数参数的例子。对于一些非整型参数的例子:
Time.at("1318996912") TypeError: can't convert String into an exact number
你不能使用String参数,但你可以在Time.at中使用Time参数,它将返回参数所在时区的结果:
Time.at
Time.at(Time.new(2007,11,1,15,25,0, "+09:00")) => 2007-11-01 15:25:00 +0900
基准
在与@AdamEberlin讨论了他的答案后,我决定发布稍微改变的基准,以使一切尽可能平等。而且,我再也不想建造它们了,所以这里是保存它们的好地方。
定出(int)。To_datetime ~ 2.8倍快
09:10:58-watsw018:~$ ruby -v ruby 2.3.7p456 (2018-03-28 revision 63024) [universal.x86_64-darwin18] 09:11:00-watsw018:~$ irb irb(main):001:0> require 'benchmark' => true irb(main):002:0> require 'date' => true irb(main):003:0> irb(main):004:0* format = '%s' => "%s" irb(main):005:0> times = ['1318996912', '1318496913'] => ["1318996912", "1318496913"] irb(main):006:0> int_times = times.map(&:to_i) => [1318996912, 1318496913] irb(main):007:0> irb(main):008:0* datetime_from_strptime = DateTime.strptime(times.first, format) => #<DateTime: 2011-10-19T04:01:52+00:00 ((2455854j,14512s,0n),+0s,2299161j)> irb(main):009:0> datetime_from_time = Time.at(int_times.first).to_datetime => #<DateTime: 2011-10-19T00:01:52-04:00 ((2455854j,14512s,0n),-14400s,2299161j)> irb(main):010:0> irb(main):011:0* datetime_from_strptime === datetime_from_time => true irb(main):012:0> irb(main):013:0* Benchmark.measure do irb(main):014:1* 100_000.times { irb(main):015:2* times.each do |i| irb(main):016:3* DateTime.strptime(i, format) irb(main):017:3> end irb(main):018:2> } irb(main):019:1> end => #<Benchmark::Tms:0x00007fbdc18f0d28 @label="", @real=0.8680500000045868, @cstime=0.0, @cutime=0.0, @stime=0.009999999999999998, @utime=0.86, @total=0.87> irb(main):020:0> irb(main):021:0* Benchmark.measure do irb(main):022:1* 100_000.times { irb(main):023:2* int_times.each do |i| irb(main):024:3* Time.at(i).to_datetime irb(main):025:3> end irb(main):026:2> } irb(main):027:1> end => #<Benchmark::Tms:0x00007fbdc3108be0 @label="", @real=0.33059399999910966, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.32000000000000006, @total=0.32000000000000006>
****编辑不完全和完全不正确的每一个方面****
* * * * * * * *添加基准
一个将日期时间转换为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
最后使用strftime对日期进行格式化
例子:
irb(main):034:0> DateTime.strptime("1410321600",'%s').strftime("%d %m %y") "10 09 14"
这将告诉您从您执行代码的那一刻起的秒数的日期。
time = Time.new + 1000000000 #date in 1 billion seconds
把(时间)
根据当前时间,我正在回答这个问题,它会打印047-05-14 05:16:16 +0000(未来10亿秒)
047-05-14 05:16:16 +0000
或者如果你想从一个特定的时间开始计数十亿秒,它的格式是Time.mktime(year, month,date,hours,minutes)
Time.mktime(year, month,date,hours,minutes)
time = Time.mktime(1987,8,18,6,45) + 1000000000
放(“我会活到10亿秒”+时间)