Odpowiedzi:
DateTime.strptime
może obsłużyć sekundy od epoki. Liczba musi zostać przekonwertowana na ciąg:
require 'date'
DateTime.strptime("1318996912",'%s')
%Q
tho ” .
Time
jest to konieczne zamiast DateTime
. Skorzystaj, Time.strptime("1318996912345",'%Q').to_f
a zobaczysz milisekundy zachowane, a DateTime.strptime("1318996912345",'%Q').to_f
nie zachowane.
Przepraszamy, krótka chwila niepowodzenia synapsy. Oto prawdziwa odpowiedź.
require 'date'
Time.at(seconds_since_epoch_integer).to_datetime
Krótki przykład (uwzględnia aktualną strefę czasową systemu):
$ 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)>
Dalsza aktualizacja (dla 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)>
Ostatnia aktualizacja : Przeprowadziłem testy porównawcze najlepszych rozwiązań w tym wątku, pracując nad usługą HA tydzień lub dwa lata temu, i byłem zaskoczony, że Time.at(..)
przewyższa to DateTime.strptime(..)
(aktualizacja: dodałem więcej testów porównawczych).
# ~ % 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>
Time.at
osiąga lepsze wyniki DateTime.strptime
. Ten ostatni musi przeanalizować ciąg znaków, który jest na ogół znacznie wolniejszy niż bezpośrednie pobieranie liczby.
DateTime.strptime
ponieważ tworzy dwa nowe ciągi w każdej iteracji, co jest bardzo drogie. To nie tylko parsowanie łańcucha, jak powiedział
Obsługa stref czasowych
Chcę tylko wyjaśnić, chociaż zostało to skomentowane, aby przyszli ludzie nie przegapili tego bardzo ważnego rozróżnienia.
DateTime.strptime("1318996912",'%s') # => Wed, 19 Oct 2011 04:01:52 +0000
wyświetla wartość zwracaną w UTC i wymaga, aby sekundy były ciągiem, i wysyła obiekt czasu UTC, natomiast
Time.at(1318996912) # => 2011-10-19 00:01:52 -0400
wyświetla wartość zwracaną w LOKALNEJ strefie czasowej, zwykle wymaga argumentu FixNum, ale sam obiekt Time wciąż jest w UTC, nawet jeśli wyświetlanie nie jest.
Więc mimo że podałem tę samą liczbę całkowitą do obu metod, najwyraźniej mam dwa różne wyniki ze względu na sposób działania #to_s
metody klasy . Jednak, ponieważ @Eero dwukrotnie musiało mi przypominać:
Time.at(1318996912) == DateTime.strptime("1318996912",'%s') # => true
Porównanie równości między dwiema zwracanymi wartościami nadal zwraca wartość true. Ponownie #==
dzieje się tak, ponieważ wartości są w zasadzie takie same (chociaż różne klasy metoda dba o to za Ciebie), ale #to_s
metoda drukuje drastycznie różne ciągi. Chociaż, jeśli spojrzymy na ciągi, zobaczymy, że rzeczywiście są one w tym samym czasie, tylko drukowane w różnych strefach czasowych.
Metoda Wyjaśnienie argumentów
Dokumenty mówią również: „Jeśli podany zostanie argument liczbowy, wynik będzie w czasie lokalnym”. co ma sens, ale było to dla mnie trochę mylące, ponieważ nie podają żadnych przykładów argumentów niecałkowitych w dokumentacji. Tak więc w przypadku niektórych argumentów niecałkowitych:
Time.at("1318996912")
TypeError: can't convert String into an exact number
nie możesz użyć argumentu String, ale możesz użyć argumentu Time do, Time.at
a zwróci wynik w strefie czasowej argumentu:
Time.at(Time.new(2007,11,1,15,25,0, "+09:00"))
=> 2007-11-01 15:25:00 +0900
Benchmarki
Po dyskusji z @AdamEberlin na temat jego odpowiedzi postanowiłem opublikować nieznacznie zmienione testy porównawcze, aby wszystko było jak najbardziej równe. Ponadto, nigdy nie chcę ich ponownie budować, więc jest to tak dobre miejsce, jak każde, aby je uratować.
Time.at (int) .to_datetime ~ 2.8x szybciej
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>
**** edytowane tak, aby nie były całkowicie i całkowicie niepoprawne pod każdym względem ****
**** dodano testy porównawcze ****
Time.at(1318996912) == DateTime.strptime("1318996912",'%s')
w strefie czasowej innej niż UTC, a zobaczysz!
Time.use_zone "Samoa" do Time.at(1318996912) == DateTime.strptime("1318996912",'%s') end
aby sprawdzić, czy czasy są równe, nie ma LOKALNEGO znacznika czasu, aw obu przypadkach uniksowy znacznik czasu jest interpretowany jako UTC. Time.at
przedstawia wynikowy obiekt Time w lokalnej strefie czasowej i DateTime.strptime
przedstawia wynikowy obiekt DateTime w UTC, ale niezależnie od prezentacji są one równe, ponieważ są równoważnym momentem w czasie.
Time.at(1318996912) # => 2011-10-19 00:01:52 -0400
wyświetla wartość zwracaną w LOKALNEJ strefie czasowej , nie wydaje się dokładne ... Czy możesz to zweryfikować? Wierzę, że twoje stwierdzenie byłoby prawdziwe tylko wtedy, gdy je użyłeśTime.zone.at(1318996912)
Jedno polecenie konwersji daty i godziny na format uniksowy, a następnie na ciąg znaków
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
w końcu strftime służy do formatowania daty
Przykład:
irb(main):034:0> DateTime.strptime("1410321600",'%s').strftime("%d %m %y")
"10 09 14"
Time.now.utc.to_i
.
Informuje o dacie liczby sekund w przyszłości od momentu wykonania kodu.
time = Time.new + 1000000000 #date in 1 billion seconds
puts (czas)
zgodnie z obecnym czasem odpowiadam na pytanie, które drukuje 047-05-14 05:16:16 +0000
(1 miliard sekund w przyszłości)
lub jeśli chcesz liczyć miliardy sekund od określonego czasu, jest to format Time.mktime(year, month,date,hours,minutes)
time = Time.mktime(1987,8,18,6,45) + 1000000000
puts („Miałbym 1 miliard sekund na:” + czas)