Skip to content
Snippets Groups Projects
Commit fa9373b4 authored by jan.bednarik's avatar jan.bednarik
Browse files

Timezones and localization

parent 5c4a6b16
No related branches found
No related tags found
1 merge request!1release
...@@ -8,3 +8,4 @@ celerybeat-* ...@@ -8,3 +8,4 @@ celerybeat-*
env.sh env.sh
.cache .cache
.idea/ .idea/
docker-compose.yml
...@@ -6,10 +6,26 @@ Helios is an end-to-end verifiable voting system. ...@@ -6,10 +6,26 @@ Helios is an end-to-end verifiable voting system.
## Info ## Info
větve v gitu: Větve v gitu:
- `original` je kopie https://github.com/benadida/helios-server - `original` je kopie https://github.com/benadida/helios-server
- `master` je z `original` odvozená Pirátská verze nasazená v produkci - `master` je z `original` odvozená Pirátská verze nasazená v produkci
- `test` je testovací verze odvozená z `master` nasazená pro testování - `test` je testovací verze odvozená z `master` nasazená pro testování
Obvykle děláme změny v `test` a když je to ok, releasujeme do `master`. Obvykle děláme změny v `test` a když je to ok, releasujeme do `master`.
### Jak na upgrade?
1. aktualizuj větev `original`
2. udělej rebase větve `master` z větve `original`
3. udělej novou větev `test` odvozenou z `master`
## Čas
S šasy se v kódu pracuje velmi primitivně. Všechny časy jsou naivně a musí být UTC.
Což komplikuje všechno. Ale podařilo se to rozumně pořešit na vstupu a výstupu.
V kódu je to ohnuté takto:
* Vizuálně času v templatech prohnán přes filtr `|timezone:"Europe/Prague"`.
* Ve form field `SplitDateTimeField` očekáváme Europe/Prague a převádíme na UTC.
import datetime import datetime
import pytz
from django.forms import fields from django.forms import fields
from django.utils.timezone import make_aware, make_naive
from .widgets import SplitSelectDateTimeWidget from .widgets import SplitSelectDateTimeWidget
...@@ -25,6 +27,8 @@ class SplitDateTimeField(fields.MultiValueField): ...@@ -25,6 +27,8 @@ class SplitDateTimeField(fields.MultiValueField):
if data_list: if data_list:
if not (data_list[0] and data_list[1]): if not (data_list[0] and data_list[1]):
return None return None
return datetime.datetime.combine(*data_list) value = datetime.datetime.combine(*data_list)
# do formuláře zadáváme Europe/Prague, ale do DB se ukládá naivní UTC
return make_naive(make_aware(value, pytz.timezone("Europe/Prague")), pytz.UTC)
return None return None
...@@ -21,10 +21,8 @@ class ElectionForm(forms.Form): ...@@ -21,10 +21,8 @@ class ElectionForm(forms.Form):
randomize_answer_order = forms.BooleanField(required=False, initial=False, help_text=u'zvolte, pokud chcete, aby se každému voliči zobrazovaly odpovědi na otázky v náhodně zvoleném pořadí', label=u"Odpovědi v náhodném pořadí") randomize_answer_order = forms.BooleanField(required=False, initial=False, help_text=u'zvolte, pokud chcete, aby se každému voliči zobrazovaly odpovědi na otázky v náhodně zvoleném pořadí', label=u"Odpovědi v náhodném pořadí")
private_p = forms.BooleanField(required=False, initial=False, label=u"Soukromé?", help_text=u'Soukromé hlasování je viditelné jen pro registrované voliče.') private_p = forms.BooleanField(required=False, initial=False, label=u"Soukromé?", help_text=u'Soukromé hlasování je viditelné jen pro registrované voliče.')
help_email = forms.CharField(required=False, initial="", label=u"E-mail pro nápovědu", help_text=u'e-mailová adresa, na kterou se budou voliči obracet s žádostmi o pomoc.') help_email = forms.CharField(required=False, initial="", label=u"E-mail pro nápovědu", help_text=u'e-mailová adresa, na kterou se budou voliči obracet s žádostmi o pomoc.')
voting_starts_at = SplitDateTimeField(help_text = u'datum a čas zahájení hlasování; v UTC, takže oproti časovému pásmu ČR je menší o 1 hodinu v zimním, resp. o 2 hodiny v letním čase', voting_starts_at = SplitDateTimeField(help_text = u'datum a čas zahájení hlasování v lokálním čase!', widget=SplitSelectDateTimeWidget, required=False, label=u"Hlasování začíná v")
widget=SplitSelectDateTimeWidget, required=False, label=u"Hlasování začíná v") voting_ends_at = SplitDateTimeField(help_text = u'datum a čas ukončení hlasování v lokálním čase!', widget=SplitSelectDateTimeWidget, required=False, label=u"Hlasování končí v")
voting_ends_at = SplitDateTimeField(help_text = u'datum a čas ukončení hlasování; v UTC, takže oproti časovému pásmu ČR je menší o 1 v zimním, resp. o 2 hodiny v letním čase',
widget=SplitSelectDateTimeWidget, required=False, label=u"Hlasování končí v")
if settings.ALLOW_ELECTION_INFO_URL: if settings.ALLOW_ELECTION_INFO_URL:
election_info_url = forms.CharField(required=False, initial="", label=u"URL pro stažení informací o hlasování", help_text=u"URL dokumentu ve formátu PDF, obsahujícího doplňkové informace k hlasování, např. životopisy a profily kandidátů") election_info_url = forms.CharField(required=False, initial="", label=u"URL pro stažení informací o hlasování", help_text=u"URL dokumentu ve formátu PDF, obsahujícího doplňkové informace k hlasování, např. životopisy a profily kandidátů")
...@@ -32,7 +30,7 @@ class ElectionForm(forms.Form): ...@@ -32,7 +30,7 @@ class ElectionForm(forms.Form):
pass pass
class ElectionTimeExtensionForm(forms.Form): class ElectionTimeExtensionForm(forms.Form):
voting_extended_until = SplitDateTimeField(help_text = u'datum a čas prodlouženého ukončení hlasování; v UTC', voting_extended_until = SplitDateTimeField(help_text = u'datum a čas prodlouženého ukončení hlasování; v lokálním čase!',
widget=SplitSelectDateTimeWidget, required=False, label=u"Hlasování prodlouženo do") widget=SplitSelectDateTimeWidget, required=False, label=u"Hlasování prodlouženo do")
class EmailVotersForm(forms.Form): class EmailVotersForm(forms.Form):
......
{% extends TEMPLATE_BASE %} {% extends TEMPLATE_BASE %}
{% load tz %}
{% block content %} {% block content %}
...@@ -9,8 +10,8 @@ ...@@ -9,8 +10,8 @@
</p> </p>
<p> <p>
{% if election.voting_start_at %}začátek hlasování: {{election.voting_start_at}}<br />{% endif %} {% if election.voting_start_at %}začátek hlasování: {{election.voting_start_at|timezone:"Europe/Prague"}}<br />{% endif %}
{% if election.voting_end_at %}konec hlasování: {{election.voting_end_at}}<br />{% endif %} {% if election.voting_end_at %}konec hlasování: {{election.voting_end_at|timezone:"Europe/Prague"}}<br />{% endif %}
</p> </p>
<p> <p>
......
{% extends TEMPLATE_BASE %} {% extends TEMPLATE_BASE %}
{% load tz %}
{% block content %} {% block content %}
...@@ -9,8 +10,8 @@ ...@@ -9,8 +10,8 @@
</p> </p>
<p> <p>
{% if election.voting_start_at %}začátek hlasování: {{election.voting_start_at}}<br />{% endif %} {% if election.voting_start_at %}začátek hlasování: {{election.voting_start_at|timezone:"Europe/Prague"}}<br />{% endif %}
{% if election.voting_end_at %}konec hlasování: {{election.voting_end_at}}<br />{% endif %} {% if election.voting_end_at %}konec hlasování: {{election.voting_end_at|timezone:"Europe/Prague"}}<br />{% endif %}
</p> </p>
<p> <p>
......
{% extends TEMPLATE_BASE %} {% extends TEMPLATE_BASE %}
{% load tz %}
{% block title %}{{election.name}}{% endblock %} {% block title %}{{election.name}}{% endblock %}
{% block content %} {% block content %}
<div style="float: left; margin-right: 50px;"> <div style="float: left; margin-right: 50px;">
...@@ -48,8 +49,8 @@ toto {{election.election_type}} <u>není</u> zobrazeno na titulní stránce. ...@@ -48,8 +49,8 @@ toto {{election.election_type}} <u>není</u> zobrazeno na titulní stránce.
<p> <p>
{% if election.help_email and admin_p%}Email pro nápovědu: {{election.help_email}}<br />{% endif %} {% if election.help_email and admin_p%}Email pro nápovědu: {{election.help_email}}<br />{% endif %}
{% if election.voting_start_at %}Hlasování začíná: {{election.voting_start_at}}<br />{% endif %} {% if election.voting_start_at %}Hlasování začíná: {{election.voting_start_at|timezone:"Europe/Prague"}}<br />{% endif %}
{% if election.voting_end_at %}Hlasování končí: {{election.voting_end_at}}<br />{% endif %} {% if election.voting_end_at %}Hlasování končí: {{election.voting_end_at|timezone:"Europe/Prague"}}<br />{% endif %}
</p> </p>
{% if election.election_info_url %} {% if election.election_info_url %}
...@@ -97,7 +98,7 @@ toto {{election.election_type}} <u>není</u> zobrazeno na titulní stránce. ...@@ -97,7 +98,7 @@ toto {{election.election_type}} <u>není</u> zobrazeno na titulní stránce.
<br /> <br />
{% if election.voting_starts_at %} {% if election.voting_starts_at %}
jakmile to učiníte, hlasování bude připraveno k odevzdávání hlasovacích lístků a bude automaticky zahájeno<br /> jakmile to učiníte, hlasování bude připraveno k odevzdávání hlasovacích lístků a bude automaticky zahájeno<br />
v {{election.voting_starts_at}}, podle vašeho nastavení. v {{election.voting_starts_at|timezone:"Europe/Prague"}}, podle vašeho nastavení.
{% else %} {% else %}
jakmile to učiníte, hlasování bude ihned zahájeno. jakmile to učiníte, hlasování bude ihned zahájeno.
{% endif %} {% endif %}
...@@ -185,12 +186,12 @@ Poté uvidíte výsledek pouze vy jakožto zakladatel hlasování. ...@@ -185,12 +186,12 @@ Poté uvidíte výsledek pouze vy jakožto zakladatel hlasování.
<br /> <br />
<br /> <br />
{% if election.voting_extended_until %} {% if election.voting_extended_until %}
Toto {{election.election_type}} mělo původně skončit v {{election.voting_ends_at}} (UTC),<br /> Toto {{election.election_type}} mělo původně skončit v {{election.voting_ends_at|timezone:"Europe/Prague"}},<br />
ale bylo prodlouženo do {{ election.voting_extended_until }} (UTC). ale bylo prodlouženo do {{ election.voting_extended_until|timezone:"Europe/Prague" }}.
{% else %} {% else %}
{% if election.voting_ends_at %} {% if election.voting_ends_at %}
<br /> <br />
Toto {{election.election_type}} bude uzavřeno v {{election.voting_ends_at}} (UTC). Toto {{election.election_type}} bude uzavřeno v {{election.voting_ends_at|timezone:"Europe/Prague"}}.
{% else %} {% else %}
Toto {{election.election_type}} bude uzavřeno podle rozhodnutí jeho zakladatele. Toto {{election.election_type}} bude uzavřeno podle rozhodnutí jeho zakladatele.
{% endif %} {% endif %}
......
{% load tz %}
Vážený {{voter.name}}, Vážený {{voter.name}},
{{custom_message|safe}} {{custom_message|safe}}
URL Hlasování: {{election_vote_url}} URL Hlasování: {{election_vote_url}}
Otisk Hlasováné: {{voter.election.hash}} Otisk Hlasováné: {{voter.election.hash}}
{% if election.voting_start_at %}Hlasování začíná {{election.voting_start_at}} {% if election.voting_start_at %}Hlasování začíná {{election.voting_start_at|timezone:"Europe/Prague"}}
{% endif %}{% if election.voting_end_at %}Hlasování končí {{election.voting_end_at}} {% endif %}{% if election.voting_end_at %}Hlasování končí {{election.voting_end_at|timezone:"Europe/Prague"}}
{% endif %} {% endif %}
{% ifequal voter.voter_type "password" %} {% ifequal voter.voter_type "password" %}
......
...@@ -54,11 +54,11 @@ if get_from_env('DATABASE_URL', None): ...@@ -54,11 +54,11 @@ if get_from_env('DATABASE_URL', None):
# although not all choices may be available on all operating systems. # although not all choices may be available on all operating systems.
# If running in a Windows environment this must be set to the same as your # If running in a Windows environment this must be set to the same as your
# system time zone. # system time zone.
TIME_ZONE = 'America/Los_Angeles' TIME_ZONE = 'UTC'
# Language code for this installation. All choices can be found here: # Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html # http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'en-us' LANGUAGE_CODE = 'cs-cz'
SITE_ID = 1 SITE_ID = 1
...@@ -66,6 +66,8 @@ SITE_ID = 1 ...@@ -66,6 +66,8 @@ SITE_ID = 1
# to load the internationalization machinery. # to load the internationalization machinery.
USE_I18N = True USE_I18N = True
USE_L10N = True
# Absolute path to the directory that holds media. # Absolute path to the directory that holds media.
# Example: "/home/media/media.lawrence.com/" # Example: "/home/media/media.lawrence.com/"
MEDIA_ROOT = '' MEDIA_ROOT = ''
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment