Django: How to get a time difference from the time post?

31,770

Solution 1

Your code is already working; a datetime.timedelta object is returned.

To get the total number of seconds instead, you need to call the .total_seconds() method on the resulting timedelta:

from django.utils.timezone import utc

def get_time_diff(self):
    if self.time_posted:
        now = datetime.datetime.utcnow().replace(tzinfo=utc)
        timediff = now - self.time_posted
        return timediff.total_seconds()

.total_seconds() returns a float value, including microseconds.

Note that you need to use a timezone aware datetime object, since the Django DateTimeField handles timezone aware datetime objects as well. See Django Timezones documentation.

Demonstration of .total_seconds() (with naive datetime objects, but the principles are the same):

>>> import datetime
>>> time_posted = datetime.datetime(2013, 3, 31, 12, 55, 10)
>>> timediff = datetime.datetime.now() - time_posted
>>> timediff.total_seconds()
1304529.299168

Because both objects are timezone aware (have a .tzinfo attribute that is not None), calculations between them take care of timezones and subtracting one from the other will do the right thing when it comes to taking into account the timezones of either object.

Solution 2

Assuming you are doing this within a template, you can also use the timesince template tag.

For example:

{{ blog_date|timesince:comment_date }}

Solution 3

Your code

timediff = datetime.datetime.now() - self.pub_date

should work to get the time difference. However, this returns timedelta object. To get difference in seconds you use .seconds attribute

timediff = datetime.datetime.now() - self.pub_date
timediff.seconds  # difference in seconds.
Share:
31,770

Related videos on Youtube

Bob Fang
Author by

Bob Fang

@Bytedance

Updated on April 02, 2022

Comments

  • Bob Fang
    Bob Fang about 2 years

    Say I have a class in model

     class Post(models.Model):
         time_posted = models.DateTimeField(auto_now_add=True, blank=True)
    
         def get_time_diff(self):
             timediff = timediff = datetime.datetime.now() - self.time_posted
             print timediff # this line is never executed
             return timediff
    

    I defined a get_time_diff to get the time difference from the time when the Post is posted up to now, according to the document, the DateTimeField should be able to be converted to datetime automatically, is that correct? Why the print statement is never being run? How can you extract the time difference?

    Beside, if you get a time difference, is there an easy way to convert the time difference to an integer, like the number of seconds of the total time.

    • ryechus
      ryechus over 9 years
      This is old, but I noticed no one answered your question about print. Your print statement probably is working, but you won't see it in on your site. print only works in the console. If you have a look at your logs you will find your print message.
  • Aya
    Aya about 11 years
    I don't think that will work if the difference is more than one day.
  • Rohan
    Rohan about 11 years
    @Aya, I think it will. Do you know why it won't?
  • Aya
    Aya about 11 years
    Well, the docs say that the seconds attribute is "Between 0 and 86399 inclusive".
  • Bob Fang
    Bob Fang about 11 years
    Thanks first but in my case the time_posted is a DateTimeField. I tried, it does not work.
  • Martijn Pieters
    Martijn Pieters about 11 years
    @dorafmon: in your custom model method self.time_posted returns a datetime instance, see Model Methods.
  • Aya
    Aya about 11 years
    @dorafmon ...although the blank=True suggests you might not get a valid datetime back, so you may have to check its validity before doing the subtraction.
  • Martijn Pieters
    Martijn Pieters about 11 years
    @Aya: Interesting, mussed the blank=True there. Added an if statement, now get_time_diff will return None if self.time_posted is not defined.
  • Bob Fang
    Bob Fang about 11 years
    @MartijnPieters but how can you convert the DatetimeField into a datetime? I got confused here actually.
  • Martijn Pieters
    Martijn Pieters about 11 years
    @dorafmon: It has already been converted. See the documentation I linked you to; the example there uses a DateField instead but the principle is the same.
  • Martijn Pieters
    Martijn Pieters about 11 years
    @Rohan: There is a separate .days attribute. .seconds only contains the remainder; an event 10 days and 534 seconds age has a .seconds attribute with 534, and it's .days attribute will be 10. Use .total_seconds() to turn that into a seconds-only value.
  • Bob Fang
    Bob Fang about 11 years
    @MartijnPieters Sorry, I might be a little dump here, but since a DataTimeField can be converted to datatime automatically, why I cannot simply do datetime.datetime.now()-self.time_posted.
  • Martijn Pieters
    Martijn Pieters about 11 years
    @dorafmon: How are you calling the .get_time_diff() method? What error do you see when you call it? You need to tell us more about what problems you are experiencing. When you have a Post result object, calling .get_time_diff() Just Works.
  • Bob Fang
    Bob Fang about 11 years
    @MartijnPieters There is no error message, but using the code in the question up there. the print function is never executed, Also this function does not returen anything at all.
  • Martijn Pieters
    Martijn Pieters about 11 years
    @dorafmon: clearly you are not calling the code you think you are calling; there either will be a return value (at the very least None) or there will be an exception.
  • Bob Fang
    Bob Fang about 11 years
  • aorcsik
    aorcsik over 10 years
    @MartijnPieters I had to add a line to the answer, since I still needed to read through your full chat to understand my error.
  • Martijn Pieters
    Martijn Pieters over 10 years
    @aorcsik: utcnow() is not timezone aware either, but relies on your OS instead to tell it what the current UTC time is. The OS is timezone aware, but the resulting datetime.datetime object is not.
  • Martijn Pieters
    Martijn Pieters over 10 years
    @aorcsik: As such, I had to roll back your edit as it was incorrect. Only attaching a timezone object to a datetime.datetime object makes it timezone-aware.
  • aorcsik
    aorcsik over 10 years
    @MartijnPieters right, right... just figured, sry. I get the time zone from the datetime from the database and set it to the now datetime, is that correct?
  • Martijn Pieters
    Martijn Pieters over 10 years
    @aorcsik: it is the .replace(tzinfo=utc) method call that returns a new datetime.datetime() instance with a timezone object attached; that is the timezone-aware object.
  • Martijn Pieters
    Martijn Pieters over 10 years
    @aorcsik: No, just stick to UTC; because both the now object and self.time_posted are fully timezone aware, the result is always going to be accurate. The datetime.datetime() objects take care of handling the timezone details for you.
  • Martijn Pieters
    Martijn Pieters over 10 years
    @aorcsik: By sticking to UTC you save yourself all those headaches.
  • aorcsik
    aorcsik over 10 years
    @MartijnPieters yes, thank you very much! Could you please add these to the answer, maybe it will make others life easier next time :)
  • Programmer Gaurav
    Programmer Gaurav almost 4 years
    Best Answer Thank you
  • rayon
    rayon about 3 years
    Thanks! Any idea of how to get the resulting duration in seconds?