คำนวณความแตกต่างวันที่อย่างรวดเร็ว


84

ฉันมักต้องการคำนวณวันที่แบบรวดเร็วเช่น:

  • ข้อแตกต่างระหว่างสองเดทนี้คืออะไร?
  • วันคืออะไรnสัปดาห์หลังจากวันที่อื่น ๆ นี้หรือไม่?

ฉันมักจะเปิดปฏิทินและนับวัน แต่ฉันคิดว่าควรมีโปรแกรม / สคริปต์ที่ฉันสามารถใช้ในการคำนวณประเภทนี้ ข้อเสนอแนะใด ๆ


3
ดูเครื่องมือใน UNIX เพื่อลบวันที่เมื่อไม่สามารถใช้วันที่ของ GNU ได้
Gilles

คำตอบ:


106

"n สัปดาห์หลังจากวันที่" เป็นเรื่องง่ายด้วยวันที่ GNU (1):

$ date -d 'now + 3 weeks'
Tue Dec  6 23:58:04 EST 2011
$ date -d 'Aug 4 + 3 weeks'
Thu Aug 25 00:00:00 EST 2011
$ date -d 'Jan 1 1982 + 11 weeks'
Fri Mar 19 00:00:00 EST 1982

ฉันไม่รู้วิธีง่ายๆในการคำนวณความแตกต่างระหว่างวันที่สองวัน แต่คุณสามารถสรุปตรรกะรอบ ๆ วันที่ (1) ด้วยฟังก์ชันเชลล์ได้

datediff() {
    d1=$(date -d "$1" +%s)
    d2=$(date -d "$2" +%s)
    echo $(( (d1 - d2) / 86400 )) days
}
$ datediff '1 Nov' '1 Aug'
91 days

สลับd1และd2ถ้าคุณต้องการให้การคำนวณวันที่เป็นแบบอื่นหรือรับนักเล่นที่จะทำให้มันไม่สำคัญ นอกจากนี้ในกรณีที่ไม่มีการเปลี่ยนDST เป็น DSTในช่วงเวลาหนึ่งวันจะมีความยาวเพียง 23 ชั่วโมงเท่านั้น คุณสามารถชดเชยโดยเพิ่ม½วันไปที่ผลรวม

echo $(( (((d1-d2) > 0 ? (d1-d2) : (d2-d1)) + 43200) / 86400 )) days

40

สำหรับชุดเครื่องมือแบบพกพาลองของตัวเองมากของฉันdateutils ตัวอย่างสองตัวอย่างของคุณจะนำไปสู่การตอร์ปิโดหนึ่งครั้ง:

ddiff 2011-11-15 2012-04-11
=>
  148

หรือในสัปดาห์และวัน:

ddiff 2011-11-15 2012-04-11 -f '%w %d'
=>
  21 1

และ

dadd 2011-11-15 21w
=>
  2012-04-10

3
+1 เครื่องมือของคุณdateadd -i '%m%d%Y' 01012015 +1d
สั่นสะเทือน

2
@don_crissti ตัวแยกวิเคราะห์ไม่สามารถแยกความแตกต่างระหว่างวันที่ตัวเลขเท่านั้นและระยะเวลามันได้รับการแก้ไขในต้นแบบปัจจุบัน (d0008f98)
hroptatyr

คุณมีการแจกแจงฐานสองของหน้าต่าง dateutils หรือไม่?
mosh

@mosh ไม่และฉันไม่มีสิ่งอำนวยความสะดวกให้ลอง
hroptatyr

ไปงานปาร์ตี้สายที่นี่ แต่ dateutils อยู่บน cygwin ถ้าคุณต้องการใช้บน Windows
gregb212

30

ตัวอย่างไพ ธ อนสำหรับการคำนวณจำนวนวันที่ฉันเดินบนดาวเคราะห์

$ python
>>> from datetime import date as D
>>> print (D.today() - D(1980, 6, 14)).days
11476

2
ในกรณีที่มีคนต้องการให้มันทำงานเหมือนคำสั่งเดียวแทนที่จะพิมพ์ในล่ามแบบโต้ตอบ: ychaouche@ychaouche-PC ~ $ python -c "from datetime import date as d; print (d.today() - d(1980, 6, 14)).days" 12813 ychaouche@ychaouche-PC ~ $
ychaouche

1
สิ่งนี้ใช้ได้กับฉัน python3 -c "จากวันที่นำเข้าวันที่และเวลาเป็น d; พิมพ์ (d.today () - d (2016, 1, 9))" ไม่ต้องใช้วันที่สิ้นสุด
Kiran K Telukunta

13

ฉันมักจะชอบที่จะมีเวลา / วันที่ในรูปแบบ unix utime (จำนวนวินาทีตั้งแต่ยุคเมื่อเริ่มยุคที่เจ็ด UTC) ด้วยวิธีนี้จะทำให้เดือดลงไปจนถึงการลบแบบธรรมดาหรือเพิ่มวินาที

ปัญหาที่มักจะเปลี่ยนวันที่ / เวลาในรูปแบบนี้

ในเปลือกสภาพแวดล้อม / script คุณจะได้รับมันด้วยในช่วงเวลาของการเขียนเวลาปัจจุบันคือdate '+%s' 1321358027

เพื่อเปรียบเทียบกับ 2011/11/04 (วันเกิดของฉัน) ยอมdate '+%s' -d 2011-11-04 1320361200ลบ: expr 1321358027 - 1320361200ให้996827วินาทีซึ่งเป็นexpr 996827 / 86400= 11 วันที่ผ่านมา

การแปลงจาก utime (รูปแบบ 1320361200) เป็นวันที่ทำได้ง่ายมากเช่น C, PHP หรือ Perl โดยใช้ไลบรารีมาตรฐาน ด้วย GNU dateที่-dอาร์กิวเมนต์สามารถใช้ได้กับ@เพื่อบ่งชี้ถึง "วินาทีตั้งแต่ยุค" รูปแบบ


7
ด้วยวันที่ของ GNU ให้date -d @1234567890แปลงจากวินาทีตั้งแต่ยุคไปจนถึงรูปแบบวันที่ใด ๆ ที่คุณระบุ
Gilles

1
@Gilles: นั่นยอดเยี่ยม ไม่พบใน manpage คุณเรียนรู้สิ่งนั้นจากที่ไหน
MattBianco

1
@MattBianco ให้ดูinfo dateโดยเฉพาะอย่างยิ่งวินาทีตั้งแต่โหนดEpoch :“ หากคุณนำหน้าตัวเลขด้วย `@ 'จะเป็นการแทนการประทับเวลาภายในเป็นวินาทีนับจากนี้”
manatwork

8

สิ่งนี้เกิดขึ้นเมื่อใช้date -d "$death_date - $y years - $m months - $d days"เพื่อรับวันเกิด (สำหรับลำดับวงศ์ตระกูล) คำสั่งนั้นผิด เดือนไม่ได้มีความยาวเท่ากัน(date + offset) - offset != dateทั้งหมด อายุในปี / เดือน / วันเป็นมาตรการไปข้างหน้านับจากวันเดือนปีเกิด

$ date --utc -d 'mar 28 1867 +72years +11months +2days'
Fri Mar  1 00:00:00 UTC 1940

$ date --utc -d 'mar 1 1940 -72years -11months -2days'
Sat Mar 30 00:00:00 UTC 1867
# (2 days later than our starting point)

Date ให้ผลลัพธ์ที่ถูกต้องในทั้งสองกรณี แต่ในกรณีที่สองคุณกำลังถามคำถามผิด มันสำคัญที่ 11 เดือนของปีครอบคลุม +/- 11 ก่อนที่จะเพิ่ม / ลบวัน ตัวอย่างเช่น:

$ date --utc -d 'mar 31 1939  -1month'
Fri Mar  3 00:00:00 UTC 1939
$ date --utc -d 'mar 31 1940  -1month' # leap year
Sat Mar  2 00:00:00 UTC 1940
$ date --utc -d 'jan 31 1940  +1month' # leap year
Sat Mar  2 00:00:00 UTC 1940

สำหรับการลบเพื่อเป็นการดำเนินการผกผันของการเพิ่มลำดับของการดำเนินการจะต้องถูกกลับรายการ เพิ่มปี, เดือนแล้ววัน หากการลบใช้ลำดับตรงกันข้ามคุณจะกลับไปที่จุดเริ่มต้นของคุณ ไม่เช่นนั้นคุณก็ไม่ได้ถ้าวันชดเชยข้ามเขตแดนเดือนในเดือนความยาวที่แตกต่างกัน

หากคุณต้องการทำงานย้อนหลังจากวันที่และอายุที่สิ้นสุดคุณสามารถทำได้ด้วยการร้องขอหลายdateครั้ง ก่อนอื่นให้ลบวันจากนั้นเป็นเดือนและปีที่ผ่านมา (ฉันไม่คิดว่ามันปลอดภัยที่จะรวมปีและเดือนในการdateขอร้องเพียงครั้งเดียวเพราะปีอธิกสุรทินเปลี่ยนความยาวของเดือนกุมภาพันธ์)


7

หากเครื่องมือกราฟิกเป็นสิ่งที่ดีสำหรับคุณฉันขอแนะนำอย่างจริงจังqalculate(เครื่องคิดเลขที่เน้นการแปลงหน่วยมาพร้อมกับอินเตอร์เฟส GTK และ KDE, IIRC) ที่นั่นคุณสามารถพูดได้เช่น

days(1900-05-21, 1900-01-01)

เพื่อให้ได้จำนวนวัน (140 นับตั้งแต่ปี 1900 ไม่ใช่ปีอธิกสุรทิน) ระหว่างวันที่ แต่แน่นอนคุณสามารถทำเช่นเดียวกันได้ในบางครั้ง:

17:12:45 − 08:45:12

ผลตอบแทนถัวเฉลี่ยชั่วโมงหรือหากคุณตั้งค่าออกเพื่อจัดรูปแบบเวลา8.45916678:27:33


3
ที่ดีและมากยิ่งขึ้นเช่นนี้เพราะ qalculate ไม่ต้อง CLI ลองแล้วqalc help days
Sparhawk

qcalcตัวอย่าง: qalc -t 'days(1900-05-21, 1900-01-01)'-> 140
sierrasdetandil

3

ฉันมักใช้ SQL สำหรับการคำนวณวันที่ ตัวอย่างเช่นMySQL , PostgreSQLหรือSQLite :

bash-4.2$ mysql <<< "select datediff(current_date,'1980-06-14')"
datediff(current_date,'1980-06-14')
11477

bash-4.2$ psql <<< "select current_date-'1980-06-14'"
 ?column? 
----------
    11477
(1 row)

bash-4.2$ sqlite2 <<< "select julianday('now')-julianday('1980-06-14');"
11477.3524537035

บางครั้งฉันก็รู้สึกอยากได้ JavaScript ตัวอย่างเช่นSpiderMonkey , WebKit , SeedหรือNode.js :

bash-4.2$ js -e 'print((new Date()-new Date(1980,5,14))/1000/60/60/24)'
11477.477526192131

bash-4.2$ jsc-1 -e 'print((new Date()-new Date(1980,5,14))/1000/60/60/24)'
11477.47757960648

bash-4.2$ seed -e '(new Date()-new Date(1980,5,14))/1000/60/60/24'
11477.4776318287

bash-4.2$ node -pe '(new Date()-new Date(1980,5,14))/1000/60/60/24'
11624.520061481482

(ระวังเมื่อผ่านเดือนไปยังตัวสร้างDateวัตถุJavaScript เริ่มต้นด้วย 0)


3

อีกวิธีในการคำนวณความแตกต่างระหว่างวันที่สองวันในปีปฏิทินเดียวกันคุณสามารถใช้สิ่งนี้:

date_difference.sh
1  #!/bin/bash
2  DATEfirstnum=`date -d "2014/5/14" +"%j"`
3  DATElastnum=`date -d "12/31/14" +"%j"`
4  DAYSdif=$(($DATElastnum - $DATEfirstnum))
5  echo "$DAYSdif"
  • บรรทัดที่ 1 ประกาศถึงเชลล์ที่จะใช้ล่าม
  • บรรทัดที่ 2 กำหนดค่าจาก out dateto ให้กับตัวแปร DATEfirstnum การ-dตั้งค่าสถานะแสดงสตริงในรูปแบบเวลาในกรณีนี้ 14 พฤษภาคม 2014 และ+"%j"บอกdateให้จัดรูปแบบผลลัพธ์เป็นวันของปี (1-365)
  • บรรทัดที่ 3 นั้นเหมือนกับ Line 2 แต่มีวันที่แตกต่างกันและรูปแบบที่แตกต่างกันสำหรับสตริงวันที่ 31 ธันวาคม 2014
  • บรรทัดที่ 4 กำหนดค่าDAYSdifให้กับส่วนต่างของสองวัน
  • สาย 5 DAYSdifแสดงค่าของ

สิ่งนี้ใช้ได้กับรุ่น GNU dateแต่ไม่สามารถใช้กับรุ่น PC-BSD / FreeBSD ฉันติดตั้งcoreutilsจากทรีพอร์ตและใช้คำสั่ง/usr/local/bin/gdateแทน


1
สคริปต์นี้จะไม่ทำงาน มีการพิมพ์ผิดในบรรทัดสุดท้ายและช่องว่างรอบ ๆ การกำหนดตัวแปรดังนั้น bash จึงพยายามเรียกใช้โปรแกรมที่ชื่อ DATEfirst ด้วยอาร์กิวเมนต์สองตัว ลองสิ่งนี้: DATEfirstnum=$(date -d "$1" +%s) DATElastnum=$(date -d "$2" +%s) นอกจากนี้สคริปต์นี้จะไม่สามารถคำนวณความแตกต่างระหว่างสองปีที่แตกต่างกันได้ +%jอ้างถึงวันของปี (001..366) ดังนั้น./date_difference.sh 12/31/2001 12/30/2014ผลลัพธ์ -1 เช่นเดียวกับคำตอบอื่น ๆ ที่ระบุไว้คุณต้องแปลงทั้งสองวันเป็นวินาทีตั้งแต่ 1970-01-01 00:00:00 UTC
หก

คุณไม่จำเป็นต้องใช้$นิพจน์ทางคณิตศาสตร์ภายใน: $((DATElastnum - DATEfirstnum))จะใช้ได้เช่นกัน
Ruslan

3

ด้วยความช่วยเหลือของโซลูชั่น Dannas นี้สามารถทำได้ในหนึ่งบรรทัดด้วยรหัสต่อไปนี้:

python -c "from datetime import date as d; print(d.today() - d(2016, 7, 26))"

(ใช้ได้ทั้ง Python 2.x และ Python 3)


1
คุณสามารถแก้ไขโพสต์ของคุณแทนการแสดงความคิดเห็น
Stephen Rauch

3

dateและ bash สามารถทำวันที่ที่แตกต่างได้ (ตัวเลือก OS X ที่แสดง) วางวันหลังก่อน

echo $((($(date -jf%D "04/03/16" +%s) - $(date -jf%D "03/02/16" +%s)) / 86400))
# 31

1

นอกจากนี้ยังมีการคำนวณเวลาของหน่วย GNU รวมกับวันที่ GNU:

$ gunits $(gdate +%s)sec-$(gdate +%s -d -1234day)sec 'yr;mo;d;hr;min;s'
        3 yr + 4 mo + 16 d + 12 hr + 37 min + 26.751072 s
$ gunits $(gdate +%s -d '2015-1-2 3:45:00')sec-$(gdate +%s -d '2013-5-6 7:43:21')sec 'yr;mo;d;hr;min;s'
        1 yr + 7 mo + 27 d + 13 hr + 49 min + 26.206759 s

(gunits เป็นหน่วยใน Linux, gdate คือวันที่)


1

ลงวันที่แล้วบน github: gist

#!/bin/bash
#Simplest calculator two dates difference. By default in days

# Usage:
# ./datediff.sh first_date second_date [-(s|m|h|d) | --(seconds|minutes|hours|days)]

first_date=$(date -d "$1" "+%s")
second_date=$(date -d "$2" "+%s")

case "$3" in
"--seconds" | "-s") period=1;;
"--minutes" | "-m") period=60;;
"--hours" | "-h") period=$((60*60));;
"--days" | "-d" | "") period=$((60*60*24));;
esac

datediff=$(( ($first_date - $second_date)/($period) ))
echo $datediff

1

คำตอบของ camhดูแลส่วนใหญ่ แต่เราสามารถปรับปรุงการจัดการกับการปัดเศษโซนเวลา ฯลฯ รวมทั้งเราได้รับความแม่นยำพิเศษและความสามารถในการเลือกหน่วยของเรา:

datediff() {
#convert dates to decimal seconds since 1970-01-01 00:00:00 UTC
date1seconds=$(date +%s.%N -d "$date1")
date2seconds=$(date +%s.%N -d "$date2")

#Calculate time difference in various time units
timeseconds=$(printf "%0.8f\n" $(bc <<<"scale=9; ($date2sec-$date1sec)"))
timeminutes=$(printf "%0.8f\n" $(bc <<<"scale=9; ($date2sec-$date1sec)/60"))
  timehours=$(printf "%0.8f\n" $(bc <<<"scale=9; ($date2sec-$date1sec)/3600"))
   timedays=$(printf "%0.8f\n" $(bc <<<"scale=9; ($date2sec-$date1sec)/86400"))
  timeweeks=$(printf "%0.8f\n" $(bc <<<"scale=9; ($date2sec-$date1sec)/604800"))
}

-dบอกdateว่าเราจัดหาวันที่และเวลาให้กับการแปลง +%s.%Nเปลี่ยนวันที่ - เวลาเป็นวินาทีนานนับวินาทีตั้งแต่ 1970-01-01 00:00:00 UTC bcคำนวณความแตกต่างระหว่างตัวเลขสองตัวและปัจจัยหารทำให้เราได้หน่วยต่างกัน printfเพิ่ม 0 ก่อนจุดทศนิยมถ้าจำเป็น ( bcไม่) และทำให้แน่ใจว่าการปัดเศษไปใกล้ที่สุด ( bcแค่ตัด) awkนอกจากนี้คุณยังสามารถใช้

ทีนี้ลองทำสิ่งนี้กับกรณีทดสอบที่ขี้ขลาด

date1='Tue Jul  9 10:18:04.031 PST 2020'
date2='Wed May  8 15:19:34.447 CDT 2019'
datediff "$date1" "$date2"

echo $timeseconds seconds
-36971909.584000000 seconds

echo $timeminutes minutes
-616198.493066667 minutes

echo $timehours hours
-10269.974884444 hours

echo $timedays days
-427.915620185 days

echo $timeweeks weeks
-61.130802884 weeks

โปรดทราบว่าเนื่องจากความยาวของเดือนหรือปีนั้นไม่เหมือนกันเสมอจึงไม่มีคำตอบที่ "ถูกต้อง" เพียงอย่างเดียวแม้ว่าจะสามารถใช้ 365.24 วันในการประมาณที่สมเหตุสมผลในปัจจุบัน


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.