@@ -37,213 +37,67 @@ Please note that this project is currently marked as a development status of
37
37
*Beta *. Suggestions, constructive criticism, and feedback are certainly
38
38
welcomed and appreciated.
39
39
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
+ -------------
48
42
49
- $ pip install django-timezone-utils
43
+ Documentation for django-timezone-utils is available at ` Read the Docs < https:// django-timezone-utils.readthedocs.org/ >`_
50
44
45
+ Inspiration
46
+ -----------
51
47
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.
53
51
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.
55
56
56
- INSTALLED_APPS = (
57
- ...
58
- ' timezone_utils' ,
59
- )
60
57
61
- Example Usage
58
+ Quick Example
62
59
-------------
63
60
64
- Imagine you have the models ``Location `` and ``LocationReportingPeriod ``:
65
-
66
61
.. code-block :: python
67
62
68
63
from datetime import datetime
69
- from django.db import models
70
- from django.utils.translation import ugettext_lazy as _
71
64
from timezone_utils.fields import LinkedTZDateTimeField, TimeZoneField
72
65
from timezone_utils.choices import PRETTY_ALL_TIMEZONES_CHOICES
73
66
74
67
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 )
98
70
99
71
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 """
102
74
103
- Note:
104
- populate_from=lambda: instance: instance.location.timezone is not valid.
105
-
106
- """
107
75
return obj.location.timezone
108
76
109
77
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' )
156
81
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 )
159
84
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
178
85
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' )
235
89
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
+ )
242
95
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
+ )
247
101
248
102
249
103
Contributors
@@ -253,6 +107,7 @@ Contributors
253
107
254
108
Changelog
255
109
---------
110
+ - 0.6 Added RTD documentation. LinkedTZDateTimeField now returns the datetime object in the overidden timezone and time.
256
111
- 0.5 Bug fix: time override on datetime.min.time() failed to set time properly
257
112
- 0.4 Removed support for Python 2.5
258
113
- 0.3 Code cleanup.
0 commit comments