Stellen Sie den Zeitteil von DateTime in Ruby ein

103

Angenommen, ich habe ein Datum / Uhrzeit-Objekt, z DateTime.now. Ich möchte Stunden und Minuten auf 0 (Mitternacht) setzen. Wie kann ich das machen?

Jesse Aldridge
quelle

Antworten:

219

In einer Rails-Umgebung:

Dank ActiveSupport können Sie Folgendes verwenden:

DateTime.now.midnight
DateTime.now.beginning_of_day

ODER

DateTime.now.change({ hour: 0, min: 0, sec: 0 })

# More concisely
DateTime.now.change({ hour: 0 })                

In einer rein Ruby-Umgebung:

now = DateTime.now
DateTime.new(now.year, now.month, now.day, 0, 0, 0, now.zone)

ODER

now = DateTime.now
DateTime.parse(now.strftime("%Y-%m-%dT00:00:00%z"))
Ashoda
quelle
26
FWIW, die Änderungsmethode ist Teil von Schienen, die nicht rubinrot sind. Die Zeitoptionen (Stunde, Minute, Sekunde) werden kaskadierend zurückgesetzt. Wenn also nur die Stunde verstrichen ist, werden Minute und Sekunde auf 0 gesetzt. Wenn Stunde und Minute verstrichen sind, wird Sekunde auf 0 gesetzt.
Anna
1
Beachten Sie, dass DateTime.now.midnight nicht wie erwartet 24:00:00 zurückgibt, sondern 00:00:00 - den gleichen Wert wie begin_of_day. Siehe meine Antwort, warum dies in einigen Szenarien wichtig sein könnte.
rmcsharry
1
Ihre erste rein rubinrote Lösung löscht Zeitzoneninformationen, Ihre zweite nicht
Tony
1
Ich habe die Antwort aktualisiert, um die Zeitzone zu berücksichtigen, und die zweite Variante ersetzt. @ Tony sehr guter Fang, sie waren tatsächlich beide anfällig für den Verlust von Zeitzoneninformationen bei näherer Betrachtung. DateTime.new(now.year, now.month, now.day, 0,0,0, now.zone) != now.to_date.to_datetime
Ashoda
ZEITZONE: Kann durch das Schlüsselwort Offset im Argument Hash geändert werden: DateTime.now.change ({Stunde: 0, Min: 0, Sek: 0 Offset: '+02: 00'})
Ekkstein
34

Vergiss es. Müssen Sie eine neue DateTime erstellen:

DateTime.new(now.year, now.month, now.day, 0, 0, 0, 0)
Jesse Aldridge
quelle
6
Gute Antwort. Ich wollte nur hinzufügen, dass diese Nullen HOUR, MINUTE, SECOND und OFFSET (Zeitzone) in dieser Reihenfolge darstellen.
d_ethier
3
Nachdem ich dies nicht zum Laufen gebracht hatte, lernte ich das mit: DateTime.new(Time.now.year, Time.now.month, Time.now.day, 0, 0, 0)es funktioniert.
Ekkstein
2
Vergessen Sie nicht: now = DateTime.now
Abel
1
Beachten Sie auch, dass das letzte Argument eine Zeichenfolge der Zeitzone sein muss, z. B. ("- 0700") für MST, keine Ganzzahl
Donavan White
2
Verwenden Sie NICHT, es sei denn, Sie haben es mit historischen Daten zu tun DateTime. Wenn Sie in einem Land mit Sommerzeit wie Großbritannien leben, werden Sie nervige Probleme bekommen. Eine Erklärung finden Sie hier. gist.github.com/pixeltrix/e2298822dd89d854444b
fatuhoku
5

Warnung : DateTime.now.midnightund DateTime.now.beginning_of_daygeben Sie denselben Wert zurück (dies ist die Nullstunde des aktuellen Tages - Mitternacht gibt nicht 24:00:00 zurück, wie Sie es von seinem Namen erwarten würden).

Daher füge ich dies als weitere Information für jeden hinzu, der die akzeptierte Antwort verwenden könnte, um Mitternacht x Tage in der Zukunft zu berechnen.

Beispiel: Eine 14-tägige kostenlose Testversion, die am 14. Tag um Mitternacht abläuft:

DateTime.now.midnight + 14.days

ist der Morgen des 14. Tages, was einer 13-tägigen Testversion entspricht (x ist der Teil des verbleibenden Tages - wenn jetzt Mittag ist, ist es eine 13,5-tägige Testversion).

Sie müssten dies tatsächlich tun:

DateTime.now.midnight + 15.days

am 14. Tag Mitternacht zu bekommen.

Aus diesem Grund bevorzuge ich immer die Verwendung beginning_of_day, da dies 00:00:00 ist. Die Verwendung von Mitternacht kann irreführend / missverstanden sein.

rmcsharry
quelle
1

Wenn Sie es häufig verwenden, sollten Sie dieses Juwel installieren, um die Datumsanalyse zu verbessern:

https://github.com/mojombo/chronic

require 'chronic'

Chronic.parse('this 0:00')
wizztjh
quelle
Ich bin mir nicht sicher, warum diese Antwort als richtig markiert ist. Es beantwortet die Frage nicht wirklich. Ich weiß, wie man einen String auf ein Datum analysiert. Ich möchte jedoch wissen, wie ein bestimmter Teil einer bestimmten Datumsinstanz geändert werden kann. Zum Beispiel das Jahr. Irgendwelche Ideen? In Java würde ich den Setter nur für das Jahr verwenden. Aber es funktioniert nicht in Ruby :-(
Robert Reiz
1
Ich traue chronischen Edelsteinen nicht mehr. Es ist wirklich veraltet. Ich hatte Probleme beim Parsen von Datum und Uhrzeit zur Laufzeit in meiner App, was zu einem Geschäftsverlust führte.
Vijay Meena