445 Stimmen

Wie konvertiert man einen Unix-Zeitstempel (Sekunden seit Epoche) in Ruby DateTime?

Wie konvertiert man einen Unix-Zeitstempel (Sekunden seit Epoche) in Ruby DateTime?

712voto

Adam Eberlin Punkte 13455

Entschuldigung, kurzer Moment des Synapsenversagens. Hier ist die richtige Antwort.

require 'date'

Time.at(seconds_since_epoch_integer).to_datetime

Kurzes Beispiel (dabei wird die aktuelle Systemzeitzone berücksichtigt):

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

Weitere Aktualisierung (für 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)>

Aktuelles Update : Ich habe die Top-Lösungen in diesem Thread verglichen, als ich vor ein oder zwei Wochen an einem HA-Dienst arbeitete, und war überrascht, dass Time.at(..) besser abschneidet als DateTime.strptime(..) (Update: weitere Benchmarks hinzugefügt).

# ~ % 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>

399voto

steenslag Punkte 75941

DateTime.strptime kann mit Sekunden seit Epoche umgehen. Die Zahl muss in eine Zeichenkette umgewandelt werden:

require 'date'
DateTime.strptime("1318996912",'%s')

89voto

WattsInABox Punkte 4408

Handhabung von Zeitzonen

Ich möchte nur klarstellen, auch wenn dies bereits kommentiert wurde, damit künftige Personen diesen sehr wichtigen Unterschied nicht übersehen.

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

zeigt einen Rückgabewert in UTC an und erfordert, dass die Sekunden ein String sind und ein UTC-Zeitobjekt ausgegeben wird, während

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

zeigt einen Rückgabewert in der LOKALEN Zeitzone an, erfordert normalerweise ein FixNum-Argument, aber das Time-Objekt selbst ist immer noch in UTC, auch wenn die Anzeige nicht stimmt.

Obwohl ich also beiden Methoden dieselbe ganze Zahl übergeben habe, habe ich scheinbar zwei verschiedene Ergebnisse erhalten, weil die Methode der Klasse #to_s Methode funktioniert. Wie @Eero mich jedoch zweimal daran erinnern musste:

Time.at(1318996912) == DateTime.strptime("1318996912",'%s') # => true

Ein Gleichheitsvergleich zwischen den beiden Rückgabewerten ergibt immer noch true. Dies liegt wiederum daran, dass die Werte grundsätzlich gleich sind (obwohl unterschiedliche Klassen, die #== Methode übernimmt dies für Sie), aber die #to_s Methode gibt drastisch unterschiedliche Zeichenketten aus. Wenn wir uns die Zeichenketten ansehen, können wir feststellen, dass es sich tatsächlich um dieselbe Zeit handelt, die nur in unterschiedlichen Zeitzonen gedruckt wird.

Klärung von Methodenargumenten

Die Dokumentation sagt auch: "Wenn ein numerisches Argument angegeben wird, ist das Ergebnis in lokaler Zeit", was Sinn macht, aber ein wenig verwirrend für mich war, weil es keine Beispiele für nicht-ganzzahlige Argumente in der Dokumentation gibt. Also, für einige nicht-ganzzahlige Argumente Beispiele:

Time.at("1318996912")
TypeError: can't convert String into an exact number

können Sie kein String-Argument verwenden, aber Sie können ein Time-Argument in Time.at und gibt das Ergebnis in der Zeitzone des Arguments zurück:

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

Benchmarks

Nach einer Diskussion mit @AdamEberlin über seine Antwort habe ich beschlossen, leicht veränderte Benchmarks zu veröffentlichen, um alles so gleich wie möglich zu machen. Außerdem möchte ich diese nie wieder bauen müssen, also ist dies ein guter Ort, um sie zu speichern.

Time.at(int).to_datetime ~ 2,8x schneller

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>

**** so bearbeitet, dass sie nicht in jeder Hinsicht völlig falsch ist****

****added benchmarks****

12voto

Tejasvi Manmatha Punkte 504

Ein Befehl zur Konvertierung von Datum und Uhrzeit in das Unix-Format und dann in einen String

    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

schließlich wird strftime zum Formatieren des Datums verwendet

Beispiel:

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

1voto

sbutterworth Punkte 69

Hier wird die Anzahl der Sekunden in der Zukunft ab dem Zeitpunkt angegeben, an dem Sie den Code ausführen.

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

puts(time)

Nach der aktuellen Uhrzeit, zu der ich die Frage beantworte, wird Folgendes ausgedruckt 047-05-14 05:16:16 +0000 (1 Milliarde Sekunden in der Zukunft)

oder wenn Sie eine Milliarde Sekunden von einem bestimmten Zeitpunkt an zählen wollen, dann im Format Time.mktime(year, month,date,hours,minutes)

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

puts("Ich wäre 1 Milliarde Sekunden alt am: "+time)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X