UNKNOWN
Project description
Django Timezone Utils: Time Zone Utilities For Models
django-timezone-utils adds automatic time zone conversions and support utilities to Django.
Please note that this project is currently marked as a development status of Alpha. Suggestions, constructive criticism, and feedback are certainly welcomed and appreciated.
Installation
django-timezone-utils works with Django 1.4, 1.5, 1.6 and 1.7.
To install it, simply:
$ pip install django-timezone-utils
Then add timezone_utils to your settings.INSTALLED_APPS:
INSTALLED_APPS = (
...
'timezone_utils',
)
Example Usage
Imagine you have the models Location and LocationReportingPeriod:
from datetime import datetime
from django.db import models
from django.utils.translation import ugettext_lazy as _
from timezone_utils.fields import LinkedTZDateTimeField, TimeZoneField
from timezone_utils.choices import PRETTY_ALL_TIMEZONES_CHOICES
class Location(models.Model):
company = models.ForeignKey(
verbose_name='company',
to='app_label.Company',
related_name='locations',
)
name = models.CharField(
verbose_name=_('name'),
max_length=128,
)
timezone = TimeZoneField(
verbose_name=_('timezone'),
max_length=64,
choices=PRETTY_ALL_TIMEZONES_CHOICES,
)
created = LinkedTZDateTimeField(
verbose_name=_('created'),
auto_now=True,
)
modified = LinkedTZDateTimeField(
verbose_name=_('modified'),
auto_now_add=True,
)
class LocationReportingPeriod(models.Model)
location = models.ForeignKey(
verbose_name=_('location'),
to='app_label.Location',
related_name='reporting_periods',
)
start = LinkedTZDateTimeField(
verbose_name=_('start'),
# populate_from can also be a string value, provided that the string value
# is a field on the same model
populate_from=lambda instance: instance.location.timezone,
# Time override must be a datetime.time instance
time_override=datetime.min.time,
)
end = LinkedTZDateTimeField(
verbose_name=_('end'),
populate_from=lambda instance: instance.location.timezone,
# Time override must be a datetime.time instance
time_override=datetime.max.time,
)
created = LinkedTZDateTimeField(
verbose_name=_('created'),
auto_now=True,
)
modified = LinkedTZDateTimeField(
verbose_name=_('modified'),
auto_now_add=True,
)
class Meta:
ordering = ('location', '-start')
In the above code example, if we set the value of Location.timezone to US/Eastern, each time a LocationReportingPeriod is saved, it will save the LocationReportingPeriod.start as the date 12:00AM in US/Eastern time zone, and the LocationReportingPeriod.end as 11:59:59.9999999PM in the US/Eastern time zone.
So assuming the date was 2015-01-01, we would be saving the following values to the database:
# LocationReportingPeriod.start
datetime.datetime(2015, 1, 1, 0, 0, tzinfo=<DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>)
# LocationReportingPeriod.end
datetime.datetime(2015, 1, 1, 23, 59, 59, 999999, tzinfo=<DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>)
For each location, let’s say that the client wants to see the start and end of the reporting period in that location’s time zone. One thing to remember is that just because you saved the LocationReportingPeriod start/end dates as a particular time zone, it does not mean that they will come that way from the database. For example, if your application’s settings.TIME_ZONE is set to UTC, you would get back:
print(period.start)
datetime.datetime(2015, 1, 1, 5, 0, tzinfo=<UTC>)
print(period.end)
datetime.datetime(2015, 1, 2, 4, 59, 59, 999999, tzinfo=<UTC>)
Here is how we would handle the displaying conversions from view to template:
# views.py:
# Django
from django.views.generic import ListView
# App
from app_label.models import LocationReportingPeriod
class LocationReportingPeriodListView(ListView):
model = LocationReportingPeriod
template_name = 'app_label/period_list.html'
def get_queryset(self):
"""Retrieve the queryset and perform select_related on `location` since
we will be using it in the template.
"""
return super(
LocationReportingPeriodListView,
self
).get_queryset().select_related(
'location'
)
{% load tz %}
{% load i18n %}
{% block content %}
<table>
<thead>
<tr>
<th>{% trans "Location" %}</th>
<th>{% trans "Start" %}</th>
<th>{% trans "End" %}</th>
</tr>
</thead>
<tdata>
{% for period in object_list %}
{# Activate the timezone for each location #}
{% timezone period.location.timezone %}
<tr>
<td>{{ period.location.name }}</td>
<td>{{ period.start }}</td>
<td>{{ period.end }}</td>
</tr>
{% endtimezone %}
{% empty %}
<tr>
<td colspan=3>{% trans "No periods to display." %}</td>
</tr>
{% endfor %}
</tdata>
</table>
{% endblock content %}
Inspiration
On multiple occasions, I have had the need to store time zone information to the one model, then base another model’s datetime on that time zone. If you have ever had to deal with this, you will know how complicated this can be.
I created these fields to ease the process of manipulating times based on another field’s or models timezone choice. Instead of having to remember to use Model.clean_fields, we can now create the models with the validation built into the model field.
Contributors
Changelog
0.2 Multiple bug fixes based on testing.
0.1 Initial release.
License
The MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file django-timezone-utils-0.3.tar.gz
.
File metadata
- Download URL: django-timezone-utils-0.3.tar.gz
- Upload date:
- Size: 7.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8168d9a90d2a44f5d8cd293e3ef50109be2129a1b23b8d6123a094808b7857ff |
|
MD5 | ddb6d7a33e3daaf432bb9f80abe8ce03 |
|
BLAKE2b-256 | 8999f323d86b1156c87836b1cfd3ce0405adebc1eb3bbc5af2ab36b54fcac933 |