Edgewall Software

Ticket #6466: 6466-microsecond-times-r9047.patch

File 6466-microsecond-times-r9047.patch, 73.3 KB (added by rblank, 2 years ago)

Updated patch for current trunk.

  • trac/attachment.py

    diff --git a/trac/attachment.py b/trac/attachment.py
    a b  
    2121import re 
    2222import shutil 
    2323import sys 
    24 import time 
    2524import unicodedata 
    2625 
    2726from genshi.builder import tag 
     
    3635from trac.resource import * 
    3736from trac.search import search_to_sql, shorten_result 
    3837from trac.util import get_reporter_id, create_unique_file 
    39 from trac.util.datefmt import format_datetime, to_timestamp, utc 
     38from trac.util.datefmt import format_datetime, from_utimestamp, \ 
     39                              to_datetime, to_utimestamp, utc 
    4040from trac.util.text import exception_to_unicode, pretty_size, print_table, \ 
    4141                           unicode_quote, unicode_unquote 
    4242from trac.util.translation import _ 
     
    150150        self.filename = row[0] 
    151151        self.description = row[1] 
    152152        self.size = row[2] and int(row[2]) or 0 
    153         time = row[3] and int(row[3]) or 0 
    154         self.date = datetime.fromtimestamp(time, utc) 
     153        self.date = from_utimestamp(row[3]) 
    155154        self.author = row[4] 
    156155        self.ipnr = row[5] 
    157156 
     
    199198 
    200199 
    201200    def insert(self, filename, fileobj, size, t=None, db=None): 
    202         # FIXME: `t` should probably be switched to `datetime` too 
    203201        if not db: 
    204202            db = self.env.get_db_cnx() 
    205203            handle_ta = True 
     
    207205            handle_ta = False 
    208206 
    209207        self.size = size and int(size) or 0 
    210         timestamp = int(t or time.time()) 
    211         self.date = datetime.fromtimestamp(timestamp, utc) 
     208        if t is None: 
     209            t = datetime.now(utc) 
     210        elif not isinstance(t, datetime): # Compatibility with 0.11 
     211            t = to_datetime(t, utc) 
     212        self.date = t 
    212213 
    213214        # Make sure the path to the attachment is inside the environment 
    214215        # attachments directory 
     
    232233            cursor.execute("INSERT INTO attachment " 
    233234                           "VALUES (%s,%s,%s,%s,%s,%s,%s,%s)", 
    234235                           (self.parent_realm, self.parent_id, filename, 
    235                             self.size, timestamp, self.description, 
     236                            self.size, to_utimestamp(t), self.description, 
    236237                            self.author, self.ipnr)) 
    237238            shutil.copyfileobj(fileobj, targetfile) 
    238239            self.resource.id = self.filename = filename 
     
    265266            attachment.filename = filename 
    266267            attachment.description = description 
    267268            attachment.size = size and int(size) or 0 
    268             time = time and int(time) or 0 
    269             attachment.date = datetime.fromtimestamp(time, utc) 
     269            attachment.date = from_utimestamp(time or 0) 
    270270            attachment.author = author 
    271271            attachment.ipnr = ipnr 
    272272            yield attachment 
     
    452452                       "  FROM attachment " 
    453453                       "  WHERE time > %s AND time < %s " 
    454454                       "        AND type = %s", 
    455                        (to_timestamp(start), to_timestamp(stop), realm)) 
     455                       (to_utimestamp(start), to_utimestamp(stop), realm)) 
    456456        for realm, id, filename, ts, description, author in cursor: 
    457             time = datetime.fromtimestamp(ts, utc) 
     457            time = from_utimestamp(ts) 
    458458            yield ('created', realm, id, filename, time, description, author) 
    459459 
    460460    def get_timeline_events(self, req, resource_realm, start, stop): 
     
    502502            if 'ATTACHMENT_VIEW' in req.perm(attachment): 
    503503                yield (get_resource_url(self.env, attachment, req.href), 
    504504                       get_resource_shortname(self.env, attachment), 
    505                        datetime.fromtimestamp(time, utc), author, 
     505                       from_utimestamp(time), author, 
    506506                       shorten_result(desc, terms)) 
    507507     
    508508    # IResourceManager methods 
  • trac/db/api.py

    diff --git a/trac/db/api.py b/trac/db/api.py
    a b  
    8383        self._cnx_pool = None 
    8484 
    8585    def init_db(self): 
    86         connector, args = self._get_connector() 
     86        connector, args = self.get_connector() 
    8787        connector.init_db(**args) 
    8888 
    8989    def get_connection(self): 
    9090        if not self._cnx_pool: 
    91             connector, args = self._get_connector() 
     91            connector, args = self.get_connector() 
    9292            self._cnx_pool = ConnectionPool(5, connector, **args) 
    9393        return self._cnx_pool.get_cnx(self.timeout or None) 
    9494 
     
    104104        @param dest: base filename to write to. 
    105105        Returns the file actually written. 
    106106        """ 
    107         connector, args = self._get_connector() 
     107        connector, args = self.get_connector() 
    108108        if not dest: 
    109109            backup_dir = self.backup_dir 
    110110            if backup_dir[0] != "/": 
     
    120120            os.makedirs(backup_dir) 
    121121        return connector.backup(dest) 
    122122 
    123     def _get_connector(self): ### FIXME: Make it public? 
     123    def get_connector(self): 
    124124        scheme, args = _parse_db_str(self.connection_uri) 
    125125        candidates = [ 
    126126            (priority, connector) 
     
    147147            args['log'] = self.log 
    148148        return connector, args 
    149149 
     150    _get_connector = get_connector  # For 0.11 compatibility 
     151 
    150152 
    151153def _parse_db_str(db_str): 
    152154    scheme, rest = db_str.split(':', 1) 
  • trac/db/mysql_backend.py

    diff --git a/trac/db/mysql_backend.py b/trac/db/mysql_backend.py
    a b  
    5252except ImportError: 
    5353    has_mysqldb = False 
    5454 
     55# Mapping from "abstract" SQL types to DB-specific types 
     56_type_map = { 
     57    'int64': 'bigint', 
     58} 
     59 
    5560 
    5661class MySQLConnector(Component): 
    5762    """Database connector for MySQL version 4.1 and greater. 
     
    134139        coldefs = [] 
    135140        for column in table.columns: 
    136141            ctype = column.type 
     142            ctype = _type_map.get(ctype, ctype) 
    137143            if column.auto_increment: 
    138144                ctype = 'INT UNSIGNED NOT NULL AUTO_INCREMENT' 
    139145                # Override the column type, as a text field cannot 
     
    152158                  '_'.join(index.columns), table.name, 
    153159                  self._collist(table, index.columns)) 
    154160 
     161    def alter_column_types(self, table, columns): 
     162        """Yield SQL statements altering the type of one or more columns of 
     163        a table. 
     164         
     165        Type changes are specified as a `columns` dict mapping column names 
     166        to `(from, to)` SQL type tuples. 
     167        """ 
     168        alterations = [] 
     169        for name, (from_, to) in sorted(columns.iteritems()): 
     170            to = _type_map.get(to, to) 
     171            if to != _type_map.get(from_, from_): 
     172                alterations.append((name, to)) 
     173        if alterations: 
     174            yield "ALTER TABLE %s %s" % (table, 
     175                ', '.join("MODIFY %s %s" % each 
     176                          for each in alterations)) 
     177 
    155178    def backup(self, dest_file): 
    156179        try: 
    157180            from subprocess import Popen, PIPE 
     
    204227        self._is_closed = False 
    205228 
    206229    def cast(self, column, type): 
    207         if type == 'int': 
     230        if type == 'int'or type == 'int64': 
    208231            type = 'signed' 
    209232        elif type == 'text': 
    210233            type = 'char' 
  • trac/db/postgres_backend.py

    diff --git a/trac/db/postgres_backend.py b/trac/db/postgres_backend.py
    a b  
    4545 
    4646_like_escape_re = re.compile(r'([/_%])') 
    4747 
     48# Mapping from "abstract" SQL types to DB-specific types 
     49_type_map = { 
     50    'int64': 'bigint', 
     51} 
     52 
    4853 
    4954class PostgreSQLConnector(Component): 
    5055    """Database connector for PostgreSQL. 
     
    97102        coldefs = [] 
    98103        for column in table.columns: 
    99104            ctype = column.type 
     105            ctype = _type_map.get(ctype, ctype) 
    100106            if column.auto_increment: 
    101107                ctype = 'SERIAL' 
    102             if len(table.key) == 1 and column.name in table.key: 
     108            elif len(table.key) == 1 and column.name in table.key: 
    103109                ctype += ' PRIMARY KEY' 
    104110            coldefs.append('    "%s" %s' % (column.name, ctype)) 
    105111        if len(table.key) > 1: 
     
    114120                     '_'.join(index.columns), table.name, 
    115121                     '","'.join(index.columns)) 
    116122 
     123    def alter_column_types(self, table, columns): 
     124        """Yield SQL statements altering the type of one or more columns of 
     125        a table. 
     126         
     127        Type changes are specified as a `columns` dict mapping column names 
     128        to `(from, to)` SQL type tuples. 
     129        """ 
     130        alterations = [] 
     131        for name, (from_, to) in sorted(columns.iteritems()): 
     132            to = _type_map.get(to, to) 
     133            if to != _type_map.get(from_, from_): 
     134                alterations.append((name, to)) 
     135        if alterations: 
     136            yield "ALTER TABLE %s %s" % (table, 
     137                ', '.join("ALTER COLUMN %s TYPE %s" % each 
     138                          for each in alterations)) 
     139 
    117140    def backup(self, dest_file): 
    118141        try: 
    119142            from subprocess import Popen, PIPE 
     
    191214 
    192215    def cast(self, column, type): 
    193216        # Temporary hack needed for the union of selects in the search module 
    194         return 'CAST(%s AS %s)' % (column, type) 
     217        return 'CAST(%s AS %s)' % (column, _type_map.get(type, type)) 
    195218 
    196219    def concat(self, *args): 
    197220        return '||'.join(args) 
  • trac/db/sqlite_backend.py

    diff --git a/trac/db/sqlite_backend.py b/trac/db/sqlite_backend.py
    a b  
    108108                    return 
    109109                yield row 
    110110 
     111# Mapping from "abstract" SQL types to DB-specific types 
     112_type_map = { 
     113    'int': 'integer', 
     114    'int64': 'integer', 
     115} 
     116 
    111117 
    112118def _to_sql(table): 
    113119    sql = ["CREATE TABLE %s (" % table.name] 
    114120    coldefs = [] 
    115121    for column in table.columns: 
    116122        ctype = column.type.lower() 
     123        ctype = _type_map.get(ctype, ctype) 
    117124        if column.auto_increment: 
    118125            ctype = "integer PRIMARY KEY" 
    119126        elif len(table.key) == 1 and column.name in table.key: 
    120127            ctype += " PRIMARY KEY" 
    121         elif ctype == "int": 
    122             ctype = "integer" 
    123128        coldefs.append("    %s %s" % (column.name, ctype)) 
    124129    if len(table.key) > 1: 
    125130        coldefs.append("    UNIQUE (%s)" % ','.join(table.key)) 
     
    182187    def to_sql(self, table): 
    183188        return _to_sql(table) 
    184189 
     190    def alter_column_types(self, table, columns): 
     191        """Yield SQL statements altering the type of one or more columns of 
     192        a table. 
     193         
     194        Type changes are specified as a `columns` dict mapping column names 
     195        to `(from, to)` SQL type tuples. 
     196        """ 
     197        for name, (from_, to) in sorted(columns.iteritems()): 
     198            if _type_map.get(to, to) != _type_map.get(from_, from_): 
     199                raise NotImplementedError('Conversion from %s to %s is not ' 
     200                                          'implemented' % (from_, to)) 
     201        return () 
     202 
    185203    def backup(self, dest_file): 
    186204        """Simple SQLite-specific backup of the database. 
    187205 
     
    195213            raise TracError("Backup attempt failed") 
    196214        return dest_file 
    197215 
     216 
    198217class SQLiteConnection(ConnectionWrapper): 
    199218    """Connection wrapper for SQLite.""" 
    200219 
     
    243262 
    244263    def cast(self, column, type): 
    245264        if sqlite_version >= 30203: 
    246             return 'CAST(%s AS %s)' % (column, type) 
     265            return 'CAST(%s AS %s)' % (column, _type_map.get(type, type)) 
    247266        elif type == 'int': 
    248267            # hack to force older SQLite versions to convert column to an int 
    249268            return '1*' + column 
  • trac/db/tests/__init__.py

    diff --git a/trac/db/tests/__init__.py b/trac/db/tests/__init__.py
    a b  
    11import unittest 
    22 
    3 from trac.db.tests import api 
    4 from trac.db.tests import postgres_test 
     3from trac.db.tests import api, mysql_test, postgres_test 
    54 
    65from trac.db.tests.functional import functionalSuite 
    76 
     
    98 
    109    suite = unittest.TestSuite() 
    1110    suite.addTest(api.suite()) 
     11    suite.addTest(mysql_test.suite()) 
    1212    suite.addTest(postgres_test.suite()) 
    1313    return suite 
    1414 
  • new file trac/db/tests/mysql_test.py

    diff --git a/trac/db/tests/mysql_test.py b/trac/db/tests/mysql_test.py
    new file mode 100644
    - +  
     1# -*- coding: utf-8 -*- 
     2# 
     3# Copyright (C) 2009 Edgewall Software 
     4# All rights reserved. 
     5# 
     6# This software is licensed as described in the file COPYING, which 
     7# you should have received as part of this distribution. The terms 
     8# are also available at http://trac.edgewall.org/wiki/TracLicense. 
     9# 
     10# This software consists of voluntary contributions made by many 
     11# individuals. For the exact contribution history, see the revision 
     12# history and logs, available at http://trac.edgewall.org/log/. 
     13 
     14import unittest 
     15 
     16from trac.db.mysql_backend import MySQLConnector 
     17from trac.test import EnvironmentStub 
     18 
     19 
     20class MySQLTableAlterationSQLTest(unittest.TestCase): 
     21    def setUp(self): 
     22        self.env = EnvironmentStub() 
     23     
     24    def test_alter_column_types(self): 
     25        connector = MySQLConnector(self.env) 
     26        sql = connector.alter_column_types('milestone', 
     27                                           {'due': ('int', 'int64'), 
     28                                            'completed': ('int', 'int64')}) 
     29        sql = list(sql) 
     30        self.assertEqual([ 
     31            "ALTER TABLE milestone " 
     32                "MODIFY completed bigint, " 
     33                "MODIFY due bigint", 
     34            ], sql) 
     35 
     36    def test_alter_column_types_same(self): 
     37        connector = MySQLConnector(self.env) 
     38        sql = connector.alter_column_types('milestone', 
     39                                           {'due': ('int', 'int'), 
     40                                            'completed': ('int', 'int64')}) 
     41        sql = list(sql) 
     42        self.assertEqual([ 
     43            "ALTER TABLE milestone " 
     44                "MODIFY completed bigint", 
     45            ], sql) 
     46 
     47    def test_alter_column_types_none(self): 
     48        connector = MySQLConnector(self.env) 
     49        sql = connector.alter_column_types('milestone', 
     50                                           {'due': ('int', 'int')}) 
     51        self.assertEqual([], list(sql)) 
     52 
     53 
     54def suite(): 
     55    suite = unittest.TestSuite() 
     56    suite.addTest(unittest.makeSuite(MySQLTableAlterationSQLTest, 'test')) 
     57    return suite 
     58 
     59 
     60if __name__ == '__main__': 
     61    unittest.main(defaultTest='suite') 
  • trac/db/tests/postgres_test.py

    diff --git a/trac/db/tests/postgres_test.py b/trac/db/tests/postgres_test.py
    a b  
    1111class PostgresTableCreationSQLTest(unittest.TestCase): 
    1212    def setUp(self): 
    1313        self.env = EnvironmentStub() 
    14         self.db = self.env.get_db_cnx() 
    1514     
    1615    def _unroll_generator(self, generator): 
    1716        items = [] 
     
    8281        self.assertEqual(index_sql, sql_commands[1]) 
    8382 
    8483 
     84class PostgresTableAlterationSQLTest(unittest.TestCase): 
     85    def setUp(self): 
     86        self.env = EnvironmentStub() 
     87     
     88    def test_alter_column_types(self): 
     89        connector = PostgreSQLConnector(self.env) 
     90        sql = connector.alter_column_types('milestone', 
     91                                           {'due': ('int', 'int64'), 
     92                                            'completed': ('int', 'int64')}) 
     93        sql = list(sql) 
     94        self.assertEqual([ 
     95            "ALTER TABLE milestone " 
     96                "ALTER COLUMN completed TYPE bigint, " 
     97                "ALTER COLUMN due TYPE bigint", 
     98            ], sql) 
     99 
     100    def test_alter_column_types_same(self): 
     101        connector = PostgreSQLConnector(self.env) 
     102        sql = connector.alter_column_types('milestone', 
     103                                           {'due': ('int', 'int'), 
     104                                            'completed': ('int', 'int64')}) 
     105        sql = list(sql) 
     106        self.assertEqual([ 
     107            "ALTER TABLE milestone " 
     108                "ALTER COLUMN completed TYPE bigint", 
     109            ], sql) 
     110 
     111    def test_alter_column_types_none(self): 
     112        connector = PostgreSQLConnector(self.env) 
     113        sql = connector.alter_column_types('milestone', 
     114                                           {'due': ('int', 'int')}) 
     115        self.assertEqual([], list(sql)) 
     116 
     117 
    85118def suite(): 
    86     return unittest.makeSuite(PostgresTableCreationSQLTest, 'test') 
     119    suite = unittest.TestSuite() 
     120    suite.addTest(unittest.makeSuite(PostgresTableCreationSQLTest, 'test')) 
     121    suite.addTest(unittest.makeSuite(PostgresTableAlterationSQLTest, 'test')) 
     122    return suite 
     123 
    87124 
    88125if __name__ == '__main__': 
    89126    unittest.main(defaultTest='suite') 
  • trac/db_default.py

    diff --git a/trac/db_default.py b/trac/db_default.py
    a b  
    1717from trac.db import Table, Column, Index 
    1818 
    1919# Database version identifier. Used for automatic upgrades. 
    20 db_version = 22 
     20db_version = 23 
    2121 
    2222def __mkreports(reports): 
    2323    """Utility function used to create report data in same syntax as the 
     
    6767        Column('id'), 
    6868        Column('filename'), 
    6969        Column('size', type='int'), 
    70         Column('time', type='int'), 
     70        Column('time', type='int64'), 
    7171        Column('description'), 
    7272        Column('author'), 
    7373        Column('ipnr')], 
     
    7676    Table('wiki', key=('name', 'version'))[ 
    7777        Column('name'), 
    7878        Column('version', type='int'), 
    79         Column('time', type='int'), 
     79        Column('time', type='int64'), 
    8080        Column('author'), 
    8181        Column('ipnr'), 
    8282        Column('text'), 
     
    8787    # Version control cache 
    8888    Table('revision', key='rev')[ 
    8989        Column('rev'), 
    90         Column('time', type='int'), 
     90        Column('time', type='int64'), 
    9191        Column('author'), 
    9292        Column('message'), 
    9393        Index(['time'])], 
     
    104104    Table('ticket', key='id')[ 
    105105        Column('id', auto_increment=True), 
    106106        Column('type'), 
    107         Column('time', type='int'), 
    108         Column('changetime', type='int'), 
     107        Column('time', type='int64'), 
     108        Column('changetime', type='int64'), 
    109109        Column('component'), 
    110110        Column('severity'), 
    111111        Column('priority'), 
     
    123123        Index(['status'])],     
    124124    Table('ticket_change', key=('ticket', 'time', 'field'))[ 
    125125        Column('ticket', type='int'), 
    126         Column('time', type='int'), 
     126        Column('time', type='int64'), 
    127127        Column('author'), 
    128128        Column('field'), 
    129129        Column('oldvalue'), 
     
    144144        Column('description')], 
    145145    Table('milestone', key='name')[ 
    146146        Column('name'), 
    147         Column('due', type='int'), 
    148         Column('completed', type='int'), 
     147        Column('due', type='int64'), 
     148        Column('completed', type='int64'), 
    149149        Column('description')], 
    150150    Table('version', key='name')[ 
    151151        Column('name'), 
    152         Column('time', type='int'), 
     152        Column('time', type='int64'), 
    153153        Column('description')], 
    154154 
    155155    # Report system 
  • trac/ticket/model.py

    diff --git a/trac/ticket/model.py b/trac/ticket/model.py
    a b  
    2626from trac.ticket.api import TicketSystem 
    2727from trac.util import embedded_numbers, partition 
    2828from trac.util.text import empty 
    29 from trac.util.datefmt import utc, utcmax, to_timestamp 
     29from trac.util.datefmt import from_utimestamp, to_utimestamp, utc, utcmax 
    3030from trac.util.translation import _ 
    3131 
    3232__all__ = ['Ticket', 'Type', 'Status', 'Resolution', 'Priority', 'Severity', 
     
    114114        for i, field in enumerate(std_fields): 
    115115            value = row[i] 
    116116            if field in self.time_fields: 
    117                 self.values[field] = datetime.fromtimestamp(value or 0, utc) 
     117                self.values[field] = from_utimestamp(value) 
    118118            elif value is None: 
    119119                self.values[field] = empty 
    120120            else: 
     
    201201        values = dict(self.values) 
    202202        for field in self.time_fields: 
    203203            if field in values: 
    204                 values[field] = to_timestamp(values[field]) 
     204                values[field] = to_utimestamp(values[field]) 
    205205         
    206206        # Insert ticket record 
    207207        std_fields = [] 
     
    251251        cursor = db.cursor() 
    252252        if when is None: 
    253253            when = datetime.now(utc) 
    254         when_ts = to_timestamp(when) 
     254        when_ts = to_utimestamp(when) 
    255255 
    256256        if 'component' in self.values: 
    257257            # If the component is changed on a 'new' ticket then owner field 
     
    331331        db = self._get_db(db) 
    332332        cursor = db.cursor() 
    333333        sid = str(self.id) 
    334         when_ts = when and to_timestamp(when) or 0 
     334        when_ts = to_utimestamp(when) 
    335335        if when_ts: 
    336336            cursor.execute("SELECT time,author,field,oldvalue,newvalue," 
    337337                           "1 AS permanent FROM ticket_change " 
     
    359359                           (self.id, sid, sid)) 
    360360        log = [] 
    361361        for t, author, field, oldvalue, newvalue, permanent in cursor: 
    362             log.append((datetime.fromtimestamp(int(t), utc), author, field, 
    363                        oldvalue or '', newvalue or '', permanent)) 
     362            log.append((from_utimestamp(t), author, field, 
     363                        oldvalue or '', newvalue or '', permanent)) 
    364364        return log 
    365365 
    366366    def delete(self, db=None): 
     
    389389                           "WHERE ticket=%s AND time=%s", 
    390390                           (self.id, ts)) 
    391391            fields = {} 
    392             change = {'date': datetime.fromtimestamp(int(ts), utc), 
     392            change = {'date': from_utimestamp(ts), 
    393393                      'author': author, 'fields': fields} 
    394394            for field, author, old, new in cursor: 
    395395                fields[field] = {'author': author, 'old': old, 'new': new} 
     
    399399        """Modify a ticket comment specified by its date, while keeping a 
    400400        history of edits. 
    401401        """ 
    402         ts = to_timestamp(cdate) 
     402        ts = to_utimestamp(cdate) 
    403403        if when is None: 
    404404            when = datetime.now(utc) 
    405         when_ts = to_timestamp(when) 
     405        when_ts = to_utimestamp(when) 
    406406         
    407407        db, handle_ta = self._get_db_for_write(db) 
    408408        cursor = db.cursor() 
     
    444444                           (self.id, ts0, db.like_escape('_comment') + '%')) 
    445445            for field, author, comment, ts in cursor: 
    446446                rev = int(field[8:]) 
    447                 history.append((rev, datetime.fromtimestamp(int(ts0), utc), 
    448                                 author0, comment)) 
     447                history.append((rev, from_utimestamp(long(ts0)), author0, 
     448                                comment)) 
    449449                ts0, author0 = ts, author 
    450450            history.sort() 
    451451            rev = history and (history[-1][0] + 1) or 0 
    452             history.append((rev, datetime.fromtimestamp(int(ts0), utc), 
    453                             author0, last_comment)) 
     452            history.append((rev, from_utimestamp(long(ts0)), author0, 
     453                            last_comment)) 
    454454        return history 
    455455 
    456456    def _find_comment(self, cnum, fields, db): 
     
    784784    def _from_database(self, row): 
    785785        name, due, completed, description = row 
    786786        self.name = name 
    787         self.due = due and datetime.fromtimestamp(int(due), utc) or None 
    788         self.completed = completed and \ 
    789                          datetime.fromtimestamp(int(completed), utc) or None 
     787        self.due = due and from_utimestamp(due) or None 
     788        self.completed = completed and from_utimestamp(completed) or None 
    790789        self.description = description or '' 
    791790        self._to_old() 
    792791 
     
    838837        self.env.log.debug("Creating new milestone '%s'" % self.name) 
    839838        cursor.execute("INSERT INTO milestone (name,due,completed,description) " 
    840839                       "VALUES (%s,%s,%s,%s)", 
    841                        (self.name, to_timestamp(self.due), to_timestamp(self.completed), 
    842                         self.description)) 
     840                       (self.name, to_utimestamp(self.due), 
     841                        to_utimestamp(self.completed), self.description)) 
    843842        self._to_old() 
    844843        TicketSystem(self.env).reset_ticket_fields(db) 
    845844 
     
    863862        self.env.log.info('Updating milestone "%s"' % self.name) 
    864863        cursor.execute("UPDATE milestone SET name=%s,due=%s," 
    865864                       "completed=%s,description=%s WHERE name=%s", 
    866                        (self.name, to_timestamp(self.due), to_timestamp(self.completed), 
    867                         self.description, self._old['name'])) 
     865                       (self.name, to_utimestamp(self.due), 
     866                        to_utimestamp(self.completed), self.description, 
     867                        self._old['name'])) 
    868868        self.env.log.info('Updating milestone field of all tickets ' 
    869869                          'associated with milestone "%s"' % self.name) 
    870870        cursor.execute("UPDATE ticket SET milestone=%s WHERE milestone=%s", 
     
    934934                raise ResourceNotFound(_('Version %(name)s does not exist.', 
    935935                                         name=name)) 
    936936            self.name = self._old_name = name 
    937             self.time = row[0] and datetime.fromtimestamp(int(row[0]), utc) or None 
     937            self.time = row[0] and from_utimestamp(row[0]) or None 
    938938            self.description = row[1] or '' 
    939939        else: 
    940940            self.name = self._old_name = None 
     
    975975        self.env.log.debug("Creating new version '%s'" % self.name) 
    976976        cursor.execute("INSERT INTO version (name,time,description) " 
    977977                       "VALUES (%s,%s,%s)", 
    978                        (self.name, to_timestamp(self.time), self.description)) 
     978                       (self.name, to_utimestamp(self.time), self.description)) 
    979979        self._old_name = self.name 
    980980        TicketSystem(self.env).reset_ticket_fields(db) 
    981981 
     
    997997        self.env.log.info('Updating version "%s"' % self.name) 
    998998        cursor.execute("UPDATE version SET name=%s,time=%s,description=%s " 
    999999                       "WHERE name=%s", 
    1000                        (self.name, to_timestamp(self.time), self.description, 
     1000                       (self.name, to_utimestamp(self.time), self.description, 
    10011001                        self._old_name)) 
    10021002        if self.name != self._old_name: 
    10031003            # Update tickets 
     
    10191019        for name, time, description in cursor: 
    10201020            version = cls(env) 
    10211021            version.name = version._old_name = name 
    1022             version.time = time and datetime.fromtimestamp(int(time), utc) or None 
     1022            version.time = time and from_utimestamp(time) or None 
    10231023            version.description = description or '' 
    10241024            versions.append(version) 
    10251025        def version_order(v): 
  • trac/ticket/query.py

    diff --git a/trac/ticket/query.py b/trac/ticket/query.py
    a b  
    3131from trac.resource import Resource 
    3232from trac.ticket.api import TicketSystem 
    3333from trac.util import Ranges 
    34 from trac.util.datefmt import format_datetime, parse_date, to_timestamp, utc 
     34from trac.util.datefmt import format_datetime, from_utimestamp, parse_date, \ 
     35                              to_timestamp, to_utimestamp, utc 
    3536from trac.util.presentation import Paginator 
    3637from trac.util.text import empty, shorten_line, unicode_unquote 
    3738from trac.util.translation import _, tag_ 
     
    331332                elif val is None: 
    332333                    val = '--' 
    333334                elif name in self.time_fields: 
    334                     val = datetime.fromtimestamp(int(val or 0), utc) 
     335                    val = from_utimestamp(val) 
    335336                elif field and field['type'] == 'checkbox': 
    336337                    try: 
    337338                        val = bool(int(val)) 
     
    466467        def get_timestamp(date): 
    467468            if date: 
    468469                try: 
    469                     return to_timestamp(parse_date(date, req.tz)) 
     470                    return to_utimestamp(parse_date(date, req.tz)) 
    470471                except TracError, e: 
    471472                    errors.append(unicode(e)) 
    472473            return None 
     
    484485                                    value.split(';', 1)] 
    485486                else: 
    486487                    (start, end) = (value.strip(), '') 
    487                 col_cast = db.cast(col, 'int') 
     488                col_cast = db.cast(col, 'int64') 
    488489                start = get_timestamp(start) 
    489490                end = get_timestamp(end) 
    490491                if start is not None and end is not None: 
  • trac/ticket/roadmap.py

    diff --git a/trac/ticket/roadmap.py b/trac/ticket/roadmap.py
    a b  
    1818from StringIO import StringIO 
    1919from datetime import datetime 
    2020import re 
    21 from time import time 
    2221 
    2322from genshi.builder import tag 
    2423 
     
    3029from trac.perm import IPermissionRequestor 
    3130from trac.resource import * 
    3231from trac.search import ISearchSource, search_to_sql, shorten_result 
    33 from trac.util.datefmt import parse_date, utc, to_timestamp, to_datetime, \ 
     32from trac.util.datefmt import parse_date, utc, to_utimestamp, \ 
    3433                              get_date_format_hint, get_datetime_format_hint, \ 
    35                               format_date, format_datetime 
     34                              format_date, format_datetime, from_utimestamp 
    3635from trac.util.text import CRLF 
    3736from trac.util.translation import _ 
    3837from trac.ticket import Milestone, Ticket, TicketSystem, group_milestones 
     
    475474                                   (ticket.id,)) 
    476475                    row = cursor.fetchone() 
    477476                    if row: 
    478                         write_utctime('COMPLETED', to_datetime(row[0], utc)) 
     477                        write_utctime('COMPLETED', from_utimestamp(row[0])) 
    479478                write_prop('END', 'VTODO') 
    480479        write_prop('END', 'VCALENDAR') 
    481480 
     
    530529            # TODO: creation and (later) modifications should also be reported 
    531530            cursor.execute("SELECT completed,name,description FROM milestone " 
    532531                           "WHERE completed>=%s AND completed<=%s", 
    533                            (to_timestamp(start), to_timestamp(stop))) 
     532                           (to_utimestamp(start), to_utimestamp(stop))) 
    534533            for completed, name, description in cursor: 
    535534                milestone = milestone_realm(id=name) 
    536535                if 'MILESTONE_VIEW' in req.perm(milestone): 
    537                     yield('milestone', datetime.fromtimestamp(completed, utc), 
     536                    yield('milestone', from_utimestamp(completed), 
    538537                          '', (milestone, description)) # FIXME: author? 
    539538 
    540539            # Attachments 
     
    866865        for name, due, completed, description in cursor: 
    867866            milestone = milestone_realm(id=name) 
    868867            if 'MILESTONE_VIEW' in req.perm(milestone): 
     868                dt = (completed and from_utimestamp(completed) or 
     869                      due and from_utimestamp(due) or datetime.now(utc)) 
    869870                yield (get_resource_url(self.env, milestone, req.href), 
    870                        get_resource_name(self.env, milestone), 
    871                        datetime.fromtimestamp( 
    872                            completed or due or time(), utc), 
     871                       get_resource_name(self.env, milestone), dt, 
    873872                       '', shorten_result(description, terms)) 
    874873         
    875874        # Attachments 
  • trac/ticket/templates/report.rss

    diff --git a/trac/ticket/templates/report.rss b/trac/ticket/templates/report.rss
    a b  
    2626                </py:when> 
    2727                <py:when test="col in ('time', 'changetime', 'created', 'modified')"> 
    2828                  <!-- FIXME: we end up with multiple pubDate --> 
    29                   <pubDate py:if="cell.value != 'None'">${http_date(fromtimestamp(int(cell.value)))}</pubDate> 
     29                  <pubDate py:if="cell.value != 'None'">${http_date(from_utimestamp(long(cell.value)))}</pubDate> 
    3030                </py:when> 
    3131                <py:when test="col == 'summary'"> 
    3232                  <title>#$row.id: $cell.value</title> 
  • trac/ticket/templates/report_view.html

    diff --git a/trac/ticket/templates/report_view.html b/trac/ticket/templates/report_view.html
    a b  
    147147 
    148148                        <!--! generic fields --> 
    149149                        <py:when test="col == 'time'"> 
    150                           <td class="date" py:attrs="td_attrs">${cell.value != '' and format_time(int(cell.value)) or '--'} 
     150                          <td class="date" py:attrs="td_attrs">${cell.value != '' and format_time(from_utimestamp(long(cell.value))) or '--'} 
    151151                            <hr py:if="fullrow"/> 
    152152                          </td> 
    153153                        </py:when> 
    154154 
    155155                        <py:when test="col in ('date', 'created', 'modified')"> 
    156                           <td class="date" py:attrs="td_attrs">${cell.value != '' and format_date(int(cell.value)) or '--'} 
     156                          <td class="date" py:attrs="td_attrs">${cell.value != '' and format_date(from_utimestamp(long(cell.value))) or '--'} 
    157157                            <hr py:if="fullrow"/> 
    158158                          </td> 
    159159                        </py:when> 
    160160 
    161161                        <py:when test="col == 'datetime'"> 
    162                           <td class="date" py:attrs="td_attrs">${cell.value != '' and format_datetime(int(cell.value)) or '--'} 
     162                          <td class="date" py:attrs="td_attrs">${cell.value != '' and format_datetime(from_utimestamp(long(cell.value))) or '--'} 
    163163                            <hr py:if="fullrow"/> 
    164164                          </td> 
    165165                        </py:when> 
  • trac/ticket/tests/model.py

    diff --git a/trac/ticket/tests/model.py b/trac/ticket/tests/model.py
    a b  
    44from trac.ticket.model import Ticket, Component, Milestone, Priority, Type, Version 
    55from trac.ticket.api import IMilestoneChangeListener, ITicketChangeListener 
    66from trac.test import EnvironmentStub 
    7 from trac.util.datefmt import utc, to_timestamp 
     7from trac.util.datefmt import utc, to_utimestamp 
    88 
    99from datetime import datetime 
    1010import unittest 
     
    300300                       "                        description,author,ipnr) " 
    301301                       "VALUES ('ticket',%s,'file.txt',1234,%s," 
    302302                       "        'My file','mark','')", 
    303                        (str(tkt_id), to_timestamp(t2))) 
     303                       (str(tkt_id), to_utimestamp(t2))) 
    304304        db.commit() 
    305305        t3 = datetime(2001, 1, 1, 1, 1, 3, 0, utc) 
    306306        ticket.save_changes('jim', 'Other', t3) 
     
    312312                          sorted(log[1:3])) 
    313313        self.assertEqual((t3, 'jim', 'comment', '', 'Other', True), log[3]) 
    314314 
     315    def test_subsecond_change(self): 
     316        """Perform two ticket changes within a second.""" 
     317        tkt_id = self._insert_ticket('Test', reporter='joe', component='foo') 
     318        ticket = Ticket(self.env, tkt_id) 
     319        t1 = datetime(2001, 1, 1, 1, 1, 1, 123456, utc) 
     320        ticket.save_changes('jane', 'Testing', t1) 
     321        t2 = datetime(2001, 1, 1, 1, 1, 1, 789012, utc) 
     322        ticket.save_changes('jim', 'Other', t2) 
     323        log = ticket.get_changelog() 
     324        self.assertEqual(2, len(log)) 
     325        self.assertEqual((t1, 'jane', 'comment', '', 'Testing', True), log[0]) 
     326        self.assertEqual((t2, 'jim', 'comment', '', 'Other', True), log[1]) 
     327 
    315328    def test_changelog_with_reverted_change(self): 
    316329        tkt_id = self._insert_ticket('Test', reporter='joe', component='foo') 
    317330        ticket = Ticket(self.env, tkt_id) 
     
    545558 
    546559        cursor = self.db.cursor() 
    547560        cursor.execute("SELECT * FROM milestone WHERE name='Test'") 
    548         self.assertEqual(('Test', to_timestamp(t1), to_timestamp(t2), 'Foo bar'), 
     561        self.assertEqual(('Test', to_utimestamp(t1), to_utimestamp(t2), 
     562                          'Foo bar'), 
    549563                         cursor.fetchone()) 
    550564 
    551565    def test_update_milestone_without_name(self): 
  • trac/ticket/tests/query.py

    diff --git a/trac/ticket/tests/query.py b/trac/ticket/tests/query.py
    a b  
    358358  LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority) 
    359359WHERE (((%(cast_time)s>=%%s AND %(cast_time)s<%%s))) 
    360360ORDER BY COALESCE(t.id,0)=0,t.id""" % { 
    361           'cast_time': self.env.get_db_cnx().cast('t.time', 'int')}) 
    362         self.assertEqual([1217548800, 1220227200], args) 
     361          'cast_time': self.env.get_db_cnx().cast('t.time', 'int64')}) 
     362        self.assertEqual([1217548800000000L, 1220227200000000L], args) 
    363363        tickets = query.execute(self.req) 
    364364 
    365365    def test_constrained_by_time_range_exclusion(self): 
     
    371371  LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority) 
    372372WHERE ((NOT (%(cast_time)s>=%%s AND %(cast_time)s<%%s))) 
    373373ORDER BY COALESCE(t.id,0)=0,t.id""" % { 
    374           'cast_time': self.env.get_db_cnx().cast('t.time', 'int')}) 
    375         self.assertEqual([1217548800, 1220227200], args) 
     374          'cast_time': self.env.get_db_cnx().cast('t.time', 'int64')}) 
     375        self.assertEqual([1217548800000000L, 1220227200000000L], args) 
    376376        tickets = query.execute(self.req) 
    377377 
    378378    def test_constrained_by_time_range_open_right(self): 
     
    384384  LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority) 
    385385WHERE ((%(cast_time)s>=%%s)) 
    386386ORDER BY COALESCE(t.id,0)=0,t.id""" % { 
    387           'cast_time': self.env.get_db_cnx().cast('t.time', 'int')}) 
    388         self.assertEqual([1217548800], args) 
     387          'cast_time': self.env.get_db_cnx().cast('t.time', 'int64')}) 
     388        self.assertEqual([1217548800000000L], args) 
    389389        tickets = query.execute(self.req) 
    390390 
    391391    def test_constrained_by_time_range_open_left(self): 
     
    397397  LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority) 
    398398WHERE ((%(cast_time)s<%%s)) 
    399399ORDER BY COALESCE(t.id,0)=0,t.id""" % { 
    400           'cast_time': self.env.get_db_cnx().cast('t.time', 'int')}) 
    401         self.assertEqual([1220227200], args) 
     400          'cast_time': self.env.get_db_cnx().cast('t.time', 'int64')}) 
     401        self.assertEqual([1220227200000000L], args) 
    402402        tickets = query.execute(self.req) 
    403403 
    404404    def test_constrained_by_time_range_modified(self): 
     
    410410  LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority) 
    411411WHERE (((%(cast_changetime)s>=%%s AND %(cast_changetime)s<%%s))) 
    412412ORDER BY COALESCE(t.id,0)=0,t.id""" % { 
    413           'cast_changetime': self.env.get_db_cnx().cast('t.changetime', 'int')}) 
    414         self.assertEqual([1217548800, 1220227200], args) 
     413          'cast_changetime': self.env.get_db_cnx().cast('t.changetime', 'int64')}) 
     414        self.assertEqual([1217548800000000L, 1220227200000000L], args) 
    415415        tickets = query.execute(self.req) 
    416416 
    417417    def test_constrained_by_keywords(self): 
  • trac/ticket/web_ui.py

    diff --git a/trac/ticket/web_ui.py b/trac/ticket/web_ui.py
    a b  
    3636from trac.timeline.api import ITimelineEventProvider 
    3737from trac.util import get_reporter_id 
    3838from trac.util.compat import any 
    39 from trac.util.datefmt import format_datetime, to_timestamp, utc 
     39from trac.util.datefmt import format_datetime, from_utimestamp, \ 
     40                              to_utimestamp, utc 
    4041from trac.util.text import exception_to_unicode, obfuscate_email_address,  \ 
    4142                           shorten_line, to_unicode 
    4243from trac.util.presentation import separated 
     
    214215                           ': ', 
    215216                           ticketsystem.format_summary(summary, status, 
    216217                                                       resolution, type)), 
    217                        datetime.fromtimestamp(ts, utc), author, 
     218                       from_utimestamp(ts), author, 
    218219                       shorten_result(desc, terms)) 
    219220         
    220221        # Attachments 
     
    231232                yield ('ticket_details', _('Ticket updates'), False) 
    232233 
    233234    def get_timeline_events(self, req, start, stop, filters): 
    234         ts_start = to_timestamp(start) 
    235         ts_stop = to_timestamp(stop) 
     235        ts_start = to_utimestamp(start) 
     236        ts_stop = to_utimestamp(stop) 
    236237 
    237238        status_map = {'new': ('newticket', N_('created')), 
    238239                      'reopened': ('reopenedticket', N_('reopened')), 
     
    268269            else: 
    269270                return None 
    270271            kind, verb = status_map[status] 
    271             return (kind, datetime.fromtimestamp(ts, utc), author, 
     272            return (kind, from_utimestamp(ts), author, 
    272273                    (ticket, verb, info, summary, status, resolution, type, 
    273274                     description, comment, cid)) 
    274275 
     
    16431644                rev = int(field[8:]) 
    16441645                comment_history.setdefault(rev, {}).update({'comment': old}) 
    16451646                comment_history.setdefault(rev + 1, {}).update( 
    1646                         {'author': author, 
    1647                          'date': datetime.fromtimestamp(int(new), utc)}) 
     1647                        {'author': author, 'date': from_utimestamp(long(new))}) 
    16481648            elif old or new: 
    16491649                current['fields'][field] = {'old': old, 'new': new} 
    16501650        if current: 
  • trac/timeline/web_ui.py

    diff --git a/trac/timeline/web_ui.py b/trac/timeline/web_ui.py
    a b  
    2929from trac.perm import IPermissionRequestor 
    3030from trac.timeline.api import ITimelineEventProvider 
    3131from trac.util.datefmt import format_date, format_datetime, parse_date, \ 
    32                               to_timestamp, utc, pretty_timedelta 
     32                              to_utimestamp, utc, pretty_timedelta 
    3333from trac.util.text import exception_to_unicode, to_unicode 
    3434from trac.util.translation import _, tag_ 
    3535from trac.web import IRequestHandler, IRequestFilter 
     
    106106                precision = timedelta(hours=1) 
    107107            else: 
    108108                precision = None 
    109         fromdate = fromdate.replace(hour=23, minute=59, second=59) 
     109        fromdate = fromdate.replace(hour=23, minute=59, second=59, 
     110                                    microsecond=999999) 
    110111        try: 
    111112            daysback = int(req.args.get('daysback', '')) 
    112113        except ValueError: 
     
    312313                kind, date, author, data = event 
    313314            render = lambda field, context: \ 
    314315                    provider.render_timeline_event(context, field, event) 
    315         if isinstance(date, datetime): 
    316             dateuid = to_timestamp(date) 
    317         else: 
    318             dateuid = date 
     316        if not isinstance(date, datetime): 
    319317            date = datetime.fromtimestamp(date, utc) 
     318        dateuid = to_utimestamp(date) 
    320319        return {'kind': kind, 'author': author, 'date': date, 
    321320                'dateuid': dateuid, 'render': render, 'event': event, 
    322321                'data': data, 'provider': provider} 
  • trac/upgrades/db15.py

    diff --git a/trac/upgrades/db15.py b/trac/upgrades/db15.py
    a b  
    1010        Column('authenticated', type='int'), 
    1111        Column('var_name'), 
    1212        Column('var_value')] 
    13     db_backend, _ = DatabaseManager(env)._get_connector() 
     13    db_backend, _ = DatabaseManager(env).get_connector() 
    1414    for stmt in db_backend.to_sql(session_table): 
    1515        cursor.execute(stmt) 
    1616 
  • trac/upgrades/db17.py

    diff --git a/trac/upgrades/db17.py b/trac/upgrades/db17.py
    a b  
    1616        Column('base_rev'), 
    1717        Index(['rev']) 
    1818    ] 
    19     db_connector, _ = DatabaseManager(env)._get_connector() 
     19    db_connector, _ = DatabaseManager(env).get_connector() 
    2020    for stmt in db_connector.to_sql(table): 
    2121        cursor.execute(stmt) 
    2222 
  • trac/upgrades/db18.py

    diff --git a/trac/upgrades/db18.py b/trac/upgrades/db18.py
    a b  
    2929                Index(['ticket']), 
    3030                Index(['time'])]] 
    3131     
    32     db_connector, _ = DatabaseManager(env)._get_connector() 
     32    db_connector, _ = DatabaseManager(env).get_connector() 
    3333    for table in tables: 
    3434        for stmt in db_connector.to_sql(table): 
    3535            cursor.execute(stmt) 
  • trac/upgrades/db19.py

    diff --git a/trac/upgrades/db19.py b/trac/upgrades/db19.py
    a b  
    1313        Column('query'), 
    1414        Column('description') 
    1515    ] 
    16     db_connector, _ = DatabaseManager(env)._get_connector() 
     16    db_connector, _ = DatabaseManager(env).get_connector() 
    1717    for stmt in db_connector.to_sql(table): 
    1818        cursor.execute(stmt) 
    1919 
  • trac/upgrades/db22.py

    diff --git a/trac/upgrades/db22.py b/trac/upgrades/db22.py
    a b  
    66        Column('id'), 
    77        Column('generation', type='int') 
    88    ] 
    9     db_connector, _ = DatabaseManager(env)._get_connector() 
     9    db_connector, _ = DatabaseManager(env).get_connector() 
    1010    for stmt in db_connector.to_sql(table): 
    1111        cursor.execute(stmt) 
  • new file trac/upgrades/db23.py

    diff --git a/trac/upgrades/db23.py b/trac/upgrades/db23.py
    new file mode 100644
    - +  
     1from trac.db import DatabaseManager 
     2 
     3 
     4def do_upgrade(env, ver, cursor): 
     5    """Convert time values from integer seconds to integer microseconds.""" 
     6    tables = [ 
     7        ('attachment', {'time': ('int', 'int64')}), 
     8        ('wiki', {'time': ('int', 'int64')}), 
     9        ('revision', {'time': ('int', 'int64')}), 
     10        ('ticket', {'time': ('int', 'int64'), 
     11                    'changetime': ('int', 'int64')}), 
     12        ('ticket_change', {'time': ('int', 'int64')}), 
     13        ('milestone', {'due': ('int', 'int64'), 
     14                       'completed': ('int', 'int64')}), 
     15        ('version', {'time': ('int', 'int64')}), 
     16    ] 
     17     
     18    db_connector, _ = DatabaseManager(env).get_connector() 
     19    db = env.get_db_cnx() 
     20    for table, columns in tables: 
     21        # Alter column types 
     22        for sql in db_connector.alter_column_types(table, columns): 
     23            cursor.execute(sql) 
     24         
     25        # Convert timestamps to microseconds 
     26        cursor.execute("UPDATE %s SET %s" % (table, 
     27                        ', '.join("%s=%s*1000000" % (column, column) 
     28                                  for column in columns))) 
     29     
     30    # Convert comment edit timestamps to microseconds 
     31    cursor.execute("UPDATE ticket_change SET newvalue=%s*1000000 " 
     32                   "WHERE field %s" % (db.cast('newvalue', 'int64'), 
     33                                       db.like()), 
     34                   ('_comment%',)) 
  • trac/util/datefmt.py

    diff --git a/trac/util/datefmt.py b/trac/util/datefmt.py
    a b  
    6161    else: 
    6262        return 0 
    6363 
     64def to_utimestamp(dt): 
     65    """Return a microsecond POSIX timestamp for the given `datetime`.""" 
     66    if not dt: 
     67        return 0 
     68    diff = dt - _epoc 
     69    return (diff.days * 86400000000L + diff.seconds * 1000000 
     70            + diff.microseconds) 
     71 
     72def from_utimestamp(ts): 
     73    """Return the `datetime` for the given microsecond POSIX timestamp.""" 
     74    return _epoc + timedelta(microseconds=ts or 0) 
    6475 
    6576# -- formatting 
    6677 
  • trac/util/tests/datefmt.py

    diff --git a/trac/util/tests/datefmt.py b/trac/util/tests/datefmt.py
    a b  
    113113                         datefmt.format_date(a_date, format='%Y-%m-%d')) 
    114114 
    115115 
     116class UTimestampTestCase(unittest.TestCase): 
     117     
     118    def test_sub_second(self): 
     119        t = datetime.datetime(2001, 2, 3, 4, 5, 6, 123456, datefmt.utc) 
     120        ts = datefmt.to_utimestamp(t) 
     121        self.assertEqual(t, datefmt.from_utimestamp(ts)) 
     122 
     123 
    116124def suite(): 
    117125    suite = unittest.TestSuite() 
    118126    if PytzTestCase: 
     
    120128    else: 
    121129        print "SKIP: utils/tests/datefmt.py (no pytz installed)" 
    122130    suite.addTest(unittest.makeSuite(DateFormatTestCase)) 
     131    suite.addTest(unittest.makeSuite(UTimestampTestCase)) 
    123132    return suite 
    124133 
    125134if __name__ == '__main__': 
  • trac/versioncontrol/cache.py

    diff --git a/trac/versioncontrol/cache.py b/trac/versioncontrol/cache.py
    a b  
    1414# 
    1515# Author: Christopher Lenz <cmlenz@gmx.de> 
    1616 
    17 from datetime import datetime 
    1817import os 
    1918import posixpath 
    2019 
    2120from trac.core import TracError 
    22 from trac.util.datefmt import utc, to_timestamp 
     21from trac.util.datefmt import from_utimestamp, to_utimestamp 
    2322from trac.util.translation import _ 
    2423from trac.versioncontrol import Changeset, Node, Repository, Authorizer, \ 
    2524                                NoSuchChangeset 
     
    6766        cursor.execute("SELECT rev FROM revision " 
    6867                       "WHERE time >= %s AND time < %s " 
    6968                       "ORDER BY time DESC, rev DESC", 
    70                        (to_timestamp(start), to_timestamp(stop))) 
     69                       (to_utimestamp(start), to_utimestamp(stop))) 
    7170        for rev, in cursor: 
    7271            try: 
    7372                if self.authz.has_permission_for_changeset(rev): 
     
    8079        db = self.getdb() 
    8180        cursor = db.cursor() 
    8281        cursor.execute("UPDATE revision SET time=%s, author=%s, message=%s " 
    83                        "WHERE rev=%s", (to_timestamp(cset.date), 
     82                       "WHERE rev=%s", (to_utimestamp(cset.date), 
    8483                                        cset.author, cset.message, 
    8584                                        (str(cset.rev)))) 
    8685        db.commit() 
     
    187186                                       " (rev,time,author,message) " 
    188187                                       "VALUES (%s,%s,%s,%s)", 
    189188                                       (str(next_youngest), 
    190                                         to_timestamp(cset.date), 
     189                                        to_utimestamp(cset.date), 
    191190                                        cset.author, cset.message)) 
    192191                    except Exception, e: # *another* 1.1. resync attempt won  
    193192                        self.log.warning('Revision %s already cached: %s' % 
     
    339338        cursor = db.cursor() 
    340339        cursor.execute("SELECT time,author,message FROM revision " 
    341340                       "WHERE rev=%s", (str(rev),)) 
    342         row = cursor.fetchone() 
    343         if row: 
    344             _date, author, message = row 
    345             date = datetime.fromtimestamp(_date, utc) 
     341        for _date, author, message in cursor: 
     342            date = from_utimestamp(_date) 
    346343            Changeset.__init__(self, rev, message, author, date) 
     344            break 
    347345        else: 
    348346            raise NoSuchChangeset(rev) 
    349347        self.scope = getattr(repos, 'scope', '') 
  • trac/versioncontrol/svn_fs.py

    diff --git a/trac/versioncontrol/svn_fs.py b/trac/versioncontrol/svn_fs.py
    a b  
    4646import os.path 
    4747import weakref 
    4848import posixpath 
    49 from datetime import datetime 
    5049 
    5150from trac.config import ListOption 
    5251from trac.core import * 
     
    5857from trac.util import embedded_numbers 
    5958from trac.util.text import exception_to_unicode, to_unicode 
    6059from trac.util.translation import _ 
    61 from trac.util.datefmt import utc 
     60from trac.util.datefmt import from_utimestamp 
    6261 
    6362 
    6463application_pool = None 
     
    783782                                 core.SVN_PROP_REVISION_DATE, self.pool()) 
    784783        if not _date: 
    785784            return None 
    786         ts = core.svn_time_from_cstring(_date, self.pool()) / 1000000 
    787         return datetime.fromtimestamp(ts, utc) 
     785        return from_utimestamp(core.svn_time_from_cstring(_date, self.pool())) 
    788786 
    789787    def _get_prop(self, name): 
    790788        return fs.node_prop(self.root, self._scoped_path_utf8, name, 
     
    849847        author = author and to_unicode(author, 'utf-8') 
    850848        _date = self._get_prop(core.SVN_PROP_REVISION_DATE) 
    851849        if _date: 
    852             ts = core.svn_time_from_cstring(_date, self.pool()) / 1000000 
    853             date = datetime.fromtimestamp(ts, utc) 
     850            ts = core.svn_time_from_cstring(_date, self.pool()) 
     851            date = from_utimestamp(ts) 
    854852        else: 
    855853            date = None 
    856854        Changeset.__init__(self, rev, message, author, date) 
  • trac/versioncontrol/tests/cache.py

    diff --git a/trac/versioncontrol/tests/cache.py b/trac/versioncontrol/tests/cache.py
    a b  
    1818 
    1919from trac.log import logger_factory 
    2020from trac.test import Mock, InMemoryDatabase 
    21 from trac.util.datefmt import to_timestamp, utc 
     21from trac.util.datefmt import to_utimestamp, utc 
    2222from trac.versioncontrol import Repository, Changeset, Node, NoSuchChangeset 
    2323from trac.versioncontrol.cache import CachedRepository 
    2424 
     
    7373 
    7474        cursor = self.db.cursor() 
    7575        cursor.execute("SELECT rev,time,author,message FROM revision") 
    76         self.assertEquals(('0', to_timestamp(t1), '', ''), cursor.fetchone()) 
    77         self.assertEquals(('1', to_timestamp(t2), 'joe', 'Import'), cursor.fetchone()) 
     76        self.assertEquals(('0', to_utimestamp(t1), '', ''), cursor.fetchone()) 
     77        self.assertEquals(('1', to_utimestamp(t2), 'joe', 'Import'), cursor.fetchone()) 
    7878        self.assertEquals(None, cursor.fetchone()) 
    7979        cursor.execute("SELECT rev,path,node_type,change_type,base_path," 
    8080                       "base_rev FROM node_change") 
     
    9090        t3 = datetime(2003, 1, 1, 1, 1, 1, 0, utc) 
    9191        cursor = self.db.cursor() 
    9292        cursor.execute("INSERT INTO revision (rev,time,author,message) " 
    93                        "VALUES (0,%s,'','')", (to_timestamp(t1),)) 
     93                       "VALUES (0,%s,'','')", (to_utimestamp(t1),)) 
    9494        cursor.execute("INSERT INTO revision (rev,time,author,message) " 
    95                        "VALUES (1,%s,'joe','Import')", (to_timestamp(t2),)) 
     95                       "VALUES (1,%s,'joe','Import')", (to_utimestamp(t2),)) 
    9696        cursor.executemany("INSERT INTO node_change (rev,path,node_type," 
    9797                           "change_type,base_path,base_rev) " 
    9898                           "VALUES ('1',%s,%s,%s,%s,%s)", 
     
    114114 
    115115        cursor = self.db.cursor() 
    116116        cursor.execute("SELECT time,author,message FROM revision WHERE rev='2'") 
    117         self.assertEquals((to_timestamp(t3), 'joe', 'Update'), cursor.fetchone()) 
     117        self.assertEquals((to_utimestamp(t3), 'joe', 'Update'), cursor.fetchone()) 
    118118        self.assertEquals(None, cursor.fetchone()) 
    119119        cursor.execute("SELECT path,node_type,change_type,base_path,base_rev " 
    120120                       "FROM node_change WHERE rev='2'") 
     
    127127        t2 = datetime(2002, 1, 1, 1, 1, 1, 0, utc) 
    128128        cursor = self.db.cursor() 
    129129        cursor.execute("INSERT INTO revision (rev,time,author,message) " 
    130                        "VALUES (0,%s,'','')", (to_timestamp(t1),)) 
     130                       "VALUES (0,%s,'','')", (to_utimestamp(t1),)) 
    131131        cursor.execute("INSERT INTO revision (rev,time,author,message) " 
    132                        "VALUES (1,%s,'joe','Import')", (to_timestamp(t2),)) 
     132                       "VALUES (1,%s,'joe','Import')", (to_utimestamp(t2),)) 
    133133        cursor.executemany("INSERT INTO node_change (rev,path,node_type," 
    134134                           "change_type,base_path,base_rev) " 
    135135                           "VALUES ('1',%s,%s,%s,%s,%s)", 
  • trac/versioncontrol/tests/svn_fs.py

    diff --git a/trac/versioncontrol/tests/svn_fs.py b/trac/versioncontrol/tests/svn_fs.py
    a b  
    145145        self.assertEqual(u'/tête', node.path) 
    146146        self.assertEqual(Node.DIRECTORY, node.kind) 
    147147        self.assertEqual(HEAD, node.rev) 
    148         self.assertEqual(datetime(2007, 4, 30, 17, 45, 26, 0, utc), 
     148        self.assertEqual(datetime(2007, 4, 30, 17, 45, 26, 234375, utc), 
    149149                         node.last_modified) 
    150150        node = self.repos.get_node(u'/tête/README.txt') 
    151151        self.assertEqual('README.txt', node.name) 
    152152        self.assertEqual(u'/tête/README.txt', node.path) 
    153153        self.assertEqual(Node.FILE, node.kind) 
    154154        self.assertEqual(3, node.rev) 
    155         self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 0, utc), node.last_modified) 
     155        self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 234643, utc), node.last_modified) 
    156156 
    157157    def test_get_node_specific_rev(self): 
    158158        node = self.repos.get_node(u'/tête', 1) 
     
    160160        self.assertEqual(u'/tête', node.path) 
    161161        self.assertEqual(Node.DIRECTORY, node.kind) 
    162162        self.assertEqual(1, node.rev) 
    163         self.assertEqual(datetime(2005, 4, 1, 10, 0, 52, 0, utc), node.last_modified) 
     163        self.assertEqual(datetime(2005, 4, 1, 10, 0, 52, 353248, utc), node.last_modified) 
    164164        node = self.repos.get_node(u'/tête/README.txt', 2) 
    165165        self.assertEqual('README.txt', node.name) 
    166166        self.assertEqual(u'/tête/README.txt', node.path) 
    167167        self.assertEqual(Node.FILE, node.kind) 
    168168        self.assertEqual(2, node.rev) 
    169         self.assertEqual(datetime(2005, 4, 1, 13, 12, 18, 0, utc), node.last_modified) 
     169        self.assertEqual(datetime(2005, 4, 1, 13, 12, 18, 216267, utc), node.last_modified) 
    170170 
    171171    def test_get_dir_entries(self): 
    172172        node = self.repos.get_node(u'/tête') 
     
    383383        self.assertEqual(0, chgset.rev) 
    384384        self.assertEqual('', chgset.message) 
    385385        self.assertEqual('', chgset.author) 
    386         self.assertEqual(datetime(2005, 4, 1, 9, 57, 41, 0, utc), chgset.date) 
     386        self.assertEqual(datetime(2005, 4, 1, 9, 57, 41, 312767, utc), chgset.date) 
    387387        self.assertRaises(StopIteration, chgset.get_changes().next) 
    388388 
    389389    def test_changeset_added_dirs(self): 
     
    391391        self.assertEqual(1, chgset.rev) 
    392392        self.assertEqual('Initial directory layout.', chgset.message) 
    393393        self.assertEqual('john', chgset.author) 
    394         self.assertEqual(datetime(2005, 4, 1, 10, 0, 52, 0, utc), chgset.date) 
     394        self.assertEqual(datetime(2005, 4, 1, 10, 0, 52, 353248, utc), chgset.date) 
    395395 
    396396        changes = chgset.get_changes() 
    397397        self.assertEqual(('branches', Node.DIRECTORY, Changeset.ADD, None, -1), 
     
    407407        self.assertEqual(3, chgset.rev) 
    408408        self.assertEqual('Fixed README.\n', chgset.message) 
    409409        self.assertEqual('kate', chgset.author) 
    410         self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 0, utc), chgset.date) 
     410        self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 234643, utc), chgset.date) 
    411411 
    412412        changes = chgset.get_changes() 
    413413        self.assertEqual((u'tête/README.txt', Node.FILE, Changeset.EDIT, 
     
    419419        self.assertEqual(5, chgset.rev) 
    420420        self.assertEqual('Moved directories.', chgset.message) 
    421421        self.assertEqual('kate', chgset.author) 
    422         self.assertEqual(datetime(2005, 4, 1, 16, 25, 39, 0, utc), chgset.date) 
     422        self.assertEqual(datetime(2005, 4, 1, 16, 25, 39, 658099, utc), chgset.date) 
    423423 
    424424        changes = chgset.get_changes() 
    425425        self.assertEqual((u'tête/dir1/dir2', Node.DIRECTORY, Changeset.MOVE, 
     
    433433        self.assertEqual(6, chgset.rev) 
    434434        self.assertEqual('More things to read', chgset.message) 
    435435        self.assertEqual('john', chgset.author) 
    436         self.assertEqual(datetime(2005, 4, 1, 18, 56, 46, 0, utc), chgset.date) 
     436        self.assertEqual(datetime(2005, 4, 1, 18, 56, 46, 985846, utc), chgset.date) 
    437437 
    438438        changes = chgset.get_changes() 
    439439        self.assertEqual((u'tête/README2.txt', Node.FILE, Changeset.COPY, 
     
    550550        self.assertEqual('/dir1', node.path) 
    551551        self.assertEqual(Node.DIRECTORY, node.kind) 
    552552        self.assertEqual(5, node.rev) 
    553         self.assertEqual(datetime(2005, 4, 1, 16, 25, 39, 0, utc), node.last_modified) 
     553        self.assertEqual(datetime(2005, 4, 1, 16, 25, 39, 658099, utc), node.last_modified) 
    554554        node = self.repos.get_node('/README.txt') 
    555555        self.assertEqual('README.txt', node.name) 
    556556        self.assertEqual('/README.txt', node.path) 
    557557        self.assertEqual(Node.FILE, node.kind) 
    558558        self.assertEqual(3, node.rev) 
    559         self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 0, utc), node.last_modified) 
     559        self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 234643, utc), node.last_modified) 
    560560 
    561561    def test_get_node_specific_rev(self): 
    562562        node = self.repos.get_node('/dir1', 4) 
     
    564564        self.assertEqual('/dir1', node.path) 
    565565        self.assertEqual(Node.DIRECTORY, node.kind) 
    566566        self.assertEqual(4, node.rev) 
    567         self.assertEqual(datetime(2005, 4, 1, 15, 42, 35, 0, utc), node.last_modified) 
     567        self.assertEqual(datetime(2005, 4, 1, 15, 42, 35, 450595, utc), node.last_modified) 
    568568        node = self.repos.get_node('/README.txt', 2) 
    569569        self.assertEqual('README.txt', node.name) 
    570570        self.assertEqual('/README.txt', node.path) 
    571571        self.assertEqual(Node.FILE, node.kind) 
    572572        self.assertEqual(2, node.rev) 
    573         self.assertEqual(datetime(2005, 4, 1, 13, 12, 18, 0, utc), node.last_modified) 
     573        self.assertEqual(datetime(2005, 4, 1, 13, 12, 18, 216267, utc), node.last_modified) 
    574574 
    575575    def test_get_dir_entries(self): 
    576576        node = self.repos.get_node('/') 
     
    675675        self.assertEqual(0, chgset.rev) 
    676676        self.assertEqual('', chgset.message) 
    677677        self.assertEqual('', chgset.author) 
    678         self.assertEqual(datetime(2005, 4, 1, 9, 57, 41, 0, utc), chgset.date) 
     678        self.assertEqual(datetime(2005, 4, 1, 9, 57, 41, 312767, utc), chgset.date) 
    679679        self.assertRaises(StopIteration, chgset.get_changes().next) 
    680680 
    681681    def test_changeset_added_dirs(self): 
     
    683683        self.assertEqual(4, chgset.rev) 
    684684        self.assertEqual('More directories.', chgset.message) 
    685685        self.assertEqual('john', chgset.author) 
    686         self.assertEqual(datetime(2005, 4, 1, 15, 42, 35, 0, utc), chgset.date) 
     686        self.assertEqual(datetime(2005, 4, 1, 15, 42, 35, 450595, utc), chgset.date) 
    687687 
    688688        changes = chgset.get_changes() 
    689689        self.assertEqual(('dir1', Node.DIRECTORY, 'add', None, -1), 
     
    699699        self.assertEqual(3, chgset.rev) 
    700700        self.assertEqual('Fixed README.\n', chgset.message) 
    701701        self.assertEqual('kate', chgset.author) 
    702         self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 0, utc), chgset.date) 
     702        self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 234643, utc), chgset.date) 
    703703 
    704704        changes = chgset.get_changes() 
    705705        self.assertEqual(('README.txt', Node.FILE, Changeset.EDIT, 
     
    711711        self.assertEqual(5, chgset.rev) 
    712712        self.assertEqual('Moved directories.', chgset.message) 
    713713        self.assertEqual('kate', chgset.author) 
    714         self.assertEqual(datetime(2005, 4, 1, 16, 25, 39, 0, utc), chgset.date) 
     714        self.assertEqual(datetime(2005, 4, 1, 16, 25, 39, 658099, utc), chgset.date) 
    715715 
    716716        changes = chgset.get_changes() 
    717717        self.assertEqual(('dir1/dir2', Node.DIRECTORY, Changeset.MOVE, 
     
    725725        self.assertEqual(6, chgset.rev) 
    726726        self.assertEqual('More things to read', chgset.message) 
    727727        self.assertEqual('john', chgset.author) 
    728         self.assertEqual(datetime(2005, 4, 1, 18, 56, 46, 0, utc), chgset.date) 
     728        self.assertEqual(datetime(2005, 4, 1, 18, 56, 46, 985846, utc), chgset.date) 
    729729 
    730730        changes = chgset.get_changes() 
    731731        self.assertEqual(('README2.txt', Node.FILE, Changeset.COPY, 
  • trac/versioncontrol/web_ui/changeset.py

    diff --git a/trac/versioncontrol/web_ui/changeset.py b/trac/versioncontrol/web_ui/changeset.py
    a b  
    1818#         Christopher Lenz <cmlenz@gmx.de> 
    1919#         Christian Boos <cboos@neuf.fr> 
    2020 
    21 from datetime import datetime 
    2221from itertools import groupby 
    2322import os 
    2423import posixpath 
     
    3635from trac.timeline.api import ITimelineEventProvider 
    3736from trac.util import embedded_numbers, content_disposition 
    3837from trac.util.compat import any 
    39 from trac.util.datefmt import pretty_timedelta, utc 
     38from trac.util.datefmt import from_utimestamp, pretty_timedelta 
    4039from trac.util.text import exception_to_unicode, unicode_urlencode, \ 
    4140                           shorten_line, CRLF 
    4241from trac.util.translation import _ 
     
    992991                continue 
    993992            yield (req.href.changeset(rev), 
    994993                   '[%s]: %s' % (rev, shorten_line(log)), 
    995                    datetime.fromtimestamp(ts, utc), author, 
    996                    shorten_result(log, terms)) 
     994                   from_utimestamp(ts), author, shorten_result(log, terms)) 
    997995 
    998996 
    999997class AnyDiffModule(Component): 
  • trac/web/chrome.py

    diff --git a/trac/web/chrome.py b/trac/web/chrome.py
    a b  
    6565                           shorten_line, unicode_quote_plus, to_unicode, \ 
    6666                           javascript_quote, exception_to_unicode 
    6767from trac.util.datefmt import pretty_timedelta, format_datetime, format_date, \ 
    68                               format_time, http_date, utc 
     68                              format_time, from_utimestamp, http_date, utc 
    6969from trac.util.translation import _ 
    7070from trac.web.api import IRequestHandler, ITemplateStreamFilter, HTTPNotFound 
    7171from trac.web.href import Href 
     
    751751            'format_time': partial(format_time, tzinfo=tzinfo), 
    752752            'fromtimestamp': partial(datetime.datetime.fromtimestamp, 
    753753                                     tz=tzinfo), 
     754            'from_utimestamp': from_utimestamp, 
    754755 
    755756            # Wiki-formatting functions 
    756757            'wiki_to': partial(format_to, self.env), 
  • trac/web/tests/session.py

    diff --git a/trac/web/tests/session.py b/trac/web/tests/session.py
    a b  
    166166                       (0,)) 
    167167        cursor.execute("INSERT INTO session " 
    168168                       "VALUES ('987654', 0, %s)", 
    169                        (time.time() - PURGE_AGE - 3600,)) 
     169                       (int(time.time() - PURGE_AGE - 3600),)) 
    170170        cursor.execute("INSERT INTO session_attribute VALUES " 
    171171                       "('987654', 0, 'foo', 'bar')") 
    172172         
  • trac/wiki/admin.py

    diff --git a/trac/wiki/admin.py b/trac/wiki/admin.py
    a b  
    1515import os.path 
    1616import pkg_resources 
    1717import sys 
    18 import time 
    1918 
    2019from trac.admin import * 
    2120from trac.core import * 
     
    2322from trac.wiki.api import WikiSystem 
    2423from trac.util import read_file 
    2524from trac.util.compat import any 
    26 from trac.util.datefmt import format_datetime, utc 
     25from trac.util.datefmt import format_datetime, from_utimestamp, \ 
     26                              to_utimestamp, utc 
    2727from trac.util.text import to_unicode, unicode_quote, unicode_unquote, \ 
    2828                           print_table, printout 
    2929from trac.util.translation import _ 
     
    144144                           "SELECT 1+COALESCE(max(version),0),%s,%s," 
    145145                           "       'trac','127.0.0.1',%s FROM wiki " 
    146146                           "WHERE name=%s", 
    147                            (title, int(time.time()), data, title)) 
     147                           (title, to_utimestamp(datetime.now(utc)), data, 
     148                            title)) 
    148149        if not old: 
    149150            WikiSystem(self.env).pages.invalidate(db) 
    150151        if handle_ta: 
     
    190191        cursor.execute("SELECT name, max(version), max(time) " 
    191192                       "FROM wiki GROUP BY name ORDER BY name") 
    192193        print_table([(r[0], int(r[1]), 
    193                       format_datetime(datetime.fromtimestamp(r[2], utc), 
     194                      format_datetime(from_utimestamp(r[2]), 
    194195                                      console_datetime_format)) 
    195196                     for r in cursor], 
    196197                    [_('Title'), _('Edits'), _('Modified')]) 
  • trac/wiki/macros.py

    diff --git a/trac/wiki/macros.py b/trac/wiki/macros.py
    a b  
    1414# 
    1515# Author: Christopher Lenz <cmlenz@gmx.de> 
    1616 
    17 from datetime import datetime 
    1817from itertools import groupby 
    1918import inspect 
    2019import os 
     
    2726from trac.core import * 
    2827from trac.resource import Resource, get_resource_url, get_resource_summary 
    2928from trac.util.compat import rpartition 
    30 from trac.util.datefmt import format_date, utc 
     29from trac.util.datefmt import format_date, from_utimestamp 
    3130from trac.util.html import escape 
    3231from trac.util.presentation import separated 
    3332from trac.util.text import unquote, to_unicode 
     
    225224        for name, version, ts in cursor: 
    226225            if not 'WIKI_VIEW' in formatter.perm('wiki', name, version): 
    227226                continue 
    228             time = datetime.fromtimestamp(ts, utc) 
    229             date = format_date(time) 
     227            date = format_date(from_utimestamp(ts)) 
    230228            if date != prevdate: 
    231229                prevdate = date 
    232230                entries_per_date.append((date, [])) 
  • trac/wiki/model.py

    diff --git a/trac/wiki/model.py b/trac/wiki/model.py
    a b  
    2020 
    2121from trac.core import * 
    2222from trac.resource import Resource 
    23 from trac.util.datefmt import utc, to_timestamp 
     23from trac.util.datefmt import from_utimestamp, to_utimestamp, utc 
    2424from trac.util.translation import _ 
    2525from trac.wiki.api import WikiSystem 
    2626 
     
    6969            version, time, author, text, comment, readonly = row 
    7070            self.version = int(version) 
    7171            self.author = author 
    72             self.time = datetime.fromtimestamp(time, utc) 
     72            self.time = from_utimestamp(time) 
    7373            self.text = text 
    7474            self.comment = comment 
    7575            self.readonly = readonly and int(readonly) or 0 
     
    138138            cursor.execute("INSERT INTO wiki (name,version,time,author,ipnr," 
    139139                           "text,comment,readonly) VALUES (%s,%s,%s,%s,%s,%s," 
    140140                           "%s,%s)", (self.name, self.version + 1, 
    141                                       to_timestamp(t), author, remote_addr, 
     141                                      to_utimestamp(t), author, remote_addr, 
    142142                                      self.text, comment, self.readonly)) 
    143143            self.version += 1 
    144144            self.resource = self.resource(version=self.version) 
     
    178178                       "WHERE name=%s AND version<=%s " 
    179179                       "ORDER BY version DESC", (self.name, self.version)) 
    180180        for version, ts, author, comment, ipnr in cursor: 
    181             time = datetime.fromtimestamp(ts, utc) 
    182             yield version, time, author, comment, ipnr 
     181            yield version, from_utimestamp(ts), author, comment, ipnr 
  • trac/wiki/tests/model.py

    diff --git a/trac/wiki/tests/model.py b/trac/wiki/tests/model.py
    a b  
    33 
    44from trac.core import * 
    55from trac.test import EnvironmentStub 
    6 from trac.util.datefmt import utc, to_timestamp 
     6from trac.util.datefmt import utc, to_utimestamp 
    77from trac.wiki import WikiPage, IWikiChangeListener 
    88 
    99 
     
    5252        t = datetime(2001, 1, 1, 1, 1, 1, 0, utc) 
    5353        cursor = self.db.cursor() 
    5454        cursor.execute("INSERT INTO wiki VALUES(%s,%s,%s,%s,%s,%s,%s,%s)", 
    55                        ('TestPage', 1, to_timestamp(t), 'joe', '::1', 
     55                       ('TestPage', 1, to_utimestamp(t), 'joe', '::1', 
    5656                        'Bla bla', 'Testing', 0)) 
    5757 
    5858        page = WikiPage(self.env, 'TestPage') 
     
    9191        cursor = self.db.cursor() 
    9292        cursor.execute("SELECT version,time,author,ipnr,text,comment," 
    9393                       "readonly FROM wiki WHERE name=%s", ('TestPage',)) 
    94         self.assertEqual((1, to_timestamp(t), 'joe', '::1', 'Bla bla', 
     94        self.assertEqual((1, to_utimestamp(t), 'joe', '::1', 'Bla bla', 
    9595                          'Testing', 0), 
    9696                         cursor.fetchone()) 
    9797 
     
    103103        t = datetime(2001, 1, 1, 1, 1, 1, 0, utc) 
    104104        t2 = datetime(2002, 1, 1, 1, 1, 1, 0, utc) 
    105105        cursor.execute("INSERT INTO wiki VALUES(%s,%s,%s,%s,%s,%s,%s,%s)", 
    106                        ('TestPage', 1, to_timestamp(t), 'joe', '::1', 
     106                       ('TestPage', 1, to_utimestamp(t), 'joe', '::1', 
    107107                        'Bla bla', 'Testing', 0)) 
    108108 
    109109        page = WikiPage(self.env, 'TestPage') 
     
    119119 
    120120        cursor.execute("SELECT version,time,author,ipnr,text,comment," 
    121121                       "readonly FROM wiki WHERE name=%s", ('TestPage',)) 
    122         self.assertEqual((1, to_timestamp(t), 'joe', '::1', 'Bla bla', 
     122        self.assertEqual((1, to_utimestamp(t), 'joe', '::1', 'Bla bla', 
    123123                          'Testing', 0), 
    124124                         cursor.fetchone()) 
    125         self.assertEqual((2, to_timestamp(t2), 'kate', '192.168.0.101', 'Bla', 
     125        self.assertEqual((2, to_utimestamp(t2), 'kate', '192.168.0.101', 'Bla', 
    126126                          'Changing', 0), cursor.fetchone()) 
    127127 
    128128        listener = TestWikiChangeListener(self.env) 
  • trac/wiki/web_ui.py

    diff --git a/trac/wiki/web_ui.py b/trac/wiki/web_ui.py
    a b  
    1616# Author: Jonas Borgström <jonas@edgewall.com> 
    1717#         Christopher Lenz <cmlenz@gmx.de> 
    1818 
    19 from datetime import datetime 
    2019import pkg_resources 
    2120import re 
    2221 
     
    3130from trac.search import ISearchSource, search_to_sql, shorten_result 
    3231from trac.timeline.api import ITimelineEventProvider 
    3332from trac.util import get_reporter_id 
    34 from trac.util.datefmt import to_timestamp, utc 
     33from trac.util.datefmt import from_utimestamp, to_utimestamp 
    3534from trac.util.text import shorten_line 
    3635from trac.util.translation import _ 
    3736from trac.versioncontrol.diff import get_diff_options, diff_blocks 
     
    630629            cursor = db.cursor() 
    631630            cursor.execute("SELECT time,name,comment,author,version " 
    632631                           "FROM wiki WHERE time>=%s AND time<=%s", 
    633                            (to_timestamp(start), to_timestamp(stop))) 
     632                           (to_utimestamp(start), to_utimestamp(stop))) 
    634633            for ts, name, comment, author, version in cursor: 
    635634                wiki_page = wiki_realm(id=name, version=version) 
    636635                if 'WIKI_VIEW' not in req.perm(wiki_page): 
    637636                    continue 
    638                 yield ('wiki', datetime.fromtimestamp(ts, utc), author, 
     637                yield ('wiki', from_utimestamp(ts), author, 
    639638                       (wiki_page, comment)) 
    640639 
    641640            # Attachments 
     
    686685            if 'WIKI_VIEW' in req.perm(page): 
    687686                yield (get_resource_url(self.env, page, req.href), 
    688687                       '%s: %s' % (name, shorten_line(text)), 
    689                        datetime.fromtimestamp(ts, utc), author, 
     688                       from_utimestamp(ts), author, 
    690689                       shorten_result(text, terms)) 
    691690         
    692691        # Attachments