diff --git a/contrib/sourceforge2trac.py b/contrib/sourceforge2trac.py
--- a/contrib/sourceforge2trac.py
+++ b/contrib/sourceforge2trac.py
@@ -19,7 +19,7 @@
     def __init__(self, e):
         for field in e:
             if field.get('name').endswith('date'):
-                setattr(self, field.get('name'), datetime.fromtimestamp(int(field.text)))
+                setattr(self, field.get('name'), datetime.fromtimestamp(float(field.text)))
             else:
                 setattr(self, field.get('name'), field.text)        
 
diff --git a/trac/attachment.py b/trac/attachment.py
--- a/trac/attachment.py
+++ b/trac/attachment.py
@@ -150,7 +150,7 @@
         self.filename = row[0]
         self.description = row[1]
         self.size = row[2] and int(row[2]) or 0
-        time = row[3] and int(row[3]) or 0
+        time = row[3] or 0.0
         self.date = datetime.fromtimestamp(time, utc)
         self.author = row[4]
         self.ipnr = row[5]
@@ -207,7 +207,7 @@
             handle_ta = False
 
         self.size = size and int(size) or 0
-        timestamp = int(t or time.time())
+        timestamp = float(t or time.time())
         self.date = datetime.fromtimestamp(timestamp, utc)
 
         # Make sure the path to the attachment is inside the environment
@@ -265,7 +265,7 @@
             attachment.filename = filename
             attachment.description = description
             attachment.size = size and int(size) or 0
-            time = time and int(time) or 0
+            time = time or 0.0
             attachment.date = datetime.fromtimestamp(time, utc)
             attachment.author = author
             attachment.ipnr = ipnr
diff --git a/trac/db/mysql_backend.py b/trac/db/mysql_backend.py
--- a/trac/db/mysql_backend.py
+++ b/trac/db/mysql_backend.py
@@ -133,6 +133,8 @@
         coldefs = []
         for column in table.columns:
             ctype = column.type
+            if ctype == 'real':
+                ctype = 'double precision'
             if column.auto_increment:
                 ctype = 'INT UNSIGNED NOT NULL AUTO_INCREMENT'
                 # Override the column type, as a text field cannot
diff --git a/trac/db/postgres_backend.py b/trac/db/postgres_backend.py
--- a/trac/db/postgres_backend.py
+++ b/trac/db/postgres_backend.py
@@ -38,6 +38,9 @@
     register_type(UNICODE)
     register_adapter(Markup, lambda markup: QuotedString(unicode(markup)))
     register_adapter(Empty, lambda empty: AsIs("''"))
+    # Work around a loss of precision for float values in psycopg
+    # See http://trac.edgewall.org/ticket/6466#comment:17
+    register_adapter(float, lambda value: AsIs(repr(value)))
 
     has_psycopg = True
 except ImportError:
@@ -92,6 +95,8 @@
         coldefs = []
         for column in table.columns:
             ctype = column.type
+            if ctype == 'real':
+                ctype = 'double precision'
             if column.auto_increment:
                 ctype = 'SERIAL'
             if len(table.key) == 1 and column.name in table.key:
@@ -173,11 +178,14 @@
             dsn.append('port=' + str(port))
         cnx = psycopg.connect(' '.join(dsn))
         cnx.set_client_encoding('UNICODE')
+        cursor = cnx.cursor()
+        cursor.execute("SET extra_float_digits TO 2")
+        cnx.commit()
         try:
             self.schema = None
             if 'schema' in params:
                 self.schema = params['schema']
-                cnx.cursor().execute('SET search_path TO %s', (self.schema,))
+                cursor.execute('SET search_path TO %s', (self.schema,))
                 cnx.commit()
         except PGSchemaError:
             cnx.rollback()
diff --git a/trac/db/tests/api.py b/trac/db/tests/api.py
--- a/trac/db/tests/api.py
+++ b/trac/db/tests/api.py
@@ -1,9 +1,11 @@
 # -*- coding: utf-8 -*-
 
+from datetime import datetime, timedelta
 import os
 import unittest
 
 from trac.db.api import _parse_db_str
+from trac.util.datefmt import to_timestamp, utc
 from trac.test import EnvironmentStub
 
 
@@ -108,10 +110,47 @@
         self.assertEqual([(u'<em>märkup</em>',)], cursor.fetchall())
 
 
+class RealsTestCase(unittest.TestCase):
+    
+    def setUp(self):
+        self.env = EnvironmentStub()
+        self.id = 0
+    
+    def assertRoundTrips(self, db, when):
+        """Check that a time stored as a timestamp makes a perfect round-trip
+        through the database."""
+        cursor = db.cursor()
+        self.id += 1
+        when_ts = to_timestamp(when)
+        cursor.execute("INSERT INTO ticket_change (ticket,time,field) "
+                       "VALUES (%s,%s,'field')", (self.id, when_ts))
+        db.commit()
+        cursor.execute("SELECT time FROM ticket_change "
+                       "WHERE ticket=%s AND field='field'", (self.id,))
+        rows = cursor.fetchall()
+        self.assertEqual([(when_ts,)], rows)
+        self.assertEqual(when, datetime.fromtimestamp(rows[0][0], utc))
+        cursor.execute("SELECT ticket FROM ticket_change "
+                       "WHERE time=%s AND field='field'", (when_ts,))
+        self.assertEqual([(self.id,)], cursor.fetchall())
+        
+    def test_time_round_trip(self):
+        """Vary each digit in the microseconds field of a time and check a
+        round-trip through the database."""
+        db = self.env.get_db_cnx()
+        base = datetime(2037, 2, 3, 4, 5, 6, 123456, utc)
+        self.assertRoundTrips(db, base)
+        for digit in range(7):
+            for i in range(1, 10):
+                when = base + timedelta(0, 0, i * 10 ** digit)
+                self.assertRoundTrips(db, when)
+
+
 def suite():
     suite = unittest.TestSuite()
     suite.addTest(unittest.makeSuite(ParseConnectionStringTestCase, 'test'))
     suite.addTest(unittest.makeSuite(StringsTestCase, 'test'))
+    suite.addTest(unittest.makeSuite(RealsTestCase, 'test'))
     return suite
 
 if __name__ == '__main__':
diff --git a/trac/db_default.py b/trac/db_default.py
--- a/trac/db_default.py
+++ b/trac/db_default.py
@@ -17,7 +17,7 @@
 from trac.db import Table, Column, Index
 
 # Database version identifier. Used for automatic upgrades.
-db_version = 22
+db_version = 23
 
 def __mkreports(reports):
     """Utility function used to create report data in same syntax as the
@@ -45,11 +45,11 @@
         Column('cookie'),
         Column('name'),
         Column('ipnr'),
-        Column('time', type='int')],
+        Column('time', type='real')],
     Table('session', key=('sid', 'authenticated'))[
         Column('sid'),
         Column('authenticated', type='int'),
-        Column('last_visit', type='int'),
+        Column('last_visit', type='real'),
         Index(['last_visit']),
         Index(['authenticated'])],
     Table('session_attribute', key=('sid', 'authenticated', 'name'))[
@@ -67,7 +67,7 @@
         Column('id'),
         Column('filename'),
         Column('size', type='int'),
-        Column('time', type='int'),
+        Column('time', type='real'),
         Column('description'),
         Column('author'),
         Column('ipnr')],
@@ -76,7 +76,7 @@
     Table('wiki', key=('name', 'version'))[
         Column('name'),
         Column('version', type='int'),
-        Column('time', type='int'),
+        Column('time', type='real'),
         Column('author'),
         Column('ipnr'),
         Column('text'),
@@ -87,7 +87,7 @@
     # Version control cache
     Table('revision', key='rev')[
         Column('rev'),
-        Column('time', type='int'),
+        Column('time', type='real'),
         Column('author'),
         Column('message'),
         Index(['time'])],
@@ -104,8 +104,8 @@
     Table('ticket', key='id')[
         Column('id', auto_increment=True),
         Column('type'),
-        Column('time', type='int'),
-        Column('changetime', type='int'),
+        Column('time', type='real'),
+        Column('changetime', type='real'),
         Column('component'),
         Column('severity'),
         Column('priority'),
@@ -123,7 +123,7 @@
         Index(['status'])],    
     Table('ticket_change', key=('ticket', 'time', 'field'))[
         Column('ticket', type='int'),
-        Column('time', type='int'),
+        Column('time', type='real'),
         Column('author'),
         Column('field'),
         Column('oldvalue'),
@@ -144,12 +144,12 @@
         Column('description')],
     Table('milestone', key='name')[
         Column('name'),
-        Column('due', type='int'),
-        Column('completed', type='int'),
+        Column('due', type='real'),
+        Column('completed', type='real'),
         Column('description')],
     Table('version', key='name')[
         Column('name'),
-        Column('time', type='int'),
+        Column('time', type='real'),
         Column('description')],
 
     # Report system
diff --git a/trac/ticket/model.py b/trac/ticket/model.py
--- a/trac/ticket/model.py
+++ b/trac/ticket/model.py
@@ -328,7 +328,7 @@
         db = self._get_db(db)
         cursor = db.cursor()
         sid = str(self.id)
-        when_ts = when and to_timestamp(when) or 0
+        when_ts = to_timestamp(when)
         if when_ts:
             cursor.execute("SELECT time,author,field,oldvalue,newvalue,"
                            "1 AS permanent FROM ticket_change "
@@ -356,7 +356,7 @@
                            (self.id, sid, sid))
         log = []
         for t, author, field, oldvalue, newvalue, permanent in cursor:
-            log.append((datetime.fromtimestamp(int(t), utc), author, field,
+            log.append((datetime.fromtimestamp(t, utc), author, field,
                        oldvalue or '', newvalue or '', permanent))
         return log
 
@@ -389,7 +389,7 @@
                            "WHERE ticket=%s AND time=%s",
                            (self.id, ts))
             fields = {}
-            change = {'date': datetime.fromtimestamp(int(ts), utc),
+            change = {'date': datetime.fromtimestamp(ts, utc),
                       'author': author, 'fields': fields}
             for field, author, old, new in cursor:
                 fields[field] = {'author': author, 'old': old, 'new': new}
@@ -445,12 +445,12 @@
                            (self.id, ts0, db.like_escape('_comment') + '%'))
             for field, author, comment, ts in cursor:
                 rev = int(field[8:])
-                history.append((rev, datetime.fromtimestamp(int(ts0), utc),
+                history.append((rev, datetime.fromtimestamp(ts0, utc),
                                 author0, comment))
                 ts0, author0 = ts, author
             history.sort()
             rev = history and (history[-1][0] + 1) or 0
-            history.append((rev, datetime.fromtimestamp(int(ts), utc),
+            history.append((rev, datetime.fromtimestamp(ts, utc),
                             author, last_comment))
         return history
 
@@ -758,9 +758,9 @@
     def _from_database(self, row):
         name, due, completed, description = row
         self.name = self._old_name = name
-        self.due = due and datetime.fromtimestamp(int(due), utc) or None
+        self.due = due and datetime.fromtimestamp(due, utc) or None
         self.completed = completed and \
-                         datetime.fromtimestamp(int(completed), utc) or None
+                         datetime.fromtimestamp(completed, utc) or None
         self.description = description or ''
 
     def delete(self, retarget_to=None, author=None, db=None):
@@ -890,7 +890,7 @@
                 raise ResourceNotFound(_('Version %(name)s does not exist.',
                                          name=name))
             self.name = self._old_name = name
-            self.time = row[0] and datetime.fromtimestamp(int(row[0]), utc) or None
+            self.time = row[0] and datetime.fromtimestamp(row[0], utc) or None
             self.description = row[1] or ''
         else:
             self.name = self._old_name = None
@@ -975,7 +975,7 @@
         for name, time, description in cursor:
             version = cls(env)
             version.name = version._old_name = name
-            version.time = time and datetime.fromtimestamp(int(time), utc) or None
+            version.time = time and datetime.fromtimestamp(time, utc) or None
             version.description = description or ''
             versions.append(version)
         def version_order(v):
diff --git a/trac/ticket/query.py b/trac/ticket/query.py
--- a/trac/ticket/query.py
+++ b/trac/ticket/query.py
@@ -331,7 +331,7 @@
                 elif val is None:
                     val = '--'
                 elif name in self.time_fields:
-                    val = datetime.fromtimestamp(int(val or 0), utc)
+                    val = datetime.fromtimestamp(float(val or 0), utc)
                 elif field and field['type'] == 'checkbox':
                     try:
                         val = bool(int(val))
@@ -1020,7 +1020,7 @@
         # The most recent query is stored in the user session;
         orig_list = None
         orig_time = datetime.now(utc)
-        query_time = int(req.session.get('query_time', 0))
+        query_time = float(req.session.get('query_time', 0))
         query_time = datetime.fromtimestamp(query_time, utc)
         query_constraints = unicode(query.constraints)
         try:
diff --git a/trac/ticket/templates/report.rss b/trac/ticket/templates/report.rss
--- a/trac/ticket/templates/report.rss
+++ b/trac/ticket/templates/report.rss
@@ -26,7 +26,7 @@
                 </py:when>
                 <py:when test="col in ('time', 'changetime', 'created', 'modified')">
                   <!-- FIXME: we end up with multiple pubDate -->
-                  <pubDate py:if="cell.value != 'None'">${http_date(fromtimestamp(int(cell.value)))}</pubDate>
+                  <pubDate py:if="cell.value != 'None'">${http_date(fromtimestamp(float(cell.value)))}</pubDate>
                 </py:when>
                 <py:when test="col == 'summary'">
                   <title>#$row.id: $cell.value</title>
diff --git a/trac/ticket/templates/report_view.html b/trac/ticket/templates/report_view.html
--- a/trac/ticket/templates/report_view.html
+++ b/trac/ticket/templates/report_view.html
@@ -144,19 +144,19 @@
 
                         <!--! generic fields -->
                         <py:when test="col == 'time'">
-                          <td class="date" py:attrs="td_attrs">${cell.value != '' and format_time(int(cell.value)) or '--'}
+                          <td class="date" py:attrs="td_attrs">${cell.value != '' and format_time(float(cell.value)) or '--'}
                             <hr py:if="fullrow"/>
                           </td>
                         </py:when>
 
                         <py:when test="col in ('date', 'created', 'modified')">
-                          <td class="date" py:attrs="td_attrs">${cell.value != '' and format_date(int(cell.value)) or '--'}
+                          <td class="date" py:attrs="td_attrs">${cell.value != '' and format_date(float(cell.value)) or '--'}
                             <hr py:if="fullrow"/>
                           </td>
                         </py:when>
 
                         <py:when test="col == 'datetime'">
-                          <td class="date" py:attrs="td_attrs">${cell.value != '' and format_datetime(int(cell.value)) or '--'}
+                          <td class="date" py:attrs="td_attrs">${cell.value != '' and format_datetime(float(cell.value)) or '--'}
                             <hr py:if="fullrow"/>
                           </td>
                         </py:when>
diff --git a/trac/ticket/tests/model.py b/trac/ticket/tests/model.py
--- a/trac/ticket/tests/model.py
+++ b/trac/ticket/tests/model.py
@@ -312,6 +312,19 @@
                           sorted(log[1:3]))
         self.assertEqual((t3, 'jim', 'comment', '', 'Other', True), log[3])
 
+    def test_subsecond_change(self):
+        """Perform two ticket changes within a second."""
+        tkt_id = self._insert_ticket('Test', reporter='joe', component='foo')
+        ticket = Ticket(self.env, tkt_id)
+        t1 = datetime(2001, 1, 1, 1, 1, 1, 123456, utc)
+        ticket.save_changes('jane', 'Testing', t1)
+        t2 = datetime(2001, 1, 1, 1, 1, 1, 789012, utc)
+        ticket.save_changes('jim', 'Other', t2)
+        log = ticket.get_changelog()
+        self.assertEqual(2, len(log))
+        self.assertEqual((t1, 'jane', 'comment', '', 'Testing', True), log[0])
+        self.assertEqual((t2, 'jim', 'comment', '', 'Other', True), log[1])
+
     def test_changelog_with_reverted_change(self):
         tkt_id = self._insert_ticket('Test', reporter='joe', component='foo')
         ticket = Ticket(self.env, tkt_id)
diff --git a/trac/ticket/web_ui.py b/trac/ticket/web_ui.py
--- a/trac/ticket/web_ui.py
+++ b/trac/ticket/web_ui.py
@@ -1649,7 +1649,7 @@
                 comment_history.setdefault(rev, {}).update({'comment': old})
                 comment_history.setdefault(rev + 1, {}).update(
                         {'author': author,
-                         'date': datetime.fromtimestamp(int(new), utc)})
+                         'date': datetime.fromtimestamp(float(new), utc)})
             elif old or new:
                 current['fields'][field] = {'old': old, 'new': new}
         if current:
diff --git a/trac/upgrades/db23.py b/trac/upgrades/db23.py
new file mode 100644
--- /dev/null
+++ b/trac/upgrades/db23.py
@@ -0,0 +1,95 @@
+from trac.db import Table, Column, Index, DatabaseManager
+
+def do_upgrade(env, ver, cursor):
+    # Convert time values from int to real
+    tables = [
+        Table('auth_cookie', key=('cookie', 'ipnr', 'name'))[
+            Column('cookie'),
+            Column('name'),
+            Column('ipnr'),
+            Column('time', type='real')],
+        Table('session', key=('sid', 'authenticated'))[
+            Column('sid'),
+            Column('authenticated', type='int'),
+            Column('last_visit', type='real'),
+            Index(['last_visit']),
+            Index(['authenticated'])],
+        Table('attachment', key=('type', 'id', 'filename'))[
+            Column('type'),
+            Column('id'),
+            Column('filename'),
+            Column('size', type='int'),
+            Column('time', type='real'),
+            Column('description'),
+            Column('author'),
+            Column('ipnr')],
+        Table('wiki', key=('name', 'version'))[
+            Column('name'),
+            Column('version', type='int'),
+            Column('time', type='real'),
+            Column('author'),
+            Column('ipnr'),
+            Column('text'),
+            Column('comment'),
+            Column('readonly', type='int'),
+            Index(['time'])],
+        Table('revision', key='rev')[
+            Column('rev'),
+            Column('time', type='real'),
+            Column('author'),
+            Column('message'),
+            Index(['time'])],
+        Table('ticket', key='id')[
+            Column('id', auto_increment=True),
+            Column('type'),
+            Column('time', type='real'),
+            Column('changetime', type='real'),
+            Column('component'),
+            Column('severity'),
+            Column('priority'),
+            Column('owner'),
+            Column('reporter'),
+            Column('cc'),
+            Column('version'),
+            Column('milestone'),
+            Column('status'),
+            Column('resolution'),
+            Column('summary'),
+            Column('description'),
+            Column('keywords'),
+            Index(['time']),
+            Index(['status'])],    
+        Table('ticket_change', key=('ticket', 'time', 'field'))[
+            Column('ticket', type='int'),
+            Column('time', type='real'),
+            Column('author'),
+            Column('field'),
+            Column('oldvalue'),
+            Column('newvalue'),
+            Index(['ticket']),
+            Index(['time'])],
+        Table('milestone', key='name')[
+            Column('name'),
+            Column('due', type='real'),
+            Column('completed', type='real'),
+            Column('description')],
+        Table('version', key='name')[
+            Column('name'),
+            Column('time', type='real'),
+            Column('description')],
+    ]
+    
+    for table in tables:
+        cursor.execute("CREATE TEMPORARY TABLE %s_old "
+                       "AS SELECT * FROM %s" % (table.name, table.name))
+        cursor.execute("DROP TABLE %s" % table.name)
+    
+    db_connector, _ = DatabaseManager(env)._get_connector()
+    for table in tables:
+        for stmt in db_connector.to_sql(table):
+            cursor.execute(stmt)
+    
+    for table in tables:
+        cursor.execute("INSERT INTO %s SELECT * FROM %s_old"
+                       % (table.name, table.name))
+        cursor.execute("DROP TABLE %s_old" % table.name)
diff --git a/trac/util/datefmt.py b/trac/util/datefmt.py
--- a/trac/util/datefmt.py
+++ b/trac/util/datefmt.py
@@ -57,9 +57,9 @@
     """Return the corresponding POSIX timestamp"""
     if dt:
         diff = dt - _epoc
-        return diff.days * 86400 + diff.seconds
+        return diff.days * 86400 + diff.seconds + diff.microseconds * 1e-6
     else:
-        return 0
+        return 0.0
 
 
 # -- formatting
diff --git a/trac/util/tests/datefmt.py b/trac/util/tests/datefmt.py
--- a/trac/util/tests/datefmt.py
+++ b/trac/util/tests/datefmt.py
@@ -42,6 +42,7 @@
                              tz.utcoffset(None))
             self.assertEqual('GMT +4:00', tz.zone)
 
+
 class DateFormatTestCase(unittest.TestCase):
 
     def test_to_datetime(self):
@@ -94,6 +95,16 @@
         self.assertEqual('2009-08-20', 
                          datefmt.format_date(a_date, format='%Y-%m-%d'))
 
+
+class ToTimestampTestCase(unittest.TestCase):
+    
+    def test_sub_second(self):
+        t = datetime.datetime(2001, 2, 3, 4, 5, 6, 123456, datefmt.utc)
+        ts = datefmt.to_timestamp(t)
+        self.assertNotEqual(ts, int(ts))
+        self.assertEqual(t, datetime.datetime.fromtimestamp(ts, datefmt.utc))
+
+
 def suite():
     suite = unittest.TestSuite()
     if PytzTestCase:
@@ -101,6 +112,7 @@
     else:
         print "SKIP: utils/tests/datefmt.py (no pytz installed)"
     suite.addTest(unittest.makeSuite(DateFormatTestCase))
+    suite.addTest(unittest.makeSuite(ToTimestampTestCase))
     return suite
 
 if __name__ == '__main__':
diff --git a/trac/versioncontrol/svn_fs.py b/trac/versioncontrol/svn_fs.py
--- a/trac/versioncontrol/svn_fs.py
+++ b/trac/versioncontrol/svn_fs.py
@@ -781,7 +781,7 @@
                                  core.SVN_PROP_REVISION_DATE, self.pool())
         if not _date:
             return None
-        ts = core.svn_time_from_cstring(_date, self.pool()) / 1000000
+        ts = core.svn_time_from_cstring(_date, self.pool()) / 1000000.0
         return datetime.fromtimestamp(ts, utc)
 
     def _get_prop(self, name):
@@ -847,7 +847,7 @@
         author = author and to_unicode(author, 'utf-8')
         _date = self._get_prop(core.SVN_PROP_REVISION_DATE)
         if _date:
-            ts = core.svn_time_from_cstring(_date, self.pool()) / 1000000
+            ts = core.svn_time_from_cstring(_date, self.pool()) / 1000000.0
             date = datetime.fromtimestamp(ts, utc)
         else:
             date = None
diff --git a/trac/versioncontrol/tests/svn_fs.py b/trac/versioncontrol/tests/svn_fs.py
--- a/trac/versioncontrol/tests/svn_fs.py
+++ b/trac/versioncontrol/tests/svn_fs.py
@@ -145,14 +145,14 @@
         self.assertEqual(u'/tête', node.path)
         self.assertEqual(Node.DIRECTORY, node.kind)
         self.assertEqual(HEAD, node.rev)
-        self.assertEqual(datetime(2007, 4, 30, 17, 45, 26, 0, utc),
+        self.assertEqual(datetime(2007, 4, 30, 17, 45, 26, 234375, utc),
                          node.last_modified)
         node = self.repos.get_node(u'/tête/README.txt')
         self.assertEqual('README.txt', node.name)
         self.assertEqual(u'/tête/README.txt', node.path)
         self.assertEqual(Node.FILE, node.kind)
         self.assertEqual(3, node.rev)
-        self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 0, utc), node.last_modified)
+        self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 234643, utc), node.last_modified)
 
     def test_get_node_specific_rev(self):
         node = self.repos.get_node(u'/tête', 1)
@@ -160,13 +160,13 @@
         self.assertEqual(u'/tête', node.path)
         self.assertEqual(Node.DIRECTORY, node.kind)
         self.assertEqual(1, node.rev)
-        self.assertEqual(datetime(2005, 4, 1, 10, 0, 52, 0, utc), node.last_modified)
+        self.assertEqual(datetime(2005, 4, 1, 10, 0, 52, 353248, utc), node.last_modified)
         node = self.repos.get_node(u'/tête/README.txt', 2)
         self.assertEqual('README.txt', node.name)
         self.assertEqual(u'/tête/README.txt', node.path)
         self.assertEqual(Node.FILE, node.kind)
         self.assertEqual(2, node.rev)
-        self.assertEqual(datetime(2005, 4, 1, 13, 12, 18, 0, utc), node.last_modified)
+        self.assertEqual(datetime(2005, 4, 1, 13, 12, 18, 216267, utc), node.last_modified)
 
     def test_get_dir_entries(self):
         node = self.repos.get_node(u'/tête')
@@ -383,7 +383,7 @@
         self.assertEqual(0, chgset.rev)
         self.assertEqual('', chgset.message)
         self.assertEqual('', chgset.author)
-        self.assertEqual(datetime(2005, 4, 1, 9, 57, 41, 0, utc), chgset.date)
+        self.assertEqual(datetime(2005, 4, 1, 9, 57, 41, 312767, utc), chgset.date)
         self.assertRaises(StopIteration, chgset.get_changes().next)
 
     def test_changeset_added_dirs(self):
@@ -391,7 +391,7 @@
         self.assertEqual(1, chgset.rev)
         self.assertEqual('Initial directory layout.', chgset.message)
         self.assertEqual('john', chgset.author)
-        self.assertEqual(datetime(2005, 4, 1, 10, 0, 52, 0, utc), chgset.date)
+        self.assertEqual(datetime(2005, 4, 1, 10, 0, 52, 353248, utc), chgset.date)
 
         changes = chgset.get_changes()
         self.assertEqual(('branches', Node.DIRECTORY, Changeset.ADD, None, -1),
@@ -407,7 +407,7 @@
         self.assertEqual(3, chgset.rev)
         self.assertEqual('Fixed README.\n', chgset.message)
         self.assertEqual('kate', chgset.author)
-        self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 0, utc), chgset.date)
+        self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 234643, utc), chgset.date)
 
         changes = chgset.get_changes()
         self.assertEqual((u'tête/README.txt', Node.FILE, Changeset.EDIT,
@@ -419,7 +419,7 @@
         self.assertEqual(5, chgset.rev)
         self.assertEqual('Moved directories.', chgset.message)
         self.assertEqual('kate', chgset.author)
-        self.assertEqual(datetime(2005, 4, 1, 16, 25, 39, 0, utc), chgset.date)
+        self.assertEqual(datetime(2005, 4, 1, 16, 25, 39, 658099, utc), chgset.date)
 
         changes = chgset.get_changes()
         self.assertEqual((u'tête/dir1/dir2', Node.DIRECTORY, Changeset.MOVE,
@@ -433,7 +433,7 @@
         self.assertEqual(6, chgset.rev)
         self.assertEqual('More things to read', chgset.message)
         self.assertEqual('john', chgset.author)
-        self.assertEqual(datetime(2005, 4, 1, 18, 56, 46, 0, utc), chgset.date)
+        self.assertEqual(datetime(2005, 4, 1, 18, 56, 46, 985846, utc), chgset.date)
 
         changes = chgset.get_changes()
         self.assertEqual((u'tête/README2.txt', Node.FILE, Changeset.COPY,
@@ -550,13 +550,13 @@
         self.assertEqual('/dir1', node.path)
         self.assertEqual(Node.DIRECTORY, node.kind)
         self.assertEqual(5, node.rev)
-        self.assertEqual(datetime(2005, 4, 1, 16, 25, 39, 0, utc), node.last_modified)
+        self.assertEqual(datetime(2005, 4, 1, 16, 25, 39, 658099, utc), node.last_modified)
         node = self.repos.get_node('/README.txt')
         self.assertEqual('README.txt', node.name)
         self.assertEqual('/README.txt', node.path)
         self.assertEqual(Node.FILE, node.kind)
         self.assertEqual(3, node.rev)
-        self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 0, utc), node.last_modified)
+        self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 234643, utc), node.last_modified)
 
     def test_get_node_specific_rev(self):
         node = self.repos.get_node('/dir1', 4)
@@ -564,13 +564,13 @@
         self.assertEqual('/dir1', node.path)
         self.assertEqual(Node.DIRECTORY, node.kind)
         self.assertEqual(4, node.rev)
-        self.assertEqual(datetime(2005, 4, 1, 15, 42, 35, 0, utc), node.last_modified)
+        self.assertEqual(datetime(2005, 4, 1, 15, 42, 35, 450595, utc), node.last_modified)
         node = self.repos.get_node('/README.txt', 2)
         self.assertEqual('README.txt', node.name)
         self.assertEqual('/README.txt', node.path)
         self.assertEqual(Node.FILE, node.kind)
         self.assertEqual(2, node.rev)
-        self.assertEqual(datetime(2005, 4, 1, 13, 12, 18, 0, utc), node.last_modified)
+        self.assertEqual(datetime(2005, 4, 1, 13, 12, 18, 216267, utc), node.last_modified)
 
     def test_get_dir_entries(self):
         node = self.repos.get_node('/')
@@ -675,7 +675,7 @@
         self.assertEqual(0, chgset.rev)
         self.assertEqual('', chgset.message)
         self.assertEqual('', chgset.author)
-        self.assertEqual(datetime(2005, 4, 1, 9, 57, 41, 0, utc), chgset.date)
+        self.assertEqual(datetime(2005, 4, 1, 9, 57, 41, 312767, utc), chgset.date)
         self.assertRaises(StopIteration, chgset.get_changes().next)
 
     def test_changeset_added_dirs(self):
@@ -683,7 +683,7 @@
         self.assertEqual(4, chgset.rev)
         self.assertEqual('More directories.', chgset.message)
         self.assertEqual('john', chgset.author)
-        self.assertEqual(datetime(2005, 4, 1, 15, 42, 35, 0, utc), chgset.date)
+        self.assertEqual(datetime(2005, 4, 1, 15, 42, 35, 450595, utc), chgset.date)
 
         changes = chgset.get_changes()
         self.assertEqual(('dir1', Node.DIRECTORY, 'add', None, -1),
@@ -699,7 +699,7 @@
         self.assertEqual(3, chgset.rev)
         self.assertEqual('Fixed README.\n', chgset.message)
         self.assertEqual('kate', chgset.author)
-        self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 0, utc), chgset.date)
+        self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 234643, utc), chgset.date)
 
         changes = chgset.get_changes()
         self.assertEqual(('README.txt', Node.FILE, Changeset.EDIT,
@@ -711,7 +711,7 @@
         self.assertEqual(5, chgset.rev)
         self.assertEqual('Moved directories.', chgset.message)
         self.assertEqual('kate', chgset.author)
-        self.assertEqual(datetime(2005, 4, 1, 16, 25, 39, 0, utc), chgset.date)
+        self.assertEqual(datetime(2005, 4, 1, 16, 25, 39, 658099, utc), chgset.date)
 
         changes = chgset.get_changes()
         self.assertEqual(('dir1/dir2', Node.DIRECTORY, Changeset.MOVE,
@@ -725,7 +725,7 @@
         self.assertEqual(6, chgset.rev)
         self.assertEqual('More things to read', chgset.message)
         self.assertEqual('john', chgset.author)
-        self.assertEqual(datetime(2005, 4, 1, 18, 56, 46, 0, utc), chgset.date)
+        self.assertEqual(datetime(2005, 4, 1, 18, 56, 46, 985846, utc), chgset.date)
 
         changes = chgset.get_changes()
         self.assertEqual(('README2.txt', Node.FILE, Changeset.COPY,
diff --git a/trac/web/auth.py b/trac/web/auth.py
--- a/trac/web/auth.py
+++ b/trac/web/auth.py
@@ -148,7 +148,7 @@
         cursor = db.cursor()
         cursor.execute("INSERT INTO auth_cookie (cookie,name,ipnr,time) "
                        "VALUES (%s, %s, %s, %s)", (cookie, remote_user,
-                       req.remote_addr, int(time.time())))
+                       req.remote_addr, time.time()))
         db.commit()
 
         req.authname = remote_user
@@ -173,7 +173,7 @@
         db = self.env.get_db_cnx()
         cursor = db.cursor()
         cursor.execute("DELETE FROM auth_cookie WHERE name=%s OR time < %s",
-                       (req.authname, int(time.time()) - 86400 * 10))
+                       (req.authname, time.time() - 86400 * 10))
         db.commit()
         self._expire_cookie(req)
         custom_redirect = self.config['metanav'].get('logout.redirect')
diff --git a/trac/web/session.py b/trac/web/session.py
--- a/trac/web/session.py
+++ b/trac/web/session.py
@@ -61,7 +61,7 @@
         if not row:
             return
         self._new = False
-        self.last_visit = int(row[0] or 0)
+        self.last_visit = float(row[0] or 0)
 
         cursor.execute("SELECT name,value FROM session_attribute "
                        "WHERE sid=%s and authenticated=%s",
@@ -77,7 +77,7 @@
             return
 
         authenticated = int(self.authenticated)
-        now = int(time.time())
+        now = time.time()
         db = self.env.get_db_cnx()
         cursor = db.cursor()
 
@@ -241,7 +241,7 @@
             # we didn't have an anonymous session for this sid
             cursor.execute("INSERT INTO session (sid,last_visit,authenticated)"
                            " VALUES(%s,%s,1)",
-                           (self.req.authname, int(time.time())))
+                           (self.req.authname, time.time()))
         self._new = False
         db.commit()
 
diff --git a/trac/web/tests/session.py b/trac/web/tests/session.py
--- a/trac/web/tests/session.py
+++ b/trac/web/tests/session.py
@@ -194,7 +194,7 @@
         cursor = self.db.cursor()
         cursor.execute("INSERT INTO session "
                        "VALUES ('123456', 0, %s)",
-                       (int(now - UPDATE_INTERVAL - 3600),))
+                       (now - UPDATE_INTERVAL - 3600,))
         cursor.execute("INSERT INTO session_attribute VALUES "
                        "('123456', 0, 'foo', 'bar')")
 
@@ -287,7 +287,7 @@
 
         cursor.execute("SELECT last_visit FROM session WHERE sid='123456' AND "
                        "authenticated=0")
-        self.assertAlmostEqual(now, int(cursor.fetchone()[0]), -1)
+        self.assertAlmostEqual(now, float(cursor.fetchone()[0]), -6)
 
     def test_modify_detached_session(self):
         """
diff --git a/trac/wiki/admin.py b/trac/wiki/admin.py
--- a/trac/wiki/admin.py
+++ b/trac/wiki/admin.py
@@ -116,7 +116,7 @@
                        " SELECT 1+COALESCE(max(version),0),%s,%s,"
                        " 'trac','127.0.0.1',%s FROM wiki "
                        " WHERE name=%s",
-                       (title, int(time.time()), data, title))
+                       (title, time.time(), data, title))
         if not old:
             WikiSystem(self.env).pages.invalidate(db)
         if handle_ta:

