Skip to content

Commit fd920d6

Browse files
Preparation for v0.6 release.
1 parent a0d1c89 commit fd920d6

File tree

2 files changed

+36
-182
lines changed

2 files changed

+36
-182
lines changed

README.rst

Lines changed: 36 additions & 181 deletions
Original file line numberDiff line numberDiff line change
@@ -37,213 +37,67 @@ Please note that this project is currently marked as a development status of
3737
*Beta*. Suggestions, constructive criticism, and feedback are certainly
3838
welcomed and appreciated.
3939

40-
Installation
41-
------------
42-
43-
**django-timezone-utils** works with Django 1.4, 1.5, 1.6 and 1.7.
44-
45-
To install it, simply:
46-
47-
.. code-block:: bash
40+
Documentation
41+
-------------
4842

49-
$ pip install django-timezone-utils
43+
Documentation for django-timezone-utils is available at `Read the Docs <https://django-timezone-utils.readthedocs.org/>`_
5044

45+
Inspiration
46+
-----------
5147

52-
Then add ``timezone_utils`` to your ``settings.INSTALLED_APPS``:
48+
On multiple occasions, I have had the need to store time zone information to the
49+
one model, then base another model's datetime on that time zone. If you have
50+
ever had to deal with this, you will know how complicated this can be.
5351

54-
.. code-block:: python
52+
I created these fields to ease the process of manipulating times based on
53+
another field's or models timezone choice. Instead of having to remember to use
54+
``Model.clean_fields``, we can now create the models with the validation built
55+
into the model field.
5556

56-
INSTALLED_APPS = (
57-
...
58-
'timezone_utils',
59-
)
6057

61-
Example Usage
58+
Quick Example
6259
-------------
6360

64-
Imagine you have the models ``Location`` and ``LocationReportingPeriod``:
65-
6661
.. code-block:: python
6762
6863
from datetime import datetime
69-
from django.db import models
70-
from django.utils.translation import ugettext_lazy as _
7164
from timezone_utils.fields import LinkedTZDateTimeField, TimeZoneField
7265
from timezone_utils.choices import PRETTY_ALL_TIMEZONES_CHOICES
7366
7467
class Location(models.Model):
75-
company = models.ForeignKey(
76-
verbose_name='company',
77-
to='app_label.Company',
78-
related_name='locations',
79-
)
80-
name = models.CharField(
81-
verbose_name=_('name'),
82-
max_length=128,
83-
)
84-
timezone = TimeZoneField(
85-
verbose_name=_('timezone'),
86-
max_length=64,
87-
choices=PRETTY_ALL_TIMEZONES_CHOICES,
88-
)
89-
90-
created = LinkedTZDateTimeField(
91-
verbose_name=_('created'),
92-
auto_now=True,
93-
)
94-
modified = LinkedTZDateTimeField(
95-
verbose_name=_('modified'),
96-
auto_now_add=True,
97-
)
68+
# ...
69+
timezone = TimeZoneField(choices=PRETTY_ALL_TIMEZONES_CHOICES)
9870
9971
100-
def _get_reporting_period_timezone(obj):
101-
"""Called as `obj` being the LocationReportingPeriodInstance.
72+
def get_location_timezone(obj):
73+
"""Returns the Location.timezone field from above"""
10274
103-
Note:
104-
populate_from=lambda: instance: instance.location.timezone is not valid.
105-
106-
"""
10775
return obj.location.timezone
10876
10977
110-
class LocationReportingPeriod(models.Model)
111-
location = models.ForeignKey(
112-
verbose_name=_('location'),
113-
to='app_label.Location',
114-
related_name='reporting_periods',
115-
)
116-
start = LinkedTZDateTimeField(
117-
verbose_name=_('start'),
118-
# populate_from can also be a string value, provided that the string value
119-
# is a field on the same model
120-
populate_from=_get_reporting_period_timezone,
121-
# Time override must be a datetime.time instance
122-
time_override=datetime.min.time(),
123-
)
124-
end = LinkedTZDateTimeField(
125-
verbose_name=_('end'),
126-
populate_from=_get_reporting_period_timezone,
127-
# Time override must be a datetime.time instance
128-
time_override=datetime.max.time(),
129-
)
130-
131-
created = LinkedTZDateTimeField(
132-
verbose_name=_('created'),
133-
auto_now=True,
134-
)
135-
modified = LinkedTZDateTimeField(
136-
verbose_name=_('modified'),
137-
auto_now_add=True,
138-
)
139-
140-
class Meta:
141-
ordering = ('location', '-start')
142-
143-
In the above code example, if we set the value of ``Location.timezone`` to
144-
``US/Eastern``, each time a ``LocationReportingPeriod`` is saved, it will save
145-
the ``LocationReportingPeriod.start`` as the date 12:00AM in US/Eastern
146-
time zone, and the ``LocationReportingPeriod.end`` as 11:59:59.9999999PM in the
147-
US/Eastern time zone.
148-
149-
So assuming the date was 2015-01-01, we would be saving the following values to
150-
the database:
151-
152-
.. code-block:: python
153-
154-
# LocationReportingPeriod.start
155-
datetime.datetime(2015, 1, 1, 0, 0, tzinfo=<DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>)
78+
class LocationReport(models.Model):
79+
# ...
80+
location = models.ForeignKey('app_label.Location', related_name='reports')
15681
157-
# LocationReportingPeriod.end
158-
datetime.datetime(2015, 1, 1, 23, 59, 59, 999999, tzinfo=<DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>)
82+
# Populates from the Location.timezone
83+
timestamp = LinkedTZDateTimeField(populate_from=get_location_timezone)
15984
160-
For each location, let's say that the client wants to see the start and end of
161-
the reporting period in that location's time zone. One thing to remember is that
162-
just because you saved the LocationReportingPeriod start/end dates as a
163-
particular time zone, it does not mean that they will come that way from the
164-
database. For example, if your application's ``settings.TIME_ZONE = 'UTC'``,
165-
you would get back:
166-
167-
.. code-block:: python
168-
169-
print(period.start)
170-
datetime.datetime(2015, 1, 1, 5, 0, tzinfo=<UTC>)
171-
172-
print(period.end)
173-
datetime.datetime(2015, 1, 2, 4, 59, 59, 999999, tzinfo=<UTC>)
174-
175-
Here is how we would handle the displaying conversions from view to template:
176-
177-
.. code-block:: python
17885
179-
# views.py:
180-
# Django
181-
from django.views.generic import ListView
182-
183-
# App
184-
from app_label.models import LocationReportingPeriod
185-
186-
187-
class LocationReportingPeriodListView(ListView):
188-
model = LocationReportingPeriod
189-
template_name = 'app_label/period_list.html'
190-
191-
def get_queryset(self):
192-
"""Retrieve the queryset and perform select_related on `location` since
193-
we will be using it in the template.
194-
195-
"""
196-
return super(
197-
LocationReportingPeriodListView,
198-
self
199-
).get_queryset().select_related(
200-
'location'
201-
)
202-
203-
.. code-block:: django
204-
205-
{% load tz %}
206-
{% load i18n %}
207-
208-
{% block content %}
209-
<table>
210-
<thead>
211-
<tr>
212-
<th>{% trans "Location" %}</th>
213-
<th>{% trans "Start" %}</th>
214-
<th>{% trans "End" %}</th>
215-
</tr>
216-
</thead>
217-
<tdata>
218-
{% for period in object_list %}
219-
{# Activate the timezone for each location #}
220-
{% timezone period.location.timezone %}
221-
<tr>
222-
<td>{{ period.location.name }}</td>
223-
<td>{{ period.start }}</td>
224-
<td>{{ period.end }}</td>
225-
</tr>
226-
{% endtimezone %}
227-
{% empty %}
228-
<tr>
229-
<td colspan=3>{% trans "No periods to display." %}</td>
230-
</tr>
231-
{% endfor %}
232-
</tdata>
233-
</table>
234-
{% endblock content %}
86+
class LocationPeriod(models.Model):
87+
# ...
88+
location = models.ForeignKey('app_label.Location', related_name='periods')
23589
236-
Inspiration
237-
-----------
238-
239-
On multiple occasions, I have had the need to store time zone information to the
240-
one model, then base another model's datetime on that time zone. If you have
241-
ever had to deal with this, you will know how complicated this can be.
90+
# Sets the time to 12:00am in the location.timezone
91+
start = LinkedTZDateTimeField(
92+
populate_from=get_location_timezone,
93+
time_override=datetime.min.time()
94+
)
24295
243-
I created these fields to ease the process of manipulating times based on
244-
another field's or models timezone choice. Instead of having to remember to use
245-
``Model.clean_fields``, we can now create the models with the validation built
246-
into the model field.
96+
# Sets the time to 11:59:59.99999pm in the location.timezone
97+
end = LinkedTZDateTimeField(
98+
populate_from=get_location_timezone,
99+
time_override=datetime.max.time()
100+
)
247101
248102
249103
Contributors
@@ -253,6 +107,7 @@ Contributors
253107

254108
Changelog
255109
---------
110+
- 0.6 Added RTD documentation. LinkedTZDateTimeField now returns the datetime object in the overidden timezone and time.
256111
- 0.5 Bug fix: time override on datetime.min.time() failed to set time properly
257112
- 0.4 Removed support for Python 2.5
258113
- 0.3 Code cleanup.

docs/index.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,3 @@ Indices and tables
3030
==================
3131

3232
* :ref:`genindex`
33-
* :ref:`search`

0 commit comments

Comments
 (0)