source: main/waeup.sirp/trunk/src/waeup/sirp/widgets/datewidget.py @ 7554

Last change on this file since 7554 was 7515, checked in by Henrik Bettermann, 13 years ago

In import files we can use the hash symbol at the end of a date string to
avoid annoying automatic date transformation by Excel or Calc.

  • Property svn:keywords set to Id
File size: 5.9 KB
Line 
1## $Id: datewidget.py 7515 2012-01-26 08:59:05Z henrik $
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"""
19A datewidget with customizable date format.
20"""
21from datetime import datetime
22from zope.formlib.i18n import _
23from zope.formlib.interfaces import ConversionError, IDisplayWidget
24from zope.formlib.textwidgets import (
25    DateWidget, DateDisplayWidget, escape, DatetimeDisplayWidget)
26from zope.formlib.widget import renderElement, CustomWidgetFactory
27from zope.interface import implements
28
29class FormattedDateWidget(DateWidget):
30    """A date widget that supports different (and _explicit_) date formats.
31
32    This is an input widget.
33    """
34    date_format = '%Y-%m-%d'
35
36    def _toFieldValue(self, input):
37        if input == self._missing:
38            return self.context.missing_value
39        else:
40            try:
41                # In import files we can use the hash symbol at the end of a
42                # date string to avoid annoying automatic date transformation
43                # by Excel or Calc
44                input = input.strip('#')
45                value = datetime.strptime(input, self.date_format)
46            except (ValueError, IndexError), v:
47                raise ConversionError(_("Invalid datetime data"), v)
48        return value.date()
49
50    def _toFormValue(self, value):
51        if value:
52            value = value.strftime(self.date_format)
53        return value
54
55class FormattedDateDisplayWidget(DateDisplayWidget):
56    """A date widget that supports different (and _explicit_) date formats.
57
58    This is a display widget.
59    """
60    date_format = '%Y-%m-%d'
61    implements(IDisplayWidget)
62   
63    def __call__(self):
64        if self._renderedValueSet():
65            content = self._data
66        else:
67            content = self.context.default
68        if content == self.context.missing_value:
69            return ""
70        content = content.strftime(self.date_format)
71        return renderElement("span", contents=escape(content),
72                             cssClass=self.cssClass)
73
74#: A dictionary of supported date formats.
75#:
76#: The following formats are supported:
77#:
78#: ``iso``
79#:    ISO format ``YYYY-MM-DD``
80#: ``le``
81#:    little endian with slashes: ``DD/MM/YYYY``
82#: ``de``
83#:    german date format: ``DD.MM.YYYY``
84#: ``us``
85#:    middle endian format common in the U.S.: ``MM/DD/YYYY``
86#:
87#: Furthermore we support for input widgets an additional year
88#: marker. Input date widgets with this marker provide also a year
89#: selector, handy for dates of birth etc.
90#:
91#: The year-supporting formats are similar to the basic versions above:
92#:
93#: ``iso-year``
94#:    ISO format ``YYYY-MM-DD``
95#: ``le-year``
96#:    little endian with slashes: ``DD/MM/YYYY``
97#: ``de-year``
98#:    german date format: ``DD.MM.YYYY``
99#: ``us-year``
100#:    middle endian format common in the U.S.: ``MM/DD/YYYY``
101#:   
102#: For date display widgets there is naturally no difference between a
103#: year and non-year setting (you can for instance use 'le' or 'le-year'
104#: with the same output).
105DATE_FORMATS = {
106    'iso': ('datepicker', '%Y-%m-%d'),
107    'le':  ('datepicker-le', '%d/%m/%Y'),
108    'de':  ('datepicker-de', '%d.%m.%Y'),
109    'us':  ('datepicker-us', '%m/%d/%Y'),
110    'iso-year': ('datepicker-year', '%Y-%m-%d'),
111    'le-year':  ('datepicker-le-year', '%d/%m/%Y'),
112    'de-year':  ('datepicker-de-year', '%d.%m.%Y'),
113    'us-year':  ('datepicker-us-year', '%m/%d/%Y'),
114    }
115def FriendlyDateWidget(format):
116    """Get a friendly date input widget for `format`.
117
118    This widget is suitable for edit and add forms.
119   
120    Valid `format` values are the keys of :var:`DATE_FORMATS`
121    dict. Default is ``le`` (little endian; DD/MM/YYYY).
122
123    Friendly date widgets are rendered with a specialized CSS tag for
124    enabling JavaScript datepickers.
125    """
126    css_class, date_format = DATE_FORMATS.get(format, DATE_FORMATS['le'])
127    return CustomWidgetFactory(
128        FormattedDateWidget,
129        cssClass=css_class,
130        date_format=date_format)
131
132def FriendlyDateDisplayWidget(format):
133    """Get a friendly date display widget for `format`.
134
135    This widget is suitable for display forms.
136   
137    Valid `format` values are the keys of :var:`DATE_FORMATS`
138    dict. Default is ``le`` (little endian; DD/MM/YYYY).
139
140    This widget is not rendered with a specialized CSS tag for
141    enabling JavaScript datepickers. `css_class` is ignored which means
142    there is nor difference between e.g. ``le`` and ``le-year``.`
143    """
144    css_class, date_format = DATE_FORMATS.get(format, DATE_FORMATS['le'])
145    return CustomWidgetFactory(
146        FormattedDateDisplayWidget,
147        date_format=date_format)
148
149def FriendlyDatetimeDisplayWidget(format):
150    """Get a friendly datetime display widget for `format`.
151
152    This widget is suitable for display forms.
153
154    Valid `format` values are the keys of :var:`DATE_FORMATS`
155    dict. Default is ``le`` (little endian; DD/MM/YYYY %H:%M:%S).
156
157    This widget is not rendered with a specialized CSS tag for
158    enabling JavaScript datepickers. `css_class` is ignored which means
159    there is nor difference between e.g. ``le`` and ``le-year``.`
160    """
161    css_class, date_format = DATE_FORMATS.get(format, DATE_FORMATS['le'])
162    datetime_format = date_format + ' %H:%M:%S'
163    return CustomWidgetFactory(
164        FormattedDateDisplayWidget,
165        date_format=datetime_format)
Note: See TracBrowser for help on using the repository browser.