Here is the solution.
This does two things: first it calculates the number of full days between two dates, and since we know (well, we can get closer) that every day is 24 hours, it's pretty trivial for the weight of โdaytimeโ and โdayโ, nighttime โ (calculations are done in hours.) So now we need to find out the remaining less than 24-hour interval. The trick here is to โresetโ the time so that the โdawnโ is not in the middle of the day, but at 0, so we only have one separator for twilight, so we have only three cases: both are days an apparent both night-time, or such later date - at night, but before that - the daytime.
Updated based on comments.
The 4.588s time for 1 million function calls was 4.588s on my laptop.
from datetime import datetime,timedelta def weighteddiff(d2,d1,dawn,dusk,night_weight): #if dusk is "before" dawn, switch roles day_weight = 1 if dusk < dawn: day_weight = night_weight night_weight = 1 placeholder = dawn dawn = dusk dusk = placeholder nighttime = dawn.total_seconds()/3600 + 24 - dusk.total_seconds()/3600 daytime = 24-nighttime dt = d2-d1 total_hours = 0 total_hours += dt.days*daytime*day_weight + dt.days*nighttime*night_weight d1 += timedelta(days=dt.days) d1 -= dawn d2 -= dawn dawntime = datetime(d2.year,d2.month,d2.day,0) dusktime = dawntime + dusk - dawn if d1 < dusktime and d2 < dusktime: total_hours += (d2-d1).total_seconds()/3600*day_weight elif d1 < dusktime and d2 >= dusktime: total_hours += (dusktime - d1).total_seconds()/3600*day_weight total_hours += (d2 - dusktime).total_seconds()/3600*night_weight elif d1 >= dusktime and d2 >= dusktime: total_hours += (d2-d1).total_seconds()/3600*night_weight else: pass return total_hours weight = 0.5 #weight of nightime hours #dawn and dusk supplied as timedelta from midnight dawn = timedelta(hours=5,minutes=0,seconds=0) dusk = timedelta(hours=19,minutes=4,seconds=0) d1 = datetime(2017,10,23, 14) d2 = datetime(2017,10,23, 22) print("test1",weighteddiff(d2,d1,dawn,dusk,weight)) d1 = datetime(2016,10,22, 20) d2 = datetime(2016,10,23, 20) print("test2",weighteddiff(d2,d1,dawn,dusk,weight)) dawn = timedelta(hours=6,minutes=0,seconds=0) dusk = timedelta(hours=1,minutes=4,seconds=0) d1 = datetime(2017,10,22, 2) d2 = datetime(2017,10,23, 19) print("test3",weighteddiff(d2,d1,dawn,dusk,weight)) d1 = datetime(2016,10,22, 20) d2 = datetime(2016,10,23, 20) print("test4",weighteddiff(d2,d1,dawn,dusk,weight))