Semua pertanyaan lain pada jaringan SE berurusan dengan skenario di mana salah satu tanggal diasumsikan now
( Q ) atau di mana hanya tanggal yang ditentukan ( Q ).
Yang ingin saya lakukan adalah memberikan tanggal dan waktu, lalu kurangi waktu dari itu.
Inilah yang saya coba pertama kali:
date -d "2018-12-10 00:00:00 - 5 hours - 20 minutes - 5 seconds"
Ini menghasilkan 2018-12-10 06:39:55
- Ini menambahkan 7 jam. Kemudian kurangi 20:05 menit.
Setelah membaca man
dan info
halaman date
, saya pikir saya sudah memperbaikinya dengan ini:
date -d "2018-12-10T00:00:00 - 5 hours - 20 minutes - 5 seconds"
Tapi hasilnya sama. Dari mana bahkan mendapat 7 jam dari?
Saya mencoba kencan lain juga karena saya pikir mungkin kami memiliki 7200 detik kabisat pada hari itu, siapa tahu lol. Namun hasilnya sama.
Beberapa contoh lagi:
$ date -d "2018-12-16T00:00:00 - 24 hours" +%Y-%m-%d_%H:%M:%S
2018-12-17_02:00:00
$ date -d "2019-01-19T05:00:00 - 2 hours - 5 minutes" +%Y-%m-%d_%H:%M:%S
2019-01-19_08:55:00
Tapi di sini menjadi menarik. Jika saya menghilangkan waktu pada input, itu berfungsi dengan baik:
$ date -d "2018-12-16 - 24 hours" +%Y-%m-%d_%H:%M:%S
2018-12-15_00:00:00
$ date -d "2019-01-19 - 2 hours - 5 minutes" +%Y-%m-%d_%H:%M:%S
2019-01-18_21:55:00
$ date --version
date (GNU coreutils) 8.30
Apa yang saya lewatkan?
Pembaruan: Saya telah menambahkan Z
di akhir, dan itu mengubah perilaku:
$ date -d "2019-01-19T05:00:00Z - 2 hours" +%Y-%m-%d_%H:%M:%S
2019-01-19_04:00:00
Saya masih bingung. Tidak banyak tentang ini di halaman info GNU tentang tanggal.
Saya menduga ini adalah masalah zona waktu, tetapi mengutip The Calendar Wiki pada ISO 8601 :
Jika tidak ada informasi hubungan UTC diberikan dengan representasi waktu, waktu diasumsikan dalam waktu lokal.
Itulah yang saya inginkan. Waktu lokal saya diatur dengan benar juga. Saya tidak yakin mengapa kencan akan mengacaukan zona waktu sama sekali dalam kasus sederhana ini tentang saya menyediakan suatu waktu dan ingin mengurangi sesuatu darinya. Bukankah seharusnya mengurangi jam dari string tanggal terlebih dahulu? Bahkan jika itu mengubahnya menjadi kencan pertama dan kemudian melakukan pengurangan, jika saya meninggalkan pengurangan saya mendapatkan apa yang saya inginkan:
$ date -d "2019-01-19T05:00:00" +%Y-%m-%d_%H:%M:%S
2019-01-19_05:00:00
Jadi JIKA ini benar-benar masalah zona waktu, dari mana datangnya kegilaan itu?
Jawaban:
Contoh terakhir itu seharusnya menjelaskan hal-hal untuk Anda: zona waktu .
Karena outputnya jelas bervariasi berdasarkan zona waktu, saya menduga beberapa default yang tidak jelas diambil untuk string waktu tanpa zona waktu yang ditentukan. Menguji beberapa nilai, tampaknya UTC-05: 00 , meskipun saya tidak yakin apa itu.
Ini hanya digunakan saat melakukan aritmatika tanggal.
Tampaknya masalah di sini adalah bahwa
- 2 hours
ini tidak diambil sebagai aritmatika, tetapi sebagai sebuah specifier zona waktu :Jadi, tidak hanya tidak ada aritmatika yang dilakukan, tampaknya ada
penghematan siang haripenyesuaian waktu 1 jam pada waktu itu, yang mengarah ke waktu yang agak tidak masuk akal bagi kita.Ini juga berlaku untuk tambahan:
Debugging sedikit lebih, penguraian tampaknya menjadi:
2019-01-19T05:00:00 - 2
(-2
menjadi zona waktu), danhours
(= 1 jam), dengan tambahan tersirat. Menjadi lebih mudah untuk melihat jika Anda menggunakan menit sebagai gantinya:Jadi, well, tanggal aritmatika sedang dilakukan, hanya saja bukan yang kita minta. ¯ \ (ツ) / ¯
sumber
TZ=UTC date -d "2019-01-19T05:00:00Z - 2 hours" +%Y-%m-%d_%H:%M:%S
vsTZ=UTC date -d "2019-01-19T05:00:00 - 2 hours" +%Y-%m-%d_%H:%M:%S
)date
, sesuai standar ISO 8601, jika tidak ada zona waktu yang disediakan, waktu lokal (zona) harus diasumsikan, yang dalam kasus operasi aritmatika, bukan. Masalah yang sangat aneh bagi saya.- 2 hours
diambil sebagai penentu zona waktu di sini.--debug
opsi kencan ! Penjelasan yang bagus.Ini berfungsi dengan benar ketika Anda mengonversi tanggal input ke ISO 8601 terlebih dahulu:
sumber
date
akan mengacaukan ini tanpa pengurangan yang diberikan, zona waktu dibiarkan tidak tersentuh dan semuanya seperti yang diharapkan juga tanpa harus memasok apa pun informasi zona waktu atau konversi.date -I
juga menampilkan penentu zona waktu (mis.2018-12-10T00:00:00+02:00
) Yang memperbaiki masalah yang dijelaskan dalam jawabanTLDR: Ini bukan bug. Anda baru saja menemukan salah satu perilaku yang halus namun terdokumentasi
date
. Saat melakukan aritmatika waktudate
, gunakan format mandiri zona waktu (seperti waktu Unix) atau baca dengan cermat dokumentasi untuk mengetahui cara menggunakan perintah ini dengan benar.GNU
date
menggunakan pengaturan sistem Anda (TZ
variabel lingkungan atau, jika tidak disetel, default sistem) untuk menentukan zona waktu dari tanggal yang diumpankan dengan opsi-d
/--date
dan tanggal yang dilaporkan oleh+format
argumen. The--date
pilihan juga memungkinkan Anda mengabaikan zona waktu untuk opsi-argumen sendiri tetapi tidak mengesampingkan zona waktu+format
.Itulah akar kebingungan, IMHO.Mengingat zona waktu saya adalah UTC-6, bandingkan perintah berikut:
Yang pertama menggunakan zona waktu saya untuk keduanya
-d
dan+format
. Yang kedua menggunakan UTC untuk-d
tetapi zona waktu saya untuk+format
. Yang ketiga menggunakan UTC untuk keduanya.Sekarang, bandingkan operasi sederhana berikut:
Bahkan jika waktu Unix mengatakan hal yang sama kepada saya, waktu "Normal" berbeda karena zona waktu saya sendiri.
Jika saya ingin melakukan operasi yang sama tetapi hanya menggunakan zona waktu saya:
sumber
-08:00
), cukup tambahkan itu untuk memasukkan waktu-tanggal ... tidak ada hal lain yang perlu diutak-atik. Contoh:date -d '2019-02-28 14:05:36-08:00 +2 days 4 hours 3 seconds' +'local: %F %T'
beri lokal: 2019-03-02 18:05:36+format
argumen. Misalnya, pada sistem saya, perintah yang sama output:local: 2019-03-02 20:05:39
(jika saya menambahkan%:z
untuk+format
, menjadi jelas bahwa info yang benar dan perbedaan tersebut adalah karena zona waktu).-d
dan+format
atau waktu Unix, seperti yang saya katakan dalam jawaban, untuk menghindari hasil yang tidak terduga.GNU
date
mendukung aritmatika tanggal sederhana, meskipun perhitungan waktu seperti yang ditunjukkan dalam jawaban @sudodus terkadang lebih jelas (dan lebih portabel).Penggunaan +/- ketika tidak ada zona waktu yang ditentukan dalam stempel waktu memicu upaya untuk mencocokkan zona waktu berikutnya, sebelum yang lainnya diuraikan.
Ini salah satu cara untuk melakukannya, gunakan "lalu" daripada "-":
atau
(Meskipun Anda tidak dapat secara sewenang-wenang menggunakan "Z", itu berfungsi di zona saya, tetapi itu menjadikannya cap waktu zona UTC / GMT - gunakan zona Anda sendiri, atau% z /% Z dengan menambahkan
${TZ:-$(date +%z)}
ke stempel waktu sebagai gantinya.)Menambahkan syarat waktu tambahan dari formulir ini sesuaikan waktu:
Banyak penyesuaian kompleks, dalam urutan apa pun, dapat digunakan (meskipun istilah relatif dan variabel seperti "14 minggu maka hari Senin terakhir" meminta masalah ;-)
(Ada beartrap kecil lain di sini juga,
date
akan selalu memberikan tanggal yang valid, jadidate -d "2019-01-31 1 month"
berikan 2019-03-03, seperti halnya "bulan depan")Mengingat beragamnya format waktu dan tanggal yang didukung, penguraian zona waktu menjadi ceroboh: itu bisa berupa sufiks tunggal atau multi-huruf, satu jam atau satu jam: offset menit, nama "America / Denver" (atau bahkan nama file) dalam kasus
TZ
variabel).Anda
2018-12-10T00:00:00
versi tidak bekerja karena "T" hanya pembatas, tidak zona waktu, menambahkan "Z" di akhir membuat pekerjaan (tunduk kebenaran zona dipilih) seperti yang diharapkan juga.Lihat: https://www.gnu.org/software/tar/manual/html_node/Date-input-formats.html dan di bagian tertentu 7.7.
sumber
date -d "2018-12-10 00:00:00 now -5 hours
atautoday
atau0 hour
bukannyanow
, apa pun yang memberi tahudate
bahwa token setelah waktu tersebut bukan offset zona waktu.Solusi ini mudah dimengerti, tetapi sedikit lebih rumit, jadi saya menunjukkannya sebagai shellscript.
date
baris perintah terakhirShellscript:
sumber