Merge lp:~mhall119/loco-team-portal/team-events-localtime into lp:loco-team-portal

Proposed by Michael Hall
Status: Merged
Approved by: Michael Hall
Approved revision: 332
Merged at revision: 327
Proposed branch: lp:~mhall119/loco-team-portal/team-events-localtime
Merge into: lp:loco-team-portal
Diff against target: 338 lines (+165/-13)
11 files modified
INSTALL (+1/-1)
loco_directory/events/forms.py (+13/-0)
loco_directory/events/models.py (+38/-4)
loco_directory/templates/events/global_event_detail_basic.inc.html (+2/-2)
loco_directory/templates/events/team_event_detail_basic.inc.html (+3/-3)
loco_directory/templates/events/team_event_detail_comments.inc.html (+1/-1)
loco_directory/templates/events/team_event_list.inc.html (+2/-2)
loco_directory/templates/venues/venue_detail_basic.inc.html (+6/-0)
loco_directory/userprofiles/models.py (+17/-0)
loco_directory/venues/migrations/0005_add_venue_timezone.py (+47/-0)
loco_directory/venues/models.py (+35/-0)
To merge this branch: bzr merge lp:~mhall119/loco-team-portal/team-events-localtime
Reviewer Review Type Date Requested Status
Chris Johnston Approve
Daniel Holbach (community) Approve
Review via email: mp+41306@code.launchpad.net

Description of the change

Requires a minor db schema change to add tz CharField to Venue model.

To post a comment you must log in.
Revision history for this message
Michael Hall (mhall119) wrote :

May need python-tz installed on the server before deploying

331. By Michael Hall

Check for date difference between begin and end using localtime instead of UTC

332. By Michael Hall

Add python-tz to the list of packages to apt-get install

Revision history for this message
Daniel Holbach (dholbach) wrote :

Looks good to me.

Can somebody else try this out too? I didn't test with old data.

review: Approve
Revision history for this message
Chris Johnston (cjohnston) wrote :

It looks good to me.. Tested with events already scheduled, going back and changing the TZ of the venue, which seemed to work perfectly. Then went and created new events and new venues, which also worked well.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'INSTALL'
2--- INSTALL 2010-07-01 06:27:09 +0000
3+++ INSTALL 2010-11-19 13:47:33 +0000
4@@ -8,7 +8,7 @@
5 - sudo -u postgres createdb -O postgres loco_directory
6
7 Generally:
8- - sudo apt-get install python-django python-launchpadlib libjs-jquery-ui python-django-openid-auth python-django-south iso-codes
9+ - sudo apt-get install python-django python-launchpadlib libjs-jquery-ui python-django-openid-auth python-django-south iso-codes python-tz
10 - cd loco_directory
11 - cp local_settings.py.sample local_settings.py
12 # edit local_settings.py and set DATABASE_USER, DATABASE_PASSWORD, SECRET_KEY
13
14=== modified file 'loco_directory/events/forms.py'
15--- loco_directory/events/forms.py 2010-10-21 16:13:05 +0000
16+++ loco_directory/events/forms.py 2010-11-19 13:47:33 +0000
17@@ -8,6 +8,8 @@
18 from venues.models import Venue
19 from common.forms import RenderableMixin
20
21+import pytz
22+
23 def validate_tag(tag):
24 if tag.startswith('#'):
25 tag = tag[1:]
26@@ -64,6 +66,17 @@
27 self.fields['venue'].choices = self.grouped_venue_list()
28 from common.widgets import PopupRelatedFieldWidgetWrapper
29 self.fields['venue'].widget = PopupRelatedFieldWidgetWrapper(self.fields['venue'].widget, reverse('venue-new'))
30+
31+ self.initial['date_begin'] = self.instance.local_date_begin
32+ self.initial['date_end'] = self.instance.local_date_end
33+
34+ def clean(self):
35+ venue = self.cleaned_data.get('venue')
36+ begin = self.cleaned_data.get('date_begin')
37+ end = self.cleaned_data.get('date_end')
38+ self.cleaned_data['date_begin'] = venue.fromlocaltime(begin)
39+ self.cleaned_data['date_end'] = venue.fromlocaltime(end)
40+ return self.cleaned_data
41
42 def grouped_venue_list(self):
43 """
44
45=== modified file 'loco_directory/events/models.py'
46--- loco_directory/events/models.py 2010-10-14 20:26:51 +0000
47+++ loco_directory/events/models.py 2010-11-19 13:47:33 +0000
48@@ -86,13 +86,11 @@
49 """ manager for a team event """
50 def next_5_events(self):
51 """ a list with the next 5 events """
52-# XXX: Workaround for https://bugs.launchpad.net/loco-directory/+bug/531970
53- return self.filter(date_end__gt=datetime.datetime.now()-datetime.timedelta(days=1)).order_by('date_end')[:5]
54+ return self.filter(date_end__gt=datetime.datetime.now()).order_by('date_end')[:5]
55
56 def next_events(self):
57 """ a list with all upcoming team events """
58-# XXX: Workaround for https://bugs.launchpad.net/loco-directory/+bug/531970
59- return self.filter(date_end__gt=datetime.datetime.now()-datetime.timedelta(days=1)).order_by('date_end')
60+ return self.filter(date_end__gt=datetime.datetime.now()).order_by('date_end')
61
62 def history_events(self):
63 """ all team events in history """
64@@ -114,6 +112,30 @@
65 def __unicode__(self):
66 return "%s %s %s" % (self.name, self.venue, self.date_begin or "")
67
68+ def get_local_begin(self):
69+ if self.venue:
70+ return self.venue.tolocaltime(self.date_begin)
71+ else:
72+ return self.date_begin
73+ def set_local_begin(self, local_begin):
74+ if self.venue:
75+ self.date_begin = self.venue.fromlocaltime(local_begin)
76+ else:
77+ self.date_begin = local_begin
78+ local_date_begin = property(get_local_begin)
79+
80+ def get_local_end(self):
81+ if self.venue:
82+ return self.venue.tolocaltime(self.date_end)
83+ else:
84+ return self.date_end
85+ def set_local_end(self, local_end):
86+ if self.venue:
87+ self.date_end = self.venue.fromlocaltime(local_end)
88+ else:
89+ self.date_end = local_end
90+ local_date_end = property(get_local_end, set_local_end)
91+
92 @models.permalink
93 def get_absolute_url(self):
94 return ('team-event-detail', [str(self.id)])
95@@ -148,6 +170,18 @@
96 commenter_profile = models.ForeignKey(UserProfile, null=True)
97 comment = models.TextField(help_text=_('Comment this Event'), db_index=True)
98
99+ def get_local_created(self):
100+ if self.team_event.venue:
101+ return self.team_event.venue.tolocaltime(self.date_created)
102+ else:
103+ return self.date_created
104+ def set_local_created(self, local_created):
105+ if self.team_event.venue:
106+ self.date_created = self.team_event.venue.fromlocaltime(local_created)
107+ else:
108+ self.date_created = local_created
109+ local_date_created = property(get_local_created, set_local_created)
110+
111 def __unicode__(self):
112 return "Team Event: %s . Comment: %s" % (self.team_event.name, self.comment)
113
114
115=== modified file 'loco_directory/templates/events/global_event_detail_basic.inc.html'
116--- loco_directory/templates/events/global_event_detail_basic.inc.html 2010-09-09 19:39:40 +0000
117+++ loco_directory/templates/events/global_event_detail_basic.inc.html 2010-11-19 13:47:33 +0000
118@@ -6,9 +6,9 @@
119 <th class="form-item-label" scope="row"><label>{% trans "When:" %}</label></th>
120 <td class="form-item-value">
121 {% ifequal global_event_object.date_begin|date global_event_object.date_end|date %}
122- {{ global_event_object.date_begin|date:"D, d N Y H:i" }} - {{ global_event_object.date_end|date:"H:i O" }}
123+ {{ global_event_object.date_begin|date:"D, d N Y H:i" }} - {{ global_event_object.date_end|date:"H:i T"}}
124 {% else %}
125- {{ global_event_object.date_begin|date:"D, d N Y H:i" }} - {{ global_event_object.date_end|date:"D, d N Y H:i O" }}
126+ {{ global_event_object.date_begin|date:"D, d N Y H:i" }} - {{ global_event_object.date_end|date:"D, d N Y H:i T"}}
127 {% endifequal %}
128 </td>
129 </tr>
130
131=== modified file 'loco_directory/templates/events/team_event_detail_basic.inc.html'
132--- loco_directory/templates/events/team_event_detail_basic.inc.html 2010-08-17 08:48:39 +0000
133+++ loco_directory/templates/events/team_event_detail_basic.inc.html 2010-11-19 13:47:33 +0000
134@@ -5,10 +5,10 @@
135 <tr>
136 <th class="form-item-label" scope="row"><label>{% trans "When:" %}</label></th>
137 <td class="form-item-value">
138- {% ifequal team_event_object.date_begin|date team_event_object.date_end|date %}
139- {{ team_event_object.date_begin|date:"D, d N Y H:i" }} - {{ team_event_object.date_end|date:"H:i O" }}
140+ {% ifequal team_event_object.local_date_begin|date team_event_object.local_date_end|date %}
141+ {{ team_event_object.local_date_begin|date:"D, d N Y H:i" }} - {{ team_event_object.local_date_end|date:"H:i T (O)" }}
142 {% else %}
143- {{ team_event_object.date_begin|date:"D, d N Y H:i" }} - {{ team_event_object.date_end|date:"D, d N Y H:i O" }}
144+ {{ team_event_object.local_date_begin|date:"D, d N Y H:i" }} - {{ team_event_object.local_date_end|date:"D, d N Y H:i T (O)" }}
145 {% endifequal %}
146 </td>
147 </tr>
148
149=== modified file 'loco_directory/templates/events/team_event_detail_comments.inc.html'
150--- loco_directory/templates/events/team_event_detail_comments.inc.html 2010-11-12 11:26:24 +0000
151+++ loco_directory/templates/events/team_event_detail_comments.inc.html 2010-11-19 13:47:33 +0000
152@@ -6,7 +6,7 @@
153 <a href="{% url team-event-comment-new team_event_object.id %}#comment">{% trans "Add Comment" %}</a>
154 </td>
155 </tr>
156-{% regroup team_event_object.teameventcomment_set.all by date_created|date:"D d M Y" as comment_list %}
157+{% regroup team_event_object.teameventcomment_set.all by local_date_created|date:"D d M Y" as comment_list %}
158
159 {% for comment_date in comment_list %}
160 <tr>
161
162=== modified file 'loco_directory/templates/events/team_event_list.inc.html'
163--- loco_directory/templates/events/team_event_list.inc.html 2010-08-17 00:25:27 +0000
164+++ loco_directory/templates/events/team_event_list.inc.html 2010-11-19 13:47:33 +0000
165@@ -10,8 +10,8 @@
166 {% for team_event in team_event_list %}
167 <tr class="team_event_list_row {% cycle "odd" "even" %}">
168 <td class="event_name"><a title="{% trans "more information about this event" %}" href="{{ team_event.get_absolute_url }}">{{ team_event.name }}</a></td>
169-<td class="event_begin">{{team_event.date_begin|date}} {{ team_event.date_begin|date:"H:i T"}}</td>
170-<td class="event_end">{{team_event.date_end|date}} {{ team_event.date_end|date:"H:i T"}}</td>
171+<td class="event_begin">{{team_event.local_date_begin|date}} {{ team_event.local_date_begin|date:"H:i T"}}</td>
172+<td class="event_end">{{team_event.local_date_end|date}} {{ team_event.local_date_end|date:"H:i T"}}</td>
173 <td class="event_global">{% if team_event.global_event %}<a href="{{ team_event.global_event.get_absolute_url }}">{{ team_event.global_event.name}}</a>{% else %}--{% endif %}</td>
174 <td class="event_teams">{% for team in team_event.teams.all %}<a title="{% trans "more information about this team" %}" href="{{ team.get_absolute_url }}">{{ team.name }}</a>{% if not forloop.last %}<br/>{% endif %}{% endfor %}</td>
175 </tr>
176
177=== modified file 'loco_directory/templates/venues/venue_detail_basic.inc.html'
178--- loco_directory/templates/venues/venue_detail_basic.inc.html 2010-08-19 23:02:12 +0000
179+++ loco_directory/templates/venues/venue_detail_basic.inc.html 2010-11-19 13:47:33 +0000
180@@ -25,6 +25,12 @@
181 <td class="form-item-value">{{ venue_object.country }}</td>
182 </tr>
183 {% endif %}
184+ {% if venue_object.tz %}
185+ <tr>
186+ <th class="form-item-label" scope="row"><label>{% trans "Timezone:" %}</label></th>
187+ <td class="form-item-value">{{ venue_object.tz }}</td>
188+ </tr>
189+ {% endif %}
190 {% if venue_object.venue_url %}
191 <tr>
192 <th class="form-item-label" scope="row"><label>{% trans "Homepage:" %}</label></th>
193
194=== modified file 'loco_directory/userprofiles/models.py'
195--- loco_directory/userprofiles/models.py 2010-08-28 17:43:41 +0000
196+++ loco_directory/userprofiles/models.py 2010-11-19 13:47:33 +0000
197@@ -3,6 +3,8 @@
198 from django.contrib.auth import models as auth_models
199 # Create your models here.
200
201+import pytz
202+
203 class UserProfile(models.Model):
204 " Store profile information about a user "
205
206@@ -27,6 +29,21 @@
207 return "%s" % self.user.username
208 except:
209 return "Unknown Profile"
210+
211+ def get_timezone(self):
212+ try:
213+ return pytz.timezone(self.tz)
214+ except:
215+ return pytz.utc
216+ timezone = property(get_timezone)
217+
218+ def tolocaltime(self, dt):
219+ as_utc = pytz.utc.localize(dt)
220+ return as_utc.astimezone(self.timezone)
221+
222+ def fromlocaltime(self, dt):
223+ local = self.timezone.localize(dt)
224+ return local.astimezone(pytz.utc)
225
226 def _getUserProfile(self):
227 if not self.is_authenticated():
228
229=== added file 'loco_directory/venues/migrations/0005_add_venue_timezone.py'
230--- loco_directory/venues/migrations/0005_add_venue_timezone.py 1970-01-01 00:00:00 +0000
231+++ loco_directory/venues/migrations/0005_add_venue_timezone.py 2010-11-19 13:47:33 +0000
232@@ -0,0 +1,47 @@
233+
234+from south.db import db
235+from django.db import models
236+from venues.models import *
237+
238+class Migration:
239+
240+ def forwards(self, orm):
241+
242+ # Adding field 'Venue.tz'
243+ db.add_column('venues_venue', 'tz', orm['venues.venue:tz'])
244+
245+
246+
247+ def backwards(self, orm):
248+
249+ # Deleting field 'Venue.tz'
250+ db.delete_column('venues_venue', 'tz')
251+
252+
253+
254+ models = {
255+ 'teams.continent': {
256+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
257+ 'name': ('django.db.models.fields.TextField', [], {'max_length': '50'})
258+ },
259+ 'teams.country': {
260+ 'continents': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['teams.Continent']", 'symmetrical': 'False'}),
261+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
262+ 'name': ('django.db.models.fields.TextField', [], {'max_length': '100'})
263+ },
264+ 'venues.venue': {
265+ 'Meta': {'unique_together': "(('name', 'country', 'city'), ('longitude', 'latitude'))"},
266+ 'address': ('django.db.models.fields.CharField', [], {'max_length': '150', 'null': 'True', 'blank': 'True'}),
267+ 'city': ('django.db.models.fields.CharField', [], {'max_length': '150', 'null': 'True', 'blank': 'True'}),
268+ 'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
269+ 'country': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['teams.Country']", 'null': 'True'}),
270+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
271+ 'latitude': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
272+ 'longitude': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
273+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
274+ 'tz': ('django.db.models.fields.CharField', [], {'default': "'UTC'", 'max_length': '32'}),
275+ 'venue_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'})
276+ }
277+ }
278+
279+ complete_apps = ['venues']
280
281=== modified file 'loco_directory/venues/models.py'
282--- loco_directory/venues/models.py 2010-07-29 13:54:09 +0000
283+++ loco_directory/venues/models.py 2010-11-19 13:47:33 +0000
284@@ -3,6 +3,8 @@
285 from django.db.models import permalink
286
287 from teams.models import Country
288+import pytz
289+
290
291 class VenueManager(models.Manager):
292 """
293@@ -20,6 +22,7 @@
294 address = models.CharField(help_text=_('Address with Street and Number'), max_length=150, null=True, blank=True)
295 longitude = models.FloatField(help_text=_('Longitude in Degrees East'), null=True, blank=True)
296 latitude = models.FloatField(help_text=_('Latitude in Degrees North'), null=True, blank=True)
297+ tz = models.CharField(max_length=32, verbose_name=_('Timezone'), default='UTC', choices=[(tz, tz) for tz in pytz.all_timezones], blank=False, null=False)
298 venue_url = models.URLField(help_text=_('URL for the Venue Homepage'), verbose_name=_('URL of the Venue'), max_length=200, verify_exists=False, blank=True, null=True)
299 comment = models.TextField(help_text=_('Comment about the Venue'), blank=True, null=True)
300
301@@ -40,5 +43,37 @@
302 """ get the absolute url for the venue """
303 return ('venue-detail', [self.id])
304
305+ def get_timezone(self):
306+ try:
307+ return pytz.timezone(self.tz)
308+ except:
309+ return pytz.utc
310+ timezone = property(get_timezone)
311+
312+ def tolocaltime(self, dt):
313+ as_utc = pytz.utc.localize(dt)
314+ return as_utc.astimezone(self.timezone)
315+
316+ def fromlocaltime(self, dt):
317+ local = self.timezone.localize(dt)
318+ return local.astimezone(pytz.utc)
319+
320+ def save(self, *args, **kargs):
321+ if self.id:
322+ from events.models import TeamEvent
323+ old = Venue.objects.get(id=self.id)
324+ retval = super(Venue, self).save(*args, **kargs)
325+ if old.tz != self.tz:
326+ events = TeamEvent.objects.filter(venue=self)
327+ for e in events:
328+ old_offset = old.tolocaltime(e.date_begin).utcoffset()
329+ new_offset = self.tolocaltime(e.date_begin).utcoffset()
330+ e.date_begin = e.date_begin + (old_offset - new_offset)
331+ e.date_end = e.date_end + (old_offset - new_offset)
332+ e.save()
333+ else:
334+ retval = super(Venue, self).save(*args, **kargs)
335+ return retval
336+
337 def venues_without_country():
338 return Venue.objects.filter(country__isnull=True)

Subscribers

People subscribed via source and target branches