Antworten:
DateTime.strptime
kann Sekunden seit der Epoche verarbeiten. Die Nummer muss in eine Zeichenfolge konvertiert werden:
require 'date'
DateTime.strptime("1318996912",'%s')
%Q
tho.
Time
es notwendig statt DateTime
. Verwenden Time.strptime("1318996912345",'%Q').to_f
Sie also und Sie werden sehen, dass die Millisekunden erhalten bleiben, während DateTime.strptime("1318996912345",'%Q').to_f
sie nicht erhalten bleiben.
Entschuldigung, kurzer Moment des Synapsenversagens. Hier ist die wahre Antwort.
require 'date'
Time.at(seconds_since_epoch_integer).to_datetime
Kurzes Beispiel (dies berücksichtigt die aktuelle Systemzeitzone):
$ 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)>
Weiteres Update (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)>
Letztes Update : Ich habe die Top-Lösungen in diesem Thread vor ein oder zwei Wochen bei der Arbeit an einem HA-Service verglichen und war überrascht, dass diese Time.at(..)
Outperformance erzielt wurde 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>
Time.at
besser abschneidet DateTime.strptime
. Letzterer muss eine Zeichenfolge analysieren, die im Allgemeinen viel langsamer ist als die direkte Eingabe einer Zahl.
DateTime.strptime
da bei jeder Iteration zwei neue Strings erstellt werden, was sehr teuer ist. Es ist nicht nur das Parsen von Strings, wie @claw sagte
Zeitzonenbehandlung
Ich möchte nur klarstellen, obwohl dies kommentiert wurde, damit zukünftige Leute diese sehr wichtige Unterscheidung nicht verpassen.
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 gibt ein UTC-Zeitobjekt aus
Time.at(1318996912) # => 2011-10-19 00:01:52 -0400
Zeigt einen Rückgabewert in der LOCAL-Zeitzone an, erfordert normalerweise ein FixNum-Argument, aber das Time-Objekt selbst befindet sich immer noch in UTC, obwohl die Anzeige dies nicht ist.
Obwohl ich beiden Methoden dieselbe Ganzzahl übergeben habe, habe ich aufgrund der Funktionsweise der Klassenmethode anscheinend zwei unterschiedliche Ergebnisse erzielt #to_s
. Da @Eero mich jedoch zweimal daran erinnern musste:
Time.at(1318996912) == DateTime.strptime("1318996912",'%s') # => true
Ein Gleichheitsvergleich zwischen den beiden Rückgabewerten gibt weiterhin true zurück. Dies liegt wiederum daran, dass die Werte im Grunde genommen gleich sind (obwohl verschiedene Klassen, die #==
Methode kümmert sich für Sie darum), aber die #to_s
Methode druckt drastisch unterschiedliche Zeichenfolgen. Wenn wir uns die Zeichenfolgen ansehen, können wir jedoch feststellen, dass sie tatsächlich dieselbe Zeit sind und nur in verschiedenen Zeitzonen gedruckt werden.
Klärung des Methodenarguments
In den Dokumenten heißt es außerdem: "Wenn ein numerisches Argument angegeben wird, ist das Ergebnis in Ortszeit." Das macht Sinn, war aber für mich etwas verwirrend, weil sie in den Dokumenten keine Beispiele für nicht ganzzahlige Argumente enthalten. Für einige Beispiele für nicht ganzzahlige Argumente:
Time.at("1318996912")
TypeError: can't convert String into an exact number
Sie können kein String-Argument verwenden, aber Sie können ein Time-Argument in verwenden, Time.at
und das Ergebnis wird in der Zeitzone des Arguments zurückgegeben:
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 geä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, damit dies so gut wie jeder andere Ort ist, um sie zu retten.
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>
**** bearbeitet, um nicht in jeder Hinsicht vollständig und völlig falsch zu sein ****
**** Benchmarks hinzugefügt ****
Time.at(1318996912) == DateTime.strptime("1318996912",'%s')
in einer Nicht-UTC-Zeitzone und Sie werden sehen!
Time.use_zone "Samoa" do Time.at(1318996912) == DateTime.strptime("1318996912",'%s') end
, um sicherzustellen , dass die Zeiten gleich sind. Es gibt keinen lokalen Zeitstempel. In beiden Fällen wird der Unix-Zeitstempel als UTC interpretiert. Time.at
präsentiert das resultierende Zeitobjekt in der lokalen Zeitzone, und DateTime.strptime
präsentiert das resultierende Datetime - Objekt in UTC, aber unabhängig davon , Präsentation sie gleich sind, da sie der entsprechende Zeitpunkt ist.
Time.at(1318996912) # => 2011-10-19 00:01:52 -0400
ein Rückgabewert in der lokalen Zeitzone angezeigt wird, scheint nicht korrekt zu sein ... Können Sie dies bitte überprüfen? Ich glaube, Ihre Aussage wäre nur wahr, wenn SieTime.zone.at(1318996912)
Ein Befehl zum Konvertieren der Datums- und Uhrzeit in das Unix-Format und anschließend in eine Zeichenfolge
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"
Time.now.utc.to_i
.
Hier erfahren Sie das Datum der Anzahl der Sekunden in der Zukunft ab dem Zeitpunkt, an dem Sie den Code ausführen.
time = Time.new + 1000000000 #date in 1 billion seconds
setzt (Zeit)
Nach der aktuellen Zeit beantworte ich die Frage, die gedruckt wird 047-05-14 05:16:16 +0000
(1 Milliarde Sekunden in der Zukunft).
oder wenn Sie Milliarden Sekunden ab einer bestimmten Zeit zählen möchten, ist es im Format Time.mktime(year, month,date,hours,minutes)
time = Time.mktime(1987,8,18,6,45) + 1000000000
setzt ("Ich wäre 1 Milliarde Sekunden alt auf:" + Zeit)