Archive for the ‘Django’ Category

A funny story – featuring UTC offset

March 28, 2013

I don’t normally write about mistakes I make.

You know mistakes! You’re supposed to accept them, learn from them and never talk about them, especially online where your customers can read about them. No! You’re supposed to project an image of self-confidence, invulnerability and super human coding abilities.

Well, this mistake is funny and relatively harmless. I just have to write about it.

I’ve been writing before about the implementation of our CRM sync service. With every refresh, that sync service sends two things to the server: the timestamp of the last sync (to only get the delta from there) and the utc offset of the client (provided by the browser). This UTC offset is only reliable for getting the utc offset for that session, not to be reused as the UTC offset in general, and that’s because:

  1. The browser’s UTC offset is a naive offset, it’s not a timezone. In particular, it doesn’t know about daylight saving (although it applies it if in effect at the time of the request)
  2. The user might be travelling and using the service from a hotel in a totally different timezone

Anyways. We only use it in order to associate the dates and times with words like Today, Yesterday, etc. in the current session.

On the server, which uses python by the way, I use to have this naive handling of the UTC offset.


    try:
        utcoffset = int( request.GET.get('utcoffset', 0) )
    except:
        utcoffset = 0

The defaulting to 0 should never happen, as this parameter is always sent and the UTC offset, populated in javascript, should always be available in the browser. The try/except was more of a “just in case”.

So one day, I’ve decided that try/except doesn’t make sense, for the reasons highlighted above. Further more, I didn’t want the exception to be swallowed, I wanted to know about it. Django has a nice feature where you get an email every time an exception is thrown and not handled.

So I took that out, and my code now looked like this:


    utcoffset = int( request.GET.get('utcoffset', 0) )

Great, I thought. However, in my ignorance, I totally forgot about half hour timezones. India for example has a 6.5 UTC offset and there are half-hour timezones in Canada and Australia.

I caught this one pretty quickly when someone from India used the website and passed in a 6.5 offset. That line started throwing and flooding me with emails for every failure. Now this sync service actually polls for updates, so you can imagine I got quite a few emails.

Luckily for me, the fix was straightforward:


    utcoffset = float( request.GET.get('utcoffset', 0) )

Using a float instead of an int.

I suppose the moral of the story is twofold:

  1. Never swallow exceptions as the code might end up doing something you have not intended (using UTC offset 0 for half-hour timezones) and you will not know about it to fix it
  2. Learn about timezones
Advertisements

django url rules and spaces

February 28, 2013

I’ve been caught out by the copy’n’paste programming style where you just copy snippets of code, test them and off you go, without too much thinking. It’s so appealing this copy’n’paste programming style. You’re essentially encapsulating complexity within that snippet, which you trust because you’re copying and pasting from a reference source or from a place in the code where the snippet “proved itself” to work.

The problem is of course that the new context you’re placing it in can be slightly different from the context where you’re copying from. Thus, bugs appear.

Recently I’ve been caught out by a simple django URL rule which I’ve copied from the django reference website. Here’s the rule:

(r’^operationstatus/(?P<status>\w+)$’, ‘myapp.backbone_view’)

This does not match statuses with spaces in them, e.g.:

http://HOST/operationstatus/Global%20Status

You get a 404.

My quick solution was to change the regex to:

(r’^operationstatus/(?P<status>.*)$’, ‘myapp.backbone_view’)

which works as expected.