Changeset 8207


Ignore:
Timestamp:
18 Apr 2012, 12:46:52 (13 years ago)
Author:
uli
Message:

Try to be smart (evil?). Interpret entered datetimes w/o TZ as app-wide TZ data.

Location:
main/waeup.kofa/trunk/src/waeup/kofa/widgets
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/trunk/src/waeup/kofa/widgets/datetimewidget.py

    r8198 r8207  
    2020import datetime
    2121import pytz
     22from zope.component import queryUtility
     23from zope.datetime import parseDatetimetz
     24from zope.datetime import DateTimeError
     25from zope.formlib.i18n import _
     26from zope.formlib.interfaces import ConversionError
    2227from zope.formlib.textwidgets import DatetimeWidget
     28from waeup.kofa.utils.helpers import to_timezone
     29from waeup.kofa.interfaces import IKofaUtils
     30
     31class _DummyUtils(object):
     32    tzinfo = pytz.utc
     33
     34# A fallback, if no IKofaUtils can be found
     35_DUMMY_UTILS = _DummyUtils()
    2336
    2437class PytzDatetimeWidget(DatetimeWidget):
     
    3851    go into the DB.
    3952
     53    For datetimes without any timezone set, we interpret the input to
     54    be meant as local app-time. I.e. if application TZ is
     55    ``Africa/Lagos``, we assume that a string like '2012-02-01 12:13'
     56    (apparently not providing TZ info) was meant as 12:13 h Lagos
     57    time.
     58
    4059    From zope.datetime, however, we save the parser abilities to
    4160    interpret even bizarre entered data as some datetime.
     
    4766
    4867        """
    49         value = super(PytzDatetimeWidget, self)._toFieldValue(string)
     68        if string == self._missing:
     69            return self.context.missing_value
     70        else:
     71            try:
     72                # Different to original implementation we do not
     73                # automatically request local server time if no TZ was
     74                # set in `string`. In this case we want a datetime with
     75                # tzinfo set to `None` instead.
     76                value = parseDatetimetz(string, local=False)
     77            except (DateTimeError, ValueError, IndexError), v:
     78                raise ConversionError(_("Invalid datetime data"), v)
     79
    5080        if not isinstance(value, datetime.datetime):
    5181            return value
    5282        if value.tzinfo is None:
    53             return pytz.utc.localize(value)
     83            utils = queryUtility(IKofaUtils, default=_DUMMY_UTILS)
     84            value = utils.tzinfo.localize(value)
    5485        return value.astimezone(pytz.utc)
  • main/waeup.kofa/trunk/src/waeup/kofa/widgets/tests/test_datetimewidget.py

    r8199 r8207  
    33import pytz
    44from zope import schema
     5from zope.component import getGlobalSiteManager
    56from zope.formlib import form
    67from zope.formlib.interfaces import IInputWidget, IDisplayWidget
     
    1112from zope.interface.verify import verifyClass, verifyObject
    1213from zope.publisher.browser import TestRequest
     14from waeup.kofa.interfaces import IKofaUtils
    1315from waeup.kofa.widgets.datetimewidget import PytzDatetimeWidget
    1416
     
    2527    form_fields = form.fields(IContent)
    2628    form_fields['my_dt'].custom_widget = PytzDatetimeWidget
     29
     30class FakeUtils(object):
     31    # Fake app-wide set timezone.
     32    implements(IKofaUtils)
     33    tzinfo = pytz.timezone('America/Sao_Paulo')
     34
    2735
    2836class PytzDatetimeWidgetTests(FunctionalWidgetTestCase):
     
    6674        self.assertTrue(content.my_dt.tzinfo is pytz.utc)
    6775        return
     76
     77    def setUp(self):
     78        super(PytzDatetimeWidgetTests, self).setUp()
     79        self.gsm = getGlobalSiteManager()
     80        self.utils = FakeUtils()
     81        self.gsm.registerUtility(self.utils)
     82        return
     83
     84    def tearDown(self):
     85        super(PytzDatetimeWidgetTests, self).tearDown()
     86        self.gsm.unregisterUtility(self.utils)
     87        return
     88
     89    def test_datetimes_wo_tz(self):
     90        # Datetimes w/o tz are considered to be meant in app-wide timezone.
     91        content = Content()
     92        request = TestRequest()
     93
     94        request.form['form.my_dt'] = u'2011-11-11 11:11:11'
     95        request.form['form.actions.apply'] = u''
     96        SampleForm(content, request)()
     97
     98        # Sao Paulo was two hours back UTC on 2011-11-11
     99        self.assertEqual(content.my_dt, datetime.datetime(
     100            2011, 11, 11, 13, 11, 11, tzinfo=pytz.utc))
     101        self.assertTrue(content.my_dt.tzinfo is pytz.utc)
     102        return
Note: See TracChangeset for help on using the changeset viewer.