source: main/waeup.kofa/trunk/src/waeup/kofa/widgets/datetimewidget.py @ 8367

Last change on this file since 8367 was 8207, checked in by uli, 13 years ago

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

File size: 3.3 KB
Line 
1## $Id$
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18"""Datetimewidgets that are compatible with pytz.
19"""
20import datetime
21import 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
27from 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()
36
37class PytzDatetimeWidget(DatetimeWidget):
38    """pytz-conform, non-ambigous UTC datetimes.
39
40    While the standard formlib datetime widget makes use of
41    zope.datetime and creates also not too reliable (or ambigous)
42    datetimes based on local servertime, this widget provides
43    non-ambigous UTC datetimes with a pytz timezone (pytz.utc).
44
45    Using this widget for datetime data we always get clean UTC
46    datetimes compatible with other Python packages (as pytz is more
47    wide-spread than zope.datetime).
48
49    For datetimes in other timezones we compute the correct UTC value
50    and store this. A way to help making sure, only UTC-based values
51    go into the DB.
52
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
59    From zope.datetime, however, we save the parser abilities to
60    interpret even bizarre entered data as some datetime.
61    """
62    def _toFieldValue(self, string):
63        """Turn string into a UTC-based datetime.
64
65        The TZ data is guaranteed to be pytz.utc.
66
67        """
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
80        if not isinstance(value, datetime.datetime):
81            return value
82        if value.tzinfo is None:
83            utils = queryUtility(IKofaUtils, default=_DUMMY_UTILS)
84            value = utils.tzinfo.localize(value)
85        return value.astimezone(pytz.utc)
Note: See TracBrowser for help on using the repository browser.