From: Mike Bayer Date: Fri, 27 Jun 2008 20:21:37 +0000 (+0000) Subject: - applied the "reverse" of r4877 from trunk; correct microsecond behavior is availabl... X-Git-Tag: rel_0_4_7~13 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3591ef591f205f6563aa7f8f5c6cce261dc76d4f;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - applied the "reverse" of r4877 from trunk; correct microsecond behavior is available in 0.4 if you turn off "__legacy_microseconds__" [ticket:1090] --- diff --git a/CHANGES b/CHANGES index f5e50fbc0e..d985593991 100644 --- a/CHANGES +++ b/CHANGES @@ -74,6 +74,30 @@ CHANGES that row request (so BufferedColumnRow is still needed, but less so). [ticket:1062] +- sqlite + - SQLite supports a "forwards compatible" mode for its + DateTime and Time types, regarding the representation of + microseconds. When the mode is enabled, microseconds + are represented as fractional seconds in string format. + This makes SQLA's SQLite date type compatible with datetimes + that were saved directly using Pysqlite (which just calls + str()). This mode is the default in 0.5, where the + same selector flag exists with the reverse default value. + + To get the new behavior globally: + + from sqlalchemy.databases.sqlite import DateTimeMixin + DateTimeMixin.__legacy_microseconds__ = False + + To get the behavior on individual DateTime types: + + t = sqlite.SLDateTime() + t.__legacy_microseconds__ = False + + Then use "t" as the type on the Column. + + [ticket:1090] + 0.4.6 ===== diff --git a/lib/sqlalchemy/databases/sqlite.py b/lib/sqlalchemy/databases/sqlite.py index f8bea90ebc..040e23a4bd 100644 --- a/lib/sqlalchemy/databases/sqlite.py +++ b/lib/sqlalchemy/databases/sqlite.py @@ -42,7 +42,8 @@ class SLSmallInteger(sqltypes.Smallinteger): class DateTimeMixin(object): __format__ = "%Y-%m-%d %H:%M:%S" - + __legacy_microseconds__ = True + def bind_processor(self, dialect): def process(value): if isinstance(value, basestring): @@ -50,7 +51,10 @@ class DateTimeMixin(object): return value elif value is not None: if self.__microsecond__ and getattr(value, 'microsecond', None) is not None: - return value.strftime(self.__format__ + "." + str(value.microsecond)) + if self.__legacy_microseconds__: + return value.strftime(self.__format__ + '.' + str(value.microsecond)) + else: + return value.strftime(self.__format__ + ('.%06d' % value.microsecond)) else: return value.strftime(self.__format__) else: @@ -62,7 +66,10 @@ class DateTimeMixin(object): return None try: (value, microsecond) = value.split('.') - microsecond = int(microsecond) + if self.__legacy_microseconds__: + microsecond = int(microsecond) + else: + microsecond = int((microsecond + '000000')[0:6]) except ValueError: microsecond = 0 return time.strptime(value, self.__format__)[0:6] + (microsecond,) diff --git a/test/dialect/sqlite.py b/test/dialect/sqlite.py index 585a853d2a..50fadcae9a 100644 --- a/test/dialect/sqlite.py +++ b/test/dialect/sqlite.py @@ -30,7 +30,23 @@ class TestTypes(TestBase, AssertsExecutionResults): finally: meta.drop_all() - + + def test_time_microseconds(self): + dt = datetime.datetime(2008, 6, 27, 12, 0, 0, 125) # 125 usec + + self.assertEquals(str(dt), '2008-06-27 12:00:00.000125') + sldt = sqlite.SLDateTime() + bp = sldt.bind_processor(None) + self.assertEquals(bp(dt), '2008-06-27 12:00:00.125') + + rp = sldt.result_processor(None) + self.assertEquals(rp(bp(dt)), dt) + + sldt.__legacy_microseconds__ = False + self.assertEquals(bp(dt), '2008-06-27 12:00:00.000125') + self.assertEquals(rp(bp(dt)), dt) + + @testing.uses_deprecated('Using String type with no length') def test_type_reflection(self): # (ask_for, roundtripped_as_if_different)