Friday, March 16, 2018

Time zones

Yesterday I opened #2345 and started working on it. Here comes the result.

Until today we had just had a field User.timezone (a Charfield(max_length=15) when USE_TZ was True. In order to get an aware datetime of the start and end times of a session, we used the user’s time zone. Which was okay unless the user travels and works in changing time zones.

Jane is the only production site with USE_TZ

Now I added a timezone field per working.Session as well.

But before doing this I reviewed and optimized the whole system a bit. I added a choicelist about.Timezones which defines a subset of all timezones known to pytz. This has one theoretical disadvantage (it requires local system admins to define their own list of timezones allowed on their site) but some advantages: it reduces server load because it uses only 2 instead of 15 bytes per Session record and (more important) avoids a lookup into the pytz database (a dict containing 439 keys) for every incoming web request. Also it will probably be more ergonimic.

>>> import pytz
>>> len(pytz.common_timezones)
439

The django.utils.timezone.activate() function (called for every incoming request) is smart enough and would avoid the lookup if we would provide the tzinfo object ourselves:

def activate(timezone):
    if isinstance(timezone, tzinfo):
        _active.value = timezone
    elif isinstance(timezone, six.string_types):
        _active.value = pytz.timezone(timezone)
    else:
        raise ValueError("Invalid timezone: %r" % timezone)

We currently store the timezone (either per user or system-wide) as a string. That is, for the moment we are using the inefficient variant.

Where to put our TimeZones choicelists? To lino.modlib.about? Or into a separate plugin lino.modlib.timezones? I noted that we have two plugins lino.modlib.about and lino.modlib.system which should maybe get merged. One difference is that about is always there while system only when needed. Though it is needed by lino.modlib.users and therefore they are almost always both present.

Changes:

Another change of more general impact:

New page The lino.modlib.about plugin.

Here is the line to modify in the restore.py file when upgrading a production site:

kw.update(time_zone=settings.SITE.models.about.TimeZones.find(text=timezone))

After installing it on Jane I started to get the feeling that maintaining a local list of “allowed” time zones will be cumbersome. To be observed.

About inspired working

I have been asking myself “Why the hell did I open and fix that #2345? Why now? Aren’t there more urgent things to do?”

It is what I would call inspired working. Every well-educated project manager will give me -1 for this technique.

It happened after updating our jobs page and reviewing the The Lino Book (in case somebody looks at it).