Django Partial Dates#

A Django model field for dates that are known only to the year, to the month or to the day: 1990, 1990-06 or 1990-06-14. It stores a date at the precision it was recorded at and never holds a part nobody gave.

Features#

  • Work with a partial date in Python: an immutable value that sorts, compares, hashes and says which period it covers.

  • Store a partial date in one text column, as its ISO form, with the database refusing anything else.

  • Filter partial dates by year, month, day or a range, in the database, knowing which uncertain dates each filter includes.

  • Order, select and group partial dates by the date or by one of its parts, and put them on a date axis with start.

  • Enter a partial date in a model form, the admin or a plain form, with a year, a month and a day select, giving as much of the date as the user knows.

  • Show a partial date to a reader at the precision it was recorded, in the language of the page, in a template, in Python and in the admin.

  • Filter a list of records by a date or a range of dates with django-filter, giving a person the selects and an API client the ISO form, and knowing which uncertain dates each filter includes.

  • Expose a partial date through an API with a Django REST framework serializer field that reads and writes the ISO form and reports anything else as a validation error.

  • Move from django-partial-date with a migration that converts the column in place and loses no value.

Requirements#

  • Python 3.12 or later

  • Django 5.2 or later

  • PostgreSQL or SQLite

  • django-filter 26.2 or later, only for the django-filter extra

  • Django REST framework 3.18 or later, only for the djangorestframework extra

Installation#

  1. Install the package.

    $ pip install django-partial-dates
    
  2. Declare the field on a model.

    from django.db import models
    
    from partial_dates import PartialDateField
    
    
    class Sample(models.Model):
        collected = PartialDateField(null=True, blank=True, db_index=True)
    
  3. Make and apply the migration.

    $ python manage.py makemigrations
    $ python manage.py migrate
    

The installation page says what each step sets up.

Example#

from partial_dates import PartialDate

Sample.objects.create(collected=PartialDate(1990, 6))
Sample.objects.filter(collected__month=6)

The first line stores 1990-06. The second finds every sample collected in a June, and leaves out samples whose month nobody recorded.

Next steps#

About the project#

Support#

Report a problem or ask a question in the issue tracker. See Contributing for how to run the tests and work on the package. Everyone taking part follows the code of conduct.

Licence#

MIT. See the licence.