diff options
Diffstat (limited to 'postgresqleu/util')
| -rw-r--r-- | postgresqleu/util/backendforms.py | 4 | ||||
| -rw-r--r-- | postgresqleu/util/db.py | 52 | ||||
| -rwxr-xr-x | postgresqleu/util/misc/baseinvoice.py | 11 | ||||
| -rw-r--r-- | postgresqleu/util/time.py | 9 |
4 files changed, 59 insertions, 17 deletions
diff --git a/postgresqleu/util/backendforms.py b/postgresqleu/util/backendforms.py index 069061eb..b285d1bf 100644 --- a/postgresqleu/util/backendforms.py +++ b/postgresqleu/util/backendforms.py @@ -86,8 +86,8 @@ class BackendForm(ConcurrentProtectedModelForm): if self.conference: if isinstance(v, django.forms.fields.DateTimeField) and k not in self.exclude_date_validators: v.validators.extend([ - MinValueValidator(datetime.datetime.combine(self.conference.startdate, datetime.time(0, 0, 0))), - MaxValueValidator(datetime.datetime.combine(self.conference.enddate + datetime.timedelta(days=1), datetime.time(0, 0, 0))), + MinValueValidator(conference.localize_datetime(datetime.datetime.combine(self.conference.startdate, datetime.time(0, 0, 0)))), + MaxValueValidator(conference.localize_datetime(datetime.datetime.combine(self.conference.enddate + datetime.timedelta(days=1), datetime.time(0, 0, 0)))), ]) elif isinstance(v, django.forms.fields.DateField) and k not in self.exclude_date_validators: v.validators.extend([ diff --git a/postgresqleu/util/db.py b/postgresqleu/util/db.py index c9d8f5c3..e0a07381 100644 --- a/postgresqleu/util/db.py +++ b/postgresqleu/util/db.py @@ -1,33 +1,43 @@ from django.db import connection +from django.conf import settings import collections +from psycopg2.tz import LocalTimezone -def exec_no_result(query, params=None): + +def get_native_cursor(): + # Remove djangos dumb prevention of us to change the timezone curs = connection.cursor() + curs.cursor.tzinfo_factory = LocalTimezone + return curs + + +def exec_no_result(query, params=None): + curs = get_native_cursor() curs.execute(query, params) def exec_to_list(query, params=None): - curs = connection.cursor() + curs = get_native_cursor() curs.execute(query, params) return curs.fetchall() def exec_to_single_list(query, params=None): - curs = connection.cursor() + curs = get_native_cursor() curs.execute(query, params) return [r[0] for r in curs.fetchall()] def exec_to_dict(query, params=None): - curs = connection.cursor() + curs = get_native_cursor() curs.execute(query, params) columns = [col[0] for col in curs.description] return [dict(list(zip(columns, row)))for row in curs.fetchall()] def exec_to_scalar(query, params=None): - curs = connection.cursor() + curs = get_native_cursor() curs.execute(query, params) r = curs.fetchone() if r: @@ -44,20 +54,20 @@ def conditional_exec_to_scalar(condition, query, params=None): def exec_to_keyed_dict(query, params=None): - curs = connection.cursor() + curs = get_native_cursor() curs.execute(query, params) columns = [col[0] for col in curs.description] return {r[columns[0]]: r for r in (dict(list(zip(columns, row)))for row in curs.fetchall())} def exec_to_keyed_scalar(query, params=None): - curs = connection.cursor() + curs = get_native_cursor() curs.execute(query, params) return dict(curs.fetchall()) def exec_to_grouped_dict(query, params=None): - curs = connection.cursor() + curs = get_native_cursor() curs.execute(query, params) columns = [col[0] for col in curs.description[1:]] full = collections.OrderedDict() @@ -73,3 +83,29 @@ def exec_to_grouped_dict(query, params=None): if last: full[last] = curr return full + + +class ensure_conference_timezone(): + """ + This context handler will set the timezone *in PostgreSQL* to the one from the + specified conference, and reset it back to UTC when it's done. During this time, + calls from django's own ORM will fail, it's intended only to wrap native SQL + querying that needs to use the appropriate timezone. + If None is specified as the conference, set the timezone to the global one for + the installation (otherwise the default is UTC). + """ + def __init__(self, conference): + if conference is None: + self.tzname = settings.TIME_ZONE + else: + self.tzname = conference.tzname + + def __enter__(self): + c = connection.cursor() + c.execute("SET TIMEZONE=%(tz)s", { + 'tz': self.tzname, + }) + return c + + def __exit__(self, *args): + connection.cursor().execute("SET TIMEZONE='UTC'") diff --git a/postgresqleu/util/misc/baseinvoice.py b/postgresqleu/util/misc/baseinvoice.py index 834f37bc..c36a493d 100755 --- a/postgresqleu/util/misc/baseinvoice.py +++ b/postgresqleu/util/misc/baseinvoice.py @@ -15,6 +15,7 @@ from reportlab.pdfbase.pdfmetrics import registerFont, getFont from reportlab.pdfbase.ttfonts import TTFont from io import BytesIO +from django.utils import timezone from django.conf import settings from postgresqleu.util.reporttools import cm @@ -156,7 +157,7 @@ class BaseInvoice(PDFBase): if self.receipt: self.canvas.drawCentredString(cm(10.5), cm(18.5), "Receipt for invoice number %s%s" % (self.invoicenum, suffix)) else: - self.canvas.drawCentredString(cm(10.5), cm(18.5), "Invoice number %s - %s%s" % (self.invoicenum, self.invoicedate.strftime("%B %d, %Y"), suffix)) + self.canvas.drawCentredString(cm(10.5), cm(18.5), "Invoice number %s - %s%s" % (self.invoicenum, timezone.localtime(self.invoicedate).strftime("%B %d, %Y"), suffix)) self.canvas.setFont('DejaVu Serif Bold', 10) if self.receipt: self.canvas.drawString(cm(15), cm(28), "Receipt #%s" % self.invoicenum) @@ -166,7 +167,7 @@ class BaseInvoice(PDFBase): self.canvas.setFont('DejaVu Serif Bold', 8) self.canvas.drawString(cm(15), cm(27.5), "Payment ref: %s" % self.paymentref) else: - self.canvas.drawCentredString(cm(10.5), cm(18.5), "Receipt - %s%s" % (self.invoicedate.strftime("%B %d, %Y"), suffix)) + self.canvas.drawCentredString(cm(10.5), cm(18.5), "Receipt - %s%s" % (timezone.localtime(self.invoicedate).strftime("%B %d, %Y"), suffix)) if pagenum == 0: firstcol = "Item" @@ -268,9 +269,9 @@ class BaseInvoice(PDFBase): self.canvas.setFont('DejaVu Serif Bold', 10) if self.receipt: - self.canvas.drawCentredString(cm(10.5), cm(17.3) - h, "This invoice was paid %s" % self.duedate.strftime("%B %d, %Y")) + self.canvas.drawCentredString(cm(10.5), cm(17.3) - h, "This invoice was paid %s" % timezone.localtime(self.duedate).strftime("%B %d, %Y")) else: - self.canvas.drawCentredString(cm(10.5), cm(17.3) - h, "This invoice is due: %s" % self.duedate.strftime("%B %d, %Y")) + self.canvas.drawCentredString(cm(10.5), cm(17.3) - h, "This invoice is due: %s" % timezone.localtime(self.duedate).strftime("%B %d, %Y")) if self.bankinfo: self.canvas.setFont('DejaVu Serif', 8) self.canvas.drawCentredString(cm(10.5), cm(16.8) - h, "If paying with bank transfer, use payment reference %s" % self.paymentref) @@ -431,7 +432,7 @@ class BaseRefund(PDFBase): w, h = t.wrapOn(self.canvas, cm(10), cm(10)) t.drawOn(self.canvas, (self.canvas._pagesize[0] - w) // 2, cm(17) - h * 2 - cm(1) - extraofs) - self.canvas.drawCentredString(cm(10.5), cm(16.3) - h * 2 - cm(2) - extraofs, "This refund was issued {0}".format(self.refunddate.strftime("%B %d, %Y"))) + self.canvas.drawCentredString(cm(10.5), cm(16.3) - h * 2 - cm(2) - extraofs, "This refund was issued {0}".format(timezone.localtime(self.refunddate).strftime("%B %d, %Y"))) if self.paymentmethod: self.canvas.drawCentredString(cm(10.5), cm(16.3) - h * 2 - cm(3) - extraofs, "Refunded to the original form of payment: {0}.".format(self.paymentmethod)) diff --git a/postgresqleu/util/time.py b/postgresqleu/util/time.py index 76567187..eab66cab 100644 --- a/postgresqleu/util/time.py +++ b/postgresqleu/util/time.py @@ -1,9 +1,14 @@ from django.utils import timezone +# Return a date represeting today in the timezone of the currently +# selected conference. If no conference is selected, the date will +# be returned in the global default timezone. def today_conference(): - return timezone.now().date() + return timezone.localdate(timezone.now()) +# Return a date represeting today ihn the global default timezone +# (making it suitable for everything that is not conference-related). def today_global(): - return timezone.now().date() + return timezone.localdate(timezone.now(), timezone.get_default_timezone()) |
