A = "2002-20-10"
B = "2003-22-11"
İki tarih arasındaki gün farkı nasıl bulunur?
A = "2002-20-10"
B = "2003-22-11"
İki tarih arasındaki gün farkı nasıl bulunur?
Yanıtlar:
GNU'nuz varsa, date
rastgele bir tarihin temsilini yazdırmanıza izin verir ( -d
isteğe bağlı). Bu durumda tarihleri EPOCH'tan itibaren saniyeye dönüştürün, çıkarın ve 24 * 3600'e bölün.
Veya taşınabilir bir yola mı ihtiyacınız var?
echo "( `date -d $B +%s` - `date -d $A +%s`) / (24*3600)" | bc -l
Bash yolu - tarihleri% y% m% d biçimine dönüştürün ve sonra bunu doğrudan komut satırından yapabilirsiniz:
echo $(( ($(date --date="031122" +%s) - $(date --date="021020" +%s) )/(60*60*24) ))
%y%m%d
formatta olması gerekmez . Örneğin gnu tarihi %Y-%m-%d
, OP'nin kullandığı biçimi kabul edecektir . Genel olarak, ISO-8601 iyi bir seçimdir (ve OP'nin formatı böyle bir formattır). 2 basamaklı biçimlerden kaçınılması daha iyidir.
days_diff=$(( (`date -d $B +%s` - `date -d "00:00" +%s`) / (24*3600) ))
. $days_diff
bunun bir tamsayı olacağını unutmayın (yani ondalık sayılar yok)
date
kurulu modele bağlıdır . GNU için çalışıyor date
. POSIX ile çalışmaz date
. Bu muhtemelen çoğu okuyucu için bir sorun değildir, ancak kayda değer.
%Y-%m-%d
August 2.0
October 2.0
%Y-%d-%m
tl; dr
date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s)) / (60*60*24) ))
Dikkat et! Buradaki bash çözümlerinin çoğu, yaz saati uygulamasının başladığı tarihi kapsayan tarih aralıkları için bozulmuştur (uygun olduğu yerlerde). Bunun nedeni, $ ((math)) yapısının, sonuçta elde edilen değer üzerinde bir 'kat' / kesme işlemi yapıp yalnızca tam sayıyı döndürmesidir. Göstereyim:
DST bu yıl ABD'de 8 Mart'ta başladı, bu nedenle aşağıdakileri kapsayan bir tarih aralığı kullanalım:
start_ts=$(date -d "2015-03-05" '+%s')
end_ts=$(date -d "2015-03-11" '+%s')
Çift parantez ile ne elde ettiğimize bir bakalım:
echo $(( ( end_ts - start_ts )/(60*60*24) ))
"5" değerini döndürür.
Bunu daha doğru bir şekilde 'bc' kullanarak yapmak bize farklı bir sonuç verir:
echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc
'5.95' değerini döndürür - eksik 0.05, DST geçişinden itibaren kayıp saattir.
Peki bu nasıl doğru yapılmalıdır?
Bunun yerine şunu kullanmanızı öneririm:
printf "%.0f" $(echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc)
Burada 'printf', 'bc' ile hesaplanan daha doğru sonucu yuvarlayarak bize '6' olan doğru tarih aralığını verir.
Düzenleme: Son zamanlarda kullandığım @ hank-schultz'dan gelen bir yorumda cevabı vurgulamak:
date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s) )/(60*60*24) ))
Bu, aynı zamanda, her zaman daha sonraktan önceki tarihi çıkardığınız sürece, artık saniye güvenli olmalıdır, çünkü artık saniyeler sadece farkı artıracaktır - kesme işlemi, doğru sonuca etkili bir şekilde yuvarlar.
echo $(( ($(date --date="2015-03-11 UTC" +%s) - $(date --date="2015-03-05 UTC" +%s) )/(60*60*24) ))
5 yerine 6 döndürür.
Ve pitonda
$python -c "from datetime import date; print (date(2003,11,22)-date(2002,10,20)).days"
398
bash
ve shell
ben biz * Nix sistemi hakkında konuşuyor varsayabiliriz düşünüyorum böylece. Bu tür sistemler içinde echo
ve date
güvenilir bir şekilde mevcuttur, ancak python yoktur.
Bu benim için çalışıyor:
A="2002-10-20"
B="2003-11-22"
echo $(( ($(date -d $B +%s) - $(date -d $A +%s)) / 86400 )) days
Baskılar
398 days
Ne oluyor?
date -d
Zaman dizelerini işlemek için kullanındate %s
1970'den beri zaman dizelerini saniyeye dönüştürmek için kullanın (unix epoche)Sisteminizde -d seçeneği çalışıyorsa, işte bunu yapmanın başka bir yolu. Yılda 365 gün düşündüğüm için artık yılları hesaba katmayacağına dair bir uyarı var.
date1yrs=`date -d "20100209" +%Y`
date1days=`date -d "20100209" +%j`
date2yrs=`date +%Y`
date2days=`date +%j`
diffyr=`expr $date2yrs - $date1yrs`
diffyr2days=`expr $diffyr \* 365`
diffdays=`expr $date2days - $date1days`
echo `expr $diffyr2days + $diffdays`
Rahatınız için MAC OS X sürümü burada.
$ A="2002-20-10"; B="2003-22-11";
$ echo $(((`date -jf %Y-%d-%m $B +%s` - `date -jf %Y-%d-%m $A +%s`)/86400))
nJoy!
A="2002-20-10"; B="2003-22-11"
echo $(((`date -jf "%Y-%d-%m" "$B" +%s` - `date -jf "%Y-%d-%m" "$A" +%s`)/86400))
, yani hem biçimleri hem de değişkenleri çift tırnak içine %b %d, %Y
Jul 5, 2017
GNU tarihiniz olmasa bile, muhtemelen Perl'i yükleyeceksiniz:
use Time::Local;
sub to_epoch {
my ($t) = @_;
my ($y, $d, $m) = ($t =~ /(\d{4})-(\d{2})-(\d{2})/);
return timelocal(0, 0, 0, $d+0, $m-1, $y-1900);
}
sub diff_days {
my ($t1, $t2) = @_;
return (abs(to_epoch($t2) - to_epoch($t1))) / 86400;
}
print diff_days("2002-20-10", "2003-22-11"), "\n";
Bu, 398.041666666667
gün ışığından yararlanma nedeniyle 398 gün ve bir saat döndürür .
Soru beslememde geri geldi. Perl ile paketlenmiş bir modül kullanan daha kısa bir yöntem burada
days=$(perl -MDateTime -le '
sub parse_date {
@f = split /-/, shift;
return DateTime->new(year=>$f[0], month=>$f[2], day=>$f[1]);
}
print parse_date(shift)->delta_days(parse_date(shift))->in_units("days");
' $A $B)
echo $days # => 398
Mysql komutunu kullanma
$ echo "select datediff('2013-06-20 18:12:54+08:00', '2013-05-30 18:12:54+08:00');" | mysql -N
Sonuç: 21
NOT: Hesaplamada değerlerin yalnızca tarih bölümleri kullanılır.
Referans: http://dev.mysql.com/doc/refman/5.6/en/date-and-time-functions.html#function_datediff
İşte zsh kullanarak çalışma yaklaşımım. OSX'te test edildi:
# Calculation dates
## A random old date
START_DATE="2015-11-15"
## Today's date
TODAY=$(date +%Y-%m-%d)
# Import zsh date mod
zmodload zsh/datetime
# Calculate number of days
DIFF=$(( ( $(strftime -r %Y-%m-%d $TODAY) - $(strftime -r %Y-%m-%d $START_DATE) ) / 86400 ))
echo "Your value: " $DIFF
Sonuç:
Your value: 1577
Temel olarak, tarih dizimizi tekrar bir zaman damgasına dönüştürmek için strftime
reverse ( -r
) özelliğini kullanıyoruz ve ardından hesaplamamızı yapıyoruz.
Ruby'de başka bir olası çözüm sunacağım. Şimdiye kadarki en küçük ve en temiz görünen şey gibi görünüyor
A=2003-12-11
B=2002-10-10
DIFF=$(ruby -rdate -e "puts Date.parse('$A') - Date.parse('$B')")
echo $DIFF
date
veya bazı komut dosyası dili) ve dürüst olmak gerekirse Ruby'nin buraya gitmek için iyi bir yol olduğunu düşünüyorum . Bu çözüm çok kısadır ve standart olmayan kitaplıkları veya diğer bağımlılıkları kullanmaz. Aslında, Ruby'nin kurulu olma şansının, birinin GNU tarihinin kurulu olacağından daha yüksek olduğunu düşünüyorum.
Http://cfajohnson.com/shell/ssr/ssr-scripts.tar.gz adresindeki kabuk işlevlerini kullanın ; herhangi bir standart Unix kabuğunda çalışırlar.
date1=2012-09-22
date2=2013-01-31
. date-funcs-sh
_date2julian "$date1"
jd1=$_DATE2JULIAN
_date2julian "$date2"
echo $(( _DATE2JULIAN - jd1 ))
Http://cfajohnson.com/shell/ssr/08-The-Dating-Game.shtml adresindeki belgelere bakın.
unix üzerinde GNU tarihlerinin kurulu olması gerekir. Bash'den sapmanıza gerek yoktur. İşte sadece adımları göstermek için günleri dikkate alan gergin bir çözüm. basitleştirilebilir ve tam tarihlere uzatılabilir.
DATE=$(echo `date`)
DATENOW=$(echo `date -d "$DATE" +%j`)
DATECOMING=$(echo `date -d "20131220" +%j`)
THEDAY=$(echo `expr $DATECOMING - $DATENOW`)
echo $THEDAY
Bu, bir ayın yılın 1 / 12'si olduğunu varsayar:
#!/usr/bin/awk -f
function mktm(datespec) {
split(datespec, q, "-")
return q[1] * 365.25 + q[3] * 365.25 / 12 + q[2]
}
BEGIN {
printf "%d\n", mktm(ARGV[2]) - mktm(ARGV[1])
}
Bunu bir deneyin:
perl -e 'use Date::Calc qw(Delta_Days); printf "%d\n", Delta_Days(2002,10,20,2003,11,22);'
Oracle DB yedeklemelerini üçüncü bir diske manuel olarak yeniden senkronize ettiğimizi varsayalım. Daha sonra o diskteki eski yedeklemeleri silmek istiyoruz. İşte küçük bir bash betiği:
#!/bin/sh
for backup_dir in {'/backup/cmsprd/local/backupset','/backup/cmsprd/local/autobackup','/backup/cfprd/backupset','/backup/cfprd/autobackup'}
do
for f in `find $backup_dir -type d -regex '.*_.*_.*' -printf "%f\n"`
do
f2=`echo $f | sed -e 's/_//g'`
days=$(((`date "+%s"` - `date -d "${f2}" "+%s"`)/86400))
if [ $days -gt 30 ]; then
rm -rf $backup_dir/$f
fi
done
done
Dir'leri ve saklama süresini ("30 gün") ihtiyaçlarınıza göre değiştirin.
MacOS sierra için (belki Mac OS X yosemate'den),
Bir dosyadan dönem zamanını (1970'den saniye) almak ve bir var'a kaydetmek için:
old_dt=`date -j -r YOUR_FILE "+%s"`
Geçerli zamanın çağ zamanını öğrenmek için
new_dt=`date -j "+%s"`
İki dönemin üzerindeki farkı hesaplamak için
(( diff = new_dt - old_dt ))
Farkın 23 günden fazla olup olmadığını kontrol etmek için
(( new_dt - old_dt > (23*86400) )) && echo Is more than 23 days
echo $(date +%d/%h/%y) date_today
echo " The other date is 1970/01/01"
TODAY_DATE="1970-01-01"
BEFORE_DATE=$(date +%d%h%y)
echo "THE DIFFERNS IS " $(( ($(date -d $BEFORE_DATE +%s) - $(date -d $TODAY_DATE +%s)) )) SECOUND
bugün tarihinizi ve istediğiniz tarihten itibaren saniyenizi almak için kullanın. günlerle istiyorsanız sadece 86400 ile bölün
echo $(date +%d/%h/%y) date_today
echo " The other date is 1970/01/01"
TODAY_DATE="1970-01-01"
BEFORE_DATE=$(date +%d%h%y)
echo "THE DIFFERNS IS " $(( ($(date -d $BEFORE_DATE +%s) - $(date -d $TODAY_DATE +%s))/ 86400)) SECOUND