calendar-social/calsocial/forms.py
Gergely Polonkai 8a46f3c66a Add proper time zone support
Until now event timestamps were saved in the server’s time zone.  Now they are saved in UTC,
considering the time zone set by the creator of the event.
2018-07-02 17:32:06 +02:00

90 lines
2.9 KiB
Python

from flask_babelex import lazy_gettext as _
from flask_wtf import FlaskForm
import pytz
from wtforms import BooleanField, PasswordField, SelectField, StringField
from wtforms.ext.dateutil.fields import DateTimeField
from wtforms.validators import DataRequired, Email, ValidationError
from wtforms.widgets import TextArea
class RegistrationForm(FlaskForm):
username = StringField(_('Username'), validators=[DataRequired()])
email = StringField(_('Email address'), validators=[Email()])
password = PasswordField(_('Password'), validators=[DataRequired()])
password_retype = PasswordField(_('Password, once more'), validators=[DataRequired()])
def validate_password_retype(self, field):
if field.data != self.password.data:
raise ValidationError(_('The two passwords must match!'))
class TimezoneField(SelectField):
def __init__(self, *args, **kwargs):
kwargs.update({
'choices': [
(pytz.timezone(tz), tz.replace('_', ' '))
for tz in pytz.common_timezones
],
})
SelectField.__init__(self, *args, **kwargs)
def process_formdata(self, valuelist):
if not valuelist:
self.data = None
return
try:
self.data = pytz.timezone(valuelist[0])
except pytz.exceptions.UnknownTimeZoneError:
self.data = None
raise ValueError('Unknown time zone')
@staticmethod
def is_pytz_instance(value):
return value is pytz.UTC or isinstance(value, pytz.tzinfo.BaseTzInfo)
def process_data(self, value):
if value is None:
self.data = None
return
if is_pytz_instance(value):
self.data = value
return
try:
self.data = pytz.timezone(value)
except Exception as exc:
raise ValueError(f'Unknown time zone {value}')
def iter_choices(self):
for value, label in self.choices:
yield (value, label, value == self.data)
class EventForm(FlaskForm):
title = StringField(_('Title'), validators=[DataRequired()])
time_zone = TimezoneField(_('Time zone'), validators=[DataRequired()])
start_time = DateTimeField(_('Start time'), validators=[DataRequired()])
end_time = DateTimeField(_('End time'), validators=[DataRequired()])
all_day = BooleanField(_('All day'))
description = StringField(_('Description'), widget=TextArea())
def populate_obj(self, obj):
FlaskForm.populate_obj(self, obj)
tz = self.time_zone.data
obj.time_zone = str(tz)
obj.start_time = tz.localize(self.start_time.data).astimezone(pytz.utc)
obj.end_time = tz.localize(self.end_time.data).astimezone(pytz.utc)
def validate_end_time(self, field):
if field.data < self.start_time.data:
raise ValidationError(_('End time must be later than start time!'))