Detik
Untuk mengukur waktu yang berlalu (dalam detik) kita perlu:
- bilangan bulat yang mewakili hitungan detik yang berlalu dan
- cara untuk mengkonversi bilangan bulat tersebut ke format yang dapat digunakan.
Nilai integer detik yang berlalu:
Konversikan bilangan bulat tersebut ke format yang dapat digunakan
Bash internal printf
dapat melakukannya secara langsung:
$ TZ=UTC0 printf '%(%H:%M:%S)T\n' 12345
03:25:45
demikian pula
$ elapsedseconds=$((12*60+34))
$ TZ=UTC0 printf '%(%H:%M:%S)T\n' "$elapsedseconds"
00:12:34
tetapi ini akan gagal untuk durasi lebih dari 24 jam, karena kami benar-benar mencetak waktu jam dinding, bukan durasi:
$ hours=30;mins=12;secs=24
$ elapsedseconds=$(( ((($hours*60)+$mins)*60)+$secs ))
$ TZ=UTC0 printf '%(%H:%M:%S)T\n' "$elapsedseconds"
06:12:24
Untuk pecinta detail, dari bash-hackers.org :
%(FORMAT)T
menghasilkan string tanggal-waktu yang dihasilkan dari menggunakan FORMAT sebagai string format untuk strftime(3)
. Argumen terkait adalah jumlah detik sejak Epoch , atau -1 (waktu saat ini) atau -2 (waktu startup shell). Jika tidak ada argumen yang sesuai yang diberikan, waktu saat ini digunakan sebagai standar.
Jadi, Anda mungkin ingin menelepon di textifyDuration $elpasedseconds
mana saja textifyDuration
implementasi lain dari pencetakan durasi:
textifyDuration() {
local duration=$1
local shiff=$duration
local secs=$((shiff % 60)); shiff=$((shiff / 60));
local mins=$((shiff % 60)); shiff=$((shiff / 60));
local hours=$shiff
local splur; if [ $secs -eq 1 ]; then splur=''; else splur='s'; fi
local mplur; if [ $mins -eq 1 ]; then mplur=''; else mplur='s'; fi
local hplur; if [ $hours -eq 1 ]; then hplur=''; else hplur='s'; fi
if [[ $hours -gt 0 ]]; then
txt="$hours hour$hplur, $mins minute$mplur, $secs second$splur"
elif [[ $mins -gt 0 ]]; then
txt="$mins minute$mplur, $secs second$splur"
else
txt="$secs second$splur"
fi
echo "$txt (from $duration seconds)"
}
Tanggal GNU.
Untuk mendapatkan waktu yang diformat, kita harus menggunakan alat eksternal (tanggal GNU) dalam beberapa cara untuk mendapatkan hingga hampir satu tahun dan termasuk Nanoseconds.
Matematika di dalam tanggal.
Tidak perlu untuk aritmatika eksternal, lakukan semuanya dalam satu langkah di dalam date
:
date -u -d "0 $FinalDate seconds - $StartDate seconds" +"%H:%M:%S"
Ya, ada 0
nol dalam string perintah. Itu dibutuhkan.
Itu dengan asumsi Anda bisa mengubah date +"%T"
perintah ke date +"%s"
perintah sehingga nilai akan disimpan (dicetak) dalam hitungan detik.
Perhatikan bahwa perintah ini terbatas pada:
- Nilai positif
$StartDate
dan $FinalDate
detik.
- Nilai dalam
$FinalDate
lebih besar (nanti dalam waktu) daripada $StartDate
.
- Perbedaan waktu lebih kecil dari 24 jam.
- Anda menerima format output dengan Jam, Menit dan Detik. Sangat mudah diubah.
- Dapat diterima untuk menggunakan waktu -u UTC. Untuk menghindari "DST" dan koreksi waktu setempat.
Jika Anda harus menggunakan 10:33:56
string, yah, ubah saja menjadi detik,
juga, kata detik dapat disingkat menjadi detik:
string1="10:33:56"
string2="10:36:10"
StartDate=$(date -u -d "$string1" +"%s")
FinalDate=$(date -u -d "$string2" +"%s")
date -u -d "0 $FinalDate sec - $StartDate sec" +"%H:%M:%S"
Perhatikan bahwa konversi waktu detik (seperti yang disajikan di atas) relatif terhadap awal hari "ini" (Hari ini).
Konsepnya dapat diperluas hingga nanodetik, seperti ini:
string1="10:33:56.5400022"
string2="10:36:10.8800056"
StartDate=$(date -u -d "$string1" +"%s.%N")
FinalDate=$(date -u -d "$string2" +"%s.%N")
date -u -d "0 $FinalDate sec - $StartDate sec" +"%H:%M:%S.%N"
Jika diharuskan untuk menghitung perbedaan waktu yang lebih lama (hingga 364 hari), kami harus menggunakan awal (beberapa) tahun sebagai referensi dan nilai format %j
(jumlah hari dalam tahun):
Mirip dengan:
string1="+10 days 10:33:56.5400022"
string2="+35 days 10:36:10.8800056"
StartDate=$(date -u -d "2000/1/1 $string1" +"%s.%N")
FinalDate=$(date -u -d "2000/1/1 $string2" +"%s.%N")
date -u -d "2000/1/1 $FinalDate sec - $StartDate sec" +"%j days %H:%M:%S.%N"
Output:
026 days 00:02:14.340003400
Sayangnya, dalam hal ini, kita perlu secara manual mengurangi 1
SATU dari jumlah hari. Perintah tanggal melihat hari pertama tahun ini sebagai 1. Tidak terlalu sulit ...
a=( $(date -u -d "2000/1/1 $FinalDate sec - $StartDate sec" +"%j days %H:%M:%S.%N") )
a[0]=$((10#${a[0]}-1)); echo "${a[@]}"
Penggunaan jumlah detik yang lama adalah valid dan didokumentasikan di sini:
https://www.gnu.org/software/coreutils/manual/html_node/Examples-of-date.html#Examples-of-date
Tanggal kotak bus
Alat yang digunakan pada perangkat yang lebih kecil (executable yang sangat kecil untuk diinstal): Busybox.
Buat tautan ke busybox bernama tanggal:
$ ln -s /bin/busybox date
Gunakan kemudian dengan memanggil ini date
(letakkan di direktori PATH termasuk).
Atau buat alias seperti:
$ alias date='busybox date'
Tanggal Busybox memiliki opsi yang bagus: -D untuk menerima format waktu input. Itu membuka banyak format untuk digunakan sebagai waktu. Menggunakan opsi -D kita dapat mengonversi waktu 10:33:56 secara langsung:
date -D "%H:%M:%S" -d "10:33:56" +"%Y.%m.%d-%H:%M:%S"
Dan seperti yang Anda lihat dari output Komando di atas, hari itu dianggap "hari ini". Untuk mendapatkan waktu mulai dari zaman:
$ string1="10:33:56"
$ date -u -D "%Y.%m.%d-%H:%M:%S" -d "1970.01.01-$string1" +"%Y.%m.%d-%H:%M:%S"
1970.01.01-10:33:56
Tanggal Busybox bahkan dapat menerima waktu (dalam format di atas) tanpa -D:
$ date -u -d "1970.01.01-$string1" +"%Y.%m.%d-%H:%M:%S"
1970.01.01-10:33:56
Dan format output bahkan bisa menjadi detik sejak zaman.
$ date -u -d "1970.01.01-$string1" +"%s"
52436
Untuk kedua kali, dan sedikit matematika bash (busybox belum dapat melakukan matematika, belum):
string1="10:33:56"
string2="10:36:10"
t1=$(date -u -d "1970.01.01-$string1" +"%s")
t2=$(date -u -d "1970.01.01-$string2" +"%s")
echo $(( t2 - t1 ))
Atau diformat:
$ date -u -D "%s" -d "$(( t2 - t1 ))" +"%H:%M:%S"
00:02:14
time
perintah?