Atur bagian waktu DateTime di ruby

104

Katakanlah saya memiliki objek datetime misalnya DateTime.now. Saya ingin menyetel jam dan menit ke 0 (tengah malam). Bagaimana saya bisa melakukan itu?

Jesse Aldridge
sumber

Jawaban:

220

Dalam lingkungan Rails:

Berkat ActiveSupport, Anda dapat menggunakan:

DateTime.now.midnight
DateTime.now.beginning_of_day

ATAU

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

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

Dalam lingkungan Ruby murni:

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

ATAU

now = DateTime.now
DateTime.parse(now.strftime("%Y-%m-%dT00:00:00%z"))
ashoda
sumber
26
FWIW, metode perubahan adalah bagian dari rel bukan ruby. Opsi waktu (jam, menit, detik) disetel ulang secara bertingkat, jadi jika hanya jam yang berlalu, menit dan detik disetel ke 0. Jika jam dan menit berlalu, detik disetel ke 0.
Anna
1
Sadarilah bahwa DateTime.now.midnight tidak mengembalikan 24:00:00 seperti yang Anda duga, ia mengembalikan 00:00:00 - nilai yang sama seperti start_of_day. Lihat jawaban saya mengapa ini bisa menjadi penting dalam beberapa skenario.
rmcsharry
1
Solusi ruby ​​murni pertama Anda menjatuhkan info zona waktu, yang kedua tidak
Tony
1
Saya telah memperbarui jawaban untuk memperhitungkan zona waktu dan mengganti variasi kedua. @Tony sangat bagus menangkap, mereka sebenarnya sama-sama rentan terhadap hilangnya info zona waktu jika dilihat lebih dekat. DateTime.new(now.year, now.month, now.day, 0,0,0, now.zone) != now.to_date.to_datetime
ashoda
TIMEZONE: Dapat diubah dengan kata kunci offset dalam argumen hash: DateTime.now.change ({hour: 0, min: 0, sec: 0 offset: '+02: 00'})
Ekkstein
34

Tidak apa-apa, mengerti. Perlu membuat DateTime baru:

DateTime.new(now.year, now.month, now.day, 0, 0, 0, 0)
Jesse Aldridge
sumber
6
Jawaban yang bagus. Hanya ingin menambahkan bahwa angka nol tersebut mewakili JAM, MENIT, KEDUA dan OFFSET (zona waktu) dalam urutan itu.
d_ethier
3
Setelah gagal membuat ini bekerja, saya mempelajarinya dengan: DateTime.new(Time.now.year, Time.now.month, Time.now.day, 0, 0, 0)ini berhasil.
Ekkstein
2
Jangan lupa: now = DateTime.now
Abel
1
Juga untuk dicatat bahwa argumen terakhir harus berupa string zona waktu misalnya ("- 0700") untuk MST, bukan bilangan bulat
Donavan White
2
Kecuali jika Anda berurusan dengan tanggal-tanggal bersejarah, JANGAN GUNAKAN DateTime. Anda akan mendapatkan masalah yang mengganggu jika Anda tinggal di negara yang memiliki waktu musim panas seperti Inggris. Lihat penjelasannya di sini. gist.github.com/pixeltrix/e2298822dd89d854444b
fatuhoku
5

Peringatan : DateTime.now.midnightdan DateTime.now.beginning_of_daykembalikan nilai yang sama (yang merupakan jam nol pada hari ini - tengah malam tidak menghasilkan 24:00:00 seperti yang Anda harapkan dari namanya).

Jadi saya menambahkan ini sebagai info lebih lanjut bagi siapa saja yang mungkin menggunakan jawaban yang diterima untuk menghitung tengah malam x hari di masa mendatang.

Misalnya, uji coba gratis 14 hari yang akan berakhir pada tengah malam pada hari ke-14:

DateTime.now.midnight + 14.days

adalah pagi hari ke-14, yang sama dengan percobaan 13,5 hari (x adalah sisa sisa hari - jika sekarang siang, maka percobaan 13,5 hari).

Anda sebenarnya perlu melakukan ini:

DateTime.now.midnight + 15.days

untuk mendapatkan tengah malam pada hari ke-14.

Untuk alasan ini saya selalu lebih suka menggunakan beginning_of_day, karena itu adalah 00:00:00. Menggunakan tengah malam bisa menyesatkan / disalahpahami.

rmcsharry
sumber
1

Jika Anda menggunakannya, pertimbangkan untuk menginstal permata ini untuk meningkatkan penguraian tanggal:

https://github.com/mojombo/chronic

require 'chronic'

Chronic.parse('this 0:00')
wizztjh.dll
sumber
Saya tidak yakin mengapa jawaban ini ditandai sebagai benar. Itu tidak benar-benar menjawab pertanyaan itu. Saya tahu cara mengurai string menjadi tanggal. Tapi saya ingin tahu bagaimana mengubah bagian tertentu dari contoh tanggal tertentu. Misalnya tahun. Ada ide? Di Jawa saya hanya akan menggunakan setter untuk tahun. Tapi itu tidak berfungsi di Ruby :-(
Robert Reiz
1
Saya tidak mempercayai permata kronis lagi. Ini benar-benar ketinggalan jaman. Saya mengalami masalah dalam mengurai tanggal-waktu saat menjalankan di aplikasi saya yang mengakibatkan hilangnya bisnis.
Vijay Meena