How to put timedelta in django model?

Django

Django Problem Overview


With inspectdb I was able to get a "interval" field from postgres into django. In Django, it was a TextField. The object that I retrieved was indeed a timedelta object!

Now I want to put this timedelta object in a new model. What's the best way to do this? Because putting a timedelta in a TextField results in the str version of the object...

Django Solutions


Solution 1 - Django

Since Django 1.8 you can use DurationField.

Solution 2 - Django

You can trivially normalize a timedelta to a single floating-point number in days or seconds.

Here's the "Normalize to Days" version.

float(timedelta.days) + float(timedelta.seconds) / float(86400)

You can trivially turn a floating-point number into a timedelta.

>>> datetime.timedelta(2.5)
datetime.timedelta(2, 43200)

So, store your timedelta as a float.

Here's the "Normalize to Seconds" version.

timedelta.days*86400+timedelta.seconds

Here's the reverse (using seconds)

datetime.timedelta( someSeconds/86400 )

Solution 3 - Django

Solution 4 - Django

First, define your model:

class TimeModel(models.Model):
    time = models.FloatField()

To store a timedelta object:

# td is a timedelta object
TimeModel.objects.create(time=td.total_seconds())

To get the timedelta object out of the database:

# Assume the previously created TimeModel object has an id of 1
td = timedelta(seconds=TimeModel.objects.get(id=1).time)

Note: I'm using Python 2.7 for this example.

Solution 5 - Django

There is a ticket which dates back to July 2006 relating to this: https://code.djangoproject.com/ticket/2443

Several patches were written but the one that was turned in to a project: https://github.com/johnpaulett/django-durationfield

Compared to all the other answers here this project is mature and would have been merged to core except that its inclusion is currently considered to be "bloaty".

Personally, I've just tried a bunch of solutions and this is the one that works beautifully.

from django.db import models
from durationfield.db.models.fields.duration import DurationField

class Event(models.Model):
    start = models.DateTimeField()
    duration = DurationField()

    @property
    def finish(self):
        return self.start + self.duration

Result:

$ evt = Event.objects.create(start=datetime.datetime.now(), duration='1 week')
$ evt.finish
Out[]: datetime.datetime(2013, 6, 13, 5, 29, 29, 404753)

And in admin:

Change event

Duration: 7 days, 0:00:00

Solution 6 - Django

For PostgreSQL, use django-pgsql-interval-field here: http://code.google.com/p/django-pgsql-interval-field/

Solution 7 - Django

Putting this out there cause it might be another way to solve this problem. first install this library: https://pypi.python.org/pypi/django-timedeltafield

Then:

import timedelta

class ModelWithTimeDelta(models.Model):
    timedeltafield = timedelta.fields.TimedeltaField()

within the admin you will be asked to enter data into the field with the following format: 3 days, 4 hours, 2 minutes

Solution 8 - Django

There is a workaround explained here. If you're using Postgresql, then multiplying the result of F expression with timedelta solves the problem. For example if you have a start_time and a duration in minutes, you can calculate the end_time like this:

YourModel.objects.annotate(
    end_time=ExpressionWrapper(F('start_time') + timedelta(minutes=1) * F('duration'), output_field=DateTimeField())
)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJack HaView Question on Stackoverflow
Solution 1 - DjangoMarc TuduríView Answer on Stackoverflow
Solution 2 - DjangoS.LottView Answer on Stackoverflow
Solution 3 - DjangoPythonView Answer on Stackoverflow
Solution 4 - DjangoGarrett HydeView Answer on Stackoverflow
Solution 5 - DjangoWilliamsView Answer on Stackoverflow
Solution 6 - DjangodotzView Answer on Stackoverflow
Solution 7 - Djangocolins44View Answer on Stackoverflow
Solution 8 - Djangotherealak12View Answer on Stackoverflow