How to subtract two datetime.time values ​​in a django template and how to format duration as hour, minutes

In a django application, I send a list of Entry objects to a template. Each Entry object has start and end times, which are datetime.time values ​​(from TimeFields on the form). enumerating Entry objects, I need to show the duration for each record. Filling the duration field in the model seemed to be redundant, since the start and end times were already there

model

 class Entry(models.Model): title = models.CharField(unique=True,max_length=50) starttime=models.TimeField(null=True) endtime=models.TimeField(null=True) ... 

template

 {% for entry in object_list %} <tr> <td> {{entry.title}} </td> <td> {{entry.starttime}}</td> <td> {{entry.endtime}}</td> <td> want to show duration here </td> {%endfor %} 

1. Is there any filter that can take two datetime.time values ​​and calculate the duration in seconds. i.e,

 given t1=datetime.time(2,30,50) and t2=datetime.time(3,00,50) should show 30 minutes 

2. There is also a filter that can show the duration in a given number of minutes as an hour, minutes if the minutes are more than 60

t

 if duration is 50 minutes ==> 50 minutes if duration is 150 minutes ==> 2 hours,30 minutes 

Update

 def diff_in_time(start,end): startdelta=datetime.timedelta(hours=start.hour,minutes=start.minute,seconds=start.second) enddelta=datetime.timedelta(hours=end.hour,minutes=end.minute,seconds=end.second) return (enddelta-startdelta).seconds/60 

when I tried with some sample time values, it gave me the expected result

 #start 11:35:00 pm #end 00:05:00 am start= datetime.time(23,35,00) end = datetime.time(00,05,00) print diff_in_time(start,end) ==> 30 minutes #start 00:35:00 am #end 01:35:00 am start= datetime.time(00,35,00) end = datetime.time(01,35,00) print diff_in_time(start,end) ==>60 minutes 
+6
python filter django
source share
7 answers

I don’t see where the problem is, except when the end time is later than 24 hours after the start.

Suppose the start time is 9:00:00 and the end time is 13:00:00
If these times were made on August 15, 9:00:00 and August 17, 13:00:00, there would be no point in trying to get a temporary delta between them, not knowing days 15 and 17.

Therefore, there are two cases:

  • the start and end time can really be divided by more than 24 hours, then, as already mentioned, you should move on to using datetime objects

  • or between the start time and the end time is always less than 24 hours, then the problem is simple.

============================

Consider the second case.

If a
start time 11:30:00
end of time. 12:35:00
The end, apparently, is 1 hour 5 minutes after the start

If a
start time 11:30:00
end of time. 10:35:00
The end cannot be before the start on the same morning, then the end actually occurs on the morning of the next day after the day on which it begins, that is, after 24 hours.

The same reasoning applies when the beginning begins in the afternoon, and the end time seems to be before the time starts on the same day, day or morning: the end time is actually on the next day, morning or afternoon, this depends, but he is still 24 hours later.

one)

Thus, in order to subtract the time difference, a little function is enough, for which only time attributes are required:

 def difft(start,end): a,b,c,d = start.hour, start.minute, start.second, start.microsecond w,x,y,z = end.hour, end.minute, end.second, end.microsecond delt = (wa)*60 + (xb) + (yc)/60. + (zd)/60000000 return delt + 1440 if delt<0 else delt 

The following code is intended only to better display the result:

from datetime import time

 def difft(start,end): a,b,c,d = start.hour, start.minute, start.second, start.microsecond w,x,y,z = end.hour, end.minute, end.second, end.microsecond delt = (wa)*60 + (xb) + (yc)/60. + (zd)/60000000 D = '%sh %smn %ss %sms - %sh %smn %ss %sms == ' ft = '%s + 1440 = %s (1440 = 24x60mn)' return D % (w,x,y,z,a,b,c,d) +( ft % (delt, delt+1440) if delt<0 else str(delt)) print difft(time(11,30,0),time(12,35,0)) print difft(time(11,30,0),time(10,35,0)) print print difft(time(20,40,0),time(22,41,0)) print difft(time(20,40,0),time(18,41,0)) 

result

 12h 35mn 0s 0ms - 11h 30mn 0s 0ms == 65.0 10h 35mn 0s 0ms - 11h 30mn 0s 0ms == -55.0 + 1440 = 1385.0 (1440 = 24x60mn) 22h 41mn 0s 0ms - 20h 40mn 0s 0ms == 121.0 18h 41mn 0s 0ms - 20h 40mn 0s 0ms == -119.0 + 1440 = 1321.0 (1440 = 24x60mn) 

2)

To get the duration in a more readable format:

 def difft2(start,end): a,b,c,d = start.hour, start.minute, start.second, start.microsecond w,x,y,z = end.hour, end.minute, end.second, end.microsecond delt = (wa)*60 + (xb) + (yc)/60. + (zd)/60000000. if delt < 0: delt += 1440 hh,rem = divmod(delt,60) hh = int(hh) mm = int(rem) rem = (rem - mm)*60 ss = int(rem) ms = (rem - ss)*1000000 ms = int(ms) SS = '%sh %smn %ss %sms - %sh %smn %ss %sms == %sh %smn %ss %sms' return SS % (w,x,y,z,a,b,c,d,hh,mm,ss,ms) print difft2(time(11,30,0),time(12,35,45,478129)) print difft2(time(11,30,45,11),time(10,35,45,12)) print print difft2(time(20,40,0),time(22,41,0)) print difft2(time(20,40,0),time(18,41,0)) 

result

 12h 35mn 45s 478129ms - 11h 30mn 0s 0ms == 1h 5mn 45s 478128ms 10h 35mn 45s 12ms - 11h 30mn 45s 11ms == 23h 5mn 0s 1ms 22h 41mn 0s 0ms - 20h 40mn 0s 0ms == 2h 1mn 0s 0ms 18h 41mn 0s 0ms - 20h 40mn 0s 0ms == 22h 1mn 0s 0ms 
+4
source share

You have a problem. You cannot - and cannot - compare twice. Is 11:00 a.m. before or after 1 a.m.? It depends on whether they are on the same day.

You need to either save them as datetime , or something else that represents relatively absolute time, or you need to turn them into datetime as follows:

 def todatetime(time): return datetime.datetime.today().replace(hour=time.hour, minute=time.minute, second=time.second, microsecond=time.microsecond, tzinfo=time.tzinfo) def timestodelta(starttime, endtime): return todatetime(endtime) - todatetime(starttime) 

This will not give the expected answer if the two today calls go past midnight.

Then you should probably use this application for DurationField , which stores the timedelta in order to save the result in a database for easy display.

+6
source share

Imagine the duration as a property of your model:

 from datetime import timedelta @property def duration(self): end = timedelta(self.endtime.hour, self.endtime.minute, self.endtime.second) start = timedelta(self.starttime.hour, self.starttime.minute, self.starttime.second) return end - start 

Returns a timedelta object. You can format it there as a string or use templatetag, etc.

+2
source share

You can use the built-in timedelta tag. The django template response will be:

 {{ t2|timeuntil:t1 }} 
+2
source share

one

Probably not, but you can create your own tag, take a look at this code that will do something similar: A typical Timedelta tag

2:

Again, I could not find anything like it. But it should be easy to code a custom tag to do this. Something like:

 def round_to_hours(minutes): return str(minutes/60) + ' hours and ' + str(minutes%60) + ' minutes' register.filter(round_to_hours) 

Of course, this is just the initial code, much can be improved there.

As agf pointed out, you probably need a way to create timedelta objects. You can try something like this (if you can assume that both times on the same day):

 dummydate = datetime.date(1999,1,1) delta = datetime.combine(dummydate, time1) - datetime.combine(dummydate, time2) 
+1
source share

Perhaps this is what you are looking for. Take a look at time_delta_total_seconds. You can use lib if you have complex event scheduling requirements.

http://code.google.com/p/django-swingtime/source/browse/swingtime/utils.py

+1
source share

I'll probably just add a “duration” method to your input model. It’s easy, straightforward, and you can access it in the template, like any other model field, {{entry.duration}}.

 class Entry(models.Model): title = models.CharField(unique=True,max_length=50) starttime=models.TimeField(null=True) endtime=models.TimeField(null=True) def duration(self): # perform duration calculation here return duration_display 
0
source share

All Articles