1
from __future__ import unicode_literals
8
from xml.dom.minidom import parseString
15
from django.conf import settings
16
from django.core import serializers
17
from django.core.urlresolvers import reverse
18
from django.db import connection
19
from django.db.models import Min, Max
20
from django.http import HttpRequest
21
from django.template import Context, RequestContext, Template, TemplateSyntaxError
22
from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature
23
from django.test.utils import override_settings
24
from django.utils import six
25
from django.utils import timezone
26
from django.utils.tzinfo import FixedOffset
27
from django.utils.unittest import skipIf, skipUnless
29
from .forms import EventForm, EventSplitForm, EventModelForm
30
from .models import Event, MaybeEvent, Session, SessionEvent, Timestamp, AllDayEvent
33
# These tests use the EAT (Eastern Africa Time) and ICT (Indochina Time)
34
# who don't have Daylight Saving Time, so we can represent them easily
35
# with FixedOffset, and use them directly as tzinfo in the constructors.
37
# settings.TIME_ZONE is forced to EAT. Most tests use a variant of
38
# datetime.datetime(2011, 9, 1, 13, 20, 30), which translates to
39
# 10:20:30 in UTC and 17:20:30 in ICT.
42
EAT = FixedOffset(180) # Africa/Nairobi
43
ICT = FixedOffset(420) # Asia/Bangkok
45
TZ_SUPPORT = hasattr(time, 'tzset')
47
# On OSes that don't provide tzset (Windows), we can't set the timezone
48
# in which the program runs. As a consequence, we must skip tests that
49
# don't enforce a specific timezone (with timezone.override or equivalent),
50
# or attempt to interpret naive datetimes in the default timezone.
52
requires_tz_support = skipUnless(TZ_SUPPORT,
53
"This test relies on the ability to run a program in an arbitrary "
54
"time zone, but your operating system isn't able to do that.")
57
@override_settings(TIME_ZONE='Africa/Nairobi', USE_TZ=False)
58
class LegacyDatabaseTests(TestCase):
60
def test_naive_datetime(self):
61
dt = datetime.datetime(2011, 9, 1, 13, 20, 30)
62
Event.objects.create(dt=dt)
63
event = Event.objects.get()
64
self.assertEqual(event.dt, dt)
66
@skipUnlessDBFeature('supports_microsecond_precision')
67
def test_naive_datetime_with_microsecond(self):
68
dt = datetime.datetime(2011, 9, 1, 13, 20, 30, 405060)
69
Event.objects.create(dt=dt)
70
event = Event.objects.get()
71
self.assertEqual(event.dt, dt)
73
@skipIfDBFeature('supports_microsecond_precision')
74
def test_naive_datetime_with_microsecond_unsupported(self):
75
dt = datetime.datetime(2011, 9, 1, 13, 20, 30, 405060)
76
Event.objects.create(dt=dt)
77
event = Event.objects.get()
78
# microseconds are lost during a round-trip in the database
79
self.assertEqual(event.dt, dt.replace(microsecond=0))
81
@skipUnlessDBFeature('supports_timezones')
82
def test_aware_datetime_in_local_timezone(self):
83
dt = datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT)
84
Event.objects.create(dt=dt)
85
event = Event.objects.get()
86
self.assertIsNone(event.dt.tzinfo)
87
# interpret the naive datetime in local time to get the correct value
88
self.assertEqual(event.dt.replace(tzinfo=EAT), dt)
90
@skipUnlessDBFeature('supports_timezones')
91
@skipUnlessDBFeature('supports_microsecond_precision')
92
def test_aware_datetime_in_local_timezone_with_microsecond(self):
93
dt = datetime.datetime(2011, 9, 1, 13, 20, 30, 405060, tzinfo=EAT)
94
Event.objects.create(dt=dt)
95
event = Event.objects.get()
96
self.assertIsNone(event.dt.tzinfo)
97
# interpret the naive datetime in local time to get the correct value
98
self.assertEqual(event.dt.replace(tzinfo=EAT), dt)
100
# This combination actually never happens.
101
@skipUnlessDBFeature('supports_timezones')
102
@skipIfDBFeature('supports_microsecond_precision')
103
def test_aware_datetime_in_local_timezone_with_microsecond_unsupported(self):
104
dt = datetime.datetime(2011, 9, 1, 13, 20, 30, 405060, tzinfo=EAT)
105
Event.objects.create(dt=dt)
106
event = Event.objects.get()
107
self.assertIsNone(event.dt.tzinfo)
108
# interpret the naive datetime in local time to get the correct value
109
# microseconds are lost during a round-trip in the database
110
self.assertEqual(event.dt.replace(tzinfo=EAT), dt.replace(microsecond=0))
112
@skipUnlessDBFeature('supports_timezones')
113
@skipIfDBFeature('needs_datetime_string_cast')
114
def test_aware_datetime_in_utc(self):
115
dt = datetime.datetime(2011, 9, 1, 10, 20, 30, tzinfo=UTC)
116
Event.objects.create(dt=dt)
117
event = Event.objects.get()
118
self.assertIsNone(event.dt.tzinfo)
119
# interpret the naive datetime in local time to get the correct value
120
self.assertEqual(event.dt.replace(tzinfo=EAT), dt)
122
# This combination is no longer possible since timezone support
123
# was removed from the SQLite backend -- it didn't work.
124
@skipUnlessDBFeature('supports_timezones')
125
@skipUnlessDBFeature('needs_datetime_string_cast')
126
def test_aware_datetime_in_utc_unsupported(self):
127
dt = datetime.datetime(2011, 9, 1, 10, 20, 30, tzinfo=UTC)
128
Event.objects.create(dt=dt)
129
event = Event.objects.get()
130
self.assertIsNone(event.dt.tzinfo)
131
# django.db.backend.utils.typecast_dt will just drop the
132
# timezone, so a round-trip in the database alters the data (!)
133
# interpret the naive datetime in local time and you get a wrong value
134
self.assertNotEqual(event.dt.replace(tzinfo=EAT), dt)
135
# interpret the naive datetime in original time to get the correct value
136
self.assertEqual(event.dt.replace(tzinfo=UTC), dt)
138
@skipUnlessDBFeature('supports_timezones')
139
@skipIfDBFeature('needs_datetime_string_cast')
140
def test_aware_datetime_in_other_timezone(self):
141
dt = datetime.datetime(2011, 9, 1, 17, 20, 30, tzinfo=ICT)
142
Event.objects.create(dt=dt)
143
event = Event.objects.get()
144
self.assertIsNone(event.dt.tzinfo)
145
# interpret the naive datetime in local time to get the correct value
146
self.assertEqual(event.dt.replace(tzinfo=EAT), dt)
148
# This combination is no longer possible since timezone support
149
# was removed from the SQLite backend -- it didn't work.
150
@skipUnlessDBFeature('supports_timezones')
151
@skipUnlessDBFeature('needs_datetime_string_cast')
152
def test_aware_datetime_in_other_timezone_unsupported(self):
153
dt = datetime.datetime(2011, 9, 1, 17, 20, 30, tzinfo=ICT)
154
Event.objects.create(dt=dt)
155
event = Event.objects.get()
156
self.assertIsNone(event.dt.tzinfo)
157
# django.db.backend.utils.typecast_dt will just drop the
158
# timezone, so a round-trip in the database alters the data (!)
159
# interpret the naive datetime in local time and you get a wrong value
160
self.assertNotEqual(event.dt.replace(tzinfo=EAT), dt)
161
# interpret the naive datetime in original time to get the correct value
162
self.assertEqual(event.dt.replace(tzinfo=ICT), dt)
164
@skipIfDBFeature('supports_timezones')
165
def test_aware_datetime_unspported(self):
166
dt = datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT)
167
with self.assertRaises(ValueError):
168
Event.objects.create(dt=dt)
170
def test_auto_now_and_auto_now_add(self):
171
now = datetime.datetime.now()
172
past = now - datetime.timedelta(seconds=2)
173
future = now + datetime.timedelta(seconds=2)
174
Timestamp.objects.create()
175
ts = Timestamp.objects.get()
176
self.assertLess(past, ts.created)
177
self.assertLess(past, ts.updated)
178
self.assertGreater(future, ts.updated)
179
self.assertGreater(future, ts.updated)
181
def test_query_filter(self):
182
dt1 = datetime.datetime(2011, 9, 1, 12, 20, 30)
183
dt2 = datetime.datetime(2011, 9, 1, 14, 20, 30)
184
Event.objects.create(dt=dt1)
185
Event.objects.create(dt=dt2)
186
self.assertEqual(Event.objects.filter(dt__gte=dt1).count(), 2)
187
self.assertEqual(Event.objects.filter(dt__gt=dt1).count(), 1)
188
self.assertEqual(Event.objects.filter(dt__gte=dt2).count(), 1)
189
self.assertEqual(Event.objects.filter(dt__gt=dt2).count(), 0)
191
def test_query_date_related_filters(self):
192
Event.objects.create(dt=datetime.datetime(2011, 1, 1, 1, 30, 0))
193
Event.objects.create(dt=datetime.datetime(2011, 1, 1, 4, 30, 0))
194
self.assertEqual(Event.objects.filter(dt__year=2011).count(), 2)
195
self.assertEqual(Event.objects.filter(dt__month=1).count(), 2)
196
self.assertEqual(Event.objects.filter(dt__day=1).count(), 2)
197
self.assertEqual(Event.objects.filter(dt__week_day=7).count(), 2)
199
def test_query_aggregation(self):
200
# Only min and max make sense for datetimes.
201
Event.objects.create(dt=datetime.datetime(2011, 9, 1, 23, 20, 20))
202
Event.objects.create(dt=datetime.datetime(2011, 9, 1, 13, 20, 30))
203
Event.objects.create(dt=datetime.datetime(2011, 9, 1, 3, 20, 40))
204
result = Event.objects.all().aggregate(Min('dt'), Max('dt'))
205
self.assertEqual(result, {
206
'dt__min': datetime.datetime(2011, 9, 1, 3, 20, 40),
207
'dt__max': datetime.datetime(2011, 9, 1, 23, 20, 20),
210
def test_query_annotation(self):
211
# Only min and max make sense for datetimes.
212
morning = Session.objects.create(name='morning')
213
afternoon = Session.objects.create(name='afternoon')
214
SessionEvent.objects.create(dt=datetime.datetime(2011, 9, 1, 23, 20, 20), session=afternoon)
215
SessionEvent.objects.create(dt=datetime.datetime(2011, 9, 1, 13, 20, 30), session=afternoon)
216
SessionEvent.objects.create(dt=datetime.datetime(2011, 9, 1, 3, 20, 40), session=morning)
217
morning_min_dt = datetime.datetime(2011, 9, 1, 3, 20, 40)
218
afternoon_min_dt = datetime.datetime(2011, 9, 1, 13, 20, 30)
219
self.assertQuerysetEqual(
220
Session.objects.annotate(dt=Min('events__dt')).order_by('dt'),
221
[morning_min_dt, afternoon_min_dt],
222
transform=lambda d: d.dt)
223
self.assertQuerysetEqual(
224
Session.objects.annotate(dt=Min('events__dt')).filter(dt__lt=afternoon_min_dt),
226
transform=lambda d: d.dt)
227
self.assertQuerysetEqual(
228
Session.objects.annotate(dt=Min('events__dt')).filter(dt__gte=afternoon_min_dt),
230
transform=lambda d: d.dt)
232
def test_query_dates(self):
233
Event.objects.create(dt=datetime.datetime(2011, 1, 1, 1, 30, 0))
234
Event.objects.create(dt=datetime.datetime(2011, 1, 1, 4, 30, 0))
235
self.assertQuerysetEqual(Event.objects.dates('dt', 'year'),
236
[datetime.datetime(2011, 1, 1)], transform=lambda d: d)
237
self.assertQuerysetEqual(Event.objects.dates('dt', 'month'),
238
[datetime.datetime(2011, 1, 1)], transform=lambda d: d)
239
self.assertQuerysetEqual(Event.objects.dates('dt', 'day'),
240
[datetime.datetime(2011, 1, 1)], transform=lambda d: d)
242
def test_raw_sql(self):
243
# Regression test for #17755
244
dt = datetime.datetime(2011, 9, 1, 13, 20, 30)
245
event = Event.objects.create(dt=dt)
246
self.assertQuerysetEqual(
247
Event.objects.raw('SELECT * FROM timezones_event WHERE dt = %s', [dt]),
249
transform=lambda d: d)
251
def test_filter_date_field_with_aware_datetime(self):
252
# Regression test for #17742
253
day = datetime.date(2011, 9, 1)
254
event = AllDayEvent.objects.create(day=day)
255
# This is 2011-09-02T01:30:00+03:00 in EAT
256
dt = datetime.datetime(2011, 9, 1, 22, 30, 0, tzinfo=UTC)
257
self.assertTrue(AllDayEvent.objects.filter(day__gte=dt).exists())
260
@override_settings(TIME_ZONE='Africa/Nairobi', USE_TZ=True)
261
class NewDatabaseTests(TestCase):
264
def test_naive_datetime(self):
265
dt = datetime.datetime(2011, 9, 1, 13, 20, 30)
266
with warnings.catch_warnings(record=True) as recorded:
267
warnings.simplefilter('always')
268
Event.objects.create(dt=dt)
269
self.assertEqual(len(recorded), 1)
270
msg = str(recorded[0].message)
271
self.assertTrue(msg.startswith("DateTimeField received a naive datetime"))
272
event = Event.objects.get()
273
# naive datetimes are interpreted in local time
274
self.assertEqual(event.dt, dt.replace(tzinfo=EAT))
277
def test_datetime_from_date(self):
278
dt = datetime.date(2011, 9, 1)
279
with warnings.catch_warnings(record=True) as recorded:
280
warnings.simplefilter('always')
281
Event.objects.create(dt=dt)
282
self.assertEqual(len(recorded), 1)
283
msg = str(recorded[0].message)
284
self.assertTrue(msg.startswith("DateTimeField received a naive datetime"))
285
event = Event.objects.get()
286
self.assertEqual(event.dt, datetime.datetime(2011, 9, 1, tzinfo=EAT))
289
@skipUnlessDBFeature('supports_microsecond_precision')
290
def test_naive_datetime_with_microsecond(self):
291
dt = datetime.datetime(2011, 9, 1, 13, 20, 30, 405060)
292
with warnings.catch_warnings(record=True) as recorded:
293
warnings.simplefilter('always')
294
Event.objects.create(dt=dt)
295
self.assertEqual(len(recorded), 1)
296
msg = str(recorded[0].message)
297
self.assertTrue(msg.startswith("DateTimeField received a naive datetime"))
298
event = Event.objects.get()
299
# naive datetimes are interpreted in local time
300
self.assertEqual(event.dt, dt.replace(tzinfo=EAT))
303
@skipIfDBFeature('supports_microsecond_precision')
304
def test_naive_datetime_with_microsecond_unsupported(self):
305
dt = datetime.datetime(2011, 9, 1, 13, 20, 30, 405060)
306
with warnings.catch_warnings(record=True) as recorded:
307
warnings.simplefilter('always')
308
Event.objects.create(dt=dt)
309
self.assertEqual(len(recorded), 1)
310
msg = str(recorded[0].message)
311
self.assertTrue(msg.startswith("DateTimeField received a naive datetime"))
312
event = Event.objects.get()
313
# microseconds are lost during a round-trip in the database
314
# naive datetimes are interpreted in local time
315
self.assertEqual(event.dt, dt.replace(microsecond=0, tzinfo=EAT))
317
def test_aware_datetime_in_local_timezone(self):
318
dt = datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT)
319
Event.objects.create(dt=dt)
320
event = Event.objects.get()
321
self.assertEqual(event.dt, dt)
323
@skipUnlessDBFeature('supports_microsecond_precision')
324
def test_aware_datetime_in_local_timezone_with_microsecond(self):
325
dt = datetime.datetime(2011, 9, 1, 13, 20, 30, 405060, tzinfo=EAT)
326
Event.objects.create(dt=dt)
327
event = Event.objects.get()
328
self.assertEqual(event.dt, dt)
330
@skipIfDBFeature('supports_microsecond_precision')
331
def test_aware_datetime_in_local_timezone_with_microsecond_unsupported(self):
332
dt = datetime.datetime(2011, 9, 1, 13, 20, 30, 405060, tzinfo=EAT)
333
Event.objects.create(dt=dt)
334
event = Event.objects.get()
335
# microseconds are lost during a round-trip in the database
336
self.assertEqual(event.dt, dt.replace(microsecond=0))
338
def test_aware_datetime_in_utc(self):
339
dt = datetime.datetime(2011, 9, 1, 10, 20, 30, tzinfo=UTC)
340
Event.objects.create(dt=dt)
341
event = Event.objects.get()
342
self.assertEqual(event.dt, dt)
344
def test_aware_datetime_in_other_timezone(self):
345
dt = datetime.datetime(2011, 9, 1, 17, 20, 30, tzinfo=ICT)
346
Event.objects.create(dt=dt)
347
event = Event.objects.get()
348
self.assertEqual(event.dt, dt)
350
def test_auto_now_and_auto_now_add(self):
352
past = now - datetime.timedelta(seconds=2)
353
future = now + datetime.timedelta(seconds=2)
354
Timestamp.objects.create()
355
ts = Timestamp.objects.get()
356
self.assertLess(past, ts.created)
357
self.assertLess(past, ts.updated)
358
self.assertGreater(future, ts.updated)
359
self.assertGreater(future, ts.updated)
361
def test_query_filter(self):
362
dt1 = datetime.datetime(2011, 9, 1, 12, 20, 30, tzinfo=EAT)
363
dt2 = datetime.datetime(2011, 9, 1, 14, 20, 30, tzinfo=EAT)
364
Event.objects.create(dt=dt1)
365
Event.objects.create(dt=dt2)
366
self.assertEqual(Event.objects.filter(dt__gte=dt1).count(), 2)
367
self.assertEqual(Event.objects.filter(dt__gt=dt1).count(), 1)
368
self.assertEqual(Event.objects.filter(dt__gte=dt2).count(), 1)
369
self.assertEqual(Event.objects.filter(dt__gt=dt2).count(), 0)
371
@skipIf(pytz is None, "this test requires pytz")
372
def test_query_filter_with_pytz_timezones(self):
373
tz = pytz.timezone('Europe/Paris')
374
dt = datetime.datetime(2011, 9, 1, 12, 20, 30, tzinfo=tz)
375
Event.objects.create(dt=dt)
376
next = dt + datetime.timedelta(seconds=3)
377
prev = dt - datetime.timedelta(seconds=3)
378
self.assertEqual(Event.objects.filter(dt__exact=dt).count(), 1)
379
self.assertEqual(Event.objects.filter(dt__exact=next).count(), 0)
380
self.assertEqual(Event.objects.filter(dt__in=(prev, next)).count(), 0)
381
self.assertEqual(Event.objects.filter(dt__in=(prev, dt, next)).count(), 1)
382
self.assertEqual(Event.objects.filter(dt__range=(prev, next)).count(), 1)
385
def test_query_filter_with_naive_datetime(self):
386
dt = datetime.datetime(2011, 9, 1, 12, 20, 30, tzinfo=EAT)
387
Event.objects.create(dt=dt)
388
dt = dt.replace(tzinfo=None)
389
with warnings.catch_warnings(record=True) as recorded:
390
warnings.simplefilter('always')
391
# naive datetimes are interpreted in local time
392
self.assertEqual(Event.objects.filter(dt__exact=dt).count(), 1)
393
self.assertEqual(Event.objects.filter(dt__lte=dt).count(), 1)
394
self.assertEqual(Event.objects.filter(dt__gt=dt).count(), 0)
395
self.assertEqual(len(recorded), 3)
396
for warning in recorded:
397
msg = str(warning.message)
398
self.assertTrue(msg.startswith("DateTimeField received a naive datetime"))
400
def test_query_date_related_filters(self):
401
# These two dates fall in the same day in EAT, but in different days,
402
# years and months in UTC, and aggregation is performed in UTC when
403
# time zone support is enabled. This test could be changed if the
404
# implementation is changed to perform the aggregation is local time.
405
Event.objects.create(dt=datetime.datetime(2011, 1, 1, 1, 30, 0, tzinfo=EAT))
406
Event.objects.create(dt=datetime.datetime(2011, 1, 1, 4, 30, 0, tzinfo=EAT))
407
self.assertEqual(Event.objects.filter(dt__year=2011).count(), 1)
408
self.assertEqual(Event.objects.filter(dt__month=1).count(), 1)
409
self.assertEqual(Event.objects.filter(dt__day=1).count(), 1)
410
self.assertEqual(Event.objects.filter(dt__week_day=7).count(), 1)
412
def test_query_aggregation(self):
413
# Only min and max make sense for datetimes.
414
Event.objects.create(dt=datetime.datetime(2011, 9, 1, 23, 20, 20, tzinfo=EAT))
415
Event.objects.create(dt=datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT))
416
Event.objects.create(dt=datetime.datetime(2011, 9, 1, 3, 20, 40, tzinfo=EAT))
417
result = Event.objects.all().aggregate(Min('dt'), Max('dt'))
418
self.assertEqual(result, {
419
'dt__min': datetime.datetime(2011, 9, 1, 3, 20, 40, tzinfo=EAT),
420
'dt__max': datetime.datetime(2011, 9, 1, 23, 20, 20, tzinfo=EAT),
423
def test_query_annotation(self):
424
# Only min and max make sense for datetimes.
425
morning = Session.objects.create(name='morning')
426
afternoon = Session.objects.create(name='afternoon')
427
SessionEvent.objects.create(dt=datetime.datetime(2011, 9, 1, 23, 20, 20, tzinfo=EAT), session=afternoon)
428
SessionEvent.objects.create(dt=datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT), session=afternoon)
429
SessionEvent.objects.create(dt=datetime.datetime(2011, 9, 1, 3, 20, 40, tzinfo=EAT), session=morning)
430
morning_min_dt = datetime.datetime(2011, 9, 1, 3, 20, 40, tzinfo=EAT)
431
afternoon_min_dt = datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT)
432
self.assertQuerysetEqual(
433
Session.objects.annotate(dt=Min('events__dt')).order_by('dt'),
434
[morning_min_dt, afternoon_min_dt],
435
transform=lambda d: d.dt)
436
self.assertQuerysetEqual(
437
Session.objects.annotate(dt=Min('events__dt')).filter(dt__lt=afternoon_min_dt),
439
transform=lambda d: d.dt)
440
self.assertQuerysetEqual(
441
Session.objects.annotate(dt=Min('events__dt')).filter(dt__gte=afternoon_min_dt),
443
transform=lambda d: d.dt)
445
def test_query_dates(self):
446
# Same comment as in test_query_date_related_filters.
447
Event.objects.create(dt=datetime.datetime(2011, 1, 1, 1, 30, 0, tzinfo=EAT))
448
Event.objects.create(dt=datetime.datetime(2011, 1, 1, 4, 30, 0, tzinfo=EAT))
449
self.assertQuerysetEqual(Event.objects.dates('dt', 'year'),
450
[datetime.datetime(2010, 1, 1, tzinfo=UTC),
451
datetime.datetime(2011, 1, 1, tzinfo=UTC)],
452
transform=lambda d: d)
453
self.assertQuerysetEqual(Event.objects.dates('dt', 'month'),
454
[datetime.datetime(2010, 12, 1, tzinfo=UTC),
455
datetime.datetime(2011, 1, 1, tzinfo=UTC)],
456
transform=lambda d: d)
457
self.assertQuerysetEqual(Event.objects.dates('dt', 'day'),
458
[datetime.datetime(2010, 12, 31, tzinfo=UTC),
459
datetime.datetime(2011, 1, 1, tzinfo=UTC)],
460
transform=lambda d: d)
462
def test_raw_sql(self):
463
# Regression test for #17755
464
dt = datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT)
465
event = Event.objects.create(dt=dt)
466
self.assertQuerysetEqual(
467
Event.objects.raw('SELECT * FROM timezones_event WHERE dt = %s', [dt]),
469
transform=lambda d: d)
472
def test_filter_date_field_with_aware_datetime(self):
473
# Regression test for #17742
474
day = datetime.date(2011, 9, 1)
475
event = AllDayEvent.objects.create(day=day)
476
# This is 2011-09-02T01:30:00+03:00 in EAT
477
dt = datetime.datetime(2011, 9, 1, 22, 30, 0, tzinfo=UTC)
478
self.assertFalse(AllDayEvent.objects.filter(day__gte=dt).exists())
480
def test_null_datetime(self):
481
# Regression test for #17294
482
e = MaybeEvent.objects.create()
483
self.assertEqual(e.dt, None)
486
@override_settings(TIME_ZONE='Africa/Nairobi')
487
class SerializationTests(TestCase):
489
# Backend-specific notes:
490
# - JSON supports only milliseconds, microseconds will be truncated.
491
# - PyYAML dumps the UTC offset correctly for timezone-aware datetimes,
492
# but when it loads this representation, it substracts the offset and
493
# returns a naive datetime object in UTC (http://pyyaml.org/ticket/202).
494
# Tests are adapted to take these quirks into account.
496
def assert_python_contains_datetime(self, objects, dt):
497
self.assertEqual(objects[0]['fields']['dt'], dt)
499
def assert_json_contains_datetime(self, json, dt):
500
self.assertIn('"fields": {"dt": "%s"}' % dt, json)
502
def assert_xml_contains_datetime(self, xml, dt):
503
field = parseString(xml).getElementsByTagName('field')[0]
504
self.assertXMLEqual(field.childNodes[0].wholeText, dt)
506
def assert_yaml_contains_datetime(self, yaml, dt):
507
self.assertIn("- fields: {dt: !!timestamp '%s'}" % dt, yaml)
509
def test_naive_datetime(self):
510
dt = datetime.datetime(2011, 9, 1, 13, 20, 30)
512
data = serializers.serialize('python', [Event(dt=dt)])
513
self.assert_python_contains_datetime(data, dt)
514
obj = next(serializers.deserialize('python', data)).object
515
self.assertEqual(obj.dt, dt)
517
data = serializers.serialize('json', [Event(dt=dt)])
518
self.assert_json_contains_datetime(data, "2011-09-01T13:20:30")
519
obj = next(serializers.deserialize('json', data)).object
520
self.assertEqual(obj.dt, dt)
522
data = serializers.serialize('xml', [Event(dt=dt)])
523
self.assert_xml_contains_datetime(data, "2011-09-01T13:20:30")
524
obj = next(serializers.deserialize('xml', data)).object
525
self.assertEqual(obj.dt, dt)
527
if 'yaml' in serializers.get_serializer_formats():
528
data = serializers.serialize('yaml', [Event(dt=dt)])
529
self.assert_yaml_contains_datetime(data, "2011-09-01 13:20:30")
530
obj = next(serializers.deserialize('yaml', data)).object
531
self.assertEqual(obj.dt, dt)
533
def test_naive_datetime_with_microsecond(self):
534
dt = datetime.datetime(2011, 9, 1, 13, 20, 30, 405060)
536
data = serializers.serialize('python', [Event(dt=dt)])
537
self.assert_python_contains_datetime(data, dt)
538
obj = next(serializers.deserialize('python', data)).object
539
self.assertEqual(obj.dt, dt)
541
data = serializers.serialize('json', [Event(dt=dt)])
542
self.assert_json_contains_datetime(data, "2011-09-01T13:20:30.405")
543
obj = next(serializers.deserialize('json', data)).object
544
self.assertEqual(obj.dt, dt.replace(microsecond=405000))
546
data = serializers.serialize('xml', [Event(dt=dt)])
547
self.assert_xml_contains_datetime(data, "2011-09-01T13:20:30.405060")
548
obj = next(serializers.deserialize('xml', data)).object
549
self.assertEqual(obj.dt, dt)
551
if 'yaml' in serializers.get_serializer_formats():
552
data = serializers.serialize('yaml', [Event(dt=dt)])
553
self.assert_yaml_contains_datetime(data, "2011-09-01 13:20:30.405060")
554
obj = next(serializers.deserialize('yaml', data)).object
555
self.assertEqual(obj.dt, dt)
557
def test_aware_datetime_with_microsecond(self):
558
dt = datetime.datetime(2011, 9, 1, 17, 20, 30, 405060, tzinfo=ICT)
560
data = serializers.serialize('python', [Event(dt=dt)])
561
self.assert_python_contains_datetime(data, dt)
562
obj = next(serializers.deserialize('python', data)).object
563
self.assertEqual(obj.dt, dt)
565
data = serializers.serialize('json', [Event(dt=dt)])
566
self.assert_json_contains_datetime(data, "2011-09-01T17:20:30.405+07:00")
567
obj = next(serializers.deserialize('json', data)).object
568
self.assertEqual(obj.dt, dt.replace(microsecond=405000))
570
data = serializers.serialize('xml', [Event(dt=dt)])
571
self.assert_xml_contains_datetime(data, "2011-09-01T17:20:30.405060+07:00")
572
obj = next(serializers.deserialize('xml', data)).object
573
self.assertEqual(obj.dt, dt)
575
if 'yaml' in serializers.get_serializer_formats():
576
data = serializers.serialize('yaml', [Event(dt=dt)])
577
self.assert_yaml_contains_datetime(data, "2011-09-01 17:20:30.405060+07:00")
578
obj = next(serializers.deserialize('yaml', data)).object
579
self.assertEqual(obj.dt.replace(tzinfo=UTC), dt)
581
def test_aware_datetime_in_utc(self):
582
dt = datetime.datetime(2011, 9, 1, 10, 20, 30, tzinfo=UTC)
584
data = serializers.serialize('python', [Event(dt=dt)])
585
self.assert_python_contains_datetime(data, dt)
586
obj = next(serializers.deserialize('python', data)).object
587
self.assertEqual(obj.dt, dt)
589
data = serializers.serialize('json', [Event(dt=dt)])
590
self.assert_json_contains_datetime(data, "2011-09-01T10:20:30Z")
591
obj = next(serializers.deserialize('json', data)).object
592
self.assertEqual(obj.dt, dt)
594
data = serializers.serialize('xml', [Event(dt=dt)])
595
self.assert_xml_contains_datetime(data, "2011-09-01T10:20:30+00:00")
596
obj = next(serializers.deserialize('xml', data)).object
597
self.assertEqual(obj.dt, dt)
599
if 'yaml' in serializers.get_serializer_formats():
600
data = serializers.serialize('yaml', [Event(dt=dt)])
601
self.assert_yaml_contains_datetime(data, "2011-09-01 10:20:30+00:00")
602
obj = next(serializers.deserialize('yaml', data)).object
603
self.assertEqual(obj.dt.replace(tzinfo=UTC), dt)
605
def test_aware_datetime_in_local_timezone(self):
606
dt = datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT)
608
data = serializers.serialize('python', [Event(dt=dt)])
609
self.assert_python_contains_datetime(data, dt)
610
obj = next(serializers.deserialize('python', data)).object
611
self.assertEqual(obj.dt, dt)
613
data = serializers.serialize('json', [Event(dt=dt)])
614
self.assert_json_contains_datetime(data, "2011-09-01T13:20:30+03:00")
615
obj = next(serializers.deserialize('json', data)).object
616
self.assertEqual(obj.dt, dt)
618
data = serializers.serialize('xml', [Event(dt=dt)])
619
self.assert_xml_contains_datetime(data, "2011-09-01T13:20:30+03:00")
620
obj = next(serializers.deserialize('xml', data)).object
621
self.assertEqual(obj.dt, dt)
623
if 'yaml' in serializers.get_serializer_formats():
624
data = serializers.serialize('yaml', [Event(dt=dt)])
625
self.assert_yaml_contains_datetime(data, "2011-09-01 13:20:30+03:00")
626
obj = next(serializers.deserialize('yaml', data)).object
627
self.assertEqual(obj.dt.replace(tzinfo=UTC), dt)
629
def test_aware_datetime_in_other_timezone(self):
630
dt = datetime.datetime(2011, 9, 1, 17, 20, 30, tzinfo=ICT)
632
data = serializers.serialize('python', [Event(dt=dt)])
633
self.assert_python_contains_datetime(data, dt)
634
obj = next(serializers.deserialize('python', data)).object
635
self.assertEqual(obj.dt, dt)
637
data = serializers.serialize('json', [Event(dt=dt)])
638
self.assert_json_contains_datetime(data, "2011-09-01T17:20:30+07:00")
639
obj = next(serializers.deserialize('json', data)).object
640
self.assertEqual(obj.dt, dt)
642
data = serializers.serialize('xml', [Event(dt=dt)])
643
self.assert_xml_contains_datetime(data, "2011-09-01T17:20:30+07:00")
644
obj = next(serializers.deserialize('xml', data)).object
645
self.assertEqual(obj.dt, dt)
647
if 'yaml' in serializers.get_serializer_formats():
648
data = serializers.serialize('yaml', [Event(dt=dt)])
649
self.assert_yaml_contains_datetime(data, "2011-09-01 17:20:30+07:00")
650
obj = next(serializers.deserialize('yaml', data)).object
651
self.assertEqual(obj.dt.replace(tzinfo=UTC), dt)
654
@override_settings(DATETIME_FORMAT='c', TIME_ZONE='Africa/Nairobi', USE_L10N=False, USE_TZ=True)
655
class TemplateTests(TestCase):
658
def test_localtime_templatetag_and_filters(self):
660
Test the {% localtime %} templatetag and related filters.
663
'utc': datetime.datetime(2011, 9, 1, 10, 20, 30, tzinfo=UTC),
664
'eat': datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT),
665
'ict': datetime.datetime(2011, 9, 1, 17, 20, 30, tzinfo=ICT),
666
'naive': datetime.datetime(2011, 9, 1, 13, 20, 30),
669
'notag': Template("{% load tz %}{{ dt }}|{{ dt|localtime }}|{{ dt|utc }}|{{ dt|timezone:ICT }}"),
670
'noarg': Template("{% load tz %}{% localtime %}{{ dt }}|{{ dt|localtime }}|{{ dt|utc }}|{{ dt|timezone:ICT }}{% endlocaltime %}"),
671
'on': Template("{% load tz %}{% localtime on %}{{ dt }}|{{ dt|localtime }}|{{ dt|utc }}|{{ dt|timezone:ICT }}{% endlocaltime %}"),
672
'off': Template("{% load tz %}{% localtime off %}{{ dt }}|{{ dt|localtime }}|{{ dt|utc }}|{{ dt|timezone:ICT }}{% endlocaltime %}"),
675
# Transform a list of keys in 'datetimes' to the expected template
676
# output. This makes the definition of 'results' more readable.
678
return '|'.join(datetimes[key].isoformat() for key in result)
680
# Results for USE_TZ = True
684
'notag': t('eat', 'eat', 'utc', 'ict'),
685
'noarg': t('eat', 'eat', 'utc', 'ict'),
686
'on': t('eat', 'eat', 'utc', 'ict'),
687
'off': t('utc', 'eat', 'utc', 'ict'),
690
'notag': t('eat', 'eat', 'utc', 'ict'),
691
'noarg': t('eat', 'eat', 'utc', 'ict'),
692
'on': t('eat', 'eat', 'utc', 'ict'),
693
'off': t('eat', 'eat', 'utc', 'ict'),
696
'notag': t('eat', 'eat', 'utc', 'ict'),
697
'noarg': t('eat', 'eat', 'utc', 'ict'),
698
'on': t('eat', 'eat', 'utc', 'ict'),
699
'off': t('ict', 'eat', 'utc', 'ict'),
702
'notag': t('naive', 'eat', 'utc', 'ict'),
703
'noarg': t('naive', 'eat', 'utc', 'ict'),
704
'on': t('naive', 'eat', 'utc', 'ict'),
705
'off': t('naive', 'eat', 'utc', 'ict'),
709
for k1, dt in six.iteritems(datetimes):
710
for k2, tpl in six.iteritems(templates):
711
ctx = Context({'dt': dt, 'ICT': ICT})
712
actual = tpl.render(ctx)
713
expected = results[k1][k2]
714
self.assertEqual(actual, expected, '%s / %s: %r != %r' % (k1, k2, actual, expected))
716
# Changes for USE_TZ = False
718
results['utc']['notag'] = t('utc', 'eat', 'utc', 'ict')
719
results['ict']['notag'] = t('ict', 'eat', 'utc', 'ict')
721
with self.settings(USE_TZ=False):
722
for k1, dt in six.iteritems(datetimes):
723
for k2, tpl in six.iteritems(templates):
724
ctx = Context({'dt': dt, 'ICT': ICT})
725
actual = tpl.render(ctx)
726
expected = results[k1][k2]
727
self.assertEqual(actual, expected, '%s / %s: %r != %r' % (k1, k2, actual, expected))
729
@skipIf(pytz is None, "this test requires pytz")
730
def test_localtime_filters_with_pytz(self):
732
Test the |localtime, |utc, and |timezone filters with pytz.
734
# Use a pytz timezone as local time
735
tpl = Template("{% load tz %}{{ dt|localtime }}|{{ dt|utc }}")
736
ctx = Context({'dt': datetime.datetime(2011, 9, 1, 12, 20, 30)})
738
with self.settings(TIME_ZONE='Europe/Paris'):
739
self.assertEqual(tpl.render(ctx), "2011-09-01T12:20:30+02:00|2011-09-01T10:20:30+00:00")
741
# Use a pytz timezone as argument
742
tpl = Template("{% load tz %}{{ dt|timezone:tz }}")
743
ctx = Context({'dt': datetime.datetime(2011, 9, 1, 13, 20, 30),
744
'tz': pytz.timezone('Europe/Paris')})
745
self.assertEqual(tpl.render(ctx), "2011-09-01T12:20:30+02:00")
747
# Use a pytz timezone name as argument
748
tpl = Template("{% load tz %}{{ dt|timezone:'Europe/Paris' }}")
749
ctx = Context({'dt': datetime.datetime(2011, 9, 1, 13, 20, 30),
750
'tz': pytz.timezone('Europe/Paris')})
751
self.assertEqual(tpl.render(ctx), "2011-09-01T12:20:30+02:00")
753
def test_localtime_templatetag_invalid_argument(self):
754
with self.assertRaises(TemplateSyntaxError):
755
Template("{% load tz %}{% localtime foo %}{% endlocaltime %}").render()
757
def test_localtime_filters_do_not_raise_exceptions(self):
759
Test the |localtime, |utc, and |timezone filters on bad inputs.
761
tpl = Template("{% load tz %}{{ dt }}|{{ dt|localtime }}|{{ dt|utc }}|{{ dt|timezone:tz }}")
762
with self.settings(USE_TZ=True):
764
ctx = Context({'dt': None, 'tz': ICT})
765
self.assertEqual(tpl.render(ctx), "None|||")
766
ctx = Context({'dt': 'not a date', 'tz': ICT})
767
self.assertEqual(tpl.render(ctx), "not a date|||")
769
tpl = Template("{% load tz %}{{ dt|timezone:tz }}")
770
ctx = Context({'dt': datetime.datetime(2011, 9, 1, 13, 20, 30), 'tz': None})
771
self.assertEqual(tpl.render(ctx), "")
772
ctx = Context({'dt': datetime.datetime(2011, 9, 1, 13, 20, 30), 'tz': 'not a tz'})
773
self.assertEqual(tpl.render(ctx), "")
776
def test_timezone_templatetag(self):
778
Test the {% timezone %} templatetag.
780
tpl = Template("{% load tz %}"
788
ctx = Context({'dt': datetime.datetime(2011, 9, 1, 10, 20, 30, tzinfo=UTC),
789
'tz1': ICT, 'tz2': None})
790
self.assertEqual(tpl.render(ctx), "2011-09-01T13:20:30+03:00|2011-09-01T17:20:30+07:00|2011-09-01T13:20:30+03:00")
792
@skipIf(pytz is None, "this test requires pytz")
793
def test_timezone_templatetag_with_pytz(self):
795
Test the {% timezone %} templatetag with pytz.
797
tpl = Template("{% load tz %}{% timezone tz %}{{ dt }}{% endtimezone %}")
799
# Use a pytz timezone as argument
800
ctx = Context({'dt': datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT),
801
'tz': pytz.timezone('Europe/Paris')})
802
self.assertEqual(tpl.render(ctx), "2011-09-01T12:20:30+02:00")
804
# Use a pytz timezone name as argument
805
ctx = Context({'dt': datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT),
806
'tz': 'Europe/Paris'})
807
self.assertEqual(tpl.render(ctx), "2011-09-01T12:20:30+02:00")
809
def test_timezone_templatetag_invalid_argument(self):
810
with self.assertRaises(TemplateSyntaxError):
811
Template("{% load tz %}{% timezone %}{% endtimezone %}").render()
812
with self.assertRaises(ValueError if pytz is None else pytz.UnknownTimeZoneError):
813
Template("{% load tz %}{% timezone tz %}{% endtimezone %}").render(Context({'tz': 'foobar'}))
815
@skipIf(sys.platform.startswith('win'), "Windows uses non-standard time zone names")
816
def test_get_current_timezone_templatetag(self):
818
Test the {% get_current_timezone %} templatetag.
820
tpl = Template("{% load tz %}{% get_current_timezone as time_zone %}{{ time_zone }}")
822
self.assertEqual(tpl.render(Context()), "Africa/Nairobi" if pytz else "EAT")
823
with timezone.override(UTC):
824
self.assertEqual(tpl.render(Context()), "UTC")
826
tpl = Template("{% load tz %}{% timezone tz %}{% get_current_timezone as time_zone %}{% endtimezone %}{{ time_zone }}")
828
self.assertEqual(tpl.render(Context({'tz': ICT})), "+0700")
829
with timezone.override(UTC):
830
self.assertEqual(tpl.render(Context({'tz': ICT})), "+0700")
832
@skipIf(pytz is None, "this test requires pytz")
833
def test_get_current_timezone_templatetag_with_pytz(self):
835
Test the {% get_current_timezone %} templatetag with pytz.
837
tpl = Template("{% load tz %}{% get_current_timezone as time_zone %}{{ time_zone }}")
838
with timezone.override(pytz.timezone('Europe/Paris')):
839
self.assertEqual(tpl.render(Context()), "Europe/Paris")
841
tpl = Template("{% load tz %}{% timezone 'Europe/Paris' %}{% get_current_timezone as time_zone %}{% endtimezone %}{{ time_zone }}")
842
self.assertEqual(tpl.render(Context()), "Europe/Paris")
844
def test_get_current_timezone_templatetag_invalid_argument(self):
845
with self.assertRaises(TemplateSyntaxError):
846
Template("{% load tz %}{% get_current_timezone %}").render()
848
@skipIf(sys.platform.startswith('win'), "Windows uses non-standard time zone names")
849
def test_tz_template_context_processor(self):
851
Test the django.core.context_processors.tz template context processor.
853
tpl = Template("{{ TIME_ZONE }}")
854
self.assertEqual(tpl.render(Context()), "")
855
self.assertEqual(tpl.render(RequestContext(HttpRequest())), "Africa/Nairobi" if pytz else "EAT")
858
def test_date_and_time_template_filters(self):
859
tpl = Template("{{ dt|date:'Y-m-d' }} at {{ dt|time:'H:i:s' }}")
860
ctx = Context({'dt': datetime.datetime(2011, 9, 1, 20, 20, 20, tzinfo=UTC)})
861
self.assertEqual(tpl.render(ctx), "2011-09-01 at 23:20:20")
862
with timezone.override(ICT):
863
self.assertEqual(tpl.render(ctx), "2011-09-02 at 03:20:20")
865
def test_date_and_time_template_filters_honor_localtime(self):
866
tpl = Template("{% load tz %}{% localtime off %}{{ dt|date:'Y-m-d' }} at {{ dt|time:'H:i:s' }}{% endlocaltime %}")
867
ctx = Context({'dt': datetime.datetime(2011, 9, 1, 20, 20, 20, tzinfo=UTC)})
868
self.assertEqual(tpl.render(ctx), "2011-09-01 at 20:20:20")
869
with timezone.override(ICT):
870
self.assertEqual(tpl.render(ctx), "2011-09-01 at 20:20:20")
872
def test_localtime_with_time_zone_setting_set_to_none(self):
873
# Regression for #17274
874
tpl = Template("{% load tz %}{{ dt }}")
875
ctx = Context({'dt': datetime.datetime(2011, 9, 1, 12, 20, 30, tzinfo=EAT)})
877
with self.settings(TIME_ZONE=None):
878
# the actual value depends on the system time zone of the host
879
self.assertTrue(tpl.render(ctx).startswith("2011"))
882
def test_now_template_tag_uses_current_time_zone(self):
883
# Regression for #17343
884
tpl = Template("{% now \"O\" %}")
885
self.assertEqual(tpl.render(Context({})), "+0300")
886
with timezone.override(ICT):
887
self.assertEqual(tpl.render(Context({})), "+0700")
890
@override_settings(DATETIME_FORMAT='c', TIME_ZONE='Africa/Nairobi', USE_L10N=False, USE_TZ=False)
891
class LegacyFormsTests(TestCase):
894
form = EventForm({'dt': '2011-09-01 13:20:30'})
895
self.assertTrue(form.is_valid())
896
self.assertEqual(form.cleaned_data['dt'], datetime.datetime(2011, 9, 1, 13, 20, 30))
898
@skipIf(pytz is None, "this test requires pytz")
899
def test_form_with_non_existent_time(self):
900
form = EventForm({'dt': '2011-03-27 02:30:00'})
901
with timezone.override(pytz.timezone('Europe/Paris')):
902
# this is obviously a bug
903
self.assertTrue(form.is_valid())
904
self.assertEqual(form.cleaned_data['dt'], datetime.datetime(2011, 3, 27, 2, 30, 0))
906
@skipIf(pytz is None, "this test requires pytz")
907
def test_form_with_ambiguous_time(self):
908
form = EventForm({'dt': '2011-10-30 02:30:00'})
909
with timezone.override(pytz.timezone('Europe/Paris')):
910
# this is obviously a bug
911
self.assertTrue(form.is_valid())
912
self.assertEqual(form.cleaned_data['dt'], datetime.datetime(2011, 10, 30, 2, 30, 0))
914
def test_split_form(self):
915
form = EventSplitForm({'dt_0': '2011-09-01', 'dt_1': '13:20:30'})
916
self.assertTrue(form.is_valid())
917
self.assertEqual(form.cleaned_data['dt'], datetime.datetime(2011, 9, 1, 13, 20, 30))
919
def test_model_form(self):
920
EventModelForm({'dt': '2011-09-01 13:20:30'}).save()
921
e = Event.objects.get()
922
self.assertEqual(e.dt, datetime.datetime(2011, 9, 1, 13, 20, 30))
925
@override_settings(DATETIME_FORMAT='c', TIME_ZONE='Africa/Nairobi', USE_L10N=False, USE_TZ=True)
926
class NewFormsTests(TestCase):
930
form = EventForm({'dt': '2011-09-01 13:20:30'})
931
self.assertTrue(form.is_valid())
932
self.assertEqual(form.cleaned_data['dt'], datetime.datetime(2011, 9, 1, 10, 20, 30, tzinfo=UTC))
934
def test_form_with_other_timezone(self):
935
form = EventForm({'dt': '2011-09-01 17:20:30'})
936
with timezone.override(ICT):
937
self.assertTrue(form.is_valid())
938
self.assertEqual(form.cleaned_data['dt'], datetime.datetime(2011, 9, 1, 10, 20, 30, tzinfo=UTC))
940
@skipIf(pytz is None, "this test requires pytz")
941
def test_form_with_non_existent_time(self):
942
with timezone.override(pytz.timezone('Europe/Paris')):
943
form = EventForm({'dt': '2011-03-27 02:30:00'})
944
self.assertFalse(form.is_valid())
945
self.assertEqual(form.errors['dt'],
946
["2011-03-27 02:30:00 couldn't be interpreted in time zone "
947
"Europe/Paris; it may be ambiguous or it may not exist."])
949
@skipIf(pytz is None, "this test requires pytz")
950
def test_form_with_ambiguous_time(self):
951
with timezone.override(pytz.timezone('Europe/Paris')):
952
form = EventForm({'dt': '2011-10-30 02:30:00'})
953
self.assertFalse(form.is_valid())
954
self.assertEqual(form.errors['dt'],
955
["2011-10-30 02:30:00 couldn't be interpreted in time zone "
956
"Europe/Paris; it may be ambiguous or it may not exist."])
959
def test_split_form(self):
960
form = EventSplitForm({'dt_0': '2011-09-01', 'dt_1': '13:20:30'})
961
self.assertTrue(form.is_valid())
962
self.assertEqual(form.cleaned_data['dt'], datetime.datetime(2011, 9, 1, 10, 20, 30, tzinfo=UTC))
965
def test_model_form(self):
966
EventModelForm({'dt': '2011-09-01 13:20:30'}).save()
967
e = Event.objects.get()
968
self.assertEqual(e.dt, datetime.datetime(2011, 9, 1, 10, 20, 30, tzinfo=UTC))
971
@override_settings(DATETIME_FORMAT='c', TIME_ZONE='Africa/Nairobi', USE_L10N=False, USE_TZ=True,
972
PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
973
class AdminTests(TestCase):
975
urls = 'modeltests.timezones.urls'
976
fixtures = ['tz_users.xml']
979
self.client.login(username='super', password='secret')
982
def test_changelist(self):
983
e = Event.objects.create(dt=datetime.datetime(2011, 9, 1, 10, 20, 30, tzinfo=UTC))
984
response = self.client.get(reverse('admin:timezones_event_changelist'))
985
self.assertContains(response, e.dt.astimezone(EAT).isoformat())
987
def test_changelist_in_other_timezone(self):
988
e = Event.objects.create(dt=datetime.datetime(2011, 9, 1, 10, 20, 30, tzinfo=UTC))
989
with timezone.override(ICT):
990
response = self.client.get(reverse('admin:timezones_event_changelist'))
991
self.assertContains(response, e.dt.astimezone(ICT).isoformat())
994
def test_change_editable(self):
995
e = Event.objects.create(dt=datetime.datetime(2011, 9, 1, 10, 20, 30, tzinfo=UTC))
996
response = self.client.get(reverse('admin:timezones_event_change', args=(e.pk,)))
997
self.assertContains(response, e.dt.astimezone(EAT).date().isoformat())
998
self.assertContains(response, e.dt.astimezone(EAT).time().isoformat())
1000
def test_change_editable_in_other_timezone(self):
1001
e = Event.objects.create(dt=datetime.datetime(2011, 9, 1, 10, 20, 30, tzinfo=UTC))
1002
with timezone.override(ICT):
1003
response = self.client.get(reverse('admin:timezones_event_change', args=(e.pk,)))
1004
self.assertContains(response, e.dt.astimezone(ICT).date().isoformat())
1005
self.assertContains(response, e.dt.astimezone(ICT).time().isoformat())
1007
@requires_tz_support
1008
def test_change_readonly(self):
1009
Timestamp.objects.create()
1010
# re-fetch the object for backends that lose microseconds (MySQL)
1011
t = Timestamp.objects.get()
1012
response = self.client.get(reverse('admin:timezones_timestamp_change', args=(t.pk,)))
1013
self.assertContains(response, t.created.astimezone(EAT).isoformat())
1015
def test_change_readonly_in_other_timezone(self):
1016
Timestamp.objects.create()
1017
# re-fetch the object for backends that lose microseconds (MySQL)
1018
t = Timestamp.objects.get()
1019
with timezone.override(ICT):
1020
response = self.client.get(reverse('admin:timezones_timestamp_change', args=(t.pk,)))
1021
self.assertContains(response, t.created.astimezone(ICT).isoformat())
1024
@override_settings(TIME_ZONE='Africa/Nairobi')
1025
class UtilitiesTests(TestCase):
1027
def test_make_aware(self):
1029
timezone.make_aware(datetime.datetime(2011, 9, 1, 13, 20, 30), EAT),
1030
datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT)
1033
timezone.make_aware(datetime.datetime(2011, 9, 1, 10, 20, 30), UTC),
1034
datetime.datetime(2011, 9, 1, 10, 20, 30, tzinfo=UTC)
1037
def test_make_naive(self):
1039
timezone.make_naive(datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT), EAT),
1040
datetime.datetime(2011, 9, 1, 13, 20, 30)
1043
timezone.make_naive(datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT), UTC),
1044
datetime.datetime(2011, 9, 1, 10, 20, 30)
1047
timezone.make_naive(datetime.datetime(2011, 9, 1, 10, 20, 30, tzinfo=UTC), UTC),
1048
datetime.datetime(2011, 9, 1, 10, 20, 30)