## $Id: datewidget.py 7515 2012-01-26 08:59:05Z henrik $ ## ## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## """ A datewidget with customizable date format. """ from datetime import datetime from zope.formlib.i18n import _ from zope.formlib.interfaces import ConversionError, IDisplayWidget from zope.formlib.textwidgets import ( DateWidget, DateDisplayWidget, escape, DatetimeDisplayWidget) from zope.formlib.widget import renderElement, CustomWidgetFactory from zope.interface import implements class FormattedDateWidget(DateWidget): """A date widget that supports different (and _explicit_) date formats. This is an input widget. """ date_format = '%Y-%m-%d' def _toFieldValue(self, input): if input == self._missing: return self.context.missing_value else: try: # 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 input = input.strip('#') value = datetime.strptime(input, self.date_format) except (ValueError, IndexError), v: raise ConversionError(_("Invalid datetime data"), v) return value.date() def _toFormValue(self, value): if value: value = value.strftime(self.date_format) return value class FormattedDateDisplayWidget(DateDisplayWidget): """A date widget that supports different (and _explicit_) date formats. This is a display widget. """ date_format = '%Y-%m-%d' implements(IDisplayWidget) def __call__(self): if self._renderedValueSet(): content = self._data else: content = self.context.default if content == self.context.missing_value: return "" content = content.strftime(self.date_format) return renderElement("span", contents=escape(content), cssClass=self.cssClass) #: A dictionary of supported date formats. #: #: The following formats are supported: #: #: ``iso`` #: ISO format ``YYYY-MM-DD`` #: ``le`` #: little endian with slashes: ``DD/MM/YYYY`` #: ``de`` #: german date format: ``DD.MM.YYYY`` #: ``us`` #: middle endian format common in the U.S.: ``MM/DD/YYYY`` #: #: Furthermore we support for input widgets an additional year #: marker. Input date widgets with this marker provide also a year #: selector, handy for dates of birth etc. #: #: The year-supporting formats are similar to the basic versions above: #: #: ``iso-year`` #: ISO format ``YYYY-MM-DD`` #: ``le-year`` #: little endian with slashes: ``DD/MM/YYYY`` #: ``de-year`` #: german date format: ``DD.MM.YYYY`` #: ``us-year`` #: middle endian format common in the U.S.: ``MM/DD/YYYY`` #: #: For date display widgets there is naturally no difference between a #: year and non-year setting (you can for instance use 'le' or 'le-year' #: with the same output). DATE_FORMATS = { 'iso': ('datepicker', '%Y-%m-%d'), 'le': ('datepicker-le', '%d/%m/%Y'), 'de': ('datepicker-de', '%d.%m.%Y'), 'us': ('datepicker-us', '%m/%d/%Y'), 'iso-year': ('datepicker-year', '%Y-%m-%d'), 'le-year': ('datepicker-le-year', '%d/%m/%Y'), 'de-year': ('datepicker-de-year', '%d.%m.%Y'), 'us-year': ('datepicker-us-year', '%m/%d/%Y'), } def FriendlyDateWidget(format): """Get a friendly date input widget for `format`. This widget is suitable for edit and add forms. Valid `format` values are the keys of :var:`DATE_FORMATS` dict. Default is ``le`` (little endian; DD/MM/YYYY). Friendly date widgets are rendered with a specialized CSS tag for enabling JavaScript datepickers. """ css_class, date_format = DATE_FORMATS.get(format, DATE_FORMATS['le']) return CustomWidgetFactory( FormattedDateWidget, cssClass=css_class, date_format=date_format) def FriendlyDateDisplayWidget(format): """Get a friendly date display widget for `format`. This widget is suitable for display forms. Valid `format` values are the keys of :var:`DATE_FORMATS` dict. Default is ``le`` (little endian; DD/MM/YYYY). This widget is not rendered with a specialized CSS tag for enabling JavaScript datepickers. `css_class` is ignored which means there is nor difference between e.g. ``le`` and ``le-year``.` """ css_class, date_format = DATE_FORMATS.get(format, DATE_FORMATS['le']) return CustomWidgetFactory( FormattedDateDisplayWidget, date_format=date_format) def FriendlyDatetimeDisplayWidget(format): """Get a friendly datetime display widget for `format`. This widget is suitable for display forms. Valid `format` values are the keys of :var:`DATE_FORMATS` dict. Default is ``le`` (little endian; DD/MM/YYYY %H:%M:%S). This widget is not rendered with a specialized CSS tag for enabling JavaScript datepickers. `css_class` is ignored which means there is nor difference between e.g. ``le`` and ``le-year``.` """ css_class, date_format = DATE_FORMATS.get(format, DATE_FORMATS['le']) datetime_format = date_format + ' %H:%M:%S' return CustomWidgetFactory( FormattedDateDisplayWidget, date_format=datetime_format)