Как преобразовать метку времени Unix (секунды с начала эпохи) в Ruby DateTime? - PullRequest
345 голосов
/ 19 октября 2011

Как конвертировать метку времени Unix (секунды с начала эпохи) в Ruby DateTime?

Ответы [ 6 ]

602 голосов
/ 19 октября 2011

Извините, краткий момент сбоя синапса.Вот реальный ответ.

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)>

Недавнее обновление : я тестировал лучшие решения в этой теме, работая неделю или две назад над службой высокой доступности, и с удивлением обнаружил, что 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>
327 голосов
/ 19 октября 2011

DateTime.strptime может обрабатывать секунды с начала эпохи. Число должно быть преобразовано в строку:

require 'date'
DateTime.strptime("1318996912",'%s')
59 голосов
/ 17 октября 2013

Обработка часового пояса

Я просто хочу уточнить, хотя это было прокомментировано, чтобы будущие люди не пропустили это очень важное различие.

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

отображает возвращаемое значение в UTC и требует, чтобы секунды были строкой, и выводит объект времени UTC, тогда как

Time.at(1318996912) # => 2011-10-19 00:01:52 -0400

отображает возвращаемое значение в часовом поясе LOCAL, обычно требуется аргумент FixNum, но сам объект Time по-прежнему находится в UTC, даже если на дисплее это не так.

Так что, хотя я и передал одно и то же целое число в оба метода, я, похоже, получил два разных результата из-за того, как работает метод класса '#to_s. Однако, как @Eero пришлось дважды напомнить мне о:

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 в Time.at, и он вернет результат в часовом поясе аргумента:

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

**** отредактировано, чтобы не быть полностью и совершенно неверным во всех отношениях ****

8 голосов
/ 12 февраля 2014

Одна команда для преобразования даты и времени в формат 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"
1 голос
/ 05 сентября 2015

Здесь указывается число секунд в будущем с момента выполнения вами кода.

time = Time.new + 1000000000 #date in 1 billion seconds

ставит (время)

в соответствии с текущим временем, на которое я отвечаювопрос, который он печатает 047-05-14 05:16:16 +0000 (1 миллиард секунд в будущем)

или, если вы хотите считать миллиард секунд с определенного времени, он имеет формат Time.mktime(year, month,date,hours,minutes)

time = Time.mktime(1987,8,18,6,45) + 1000000000

«Мне было бы 1 миллиард секунд на:» + время)

0 голосов
/ 10 октября 2013

Если вы хотели просто Дату, вы можете сделать Date.strptime(invoice.date.to_s, '%s'), где invoice.date имеет форму Fixnum, а затем преобразовать в String.

...