Alat di UNIX untuk mengurangi tanggal

22

Apakah ada alat di Solaris UNIX (jadi tidak ada alat GNU tersedia) untuk mengurangi tanggal? Saya tahu bahwa di Linux kami memiliki gawkyang dapat mengurangi satu tanggal dari yang lain. Tetapi dalam Solaris, maksimum yang kita miliki adalah nawk(ditingkatkan awk) yang tidak dapat melakukan perhitungan tanggal. Saya juga tidak bisa menggunakan perl.

Apakah ada cara untuk melakukan perhitungan tanggal seperti 20100909 - 20001010?

UPDATE: Apakah bcdapat melakukan perhitungan tanggal?

jyz
sumber
1
Lihat juga Cepat menghitung perbedaan tanggal , untuk saat tanggal GNU tersedia.
Gilles 'SANGAT berhenti menjadi jahat'

Jawaban:

10

Berikut ini adalah skrip awk yang baru saja saya tulis, harus berfungsi dengan awk POSIX. Anda harus mencoba versi Solaris; ingat bahwa ada dua versi Awk pada Solaris juga, satu di / bin dan satu di / usr / xpg4 / bin / awk (yang nawk, saya percaya).

BEGIN {
    daysofmonth["01"] = 0; daysofmonth["02"] = 31; daysofmonth["03"] = 59;
    daysofmonth["04"] = 90; daysofmonth["05"] = 120; daysofmonth["06"] = 151;
    daysofmonth["07"] = 181; daysofmonth["08"] = 212; daysofmonth["09"] = 243;
    daysofmonth["10"] = 273; daysofmonth["11"] = 304; daysofmonth["12"] = 334;
    fullday = 86400;
}
/[12][09][0-9][0-9][01][0-9][0123][0-9]/ {
    year = substr($0, 1, 4); month = substr($0, 5, 2); day = substr($0, 7, 2);
    date = ((year - 1970) * 365.25) + daysofmonth[month] + day - 1;
    if ((year % 4) == 0 && month > 2) { date = date + 1; }
    print date * fullday - (25200);
}
{}

Lewati string tanggal YYYYmmdd dan akan dikonversi ke jumlah detik sejak Zaman (dengan sedikit pemberian karena berada di batas hari). Maka Anda akan dapat mengurangi keduanya.

today=`echo 20110210 | awk -f convdate.awk`
then=`echo 20001231 | awk -f convdate.awk`
sincethen=`expr $today - $then`
Arcege
sumber
Saya memeriksa logika Anda dengan Oracle. Untuk beberapa tanggal tidak masalah, namun untuk itu menghasilkan angka float. Saya khawatir saya harus memotong ke bilangan bulat, bukan?
jyz
Desimal adalah sepersekian detik dan belum tentu diperlukan.
Arcege
Periode ini berakhir 20380119. Mengapa tidak menggunakan hari Julian tahun ini? Gandakan
jas-
13

Sayangnya, tidak ada utilitas baris perintah POSIX yang menyediakan aritmatika pada tanggal. date -ddan date +%smerupakan cara untuk pergi jika Anda memilikinya, tetapi itu adalah ekstensi GNU.

Ada peretasan yang ceroboh dengan touchpekerjaan semacam itu untuk memeriksa apakah suatu kencan setidaknya n hari di masa lalu:

touch -t 201009090000 stamp
if [ -n "$(find stamp -mtime +42)" ]; then ...

(Perhatikan bahwa kode ini dapat dimatikan oleh satu jika DST mulai atau berhenti dalam interval dan skrip berjalan sebelum 01:00).

Beberapa orang akhirnya menerapkan perpustakaan manipulasi tanggal di Bourne atau POSIX shell. Ada beberapa contoh dan tautan di FAQ comp.unix.shell .

Menginstal alat-alat GNU mungkin merupakan cara yang paling tidak menyakitkan.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
11

Saya akan mencoba menggunakan dateperintah yang merupakan bagian dari POSIX sehingga hampir di mana-mana. UPDATE: Sayangnya, tampaknya -d bukan bagian dari tanggal POSIX dan kemungkinan tidak ada pada Solaris. Jadi ini kemungkinan tidak akan menjawab pertanyaan OP.

d1=`date -d 20100909 +%s`
d2=`date -d 20001010 +%s`

Sekarang d1dan d2adalah bilangan bulat yang sesuai dengan detik sejak zaman unix. Jadi untuk mendapatkan perbedaan antara keduanya, kita kurangi ( $((d1-d2))dalam bash) dan terselubung ke unit apa pun yang kita inginkan. Hari adalah yang termudah:

echo "$(((d1-d2)/86400)) days"

Cara melakukan konversi kemungkinan akan berbeda jika Anda tidak memiliki bash. Cara yang paling portabel adalah dengan menggunakan expr( halaman manual posix expr ).

Steven D
sumber
ya ini tidak menjawab pertanyaan saya karena itu Solaris ... tapi terima kasih atas ide dan postingnya :)
jyz
8

Sebagai catatan, dateutils adalah upaya saya untuk menyediakan satu set alat portabel yang mencakup aritmatika tanggal. Contoh Anda sampai

ddiff -i '%Y%m%d' 20001010 20100909
=>
  3621

The -imenentukan format masukan.

hroptatyr
sumber
2
Paket ini luar biasa, dan ada di pustaka alam semesta Ubuntu (setidaknya untuk Trusty). Di sistem lain, saya bisa mengompilasinya dengan mudah dari awal. Sangat dianjurkan. Terima kasih banyak!
Robert Muil
Juga dikemas dalam Fedora dan dalam EPEL, untuk ekosistem RH.
mattdm
4

Perl kemungkinan akan diinstal, dan cukup mudah untuk mengambil modul dari CPAN , menginstalnya di direktori home Anda, dan merujuknya di program Anda. Dalam hal ini, modul Date :: Calc memiliki Delta_Dayssubrutin yang akan membantu.

glenn jackman
sumber
3

Tanggal GNU Wrt pada Solaris:

Saya mengatakan ini lagi:

Terlalu banyak Solaris SysAdmins bangga karena tidak menginstal paket resmi dari Sun (sekarang Oracle) yang membuat sistem Solaris "kompatibel dengan GNU" ketika mereka mengonfigurasi host baru. Mengalahkan saya mengapa.

Tanggal GNU luar biasa dan harus tersedia secara default pada host Solaris, IMHO.

Pada Solaris 10

Instal paket SFWcoreu dari CD Solaris Companion. Setelah menginstal Anda akan menemukan tanggal GNU di/opt/sfw/bin/date

Pada Solaris 11

Anda mungkin sudah memilikinya karena saya percaya itu adalah bagian dari instalasi standar. Namun itu dipanggil gdateuntuk membedakannya dari versi Sun tanggal.

Lakukan ini jika tidak diinstal:

pkg instal // solaris / file / gnu-coreutils
peterh
sumber
Terima kasih atas tipnya. Bisakah Anda memberi saya contoh cara menggunakannya? Jadi saya bisa meminta sysadmin untuk menginstalnya ...
jyz
Pada Solaris 11, itu akan dipasang sebagai baik /usr/bin/gdatedan /usr/gnu/bin/datesehingga Anda dapat memilih untuk menggunakannya baik dengan nama atau dengan pengaturan PATH $.
alanc
2

Jika Anda memiliki Python:

from time import *
date1 = strptime("20100909","%Y%m%d")
date2 = strptime("20001010","%Y%m%d")
diff = mktime(date1) - mktime(date2)
print repr(d/86400) + " days"

Anda menandai pertanyaan Anda "gawk" tetapi Anda mengatakan "tidak ada alat GNU". Gawk memiliki aritmatika tanggal.

Dijeda sampai pemberitahuan lebih lanjut.
sumber
Saya tidak melakukannya. Seseorang mengedit posting saya dan memberi tag "gawk" ...
jyz
2

python:

 from datetime import datetime as dt
 a = dt(2010, 9, 9)
 b = dt(2000, 10, 10)
 print (a - b).days
akira
sumber
1

1. Tentukan format date1 dan date2 dalam %jhari tahun (001..366)

user@linux:~$ date1=`date -d 20100909 +%j` 
user@linux:~$ date2=`date -d 20001010 +%j`

2. Hitung perbedaannya dengan expr

user@linux:~$ datediff=`expr $date2 - $date1`

3. Jadi, jawabannya adalah 32 hari

user@linux:~$ echo $datediff days
32 days
user@linux:~$ 

... atau Solusi Satu Lapisan

user@linux:~$ echo $(( $(date -d 20001010 +%j) - $(date -d 20100909 +%j) )) days
32 days
user@linux:~$ 

atau

user@linux:~$ expr $(date -d 20001010 +%j) - $(date -d 20100909 +%j)
32
user@linux:~$

atau

user@linux:~$ expr `date -d 20001010 +%j` - `date -d 20100909 +%j`
32
user@linux:~$ 
Sabrina
sumber
0

Dengan tanggal BSD untuk macOS:

echo "Quelle est la date de début ?"
read DATE_DE_DEBUT
echo "Quelle est la date de fin ?"
read DATE_DE_FIN
ANNEE=$(($(echo $DATE_DE_FIN | awk -F "/" '{print $3}')-$(echo $DATE_DE_DEBUT  | awk -F "/" '{print $3}')))

echo " "

if [[ $ANNEE > 0 ]]; then

for((annee=$ANNEE-1 ; $ANNEE ; annee++))

  do
  #echo $annee  
  for((mois=0 ; 13 - $mois ; mois++))
      do
  #   echo année:$annee mois:$mois
          for((jour=0 ; 32 - $jour ; jour++))
              do
 #             echo année:$annee mois:$mois jour:$jour
           TEST=$(date -Rjf"%d/%m/%Y" -v +"$annee"y -v +"$mois"m -v +"$jour"d $DATE_DE_DEBUT +"%d/%m/%Y")
           if [[ $TEST = $DATE_DE_FIN ]]; then
                  echo "Différence entre le $DATE_DE_DEBUT et le $DATE_DE_FIN";
                  echo "est de :";
                  echo "$annee année(s) $mois mois $jour jour(s)";
             exit 0;
            fi


          done 
  done
  done

 else 
 annee=0
 for((mois=0 ; 13 - $mois ; mois++))
      do
#      echo année:$annee mois:$mois
          for((jour=0 ; 32 - $jour ; jour++))
              do
              #echo année:$annee mois:$mois jour:$jour
              TEST=$(date -Rjf"%d/%m/%Y" -v +"$annee"y -v +"$mois"m -v +"$jour"d $DATE_DE_DEBUT +"%d/%m/%Y")
              if [[ $TEST = $DATE_DE_FIN ]]; then 
                      echo "Différence entre le $DATE_DE_DEBUT et le $DATE_DE_FIN";
                     echo "est de :";
                     echo "$annee année(s) $mois mois $jour jour(s)";
              exit 0;
              fi
              done
      done

fi
OlivierOR
sumber
0

Anda dapat menggunakan perpustakaan Velk awk untuk mengembalikan perbedaan dalam hitungan detik:

$ velour -n 'print t_utc(2010, 9, 9) - t_utc(2000, 10, 10)'
312854400

Atau hari:

$ velour -n 'print t_secday(t_utc(2010, 9, 9) - t_utc(2000, 10, 10))'
3621
Steven Penny
sumber