दो तिथियों के बीच के दिनों में अंतर कैसे पता करें?


84

ए = "2002-20-10"
बी = "2003-22-11"

दो तिथियों के बीच के दिनों में अंतर कैसे पता करें?


5
जैसा कि नीचे बताया गया है, लेकिन आपकी तारीखें गलत तरीके से गोल हैं: उन्हें yyyy-mm-dd होने की आवश्यकता है
पीटर फ्लिन

कई उत्तर (GNU-) तिथि के -d विकल्प का उपयोग करते हैं। मैं जोड़ना चाहता हूं कि यह POSIX तारीख का हिस्सा नहीं है, इसलिए कम पोर्टेबल है। जब तक ओपी सोलिस की तरह यूनिक्स वितरण पर काम नहीं कर रहा है, लेकिन केवल "आम लिनक्स", वह या वह अच्छा होना चाहिए। एक संबंधित टैग imho में मदद करेगा।
काडिज़

जवाबों:


34

यदि आपके पास जीएनयू है date, तो यह एक मनमाना तिथि ( -dविकल्प) के प्रतिनिधित्व को प्रिंट करने की अनुमति देता है । इस स्थिति में, दिनांक के बाद से सेकंड में परिवर्तित करें, घटाएँ और 24 * 3600 से विभाजित करें।

या आपको एक पोर्टेबल तरीका चाहिए?


1
@ नि: शुल्क: मेरा मानना ​​है कि इसे लागू करने की तारीखों को घटाने के लिए कोई पोर्टेबल तरीका नहीं है - यह मुश्किल नहीं है, ब्याज की एकमात्र चीज छलांग साल है। लेकिन आजकल हर कोई तारीखों को घटाना चाहता है, जैसा कि लगता है: unix.stackexchange.com/questions/1825/… :) पर एक नज़र डालें

15
आलसी के लिए, मुझे लगता है कि यह वही है जो user332325 का मतलब है:echo "( `date -d $B +%s` - `date -d $A +%s`) / (24*3600)" | bc -l
पाब्लो मेंडेस

2
इस संदर्भ में पोर्टेबल का क्या अर्थ है?
htellez

@htellez कुछ है जो कई प्लेटफार्मों (विंडोज़, लिनक्स आदि ..) पर काम करता है
सुमदु

इस उत्तर के आधार पर एक लाइनर को
कोसने के लिए

64

बैश तरीका - तिथियों को% y% m% d प्रारूप में परिवर्तित करें और फिर आप इसे सीधे कमांड लाइन से कर सकते हैं:

echo $(( ($(date --date="031122" +%s) - $(date --date="021020" +%s) )/(60*60*24) ))

9
यह जरूरी नहीं कि %y%m%dप्रारूप में तारीखें हों । उदाहरण के लिए, जीपी दिनांक का %Y-%m-%dउपयोग किए गए प्रारूप को स्वीकार करेगा । सामान्य तौर पर, ISO-8601 एक अच्छा विकल्प है (और ओपी का प्रारूप एक ऐसा प्रारूप है)। 2 अंकों के वर्षों वाले प्रारूप बेहतर हैं।
mc0e

2
आज से अंतर के लिए , एक का उपयोग करना पसंद कर सकते हैं days_diff=$(( (`date -d $B +%s` - `date -d "00:00" +%s`) / (24*3600) ))। ध्यान दें कि $days_diffएक पूर्णांक (यानी कोई दशमलव नहीं) होगा
जूलियन

1
यह dateस्थापित के संस्करण पर निर्भर है। यह जीएनयू के लिए काम करता है date। यह POSIX के साथ काम नहीं करता है date। यह संभवतः अधिकांश पाठकों के लिए समस्या नहीं है, लेकिन यह ध्यान देने योग्य है।
mc0e

यदि आप वास्तव में POSIX पोर्टेबिलिटी चाहते हैं, तो इसे देखें: unix.stackexchange.com/a/7220/43835
mc0e

1
बस भ्रम से निपटने के लिए: ओपी का प्रारूप तब तक नहीं है %Y-%m-%d , जब तक हम परिचय नहीं करते हैं August 2.0और October 2.0ओपी का प्रारूप है %Y-%d-%m। प्रासंगिक xkcd: xkcd.com/1179
कंफ़ेद्दी

22

tl; डॉ

date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s)) / (60*60*24) ))

ध्यान रहे! यहां कई बैश समाधान डेट रेंज के लिए टूट गए हैं, जो कि दिन के उजाले की बचत के समय (जहां लागू हो) शुरू होने की तारीख को बढ़ाते हैं। इसका कारण यह है कि $ ((गणित)) का निर्माण परिणामी मूल्य पर एक 'फ्लोर' / ट्रंकेशन ऑपरेशन करता है, जिससे केवल पूरी संख्या लौटती है। मुझे उदाहरण दें:

DST की शुरुआत इस साल 8 मार्च को अमेरिका में हुई, तो चलिए एक तिथि सीमा का उपयोग करते हैं:

start_ts=$(date -d "2015-03-05" '+%s')
end_ts=$(date -d "2015-03-11" '+%s')

आइए देखें कि हमें डबल कोष्ठक के साथ क्या मिलता है:

echo $(( ( end_ts - start_ts )/(60*60*24) ))

लौटता है '5'।

अधिक सटीकता के साथ 'बीसी' का उपयोग करने से हमें एक अलग परिणाम मिलता है:

echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc

'5.95' लौटाता है - लापता 0.05 डीएसटी स्विचओवर से खोया हुआ घंटा है।

तो इसे सही तरीके से कैसे किया जाना चाहिए?
मैं इसके बजाय इसका उपयोग करने का सुझाव दूंगा:

printf "%.0f" $(echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc)

यहाँ, 'printf' 'bc' द्वारा परिकलित अधिक सटीक परिणाम को पूर्ण करता है, जिससे हमें '6' की सही तिथि सीमा मिलती है।

संपादित करें: नीचे दिए गए @ हांक-स्कुल्ट्ज़ की एक टिप्पणी में उत्तर को उजागर करना, जिसका मैं हाल ही में उपयोग कर रहा हूं:

date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s) )/(60*60*24) ))

यह भी दूसरी सुरक्षित छलांग होनी चाहिए जब तक कि आप हमेशा पहले की तारीख को बाद में एक से घटाते हैं, क्योंकि लीप सेकंड केवल कभी-कभी अंतर में जोड़ देगा - ट्रंकेशन प्रभावी रूप से सही परिणाम के लिए गोल हो जाता है।


6
यदि इसके बजाय, आप शुरू और अंत दोनों के लिए समय-क्षेत्र निर्दिष्ट करते हैं (और सुनिश्चित करें कि वे समान हैं), तो आपको भी अब यह समस्या नहीं है, जैसे:: echo $(( ($(date --date="2015-03-11 UTC" +%s) - $(date --date="2015-03-05 UTC" +%s) )/(60*60*24) )), जो 6 के बदले 6 देता है।
हांक शुल्त्स

1
आह, उत्तरदाताओं में से एक ने वैरिएंट में दूसरों द्वारा दोहराए गए मूल समाधान की अशुद्धियों के बारे में सोचा। थम्स अप! लीप सेकंड के बारे में कैसे? यह लीप-सेकंड-सेफ है? सॉफ्टवेयर की मिसालें हैं जो एक- दिन के परिणाम से वापस आ जाती हैं, यदि निश्चित समय पर चलती हैं, तो लीप सेकंड से जुड़ी समस्याओं को दूर करें
स्टीफन गौरीचॉन

Woops, "गलत" अभिकलन जो आप उदाहरण के रूप में देते हैं, सही ढंग से 6 यहाँ लौटाता है (Ubuntu 15.04 AMD64, GNU दिनांक संस्करण 8.23)। शायद आपका उदाहरण टाइमजोन-निर्भर है? मेरा समय क्षेत्र "यूरोप / पेरिस" है।
स्टीफन गौरिचोन

MSYS पर GNU दिनांक 2.0 के साथ "गलत" अभिकलन के लिए समान परिणाम, वही टाइमज़ोन।
स्टीफन गौरिचोन

1
@ StéphaneGourichon, 29 मार्च 2015 को आपके समयक्षेत्र के दिन के उजाले की बचत में बदलाव हुआ है - इसलिए एक तिथि सीमा का प्रयास करें जिसमें यह शामिल है।
evan_b

21

और अजगर में

$python -c "from datetime import date; print (date(2003,11,22)-date(2002,10,20)).days"
398

2
@mouviciel वास्तव में नहीं। पायथन हमेशा मौजूद नहीं होता है।
mc0e

1
@ उस संदर्भ में mc0e, कुछ भी हमेशा मौजूद नहीं है
सुमदु

5
@ ओनबिस ने ओपी को निर्दिष्ट टैग के रूप में bashऔर shell, इसलिए मुझे लगता है कि हम यह मान सकते हैं कि हम एक * निक्स प्रणाली के बारे में बात कर रहे हैं। ऐसी प्रणालियों के भीतर, echoऔर dateमज़बूती से मौजूद हैं, लेकिन अजगर नहीं है।
mc0e

2
@ mc0e हाँ जो समझ में आता है। हालांकि, python2 अधिकांश * nix सिस्टम में उपलब्ध है, जब यह कम-अंत वाले उपकरणों (एम्बेडेड आदि) की बात आती है, तो हमें केवल प्राथमिक उपकरणों के साथ ही जीवित रहना होगा।
सुमुदु

13

यह मेरे लिए काम करता है:

A="2002-10-20"
B="2003-11-22"
echo $(( ($(date -d $B +%s) - $(date -d $A +%s)) / 86400 )) days

प्रिंटों

398 days

क्या हो रहा है?

  1. A और B में मान्य समय स्ट्रिंग प्रदान करें
  2. उपयोग date -dसमय के तार को संभालने के लिए
  3. date %s1970 के बाद से समय स्ट्रिंग्स को सेकंड में बदलने के लिए उपयोग करें (यूनिक्स एपोचे)
  4. बैश पैरामीटर विस्तार का उपयोग करेंसेकंड को घटाने के लिए का
  5. दिन के रूप में अंतर प्राप्त करने के लिए प्रति दिन (86400 = 60 * 60 * 24) सेकंड से विभाजित करें
  6. ! डीएसटी को ध्यान में नहीं रखा गया है! इस उत्तर को unix.stackexchange पर देखें !

7

यदि विकल्प -d आपके सिस्टम में काम करता है, तो इसे करने का दूसरा तरीका है। वहाँ एक चेतावनी है कि यह लीप वर्षों के लिए जिम्मेदार नहीं होगा क्योंकि मैंने प्रति वर्ष 365 दिन माना है।

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`

7

यहाँ आपकी सुविधा के लिए MAC OS X संस्करण है।

$ A="2002-20-10"; B="2003-22-11";
$ echo $(((`date -jf %Y-%d-%m $B +%s` - `date -jf %Y-%d-%m $A +%s`)/86400))

एन ज्वॉय!


1
-बेश: (-) / 00६४००: सिंटैक्स त्रुटि: ऑपरेंड अपेक्षित (त्रुटि टोकन है ") / --६४००")
घुड़सवार

1
@ कव्वाकेड - ऐसा इसलिए है क्योंकि आपने नहीं किया हैA="2002-20-10"; B="2003-22-11"
RAM237

धन्यवाद, इस विशेष मामले के लिए काम करने के बावजूद, मैं इसका उपयोग करने का सुझाव echo $(((`date -jf "%Y-%d-%m" "$B" +%s` - `date -jf "%Y-%d-%m" "$A" +%s`)/86400))%b %d, %YJul 5, 2017
दूंगा

@ RAM237 Thats क्या मैं भुगतान नहीं ध्यान के लिए headsmack खैर देखा, धन्यवाद
काफिले

5

यहां तक ​​कि अगर आपके पास जीएनयू तिथि नहीं है, तो संभवतः आपके पास पर्ल स्थापित होगा:

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";

यह रिटर्न 398.041666666667- दिन की बचत के कारण 398 दिन और एक घंटा है।


मेरे फीड पर सवाल वापस आया। यहां पर्ल बंडल बंडल मॉड्यूल का उपयोग करके अधिक संक्षिप्त विधि दी गई है

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


2

यह सबसे सरल है जो मैं सेंटोस 7 पर काम करने में कामयाब रहा:

OLDDATE="2018-12-31"
TODAY=$(date -d $(date +%Y-%m-%d) '+%s')
LINUXDATE=$(date -d "$OLDDATE" '+%s')
DIFFDAYS=$(( ($TODAY - $LINUXDATE) / (60*60*24) ))

echo $DIFFDAYS

2

यहाँ zsh का उपयोग करके मेरा काम करने का तरीका है। OSX पर परीक्षण किया गया:

# 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

परिणाम:

Your value:  1577

असल में, हम अपनी तारीख स्ट्रिंग को टाइमस्टैम्प में बदलने के लिए strftimeरिवर्स ( -r) सुविधा का उपयोग करते हैं , फिर हम अपनी गणना करते हैं।


1

मैं रूबी में एक और संभावित समाधान प्रस्तुत करूंगा। ऐसा लगता है कि यह अब तक का सबसे छोटा और साफ दिखने वाला है:

A=2003-12-11
B=2002-10-10
DIFF=$(ruby -rdate -e "puts Date.parse('$A') - Date.parse('$B')")
echo $DIFF

2
वह मारपीट में रास्ता तलाश रहा है।
कोजोन

2
शेल में ही करने का कोई पोर्टेबल तरीका नहीं है। सभी विकल्प विशेष रूप से बाहरी कार्यक्रमों (अर्थात GNU dateया कुछ स्क्रिप्टिंग भाषा) का उपयोग करते हैं और मुझे ईमानदारी से लगता है कि रूबी यहाँ जाने का एक अच्छा तरीका है। यह समाधान बहुत छोटा है और किसी भी गैर-मानक पुस्तकालयों या अन्य निर्भरताओं का उपयोग नहीं करता है। वास्तव में, मुझे लगता है कि रूबी स्थापित होने की उच्च संभावना है कि एक से अधिक जीएनयू तिथि स्थापित होगी।
ग्रेकैट

1

एक और पायथन संस्करण:

python -c "from datetime import date; print date(2003, 11, 22).toordinal() - date(2002, 10, 20).toordinal()"

1

Http://cfajohnson.com/shell/ssr/ssr-scripts.tar.gz से शेल फ़ंक्शन का उपयोग करें ; वे किसी भी मानक यूनिक्स शेल में काम करते हैं।

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 पर प्रलेखन देखें


1

यूनिक्स पर आपको जीएनयू तिथियां स्थापित होनी चाहिए। आपको बैश से भटकने की आवश्यकता नहीं है। यहाँ दिनों पर विचार कर समाधान निकाला गया है, बस कदम दिखाने के लिए। इसे सरल बनाया जा सकता है और पूर्ण तिथियों तक बढ़ाया जा सकता है।

DATE=$(echo `date`)
DATENOW=$(echo `date -d "$DATE" +%j`)
DATECOMING=$(echo `date -d "20131220" +%j`)
THEDAY=$(echo `expr $DATECOMING - $DATENOW`)

echo $THEDAY 

1

यह मानता है कि एक वर्ष का एक महीना 1/12 है:

#!/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])
}


0

मान लें कि हम Oracle डीबी बैकअप को तृतीयक डिस्क पर मैन्युअल रूप से rsync करते हैं। फिर हम उस डिस्क पर पुराने बैकअप को हटाना चाहते हैं। तो यहाँ एक छोटा सा बैश स्क्रिप्ट है:

#!/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

अपनी आवश्यकताओं के अनुरूप dirs और अवधारण अवधि ("30 दिन") को संशोधित करें।


Oracle Area YYYY_MM_DD ’जैसे प्रारूप का उपयोग करके फ़्लैश रिकवरी क्षेत्र में बैकअप सेट करता है, इसलिए हम इसे 'तारीख -d' में पास करने के लिए अंडरस्कोर हटाते हैं
एलेक्स चर्कास

0

मैकओएस सिएरा के लिए (शायद मैक ओएस एक्स योसेमेट से),

किसी फ़ाइल से युगांतर समय (सेकंड से 1970) प्राप्त करने के लिए, और इसे var में सहेजें: old_dt=`date -j -r YOUR_FILE "+%s"`

वर्तमान समय का युग प्राप्त करने के लिए new_dt=`date -j "+%s"`

उपर्युक्त दो युगों के अंतर की गणना करने के लिए (( diff = new_dt - old_dt ))

यह जांचने के लिए कि क्या अंतर 23 दिनों से अधिक है (( new_dt - old_dt > (23*86400) )) && echo Is more than 23 days


0
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

आज की तारीख और अपने सेकेंड को अपनी मनचाही तारीख से पाने के लिए इसका इस्तेमाल करें। यदि आप इसे दिनों के साथ चाहते हैं तो इसे 86400 के साथ विभाजित करें

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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.