mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	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:
		| @@ -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): | ||||||
|   | |||||||
							
								
								
									
										51
									
								
								tests/othertests/db_typecasts.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								tests/othertests/db_typecasts.py
									
									
									
									
									
										Normal file
									
								
							| @@ -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) | ||||||
| """ | """ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user