Bagaimana cara menghitung jumlah hari antara dua tanggal yang diberikan?

507

Jika saya memiliki dua tanggal (mis. '8/18/2008'Dan '9/26/2008'), apa cara terbaik untuk mendapatkan jumlah hari antara dua tanggal ini?

sinar
sumber

Jawaban:

801

Jika Anda memiliki dua objek tanggal, Anda bisa menguranginya, yang menghitung timedeltaobjek.

from datetime import date

d0 = date(2008, 8, 18)
d1 = date(2008, 9, 26)
delta = d1 - d0
print(delta.days)

Bagian yang relevan dari dokumen ini: https://docs.python.org/library/datetime.html .

Lihat jawaban ini untuk contoh lain.

Dana
sumber
2
Jawaban yang bagus di sini. Karena banyak orang mungkin menggunakan bingkai data panda, pemikiran mungkin berguna untuk memeriksa tautan tentang cara mengkonversi dari np.datetime64ke python datetime stackoverflow.com/questions/52982056/…
Pramit
Yang menyenangkan adalah bahwa solusi ini juga mengembalikan delta yang benar untuk tahun kabisat.
Lasma
154

Menggunakan kekuatan datetime:

from datetime import datetime
date_format = "%m/%d/%Y"
a = datetime.strptime('8/18/2008', date_format)
b = datetime.strptime('9/26/2008', date_format)
delta = b - a
print delta.days # that's it
dguaraglia
sumber
4
sebenarnya, kelas tanggal akan lebih tepat dalam hal ini daripada datetime.
Jeremy Cantrell
11
@ JeremyCantrell Namun, bahkan delapan tahun kemudian, datemasih kurang setara dengan strptime().
JAB
Mengapa perlu strptimeyang formatarg? Harus jelas dengan tanggal arg pertama yang memiliki format.
Timo
36

Hari sampai Natal:

>>> import datetime
>>> today = datetime.date.today()
>>> someday = datetime.date(2008, 12, 25)
>>> diff = someday - today
>>> diff.days
86

Lebih banyak aritmatika di sini .

Harley Holcombe
sumber
16

Anda ingin modul datetime.

>>> from datetime import datetime, timedelta 
>>> datetime(2008,08,18) - datetime(2008,09,26) 
datetime.timedelta(4) 

Contoh lain:

>>> import datetime 
>>> today = datetime.date.today() 
>>> print(today)
2008-09-01 
>>> last_year = datetime.date(2007, 9, 1) 
>>> print(today - last_year)
366 days, 0:00:00 

Seperti yang ditunjukkan di sini

kolrie
sumber
1
Bagaimana saya mendapatkan ini tanpa bagian 0:00:00?
Vicki B
@VickiBdelta = today - last_year print(delta.days)
dbakiu
8
from datetime import datetime
start_date = datetime.strptime('8/18/2008', "%m/%d/%Y")
end_date = datetime.strptime('9/26/2008', "%m/%d/%Y")
print abs((end_date-start_date).days)
Prasanna Ranganathan
sumber
2
Ini menambahkan tidak ada yang baru dibandingkan dengan jawaban yang diberikan 4 tahun sebelumnya. -1.
Mark Amery
+1 untuk penggunaan abs(), yang berguna ketika tanggal yang dibandingkan tidak diketahui sebelumnya dan itu adalah perbedaan yang Anda minati. Jika kencan kedua Anda datetime.strptime(date, date)lebih lambat dari tanggal pertama, hasilnya akan negatif. abs()membuat semua input mutlak (mis. positif).
Berlaku
7

Ini juga dapat dengan mudah dilakukan dengan arrow:

import arrow

a = arrow.get('2017-05-09')
b = arrow.get('2017-05-11')

delta = (b-a)
print delta.days

Untuk referensi: http://arrow.readthedocs.io/en/latest/

cimarie
sumber
6

tanpa menggunakan Lib hanya kode murni:

#Calculate the Days between Two Date

daysOfMonths = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

def isLeapYear(year):

    # Pseudo code for this algorithm is found at
    # http://en.wikipedia.org/wiki/Leap_year#Algorithm
    ## if (year is not divisible by 4) then (it is a common Year)
    #else if (year is not divisable by 100) then (ut us a leap year)
    #else if (year is not disible by 400) then (it is a common year)
    #else(it is aleap year)
    return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0

def Count_Days(year1, month1, day1):
    if month1 ==2:
        if isLeapYear(year1):
            if day1 < daysOfMonths[month1-1]+1:
                return year1, month1, day1+1
            else:
                if month1 ==12:
                    return year1+1,1,1
                else:
                    return year1, month1 +1 , 1
        else: 
            if day1 < daysOfMonths[month1-1]:
                return year1, month1, day1+1
            else:
                if month1 ==12:
                    return year1+1,1,1
                else:
                    return year1, month1 +1 , 1
    else:
        if day1 < daysOfMonths[month1-1]:
             return year1, month1, day1+1
        else:
            if month1 ==12:
                return year1+1,1,1
            else:
                    return year1, month1 +1 , 1


def daysBetweenDates(y1, m1, d1, y2, m2, d2,end_day):

    if y1 > y2:
        m1,m2 = m2,m1
        y1,y2 = y2,y1
        d1,d2 = d2,d1
    days=0
    while(not(m1==m2 and y1==y2 and d1==d2)):
        y1,m1,d1 = Count_Days(y1,m1,d1)
        days+=1
    if end_day:
        days+=1
    return days


# Test Case

def test():
    test_cases = [((2012,1,1,2012,2,28,False), 58), 
                  ((2012,1,1,2012,3,1,False), 60),
                  ((2011,6,30,2012,6,30,False), 366),
                  ((2011,1,1,2012,8,8,False), 585 ),
                  ((1994,5,15,2019,8,31,False), 9239),
                  ((1999,3,24,2018,2,4,False), 6892),
                  ((1999,6,24,2018,8,4,False),6981),
                  ((1995,5,24,2018,12,15,False),8606),
                  ((1994,8,24,2019,12,15,True),9245),
                  ((2019,12,15,1994,8,24,True),9245),
                  ((2019,5,15,1994,10,24,True),8970),
                  ((1994,11,24,2019,8,15,True),9031)]

    for (args, answer) in test_cases:
        result = daysBetweenDates(*args)
        if result != answer:
            print "Test with data:", args, "failed"
        else:
            print "Test case passed!"

test()
Muhammad Elsayeh
sumber
3

semua orang telah menjawab dengan sangat baik menggunakan tanggal, izinkan saya mencoba untuk menjawabnya menggunakan panda

dt = pd.to_datetime('2008/08/18', format='%Y/%m/%d')
dt1 = pd.to_datetime('2008/09/26', format='%Y/%m/%d')

(dt1-dt).days

Ini akan memberikan jawabannya. Dalam hal salah satu input adalah kolom dataframe. cukup gunakan dt.days sebagai ganti hari

(dt1-dt).dt.days
Amit Gupta
sumber
2

Ada juga datetime.toordinal()metode yang belum disebutkan:

import datetime
print(datetime.date(2008,9,26).toordinal() - datetime.date(2008,8,18).toordinal())  # 39

https://docs.python.org/3/library/datetime.html#datetime.date.toordinal

date.toordinal ()

Kembalikan ordinal Gregorian proleptic dari tanggal, di mana tanggal 1 Januari tahun 1 memiliki 1. ordinal Untuk setiap dateobjek d , date.fromordinal(d.toordinal()) == d.

Tampaknya cocok untuk menghitung perbedaan hari, meskipun tidak dapat dibaca timedelta.days.

Pekerjaan Dmitriy
sumber
1
Ada beberapa kasus di mana pendekatan ini menang. Misalnya, perbedaan aktual antara 2019-07-09 23:50 dan 2019-07-10 00:10 adalah dua puluh menit. (d1 - d0).dayskembali 0, d1.toordinal() - d0.toordinal()kembali 1. Bergantung pada apa yang Anda butuhkan di usecase Anda yang sebenarnya.
peter.slizik
pendekatan ini sebenarnya dapat membandingkan waktu dan tanggal. Misalnya untuk memeriksa apakah 2020-04-17 == 2020-04017 00:00:00
Harry Duong
2

Untuk menghitung tanggal dan waktu, ada beberapa opsi tetapi saya akan menulis dengan cara sederhana:

from datetime import timedelta, datetime, date
import dateutil.relativedelta

# current time
date_and_time = datetime.datetime.now()
date_only = date.today()
time_only = datetime.datetime.now().time()

# calculate date and time
result = date_and_time - datetime.timedelta(hours=26, minutes=25, seconds=10)

# calculate dates: years (-/+)
result = date_only - dateutil.relativedelta.relativedelta(years=10)

# months
result = date_only - dateutil.relativedelta.relativedelta(months=10)

# days
result = date_only - dateutil.relativedelta.relativedelta(days=10)

# calculate time 
result = date_and_time - datetime.timedelta(hours=26, minutes=25, seconds=10)
result.time()

Semoga ini bisa membantu

Gavriel Cohen
sumber
1

from datetime import date
def d(s):
  [month, day, year] = map(int, s.split('/'))
  return date(year, month, day)
def days(start, end):
  return (d(end) - d(start)).days
print days('8/18/2008', '9/26/2008')

Ini mengasumsikan, tentu saja, bahwa Anda telah memverifikasi bahwa tanggal Anda dalam format r'\d+/\d+/\d+'.

Tembakan Parthian
sumber
1
Ini menambahkan tidak ada yang baru dibandingkan dengan jawaban yang diberikan 8 tahun sebelumnya. -1.
Mark Amery
1
Perbedaan utama adalah sebagian besar jawaban lain bahkan tidak repot-repot memperhitungkan fakta bahwa OP memiliki tanggal sebagai string. Dan mereka yang bertanggung jawab untuk itu sebagian besar menggunakan formatters yang lebih rumit daripada yang diperlukan. Jadi, perbedaan utamanya adalah map(int, s.split('/')). Tidak persis terobosan, tapi sekali lagi pertanyaan ini adalah dasar yang sangat bodoh. Jawaban saya hanya menunjukkan cara lain untuk menguliti kucing.
Parthian Shot
Disebutkan juga memvalidasi bahwa tanggal berada dalam format yang benar, dan memberikan regex validasi aproksimasi pertama. Yang lain tidak.
Parthian Shot
1

Berikut adalah tiga cara untuk mengatasi masalah ini:

from datetime import datetime

Now = datetime.now()
StartDate = datetime.strptime(str(Now.year) +'-01-01', '%Y-%m-%d')
NumberOfDays = (Now - StartDate)

print(NumberOfDays.days)                     # Starts at 0
print(datetime.now().timetuple().tm_yday)    # Starts at 1
print(Now.strftime('%j'))                    # Starts at 1
Antoine Thiry
sumber