summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Holovaty <adrian@holovaty.com>2005-08-11 19:34:34 +0000
committerAdrian Holovaty <adrian@holovaty.com>2005-08-11 19:34:34 +0000
commit8d8da826dbf1a702f8b11c3942bf8134c4f0f165 (patch)
tree1cd6b6a0680cbfc1b9705e75f7773900a1521fd3
parent8ebe5db684ac7e97836dabbce091c41a8b2e12fd (diff)
Changed timestamp and time typecasting to preserve microseconds. Added unit tests to test this behavior, and added a db_typecast unit test module. Refs #306.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@487 bcc190cf-cafb-0310-a4f2-bffc1f526a37
-rw-r--r--django/core/db/typecasts.py7
-rw-r--r--django/core/meta/fields.py4
-rw-r--r--tests/othertests/db_typecasts.py51
-rw-r--r--tests/testapp/models/basic.py35
4 files changed, 92 insertions, 5 deletions
diff --git a/django/core/db/typecasts.py b/django/core/db/typecasts.py
index 9f73ec87a2..e78eab0180 100644
--- a/django/core/db/typecasts.py
+++ b/django/core/db/typecasts.py
@@ -5,7 +5,7 @@ import datetime
###############################################
def typecast_date(s):
- return s and datetime.date(*map(int, s.split('-'))) # returns None if s is null
+ return s and datetime.date(*map(int, s.split('-'))) or None # returns None if s is null
def typecast_time(s): # does NOT store time zone information
if not s: return None
@@ -14,7 +14,7 @@ def typecast_time(s): # does NOT store time zone information
seconds, microseconds = seconds.split('.')
else:
microseconds = '0'
- return datetime.time(int(hour), int(minutes), int(seconds), int(microseconds))
+ return datetime.time(int(hour), int(minutes), int(seconds), int(float('.'+microseconds) * 1000000))
def typecast_timestamp(s): # does NOT store time zone information
# "2005-07-29 15:48:00.590358-05"
@@ -39,10 +39,11 @@ def typecast_timestamp(s): # does NOT store time zone information
else:
microseconds = '0'
return datetime.datetime(int(dates[0]), int(dates[1]), int(dates[2]),
- int(times[0]), int(times[1]), int(seconds), int(microseconds))
+ int(times[0]), int(times[1]), int(seconds), int(float('.'+microseconds) * 1000000))
def typecast_boolean(s):
if s is None: return None
+ if not s: return False
return str(s)[0].lower() == 't'
###############################################
diff --git a/django/core/meta/fields.py b/django/core/meta/fields.py
index adbfe4ca92..6743ed79a9 100644
--- a/django/core/meta/fields.py
+++ b/django/core/meta/fields.py
@@ -299,7 +299,7 @@ class DateTimeField(DateField):
def get_db_prep_save(self, value):
# Casts dates into string format for entry into database.
if value is not None:
- value = value.strftime('%Y-%m-%d %H:%M:%S')
+ value = str(value)
return Field.get_db_prep_save(self, value)
def get_manipulator_field_objs(self):
@@ -493,7 +493,7 @@ class TimeField(Field):
def get_db_prep_save(self, value):
# Casts dates into string format for entry into database.
if value is not None:
- value = value.strftime('%H:%M:%S')
+ value = str(value)
return Field.get_db_prep_save(self, value)
def get_manipulator_field_objs(self):
diff --git a/tests/othertests/db_typecasts.py b/tests/othertests/db_typecasts.py
new file mode 100644
index 0000000000..52cab666de
--- /dev/null
+++ b/tests/othertests/db_typecasts.py
@@ -0,0 +1,51 @@
+# Unit tests for django.core.db.typecasts
+
+from django.core.db import typecasts
+import datetime
+
+TEST_CASES = {
+ 'typecast_date': (
+ ('', None),
+ (None, None),
+ ('2005-08-11', datetime.date(2005, 8, 11)),
+ ('1990-01-01', datetime.date(1990, 1, 1)),
+ ),
+ 'typecast_time': (
+ ('', None),
+ (None, None),
+ ('0:00:00', datetime.time(0, 0)),
+ ('0:30:00', datetime.time(0, 30)),
+ ('8:50:00', datetime.time(8, 50)),
+ ('08:50:00', datetime.time(8, 50)),
+ ('12:00:00', datetime.time(12, 00)),
+ ('12:30:00', datetime.time(12, 30)),
+ ('13:00:00', datetime.time(13, 00)),
+ ('23:59:00', datetime.time(23, 59)),
+ ('00:00:12', datetime.time(0, 0, 12)),
+ ('00:00:12.5', datetime.time(0, 0, 12, 500000)),
+ ('7:22:13.312', datetime.time(7, 22, 13, 312000)),
+ ),
+ 'typecast_timestamp': (
+ ('', None),
+ (None, None),
+ ('2005-08-11 0:00:00', datetime.datetime(2005, 8, 11)),
+ ('2005-08-11 0:30:00', datetime.datetime(2005, 8, 11, 0, 30)),
+ ('2005-08-11 8:50:30', datetime.datetime(2005, 8, 11, 8, 50, 30)),
+ ('2005-08-11 8:50:30.123', datetime.datetime(2005, 8, 11, 8, 50, 30, 123000)),
+ ('2005-08-11 8:50:30.9', datetime.datetime(2005, 8, 11, 8, 50, 30, 900000)),
+ ('2005-08-11 8:50:30.312-05', datetime.datetime(2005, 8, 11, 8, 50, 30, 312000)),
+ ('2005-08-11 8:50:30.312+02', datetime.datetime(2005, 8, 11, 8, 50, 30, 312000)),
+ ),
+ 'typecast_boolean': (
+ (None, None),
+ ('', False),
+ ('t', True),
+ ('f', False),
+ ('x', False),
+ ),
+}
+
+for k, v in TEST_CASES.items():
+ for inpt, expected in v:
+ got = getattr(typecasts, k)(inpt)
+ assert got == expected, "In %s: %r doesn't match %r. Got %r instead." % (k, inpt, expected, got)
diff --git a/tests/testapp/models/basic.py b/tests/testapp/models/basic.py
index 86b08122c3..3668820c94 100644
--- a/tests/testapp/models/basic.py
+++ b/tests/testapp/models/basic.py
@@ -120,4 +120,39 @@ TypeError: 'foo' is an invalid keyword argument for this function
>>> a6.save()
>>> a6.headline
'Default headline'
+
+# For DateTimeFields, Django saves as much precision (in seconds) as you
+# give it.
+>>> a7 = articles.Article(headline='Article 7', pub_date=datetime(2005, 7, 31, 12, 30))
+>>> a7.save()
+>>> articles.get_object(id__exact=7).pub_date
+datetime.datetime(2005, 7, 31, 12, 30)
+
+>>> a8 = articles.Article(headline='Article 8', pub_date=datetime(2005, 7, 31, 12, 30, 45))
+>>> a8.save()
+>>> articles.get_object(id__exact=8).pub_date
+datetime.datetime(2005, 7, 31, 12, 30, 45)
+"""
+
+from django.conf import settings
+
+building_docs = getattr(settings, 'BUILDING_DOCS', False)
+
+if building_docs or settings.DATABASE_ENGINE == 'postgresql':
+ API_TESTS += """
+# In PostgreSQL, microsecond-level precision is available.
+>>> a9 = articles.Article(headline='Article 9', pub_date=datetime(2005, 7, 31, 12, 30, 45, 180))
+>>> a9.save()
+>>> articles.get_object(id__exact=9).pub_date
+datetime.datetime(2005, 7, 31, 12, 30, 45, 180)
+"""
+
+if building_docs or settings.DATABASE_ENGINE == 'mysql':
+ API_TESTS += """
+# In MySQL, microsecond-level precision isn't available. You'll lose
+# microsecond-level precision once the data is saved.
+>>> a9 = articles.Article(headline='Article 9', pub_date=datetime(2005, 7, 31, 12, 30, 45, 180))
+>>> a9.save()
+>>> articles.get_object(id__exact=9).pub_date
+datetime.datetime(2005, 7, 31, 12, 30, 45)
"""