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
This commit is contained in:
parent
8ebe5db684
commit
8d8da826db
|
@ -5,7 +5,7 @@ import datetime
|
||||||
###############################################
|
###############################################
|
||||||
|
|
||||||
def typecast_date(s):
|
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
|
def typecast_time(s): # does NOT store time zone information
|
||||||
if not s: return None
|
if not s: return None
|
||||||
|
@ -14,7 +14,7 @@ def typecast_time(s): # does NOT store time zone information
|
||||||
seconds, microseconds = seconds.split('.')
|
seconds, microseconds = seconds.split('.')
|
||||||
else:
|
else:
|
||||||
microseconds = '0'
|
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
|
def typecast_timestamp(s): # does NOT store time zone information
|
||||||
# "2005-07-29 15:48:00.590358-05"
|
# "2005-07-29 15:48:00.590358-05"
|
||||||
|
@ -39,10 +39,11 @@ def typecast_timestamp(s): # does NOT store time zone information
|
||||||
else:
|
else:
|
||||||
microseconds = '0'
|
microseconds = '0'
|
||||||
return datetime.datetime(int(dates[0]), int(dates[1]), int(dates[2]),
|
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):
|
def typecast_boolean(s):
|
||||||
if s is None: return None
|
if s is None: return None
|
||||||
|
if not s: return False
|
||||||
return str(s)[0].lower() == 't'
|
return str(s)[0].lower() == 't'
|
||||||
|
|
||||||
###############################################
|
###############################################
|
||||||
|
|
|
@ -299,7 +299,7 @@ class DateTimeField(DateField):
|
||||||
def get_db_prep_save(self, value):
|
def get_db_prep_save(self, value):
|
||||||
# Casts dates into string format for entry into database.
|
# Casts dates into string format for entry into database.
|
||||||
if value is not None:
|
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)
|
return Field.get_db_prep_save(self, value)
|
||||||
|
|
||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
|
@ -493,7 +493,7 @@ class TimeField(Field):
|
||||||
def get_db_prep_save(self, value):
|
def get_db_prep_save(self, value):
|
||||||
# Casts dates into string format for entry into database.
|
# Casts dates into string format for entry into database.
|
||||||
if value is not None:
|
if value is not None:
|
||||||
value = value.strftime('%H:%M:%S')
|
value = str(value)
|
||||||
return Field.get_db_prep_save(self, value)
|
return Field.get_db_prep_save(self, value)
|
||||||
|
|
||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
|
|
|
@ -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)
|
|
@ -120,4 +120,39 @@ TypeError: 'foo' is an invalid keyword argument for this function
|
||||||
>>> a6.save()
|
>>> a6.save()
|
||||||
>>> a6.headline
|
>>> a6.headline
|
||||||
'Default 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)
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue