use datetime instead of mx.DateTime tls-sprint
authorsylvain.thenault@logilab.fr
Tue, 10 Mar 2009 11:35:52 +0100
branchtls-sprint
changeset 1016 26387b836099
parent 1014 4792a1bb72a9
child 1024 bb96289257bf
use datetime instead of mx.DateTime
__init__.py
appobject.py
common/uilib.py
cwvreg.py
devtools/__init__.py
devtools/devctl.py
devtools/fill.py
entities/lib.py
entities/test/unittest_base.py
etwist/request.py
etwist/server.py
schema.py
server/checkintegrity.py
server/hooks.py
server/migractions.py
server/repository.py
server/serverctl.py
server/session.py
server/sources/ldapuser.py
server/sources/native.py
server/sources/pyrorql.py
server/sqlutils.py
server/ssplanner.py
server/test/unittest_migractions.py
server/test/unittest_multisources.py
server/test/unittest_querier.py
server/test/unittest_repository.py
server/test/unittest_rql2sql.py
server/test/unittest_sqlutils.py
sobjects/test/unittest_notification.py
sobjects/test/unittest_supervising.py
test/unittest_entity.py
utils.py
web/controller.py
web/form.py
web/httpcache.py
web/test/test_views.py
web/test/unittest_controller.py
web/test/unittest_views_baseforms.py
web/test/unittest_widgets.py
web/views/basecontrollers.py
web/views/calendar.py
web/views/wdoc.py
web/widgets.py
--- a/__init__.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/__init__.py	Tue Mar 10 11:35:52 2009 +0100
@@ -2,7 +2,7 @@
 relations between entitites.
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 :license: General Public License version 2 - http://www.gnu.org/licenses
 """
--- a/appobject.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/appobject.py	Tue Mar 10 11:35:52 2009 +0100
@@ -7,8 +7,8 @@
 __docformat__ = "restructuredtext en"
 
 from warnings import warn
+from datetime import datetime, timedelta
 
-from mx.DateTime import now, oneSecond
 from simplejson import dumps
 
 from logilab.common.decorators import classproperty
@@ -22,12 +22,13 @@
 from cubicweb.selectors import yes
 from cubicweb.utils import UStringIO, ustrftime
 
+ONESECOND = timedelta(0, 1, 0)
 
 class Cache(dict):    
     def __init__(self):
         super(Cache, self).__init__()
         self.cache_creation_date = None
-        self.latest_cache_lookup = now()
+        self.latest_cache_lookup = datetime.now()
     
 CACHE_REGISTRY = {}
 
@@ -136,8 +137,8 @@
         else:
             cache = Cache()
             CACHE_REGISTRY[cachename] = cache
-        _now = now()
-        if _now > cache.latest_cache_lookup + oneSecond:
+        _now = datetime.now()
+        if _now > cache.latest_cache_lookup + ONESECOND:
             ecache = self.req.execute('Any C,T WHERE C is ECache, C name %(name)s, C timestamp T', 
                                       {'name':cachename}).get_entity(0,0)
             cache.latest_cache_lookup = _now
@@ -281,7 +282,7 @@
         return output.getvalue()
 
     def format_date(self, date, date_format=None, time=False):
-        """return a string for a mx date time according to application's
+        """return a string for a date time according to application's
         configuration
         """
         if date:
@@ -294,7 +295,7 @@
         return u''
 
     def format_time(self, time):
-        """return a string for a mx date time according to application's
+        """return a string for a time according to application's
         configuration
         """
         if time:
--- a/common/uilib.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/common/uilib.py	Tue Mar 10 11:35:52 2009 +0100
@@ -12,13 +12,11 @@
 import csv
 import decimal
 import re
+from datetime import datetime, date, timedelta
 from urllib import quote as urlquote
 from cStringIO import StringIO
 from copy import deepcopy
 
-
-from mx.DateTime import DateTimeType, DateTimeDeltaType
-
 from logilab.common.textutils import unormalize
 from logilab.mtconverter import html_escape, html_unescape
 
@@ -509,10 +507,10 @@
         ret = function(*args, **kwargs)
         if isinstance(ret, decimal.Decimal):
             ret = float(ret)
-        elif isinstance(ret, DateTimeType):
+        elif isinstance(ret, (date, datetime)):
             ret = ret.strftime('%Y-%m-%d %H:%M')
-        elif isinstance(ret, DateTimeDeltaType):
-            ret = ret.seconds
+        elif isinstance(ret, timedelta):
+            ret = (ret.days * 24*60*60) + ret.seconds
         try:
             return simplejson.dumps(ret)
         except TypeError:
--- a/cwvreg.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/cwvreg.py	Tue Mar 10 11:35:52 2009 +0100
@@ -410,7 +410,7 @@
             vobject.config = self.config
         return super(MulCnxCubicWebRegistry, self).select(vobjects, *args, **kwargs)
     
-from mx.DateTime import DateTime, Time, DateTimeDelta
+from datetime import datetime, date, time, timedelta
 
 YAMS_TO_PY = {
     'Boolean':  bool,
@@ -419,9 +419,9 @@
     'Bytes':    Binary,
     'Int':      int,
     'Float':    float,
-    'Date':     DateTime,
-    'Datetime': DateTime,
-    'Time':     Time,
-    'Interval': DateTimeDelta,
+    'Date':     date,
+    'Datetime': datetime,
+    'Time':     time,
+    'Interval': timedelta,
     }
 
--- a/devtools/__init__.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/devtools/__init__.py	Tue Mar 10 11:35:52 2009 +0100
@@ -1,19 +1,19 @@
 """Test tools for cubicweb
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
 
 import os
 import logging
+from datetime import timedelta
 from os.path import (abspath, join, exists, basename, dirname, normpath, split,
                      isfile, isabs)
 
-from mx.DateTime import strptime, DateTimeDelta
-
 from cubicweb import CW_SOFTWARE_ROOT, ConfigurationError
+from cubicweb.utils import strptime
 from cubicweb.toolsutils import read_config
 from cubicweb.cwconfig import CubicWebConfiguration, merge_options
 from cubicweb.server.serverconfig import ServerConfiguration
@@ -271,6 +271,7 @@
                     for cellindex, (value, vtype) in enumerate(zip(row, rowdesc)):
                         if vtype in ('Date', 'Datetime') and type(value) is unicode:
                             found_date = True
+                            value = value.rsplit('.', 1)[0]
                             try:
                                 row[cellindex] = strptime(value, '%Y-%m-%d %H:%M:%S')
                             except:
@@ -284,7 +285,7 @@
                                 row[cellindex] = strptime(value, '%Y-%m-%d %H:%M:%S')
                         if vtype == 'Interval' and type(value) is int:
                             found_date = True
-                            row[cellindex] = DateTimeDelta(0, 0, 0, value)
+                            row[cellindex] = timedelta(0, value, 0) # XXX value is in number of seconds?
                     if not found_date:
                         break
             return rset
--- a/devtools/devctl.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/devtools/devctl.py	Tue Mar 10 11:35:52 2009 +0100
@@ -2,12 +2,13 @@
 cubes development
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
 
 import sys
+from datetime import datetime
 from os import walk, mkdir, chdir, listdir, getcwd
 from os.path import join, exists, abspath, basename, normpath, split, isdir
 
@@ -16,9 +17,8 @@
 from logilab.common.modutils import get_module_files
 from logilab.common.textutils import get_csv
 
-from cubicweb import CW_SOFTWARE_ROOT as BASEDIR
+from cubicweb import CW_SOFTWARE_ROOT as BASEDIR, BadCommandUsage
 from cubicweb.__pkginfo__ import version as cubicwebversion
-from cubicweb import BadCommandUsage
 from cubicweb.toolsutils import Command, register_commands, confirm, copy_skeleton
 from cubicweb.web.webconfig import WebConfiguration
 from cubicweb.server.serverconfig import ServerConfiguration
@@ -102,9 +102,8 @@
     _generate_schema_pot(w, vreg, schema, libschema=libschema, cube=cube)
                 
 def _generate_schema_pot(w, vreg, schema, libschema=None, cube=None):
-    from mx.DateTime import now
     from cubicweb.common.i18n import add_msg
-    w('# schema pot file, generated on %s\n' % now().strftime('%Y-%m-%d %H:%M:%S'))
+    w('# schema pot file, generated on %s\n' % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
     w('# \n')
     w('# singular and plural forms for each entity type\n')
     w('\n')
@@ -451,14 +450,13 @@
                 dependancies = ', '.join(repr(cube) for cube in includes)
         else:
             dependancies = ''
-        from mx.DateTime import now
         context = {'cubename' : cubename,
                    'distname' : distname,
                    'shortdesc' : shortdesc,
                    'longdesc' : longdesc or shortdesc,
                    'dependancies' : dependancies,
                    'version'  : cubicwebversion,
-                   'year'  : str(now().year),
+                   'year'  : str(datetime.now().year),
                    'author': self['author'],
                    'author-email': self['author-email'],
                    'author-web-site': self['author-web-site'],
--- a/devtools/fill.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/devtools/fill.py	Tue Mar 10 11:35:52 2009 +0100
@@ -2,16 +2,16 @@
 """This modules defines func / methods for creating test repositories
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
 
 from random import randint, choice
 from copy import deepcopy
+from datetime import datetime, date, timedelta
+from decimal import Decimal
 
-from mx.DateTime import DateTime, DateTimeDelta
-from decimal import Decimal
 from yams.constraints import (SizeConstraint, StaticVocabularyConstraint,
                               IntervalBoundConstraint)
 from rql.utils import decompose_b26 as base_decompose_b26
@@ -158,15 +158,15 @@
     
     def generate_date(self, attrname, index):
         """generates a random date (format is 'yyyy-mm-dd')"""
-        return DateTime(randint(2000, 2004), randint(1, 12), randint(1, 28))
+        return date(randint(2000, 2004), randint(1, 12), randint(1, 28))
 
     def generate_time(self, attrname, index):
         """generates a random time (format is ' HH:MM')"""
-        return DateTimeDelta(0, 11, index%60) #'11:%02d' % (index % 60)
+        return timedelta(0, 11, index%60) #'11:%02d' % (index % 60)
     
     def generate_datetime(self, attrname, index):
         """generates a random date (format is 'yyyy-mm-dd HH:MM')"""
-        return DateTime(randint(2000, 2004), randint(1, 12), randint(1, 28), 11, index%60)
+        return datetime(randint(2000, 2004), randint(1, 12), randint(1, 28), 11, index%60)
         
 
     def generate_bytes(self, attrname, index, format=None):
--- a/entities/lib.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/entities/lib.py	Tue Mar 10 11:35:52 2009 +0100
@@ -7,7 +7,7 @@
 __docformat__ = "restructuredtext en"
 
 from urlparse import urlsplit, urlunsplit
-from mx.DateTime import now
+from datetime import datetime
 
 from logilab.common.decorators import cached
 
@@ -153,6 +153,7 @@
     def dc_description(self, format='text/plain'):
         return self.synopsis or u''
 
+
 class ECache(AnyEntity):
     """Cache"""
     id = 'ECache'
@@ -160,7 +161,8 @@
     fetch_attrs, fetch_order = fetch_config(['name'])
 
     def touch(self):
-        self.req.execute('SET X timestamp %(t)s WHERE X eid %(x)s', {'t': now(), 'x': self.eid}, 'x')
+        self.req.execute('SET X timestamp %(t)s WHERE X eid %(x)s',
+                         {'t': datetime.now(), 'x': self.eid}, 'x')
 
     def valid(self, date):
         return date < self.timestamp
--- a/entities/test/unittest_base.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/entities/test/unittest_base.py	Tue Mar 10 11:35:52 2009 +0100
@@ -1,8 +1,6 @@
 # -*- coding: utf-8 -*-
 """unit tests for cubicweb.entities.base module"""
 
-from mx.DateTime import now
-
 from logilab.common.testlib import unittest_main
 from logilab.common.decorators import clear_cache
 from logilab.common.interface import implements
--- a/etwist/request.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/etwist/request.py	Tue Mar 10 11:35:52 2009 +0100
@@ -1,14 +1,14 @@
 """Twisted request handler for CubicWeb
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
 
-from twisted.web2 import http, http_headers
+from datetime import datetime
 
-from mx.DateTime import DateTimeFromTicks
+from twisted.web2 import http, http_headers
 
 from cubicweb.web import DirectResponse
 from cubicweb.web.request import CubicWebRequestBase
@@ -117,7 +117,7 @@
         mtime = self.get_header('If-modified-since', raw=False)
         if mtime:
             # :/ twisted is returned a localized time stamp
-            return DateTimeFromTicks(mtime) + GMTOFFSET
+            return datetime.fromtimestamp(mtime) + GMTOFFSET
         return None
 
 
--- a/etwist/server.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/etwist/server.py	Tue Mar 10 11:35:52 2009 +0100
@@ -1,15 +1,15 @@
 """twisted server for CubicWeb web applications
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
 
 import sys
 import select
-
-from mx.DateTime import today, RelativeDate
+from time import mktime
+from datetime import date, timedelta
 
 from twisted.application import service, strports
 from twisted.internet import reactor, task, threads
@@ -62,8 +62,8 @@
             # Don't provide additional resource information to error responses
             if response.code < 400:
                 # the HTTP RFC recommands not going further than 1 year ahead
-                expires = today() + RelativeDate(months=6)
-                response.headers.setHeader('Expires', int(expires.ticks()))
+                expires = date.today() + timedelta(days=6*30)
+                response.headers.setHeader('Expires', mktime(expires.timetuple()))
             return response
         d = maybeDeferred(super(LongTimeExpiringFile, self).renderHTTP, request)
         return d.addCallback(setExpireHeader)
--- a/schema.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/schema.py	Tue Mar 10 11:35:52 2009 +0100
@@ -23,6 +23,11 @@
 
 from cubicweb import ETYPE_NAME_MAP, ValidationError, Unauthorized
 
+# XXX <3.2 bw compat
+from yams import schema
+schema.use_py_datetime()
+nodes.use_py_datetime() 
+
 _ = unicode
 
 BASEGROUPS = ('managers', 'users', 'guests', 'owners')
--- a/server/checkintegrity.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/server/checkintegrity.py	Tue Mar 10 11:35:52 2009 +0100
@@ -2,14 +2,14 @@
 is checked.
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
 
 import sys
+from datetime import datetime
 
-from mx.DateTime import now
 from logilab.common.shellutils import ProgressBar
 
 def has_eid(sqlcursor, eid, eids):
@@ -228,8 +228,8 @@
     print 'Checking metadata'
     cursor = session.system_sql("SELECT DISTINCT type FROM entities;")
     for etype, in cursor.fetchall():
-        for rel, default in ( ('creation_date', now()),
-                              ('modification_date', now()), ):
+        for rel, default in ( ('creation_date', datetime.now()),
+                              ('modification_date', datetime.now()), ):
             cursor = session.system_sql("SELECT eid FROM %s "
                                         "WHERE %s is NULL" % (etype, rel))
             for eid, in cursor.fetchall():
--- a/server/hooks.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/server/hooks.py	Tue Mar 10 11:35:52 2009 +0100
@@ -7,7 +7,7 @@
 """
 __docformat__ = "restructuredtext en"
 
-from mx.DateTime import now
+from datetime import datetime
 
 from cubicweb import UnknownProperty, ValidationError, BadConnectionId
 
@@ -30,14 +30,14 @@
     this is a conveniency hook, you shouldn't have to disable it
     """
     if not 'creation_date' in entity:
-        entity['creation_date'] = now()
+        entity['creation_date'] = datetime.now()
     if not 'modification_date' in entity:
-        entity['modification_date'] = now()
+        entity['modification_date'] = datetime.now()
 
 def setmtime_before_update_entity(session, entity):
     """update an entity -> set modification date"""
     if not 'modification_date' in entity:
-        entity['modification_date'] = now()
+        entity['modification_date'] = datetime.now()
         
 class SetCreatorOp(PreCommitOperation):
         
--- a/server/migractions.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/server/migractions.py	Tue Mar 10 11:35:52 2009 +0100
@@ -19,8 +19,8 @@
 import sys
 import os
 from os.path import join, exists
+from datetime import datetime
 
-from mx.DateTime import now
 from logilab.common.decorators import cached
 from logilab.common.adbh import get_adv_func_helper
 
@@ -83,7 +83,7 @@
         config = self.config
         source = config.sources()['system']
         helper = get_adv_func_helper(source['db-driver'])
-        date = now().strftime('%Y-%m-%d_%H:%M:%S')
+        date = datetime.now().strftime('%Y-%m-%d_%H:%M:%S')
         app = config.appid
         backupfile = backupfile or join(config.backup_dir(),
                                         '%s-%s.dump' % (app, date))
@@ -317,6 +317,7 @@
         removedcubes = super(ServerMigrationHelper, self).cmd_remove_cube(cube)
         if not removedcubes:
             return
+        print removedcubes
         fsschema = self.fs_schema
         removedcubes_schema = self.config.load_schema()
         reposchema = self.repo.schema
--- a/server/repository.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/server/repository.py	Tue Mar 10 11:35:52 2009 +0100
@@ -19,10 +19,9 @@
 import sys
 import Queue
 from os.path import join, exists
+from datetime import datetime
 from time import time, localtime, strftime
 
-from mx.DateTime import now
-
 from logilab.common.decorators import cached
 
 from yams import BadSchemaDefinition
@@ -662,7 +661,7 @@
           deleted since the given timestamp
         """
         session = self.internal_session()
-        updatetime = now()
+        updatetime = datetime.now()
         try:
             modentities, delentities = self.system_source.modified_entities(
                 session, etypes, mtime)
--- a/server/serverctl.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/server/serverctl.py	Tue Mar 10 11:35:52 2009 +0100
@@ -1,7 +1,7 @@
 """cubicweb-ctl commands and command handlers specific to the server.serverconfig
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
@@ -466,8 +466,8 @@
     if os.system(dmpcmd):
         raise ExecutionError('Error while dumping the database')
     if output is None:
-        from mx.DateTime import today
-        date = today().strftime('%Y-%m-%d')
+        from datetime import date
+        date = date.today().strftime('%Y-%m-%d')
         output = '%s-%s.dump' % (appid, date)
     cmd = 'scp %s:/tmp/%s.dump %s' % (host, appid, output)
     print cmd
--- a/server/session.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/server/session.py	Tue Mar 10 11:35:52 2009 +0100
@@ -10,10 +10,8 @@
 import threading
 from time import time
 from types import NoneType
-from decimal import Decimal
 
-from mx.DateTime import DateTimeType, DateTimeDeltaType
-from rql.nodes import VariableRef, Function
+from rql.nodes import VariableRef, Function, ETYPE_PYOBJ_MAP, etype_from_pyobj
 from yams import BASE_TYPES
 
 from cubicweb import RequestSessionMixIn, Binary
@@ -21,26 +19,7 @@
 from cubicweb.utils import make_uid
 from cubicweb.server.rqlrewrite import RQLRewriter
 
-_ETYPE_PYOBJ_MAP = { bool: 'Boolean',
-                     int: 'Int',
-                     long: 'Int',
-                     float: 'Float',
-                     Decimal: 'Decimal',
-                     unicode: 'String',
-                     NoneType: None,
-                     Binary: 'Bytes',
-                     DateTimeType: 'Datetime',
-                     DateTimeDeltaType: 'Interval',
-                     }
-
-def etype_from_pyobj(value):
-    """guess yams type from python value"""
-    # note:
-    # * Password is not selectable so no problem)
-    # * use type(value) and not value.__class__ since mx instances have no
-    #   __class__ attribute
-    # * XXX Date, Time
-    return _ETYPE_PYOBJ_MAP[type(value)]
+ETYPE_PYOBJ_MAP[Binary] = 'Bytes'
 
 def is_final(rqlst, variable, args):
     # try to find if this is a final var or not
--- a/server/sources/ldapuser.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/server/sources/ldapuser.py	Tue Mar 10 11:35:52 2009 +0100
@@ -20,7 +20,7 @@
 FOR A PARTICULAR PURPOSE.
 """
 
-from mx.DateTime import now, DateTimeDelta
+from datetime import datetime, timedelta
 
 from logilab.common.textutils import get_csv
 from rql.nodes import Relation, VariableRef, Constant, Function
@@ -53,16 +53,16 @@
 class TimedCache(dict):
     def __init__(self, ttlm, ttls=0):
         # time to live in minutes
-        self.ttl = DateTimeDelta(0, 0, ttlm, ttls)
+        self.ttl = timedelta(0, ttlm*60 + ttls, 0)
         
     def __setitem__(self, key, value):
-        dict.__setitem__(self, key, (now(), value))
+        dict.__setitem__(self, key, (datetime.now(), value))
         
     def __getitem__(self, key):
         return dict.__getitem__(self, key)[1]
     
     def clear_expired(self):
-        now_ = now()
+        now_ = datetime.now()
         ttl = self.ttl
         for key, (timestamp, value) in self.items():
             if now_ - timestamp > ttl:
--- a/server/sources/native.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/server/sources/native.py	Tue Mar 10 11:35:52 2009 +0100
@@ -1,14 +1,13 @@
 """Adapters for native cubicweb sources.
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
 
 from threading import Lock
-
-from mx.DateTime import now
+from datetime import datetime
 
 from logilab.common.cache import Cache
 from logilab.common.configuration import REQUIRED
@@ -451,7 +450,7 @@
         try:
             res = session.system_sql(sql).fetchone()
         except:
-            assert self.pool, 'session has no pool set'
+            assert session.pool, 'session has no pool set'
             raise UnknownEid(eid)
         if res is None:
             raise UnknownEid(eid)
@@ -499,7 +498,7 @@
         """add type and source info for an eid into the system table"""
         # begin by inserting eid/type/source/extid into the entities table
         attrs = {'type': str(entity.e_schema), 'eid': entity.eid,
-                 'extid': extid, 'source': source.uri, 'mtime': now()}
+                 'extid': extid, 'source': source.uri, 'mtime': datetime.now()}
         session.system_sql(self.sqlgen.insert('entities', attrs), attrs)
 
     def delete_info(self, session, eid, etype, uri, extid):
@@ -510,7 +509,7 @@
         session.system_sql(self.sqlgen.delete('entities', attrs), attrs)
         if self.has_deleted_entitites_table:
             attrs = {'type': etype, 'eid': eid, 'extid': extid,
-                     'source': uri, 'dtime': now()}
+                     'source': uri, 'dtime': datetime.now()}
             session.system_sql(self.sqlgen.insert('deleted_entities', attrs), attrs)
         
     def fti_unindex_entity(self, session, eid):
@@ -534,7 +533,7 @@
             if self.indexer is not None:
                 self.exception('error while reindexing %s', entity)
         # update entities.mtime
-        attrs = {'eid': entity.eid, 'mtime': now()}
+        attrs = {'eid': entity.eid, 'mtime': datetime.now()}
         session.system_sql(self.sqlgen.update('entities', attrs, ['eid']), attrs)
         
     def modified_entities(self, session, etypes, mtime):
--- a/server/sources/pyrorql.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/server/sources/pyrorql.py	Tue Mar 10 11:35:52 2009 +0100
@@ -1,7 +1,7 @@
 """Source to query another RQL repository using pyro
 
 :organization: Logilab
-:copyright: 2007-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2007-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
@@ -9,7 +9,8 @@
 import threading
 from os.path import join
 
-from mx.DateTime import DateTimeFromTicks
+from time import mktime
+from datetime import datetime
 
 from Pyro.errors import PyroError, ConnectionClosedError
 
@@ -145,7 +146,7 @@
             else:
                 assert len(rset) == 1
                 timestamp = int(rset[0][0])
-            return DateTimeFromTicks(timestamp)
+            return datetime.fromtimestamp(timestamp)
         finally:
             session.close()
 
@@ -194,7 +195,7 @@
                     continue
             session.execute('SET X value %(v)s WHERE X pkey %(k)s',
                             {'k': u'sources.%s.latest-update-time' % self.uri,
-                             'v': unicode(int(updatetime.ticks()))})
+                             'v': unicode(int(mktime(updatetime.timetuple())))})
             session.commit()
         finally:
             session.close()
--- a/server/sqlutils.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/server/sqlutils.py	Tue Mar 10 11:35:52 2009 +0100
@@ -1,13 +1,16 @@
 """SQL utilities functions and classes.
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
 
+from warnings import warn
+from datetime import datetime, timedelta
+
 from logilab.common.shellutils import ProgressBar
-from logilab.common.db import get_dbapi_compliant_module
+from logilab.common import db
 from logilab.common.adbh import get_adv_func_helper
 from logilab.common.sqlgen import SQLGenerator
 
@@ -18,6 +21,7 @@
 from cubicweb.server import SQL_CONNECT_HOOKS
 from cubicweb.server.utils import crypt_password, cartesian_product
 
+db.USE_MX_DATETIME = False
 
 def sqlexec(sqlstmts, cursor_or_execute, withpb=True, delimiter=';'):
     """execute sql statements ignoring DROP/ CREATE GROUP or USER statements
@@ -105,7 +109,10 @@
                      skip_entities=skip_entities, skip_relations=skip_relations))
     return '\n'.join(output)
 
-
+try:
+    from mx.DateTime import DateTimeType, DateTimeDeltaType
+except ImportError:
+    DateTimeType, DateTimeDeltaType = None
 
 class SQLAdapterMixIn(object):
     """Mixin for SQL data sources, getting a connection from a configuration
@@ -124,7 +131,7 @@
         self.dbuser = source_config.get('db-user')
         self.dbpasswd = source_config.get('db-password')
         self.encoding = source_config.get('db-encoding', 'UTF-8')
-        self.dbapi_module = get_dbapi_compliant_module(self.dbdriver)
+        self.dbapi_module = db.get_dbapi_compliant_module(self.dbdriver)
         self.binary = self.dbapi_module.Binary
         self.dbhelper = self.dbapi_module.adv_func_helper
         self.sqlgen = SQLGenerator()
@@ -152,6 +159,16 @@
                 # convert cubicweb binary into db binary
                 if isinstance(val, Binary):
                     val = self.binary(val.getvalue())
+                # XXX <3.2 bw compat
+                elif type(val) is DateTimeType:
+                    warn('found mx date time instance, please update to use datetime',
+                         DeprecationWarning)
+                    val = datetime(val.year, val.month, val.day,
+                                   val.hour, val.minute, val.second)
+                elif type(val) is DateTimeDeltaType:
+                    warn('found mx date time instance, please update to use datetime',
+                         DeprecationWarning)
+                    val = timedelta(0, val.seconds, 0)
                 args[key] = val
             # should not collide
             args.update(query_args)
--- a/server/ssplanner.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/server/ssplanner.py	Tue Mar 10 11:35:52 2009 +0100
@@ -1,7 +1,7 @@
 """plan execution of rql queries on a single source
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
--- a/server/test/unittest_migractions.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/server/test/unittest_migractions.py	Tue Mar 10 11:35:52 2009 +0100
@@ -1,7 +1,7 @@
 """unit tests for module cubicweb.server.migractions
 """
 
-from mx.DateTime import DateTime, today
+from datetime import date
 
 from logilab.common.testlib import TestCase, unittest_main
 from cubicweb.devtools.apptest import RepositoryBasedTC, get_versions
@@ -79,12 +79,12 @@
         self.failUnless('mydate' in self.schema)
         self.assertEquals(self.schema['mydate'].subjects(), ('Note', ))
         self.assertEquals(self.schema['mydate'].objects(), ('Date', ))
-        testdate = DateTime(2005, 12, 13)
+        testdate = date(2005, 12, 13)
         eid1 = self.mh.rqlexec('INSERT Note N')[0][0]
         eid2 = self.mh.rqlexec('INSERT Note N: N mydate %(mydate)s', {'mydate' : testdate})[0][0]
         d1 = self.mh.rqlexec('Any D WHERE X eid %(x)s, X mydate D', {'x': eid1}, 'x')[0][0]
         d2 = self.mh.rqlexec('Any D WHERE X eid %(x)s, X mydate D', {'x': eid2}, 'x')[0][0]
-        self.assertEquals(d1, today())
+        self.assertEquals(d1, date.today())
         self.assertEquals(d2, testdate)
         self.mh.rollback()
             
--- a/server/test/unittest_multisources.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/server/test/unittest_multisources.py	Tue Mar 10 11:35:52 2009 +0100
@@ -1,6 +1,7 @@
 from os.path import dirname, join, abspath
+from datetime import datetime, timedelta
+
 from logilab.common.decorators import cached
-from mx.DateTime import now
 
 from cubicweb.devtools import TestServerConfiguration, init_test_database
 from cubicweb.devtools.apptest import RepositoryBasedTC
@@ -23,7 +24,7 @@
 aff1 = cu.execute('INSERT Affaire X: X ref "AFFREF", X in_state S WHERE S name "pitetre"')[0][0]
 cnx2.commit()
 
-MTIME = now() - 0.1
+MTIME = datetime.now() - timedelta(0, 10)
 
 repo3, cnx3 = init_test_database('sqlite', config=ExternalSource2Configuration('data'))
 
--- a/server/test/unittest_querier.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/server/test/unittest_querier.py	Tue Mar 10 11:35:52 2009 +0100
@@ -1,17 +1,18 @@
 # -*- coding: iso-8859-1 -*-
 """unit tests for modules cubicweb.server.querier and cubicweb.server.querier_steps
 """
+from datetime import date, datetime
 
 from logilab.common.testlib import TestCase, unittest_main
-from cubicweb.devtools import init_test_database
-from cubicweb.devtools.repotest import tuplify, BaseQuerierTC
-from unittest_session import Variable
+from rql import BadRQLQuery, RQLSyntaxError
 
-from mx.DateTime import today, now, DateTimeType
-from rql import BadRQLQuery, RQLSyntaxError
 from cubicweb import QueryError, Unauthorized
 from cubicweb.server.utils import crypt_password
 from cubicweb.server.sources.native import make_schema
+from cubicweb.devtools import init_test_database
+from cubicweb.devtools.repotest import tuplify, BaseQuerierTC
+
+from unittest_session import Variable
 
 
 # register priority/severity sorting registered procedure
@@ -187,7 +188,7 @@
         self.assertEquals(rset.description[0][0], 'Boolean')
         rset = self.execute('Any %(x)s', {'x': 1.0})
         self.assertEquals(rset.description[0][0], 'Float')
-        rset = self.execute('Any %(x)s', {'x': now()})
+        rset = self.execute('Any %(x)s', {'x': datetime.now()})
         self.assertEquals(rset.description[0][0], 'Datetime')
         rset = self.execute('Any %(x)s', {'x': 'str'})
         self.assertEquals(rset.description[0][0], 'String')
@@ -655,14 +656,14 @@
 #         self.assertEquals(rset.rows, [[eid]])
         
     def test_today_bug(self):
-        self.execute("INSERT Tag X: X name 'bidule', X creation_date TODAY")
+        self.execute("INSERT Tag X: X name 'bidule', X creation_date NOW")
         self.execute("INSERT Tag Y: Y name 'toto'")
         rset = self.execute("Any D WHERE X name in ('bidule', 'toto') , X creation_date D")
-        self.assert_(isinstance(rset.rows[0][0], DateTimeType), rset.rows)
+        self.assert_(isinstance(rset.rows[0][0], datetime), rset.rows)
         rset = self.execute('Tag X WHERE X creation_date TODAY')
         self.assertEqual(len(rset.rows), 2)
         rset = self.execute('Any MAX(D) WHERE X is Tag, X creation_date D')
-        self.failUnless(isinstance(rset[0][0], DateTimeType), type(rset[0][0]))
+        self.failUnless(isinstance(rset[0][0], datetime), type(rset[0][0]))
 
     def test_today(self):
         self.execute("INSERT Tag X: X name 'bidule', X creation_date TODAY")
@@ -767,10 +768,6 @@
         eid, = self.execute("INSERT Personne X: X nom 'bidule'")[0]
         rset = self.execute('Any X, NOW - CD WHERE X is Personne, X creation_date CD')
         self.failUnlessEqual(rset.description[0][1], 'Interval')
-        # sqlite bug
-        #from mx.DateTime import DateTimeDeltaType
-        #self.assertIsInstance(rset[0][1], DateTimeDeltaType) 
-        #self.failUnless(rset[0][1].seconds > 0)
 
     def test_select_subquery_aggregat(self):
         # percent users by groups
@@ -1241,7 +1238,7 @@
 
     def test_nonregr_set_datetime(self):
         # huum, psycopg specific
-        self.execute('SET X creation_date %(date)s WHERE X eid 1', {'date': today()})
+        self.execute('SET X creation_date %(date)s WHERE X eid 1', {'date': date.today()})
 
     def test_nonregr_set_query(self):
         ueid = self.execute("INSERT EUser X: X login 'bob', X upassword 'toto'")[0][0]
--- a/server/test/unittest_repository.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/server/test/unittest_repository.py	Tue Mar 10 11:35:52 2009 +0100
@@ -6,8 +6,8 @@
 import threading
 import time
 from copy import deepcopy
+from datetime import datetime
 
-from mx.DateTime import DateTimeType, now
 from logilab.common.testlib import TestCase, unittest_main
 from cubicweb.devtools.apptest import RepositoryBasedTC
 from cubicweb.devtools.repotest import tuplify
@@ -333,7 +333,7 @@
         cursor = self.session.pool['system']
         cursor.execute('SELECT * FROM entities WHERE eid = -1')
         data = cursor.fetchall()
-        self.assertIsInstance(data[0][3], DateTimeType)
+        self.assertIsInstance(data[0][3], datetime)
         data[0] = list(data[0])
         data[0][3] = None
         self.assertEquals(tuplify(data), [(-1, 'Personne', 'system', None, None)])
@@ -350,7 +350,7 @@
         cursor = self.session.pool['system']
         eidp = self.execute('INSERT Personne X: X nom "toto", X prenom "tutu"')[0][0]
         self.commit()
-        ts = now()
+        ts = datetime.now()
         self.assertEquals(len(self.execute('Personne X WHERE X has_text "tutu"')), 1)
         cursor.execute('SELECT mtime, eid FROM entities WHERE eid = %s' % eidp)
         omtime = cursor.fetchone()[0]
--- a/server/test/unittest_rql2sql.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/server/test/unittest_rql2sql.py	Tue Mar 10 11:35:52 2009 +0100
@@ -1,7 +1,6 @@
 """unit tests for module cubicweb.server.sources.rql2sql"""
 
 import sys
-from mx.DateTime import today
 
 from logilab.common.testlib import TestCase, unittest_main
 
--- a/server/test/unittest_sqlutils.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/server/test/unittest_sqlutils.py	Tue Mar 10 11:35:52 2009 +0100
@@ -2,7 +2,6 @@
 """
 
 import sys
-from mx.DateTime import now
 
 from logilab.common.testlib import TestCase, unittest_main
 
--- a/sobjects/test/unittest_notification.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/sobjects/test/unittest_notification.py	Tue Mar 10 11:35:52 2009 +0100
@@ -4,8 +4,6 @@
 from logilab.common.testlib import unittest_main, TestCase
 from cubicweb.devtools.apptest import EnvBasedTC
 
-from mx.DateTime import now
-
 from cubicweb.sobjects.notification import construct_message_id, parse_message_id
 
 class MessageIdTC(TestCase):
--- a/sobjects/test/unittest_supervising.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/sobjects/test/unittest_supervising.py	Tue Mar 10 11:35:52 2009 +0100
@@ -4,8 +4,6 @@
 from logilab.common.testlib import unittest_main
 from cubicweb.devtools.apptest import EnvBasedTC
 
-from mx.DateTime import now
-
 from cubicweb.sobjects.supervising import SendMailOp, SupervisionMailOp
 
 
--- a/test/unittest_entity.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/test/unittest_entity.py	Tue Mar 10 11:35:52 2009 +0100
@@ -1,11 +1,10 @@
 # -*- coding: utf-8 -*-
 """unit tests for cubicweb.web.views.entities module"""
 
-from cubicweb.devtools.apptest import EnvBasedTC
-
-from mx.DateTime import DateTimeType, now
+from datetime import datetime
 
 from cubicweb import Binary
+from cubicweb.devtools.apptest import EnvBasedTC
 from cubicweb.common.mttransforms import HAS_TAL
 
 class EntityTC(EnvBasedTC):
@@ -199,7 +198,7 @@
         self.add_entity('Personne', nom=u'di mascio', prenom=u'adrien')
         self.add_entity('Personne', nom=u'di mascio', prenom=u'gwen')
         rschema = e.e_schema.subject_relation('tags')
-        self.assertEquals(len(e.vocabulary(rschema, 'subject', limit=1)),
+        self.assertEquals(len(e.unrelated(rschema, 'Personne', 'subject', limit=1)),
                           1)
         
     def test_new_entity_unrelated(self):
@@ -420,7 +419,7 @@
                                'U login "admin", S2 name "activated"')[0][0]
             trinfo = self.entity('Any X WHERE X eid %(x)s', {'x': eid}, 'x')
             trinfo.complete()
-            self.failUnless(isinstance(trinfo.creation_date, DateTimeType))
+            self.failUnless(isinstance(trinfo.creation_date, datetime))
             self.failUnless(trinfo.relation_cached('from_state', 'subject'))
             self.failUnless(trinfo.relation_cached('to_state', 'subject'))
             self.failUnless(trinfo.relation_cached('wf_info_for', 'subject'))
--- a/utils.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/utils.py	Tue Mar 10 11:35:52 2009 +0100
@@ -8,9 +8,17 @@
 
 import locale
 from md5 import md5
+from datetime import datetime, timedelta
 from time import time
 from random import randint, seed
 
+try:
+    strptime = datetime.strptime
+except AttributeError: # py < 2.5
+    from time import strptime as time_strptime
+    def strptime(value, format):
+        return datetime(*time_strptime(value, format)[:6])
+    
 # initialize random seed from current time
 seed()
 
@@ -38,6 +46,7 @@
                     should be included.
     """
     date = begin
+    incr = timedelta(incr, 0, 0)
     while date <= end:
         if include is None or include(date): 
             yield date
--- a/web/controller.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/web/controller.py	Tue Mar 10 11:35:52 2009 +0100
@@ -7,9 +7,10 @@
 """
 __docformat__ = "restructuredtext en"
 
-from mx.DateTime import strptime, Error as MxDTError, TimeDelta
+from datetime import timedelta
 
 from cubicweb import typed_eid
+from cubicweb.utils import strptime
 from cubicweb.common.registerers import priority_registerer
 from cubicweb.selectors import yes, require_group_compat
 from cubicweb.appobject import AppObject
@@ -107,20 +108,20 @@
             format = self.req.property_value('ui.datetime-format')
             try:
                 return strptime(value, format)
-            except MxDTError:
+            except:
                 pass
         elif etype == 'Time':
             format = self.req.property_value('ui.time-format')
             try:
                 # (adim) I can't find a way to parse a Time with a custom format
                 date = strptime(value, format) # this returns a DateTime
-                return TimeDelta(date.hour, date.minute, date.second)
-            except MxDTError:
+                return timedelta(0, date.hour *60*60 + date.minute*60 + date.second, 0)
+            except:
                 raise ValueError('can\'t parse %r (expected %s)' % (value, format))
         try:
             format = self.req.property_value('ui.date-format')
             return strptime(value, format)
-        except MxDTError:
+        except:
             raise ValueError('can\'t parse %r (expected %s)' % (value, format))
 
 
--- a/web/form.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/web/form.py	Tue Mar 10 11:35:52 2009 +0100
@@ -7,8 +7,9 @@
 __docformat__ = "restructuredtext en"
 
 from warnings import warn
+from datetime import date, datetime
+
 from simplejson import dumps
-from mx.DateTime import today, now
 
 from logilab.common.compat import any
 from logilab.mtconverter import html_escape
@@ -412,7 +413,7 @@
         inputid = form.context[field]['id']
         helperid = '%shelper' % inputid
         if not value:
-            value = today()
+            value = date.today()
         year, month = value.year, value.month
         onclick = "toggleCalendar('%s', '%s', %s, %s);" % (
             helperid, inputid, year, month)
@@ -643,7 +644,7 @@
         return value and ustrftime(value, req.property_value(self.format_prop)) or u''
 
     def render_example(self, req):
-        return self.format_value(req, now())
+        return self.format_value(req, datetime.now())
 
 
 class DateTimeField(DateField):
--- a/web/httpcache.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/web/httpcache.py	Tue Mar 10 11:35:52 2009 +0100
@@ -7,10 +7,10 @@
 """
 __docformat__ = "restructuredtext en"
 
-from mx.DateTime import DateTimeFromTicks, now, gmtime
+from datetime import datetime
 
 # time delta usable to convert localized time to GMT time
-GMTOFFSET = - (now() - gmtime())
+GMTOFFSET = - (datetime.now() - datetime.utcnow())
 
 class NoHTTPCacheManager(object):
     """default cache manager: set no-cache cache control policy"""
@@ -105,11 +105,12 @@
     /!\ must return GMT time /!\
     """
     # XXX check view module's file modification time in dev mod ?
-    ctime = gmtime()
+    ctime = datetime.utcnow()
     if self.cache_max_age:
         mtime = self.req.header_if_modified_since()
         if mtime:
-            if (ctime - mtime).seconds > self.cache_max_age:
+            tdelta = (ctime - mtime)
+            if tdelta.days * 24*60*60 + tdelta.seconds > self.cache_max_age:
                 mtime = ctime
         else:
             mtime = ctime
--- a/web/test/test_views.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/web/test/test_views.py	Tue Mar 10 11:35:52 2009 +0100
@@ -1,9 +1,7 @@
 """automatic tests"""
 
-from mx.DateTime import now
-
 from cubicweb.devtools.testlib import WebTest, AutomaticWebTest
-from cubicweb.common.view import AnyRsetView
+from cubicweb.view import AnyRsetView
 
 AutomaticWebTest.application_rql = [
     'Any L,F WHERE E is EUser, E login L, E firstname F',
--- a/web/test/unittest_controller.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/web/test/unittest_controller.py	Tue Mar 10 11:35:52 2009 +0100
@@ -2,7 +2,7 @@
 
 """
 
-from mx.DateTime import DateTimeType, DateTimeDeltaType
+from datetime import datetime, date, time
 
 from logilab.common.testlib import unittest_main
 
@@ -10,12 +10,12 @@
 
 class BaseControllerTC(apptest.ControllerTC):
     def test_parse_datetime(self):
-        self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24 12:18'), DateTimeType)
-        self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24'), DateTimeType)
-        self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24 12:18', 'Datetime'), DateTimeType)
-        self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24', 'Datetime'), DateTimeType)
-        self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24', 'Date'), DateTimeType)
-        self.assertIsInstance(self.ctrl.parse_datetime('12:18', 'Time'), DateTimeDeltaType)
+        self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24 12:18'), datetime)
+        self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24'), datetime)
+        self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24 12:18', 'Datetime'), datetime)
+        self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24', 'Datetime'), datetime)
+        self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24', 'Date'), date)
+        self.assertIsInstance(self.ctrl.parse_datetime('12:18', 'Time'), time)
         self.assertRaises(ValueError,
                           self.ctrl.parse_datetime, '2006/06/24 12:188', 'Datetime')
         self.assertRaises(ValueError,
--- a/web/test/unittest_views_baseforms.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/web/test/unittest_views_baseforms.py	Tue Mar 10 11:35:52 2009 +0100
@@ -1,9 +1,9 @@
 """cubicweb.web.views.baseforms unit tests"""
 
 from StringIO import StringIO
+from datetime import date
 import re
 
-from mx.DateTime import DateTime
 
 from logilab.common.testlib import unittest_main
 from logilab.common.decorators import clear_cache
@@ -11,17 +11,15 @@
 from cubicweb.entities import AnyEntity
 from cubicweb.web import widgets
 
-orig_today = widgets.today
-orig_now = widgets.now
+orig_now = widgets.datetime.now
 
 def setup_module(options):
     def _today():
-        return DateTime(0000, 1, 1)
-    widgets.today = widgets.now = _today
+        return date(0000, 1, 1)
+    widgets.datetime.now = _today
 
 def teardown_module(options, results):
-    widgets.today = orig_today
-    widgets.now = orig_now
+    widgets.datetime.now = orig_now
 
 
 def cleanup_text(text):
--- a/web/test/unittest_widgets.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/web/test/unittest_widgets.py	Tue Mar 10 11:35:52 2009 +0100
@@ -2,8 +2,9 @@
 
 """
 
-from mx.DateTime import now
-NOW = now()
+from datetime import datetime
+NOW = datetime.now()
+
 from logilab.common.testlib import unittest_main
 from cubicweb.devtools.apptest import EnvBasedTC
 
@@ -186,10 +187,9 @@
     def test_datetime_widget(self):
         w = self.get_widget('Personne', 'datenaiss', 'Datetime')
         self.assertEquals(w.name, 'datenaiss')
-        now_ = now()
         example = '%s, or without time: %s' % (        
-            now_.strftime(self.vreg.property_value('ui.datetime-format')),
-            now_.strftime(self.vreg.property_value('ui.date-format')))
+            NOW.strftime(self.vreg.property_value('ui.datetime-format')),
+            NOW.strftime(self.vreg.property_value('ui.date-format')))
         self.assertEquals(w.render_example(self.request()), example)
         self.assertDictEquals(w.attrs, {'accesskey': 'd', 'maxlength': 16, 'size': 16})
         entity = self.etype_instance('Personne')
--- a/web/views/basecontrollers.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/web/views/basecontrollers.py	Tue Mar 10 11:35:52 2009 +0100
@@ -13,11 +13,10 @@
 
 import simplejson
 
-from mx.DateTime.Parser import DateFromString
-
 from logilab.common.decorators import cached
 
 from cubicweb import NoSelectableObject, ValidationError, ObjectNotFound, typed_eid
+from cubicweb.utils import strptime
 from cubicweb.selectors import yes, match_user_groups
 from cubicweb.view import STRICT_DOCTYPE, CW_XHTML_EXTENSIONS
 from cubicweb.common.mail import format_mail
@@ -390,7 +389,7 @@
 
     def js_format_date(self, strdate):
         """returns the formatted date for `msgid`"""
-        date = DateFromString(strdate)
+        date = strptime(strdate)
         return self.format_date(date)
 
     def js_external_resource(self, resource):
--- a/web/views/calendar.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/web/views/calendar.py	Tue Mar 10 11:35:52 2009 +0100
@@ -5,8 +5,7 @@
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 
-from mx.DateTime import DateTime, RelativeDateTime, today, ISO
-from datetime import datetime
+from datetime import datetime, date, timedelta
 
 from vobject import iCalendar, icalendar
 
@@ -14,7 +13,7 @@
 
 from cubicweb.interfaces import ICalendarable
 from cubicweb.selectors import implements
-from cubicweb.utils import date_range
+from cubicweb.utils import strptime, date_range
 from cubicweb.view import EntityView
 from cubicweb.common.uilib import ajax_replace_url
 
@@ -30,26 +29,18 @@
 
 _ = unicode
 
-# useful constants & functions
-def mkdt(mxdate):
-    """
-    Build a stdlib datetime date from a mx.datetime 
-    """
-    d = mxdate
-    return datetime(d.year, d.month, d.day, d.hour, d.minute,
-                    tzinfo=icalendar.utc)
-def iso(mxdate):
-    """
-    Format a ms datetime in ISO 8601 string 
-    """
-    # XXX What about timezone?
-    return ISO.str(mxdate)
+# # useful constants & functions
+# def mkdt(mxdate):
+#     """
+#     Build a stdlib datetime date from a mx.datetime 
+#     """
+#     d = mxdate
+#     return datetime(d.year, d.month, d.day, d.hour, d.minute,
+#                     tzinfo=icalendar.utc)
 
-# mx.DateTime and ustrftime could be used to build WEEKDAYS
+# used by i18n tools
 WEEKDAYS = (_("monday"), _("tuesday"), _("wednesday"), _("thursday"),
             _("friday"), _("saturday"), _("sunday"))
-
-# used by i18n tools
 MONTHNAMES = ( _('january'), _('february'), _('march'), _('april'), _('may'),
                _('june'), _('july'), _('august'), _('september'), _('october'),
                _('november'), _('december')
@@ -97,9 +88,9 @@
             event.add('summary').value = task.dc_title()
             event.add('description').value = task.dc_description()
             if task.start:
-                event.add('dtstart').value = mkdt(task.start)
+                event.add('dtstart').value = task.start
             if task.stop:
-                event.add('dtend').value = mkdt(task.stop)
+                event.add('dtend').value = task.stop
 
         buff = ical.serialize()
         if not isinstance(buff, unicode):
@@ -125,9 +116,9 @@
             self.w(u'<h3 class="summary">%s</h3>' % html_escape(task.dc_title()))
             self.w(u'<div class="description">%s</div>' % html_escape(task.dc_description()))
             if task.start:
-                self.w(u'<abbr class="dtstart" title="%s">%s</abbr>' % (iso(task.start), self.format_date(task.start)))
+                self.w(u'<abbr class="dtstart" title="%s">%s</abbr>' % (task.start.isoformat(), self.format_date(task.start)))
             if task.stop:
-                self.w(u'<abbr class="dtstop" title="%s">%s</abbr>' % (iso(task.stop), self.format_date(task.stop)))
+                self.w(u'<abbr class="dtstop" title="%s">%s</abbr>' % (task.stop.isoformat(), self.format_date(task.stop)))
             self.w(u'</div>')
         self.w(u'</div>')
 
@@ -150,7 +141,7 @@
         self.req.add_js('cubicweb.ajax.js')
         self.req.add_css('cubicweb.calendar.css')
         # XXX: restrict courses directy with RQL
-        _today =  today()
+        _today =  datetime.today()
 
         if 'year' in self.req.form:
             year = int(self.req.form['year'])
@@ -161,9 +152,13 @@
         else:
             month = _today.month
 
-        first_day_of_month = DateTime(year, month, 1)
-        lastday = first_day_of_month + RelativeDateTime(months=1,weekday=(6,1))
-        firstday= first_day_of_month + RelativeDateTime(months=-1,weekday=(0,-1))
+        first_day_of_month = date(year, month, 1)
+        firstday = first_day_of_month - timedelta(first_day_of_month.weekday(), 0, 0)
+        if month >= 12:
+            last_day_of_month = date(year + 1, 1, 1) - timedelta(1, 0, 0)
+        else:
+            last_day_of_month = date(year, month + 1, 1) - timedelta(1, 0, 0)
+        lastday = last_day_of_month + timedelta(6 - last_day_of_month.weekday(), 0, 0)
         month_dates = list(date_range(firstday, lastday))
         dates = {}
         users = []
@@ -184,7 +179,7 @@
                     continue
                 the_dates = [task.stop]
             if task.start and task.stop:
-                if task.start.absdate == task.stop.absdate:
+                if task.start.isocalendar() == task.stop.isocalendar():
                     date = task.start
                     if firstday<= date <= lastday:
                         the_dates = [date]
@@ -259,17 +254,17 @@
         
         # build calendar
         for date, task_rows in zip(month_dates, days):
-            if date.day_of_week == 0:
+            if date.weekday() == 0:
                 self.w(u'<tr>')
             self._build_calendar_cell(date, task_rows, curdate)
-            if date.day_of_week == 6:
+            if date.weekday() == 6:
                 self.w(u'</tr>')
         self.w(u'</table></div>')
 
     def _prevnext_links(self, curdate):
-        prevdate = curdate - RelativeDateTime(months=1)
-        nextdate = curdate + RelativeDateTime(months=1)
-        rql = self.rset.rql
+        prevdate = curdate - timedelta(31, 0, 0)
+        nextdate = curdate + timedelta(31, 0, 0)
+        rql = self.rset.printable_rql()
         prevlink = ajax_replace_url('onemonthcalid', rql, 'onemonthcal',
                                     year=prevdate.year, month=prevdate.month)
         nextlink = ajax_replace_url('onemonthcalid', rql, 'onemonthcal',
@@ -281,7 +276,7 @@
         classes = ""
         if date.month != curmonth:
             classes += " outOfRange"
-        if date == today():
+        if date == datetime.today():
             classes += " today"
         self.w(u'<td class="cell%s">' % classes)
         self.w(u'<div class="calCellTitle%s">' % classes)
@@ -292,7 +287,7 @@
             url = self.build_url(vid='creation', etype=etype,
                                  schedule=True,
                                  start=self.format_date(date), stop=self.format_date(date),
-                                 __redirectrql=self.rset.rql,
+                                 __redirectrql=self.rset.printable_rql(),
                                  __redirectparams=self.req.build_url_params(year=curdate.year, month=curmonth),
                                  __redirectvid=self.id
                                  )
@@ -306,7 +301,7 @@
                 self.w(u'<div class="task %s">' % task_descr.color)
                 task.view('calendaritem', w=self.w )
                 url = task.absolute_url(vid='edition',
-                                        __redirectrql=self.rset.rql,
+                                        __redirectrql=self.rset.printable_rql(),
                                         __redirectparams=self.req.build_url_params(year=curdate.year, month=curmonth),
                                         __redirectvid=self.id
                                         )
@@ -332,9 +327,8 @@
     def call(self):
         self.req.add_js( ('cubicweb.ajax.js', 'cubicweb.calendar.js') )
         self.req.add_css('cubicweb.calendar.css')
-        # XXX: restrict courses directy with RQL
-        _today =  today()
-
+        # XXX: restrict directly with RQL
+        _today =  datetime.today()
         if 'year' in self.req.form:
             year = int(self.req.form['year'])
         else:
@@ -342,11 +336,11 @@
         if 'week' in self.req.form:
             week = int(self.req.form['week'])
         else:
-            week = _today.iso_week[1]        
-
-        first_day_of_week = ISO.ParseWeek("%s-W%s-1"%(year, week))
-        lastday = first_day_of_week + RelativeDateTime(days=6)
-        firstday= first_day_of_week
+            week = _today.isocalendar()[1]        
+        # week - 1 since we get week number > 0 while we want it to start from 0
+        first_day_of_week = strptime('%s-%s-1' % (year, week - 1), '%Y-%U-%w')
+        lastday = first_day_of_week + timedelta(6, 0, 0)
+        firstday = first_day_of_week
         dates = [[] for i in range(7)]
         task_max = 0
         task_colors = {}   # remember a color assigned to a task
@@ -369,17 +363,17 @@
                     continue
                 the_dates = [task.stop]
             if task.start and task.stop:
-                the_dates = date_range(max(task.start,firstday),
-                                       min(task.stop,lastday))
+                the_dates = date_range(max(task.start, firstday),
+                                       min(task.stop, lastday))
             if not the_dates:
                 continue
                 
             if task not in task_colors:
                 task_colors[task] = colors[next_color_index]
-                next_color_index = (next_color_index+1)%len(colors)
+                next_color_index = (next_color_index+1) % len(colors)
             
             for d in the_dates:
-                day = d.day_of_week
+                day = d.weekday()
                 task_descr = _TaskEntry(task, task_colors[task])  
                 dates[day].append(task_descr)
             
@@ -391,7 +385,7 @@
         self.w(u'<th><a href="%s">&lt;&lt;</a></th><th colspan="5">%s %s %s</th>'
                u'<th><a href="%s">&gt;&gt;</a></th></tr>' %
                (html_escape(prevlink), first_day_of_week.year,
-                self.req._(u'week'), first_day_of_week.iso_week[1],
+                self.req._(u'week'), first_day_of_week.isocalendar()[1],
                 html_escape(nextlink)))
 
         # output header
@@ -400,12 +394,11 @@
         _today = today()
         for i, day in enumerate(WEEKDAYS):
             date = first_day_of_week + i
-            if date.absdate == _today.absdate:
+            if date.isocalendar() == _today.isocalendar():
                 self.w(u'<th class="today">%s<br/>%s</th>' % (self.req._(day), self.format_date(date)))
             else:
                 self.w(u'<th>%s<br/>%s</th>' % (self.req._(day), self.format_date(date)))
         self.w(u'</tr>')
-
         
         # build week calendar
         self.w(u'<tr>')
@@ -420,14 +413,14 @@
         for i, day in enumerate(WEEKDAYS):
             date = first_day_of_week + i
             classes = ""
-            if date.absdate == _today.absdate:
+            if date.isocalendar() == _today.isocalendar():
                 classes = " today"
             self.w(u'<td class="column %s" id="%s">'%(classes, day))
             if len(self.rset.column_types(0)) == 1:
                 etype = list(self.rset.column_types(0))[0]
                 url = self.build_url(vid='creation', etype=etype,
                                      schedule=True,
-                                     __redirectrql=self.rset.rql,
+                                     __redirectrql=self.rset.printable_rql(),
                                      __redirectparams=self.req.build_url_params(year=year, week=week),
                                      __redirectvid=self.id
                                      )
@@ -452,7 +445,7 @@
         Return true if the task is a "one day" task; ie it have a start and a stop the same day
         """
         if task.start and task.stop:
-            if task.start.absdate ==  task.stop.absdate:
+            if task.start.isocalendar() ==  task.stop.isocalendar():
                 return True
         return False
         
@@ -508,8 +501,8 @@
                        (task_desc.color, style))
             task.view('calendaritem', dates=False, w=self.w)
             url = task.absolute_url(vid='edition',
-                                    __redirectrql=self.rset.rql,
-                                    __redirectparams=self.req.build_url_params(year=date.year, week=date.iso_week[1]),
+                                    __redirectrql=self.rset.printable_rql(),
+                                    __redirectparams=self.req.build_url_params(year=date.year, week=date.isocalendar()[1]),
                                     __redirectvid=self.id
                                  )
 
@@ -530,12 +523,12 @@
 
             
     def _prevnext_links(self, curdate):
-        prevdate = curdate - RelativeDateTime(days=7)
-        nextdate = curdate + RelativeDateTime(days=7)
-        rql = self.rset.rql
+        prevdate = curdate - timedelta(7, 0, 0)
+        nextdate = curdate + timedelta(7, 0, 0)
+        rql = self.rset.printable_rql()
         prevlink = ajax_replace_url('oneweekcalid', rql, 'oneweekcal',
-                                    year=prevdate.year, week=prevdate.iso_week[1])
+                                    year=prevdate.year, week=prevdate.isocalendar()[1])
         nextlink = ajax_replace_url('oneweekcalid', rql, 'oneweekcal',
-                                    year=nextdate.year, week=nextdate.iso_week[1])
+                                    year=nextdate.year, week=nextdate.isocalendar()[1])
         return prevlink, nextlink
 
--- a/web/views/wdoc.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/web/views/wdoc.py	Tue Mar 10 11:35:52 2009 +0100
@@ -9,14 +9,14 @@
 from itertools import chain
 from os.path import join
 from bisect import bisect_right
-
-from mx.DateTime import strptime, today
+from datetime import date
 
 from logilab.common.changelog import ChangeLog
 from logilab.mtconverter import CHARSET_DECL_RGX
 
 from cubicweb.selectors import match_form_params
 from cubicweb.view import StartupView
+from cubicweb.utils import strptime
 from cubicweb.common.uilib import rest_publish
 from cubicweb.web import NotFound
 
@@ -207,7 +207,7 @@
                 if entry.date:
                     date = strptime(entry.date, '%Y-%m-%d')
                 else:
-                    date = today()
+                    date = date.today()
                 messages = []
                 for msglines, submsgs in entry.messages:
                     msgstr = unicode(' '.join(l.strip() for l in msglines), encoding)
--- a/web/widgets.py	Mon Mar 09 12:12:53 2009 +0100
+++ b/web/widgets.py	Tue Mar 10 11:35:52 2009 +0100
@@ -10,7 +10,7 @@
 __docformat__ = "restructuredtext en"
 
 from simplejson import dumps
-from mx.DateTime import now, today
+from datetime import datetime
 
 from logilab.mtconverter import html_escape
 
@@ -735,7 +735,7 @@
 
     def render_example(self, req):
         formatstr = req.property_value(self.format_key)
-        return now().strftime(formatstr)
+        return datetime.now().strftime(formatstr)
 
 
     def _edit_render(self, entity):
@@ -764,7 +764,7 @@
         req.add_css(('cubicweb.calendar_popup.css',))
         inputid = self.attrs.get('id', self.rname)
         helperid = "%shelper" % inputid
-        _today = today()
+        _today = datetime.now()
         year = int(req.form.get('year', _today.year))
         month = int(req.form.get('month', _today.month))
 
@@ -785,8 +785,8 @@
         formatstr1 = req.property_value('ui.datetime-format')
         formatstr2 = req.property_value('ui.date-format')
         return req._('%(fmt1)s, or without time: %(fmt2)s') % {
-            'fmt1': now().strftime(formatstr1),
-            'fmt2': now().strftime(formatstr2),
+            'fmt1': datetime.now().strftime(formatstr1),
+            'fmt2': datetime.now().strftime(formatstr2),
             }