howto: create your own time zone

Tomorrow I won't have to deal with it getting dark at a soul-crushing 5:30 pm. Nor will I have to wake up blearily an hour early in the spring. Instead I will be enjoying my new, custom time zone. It's "JEST", for "Joey's Eastern (non)Standard Time", and in JEST, there is no spring forward or fall back stress.

The folly of daylight savings time (Ben Franlin's best prank ever) really becomes apparent when you have solar power. It's bad enough that the sun is setting at 6:30 without compounding that by an hour. By keeping my clock set so the sun sets in midwinter at 6 pm, I will maximise what little light there is, and minimise time spent using batteries in the dark.

Of course, it helps that I'm my own boss, and that most of the people I work with are probably not in a nearby timezone anyway, and that most things are done asynchronously. Since JEST is an hour ahead of local time here in the winter, I will, at worst, tend to be running early.

So I only have to change my clocks one time -- and by "change", I mean create a custom timezone in Linux. Here's how to do that.

  1. Make a custom timezone file. The standard one for North America is a bewildering 3000 lines of special cases, conflicting legistlation, and historical weirdness, but I only need one:

    echo "Zone JEST -4:00 - JEST" > JEST.zone

  2. Compile and install it to somewhere; I put it in ~/.zoneinfo

    zic JEST.zone -d ~/.zoneinfo

  3. Set TZ to use it. Also TZDIR if it's not in the system directory.

    export TZDIR=~/.zoneinfo TZ=JEST

Update: Turns out it was easier than I thought, just setting TZ=FOO+4 will make date display a timezone "FOO" that is 4 hours behind GMT. So all I need is to set TZ=JEST+4

Result:

date: Sat Oct 30 21:43:39 JEST 2010
date -R: Sat, 30 Oct 2010 21:43:39 -0400

Previously:

Also, for Android:

Android does not seem to have an way to define your own time zone. I select Barbados from the time zone list, since it is on GMT-4 year round with no daylight savings.

Posted
chop chop

I've always loathed cheap particle board and peg bookcases, and when I broke one while reorgaising the living room at the Hollow today, I finally found a good use for them. They're great fun to chop up with an axe, and make for a very hot fire in the stove later.

I released git-annex 0.03 today. The main improvements are being able to configure the backend to use on a per-extension basis in .gitattributes, a fsck subcommand that will find dangling annexed content, and bugfixes, including massive memory use savings. The big feature under development next is an idea Josh Triplett and I batted around; a way to checkout annexed files to edit their contents.

Today I also got the radio working well here. Set up a car radio with a 40 foot wire for an antenna, and I finally got it almost static free. Pity that running a nslu2 on the same power circuit causes interference, so I am not able to use that to feed in music via the radio's AUX jack yet, which is the eventual plan. And the radio's powered USB outlet is wasted, I had hoped to run the nslu2 from that. Seems I can run the radio for 9 hours and still have plenty of solar power, even this time of year.

Wish it were colder..

Posted
debugging musings

Debugging a computer program is such an interesting activity because it's not really a matter of fixing a program. It's a matter of fixing your own understanding to the point that the cause of the bug becomes obvious. So debugging means constantly challenging your assumptions, constantly looking for the overlooked insignificant thing that turns out to be crucial.

I mostly debug by print statements. I don't like it much, but it works. I add some print statements around the problem area and see if what's going on matches what the model in my head thinks should be going on. If it doesn't, I try to fix the model, and if it does, I focus the print statements in tighter and tighter, deeper and deeper, until I finally reach the bug. It's nasty and ah-hoc, but it works really well, mostly. And I know I'm in good company doing it.

But that method can fail; I myself can end up caught in a loop. Like today, tracking down an obscure bug in Branchable's auditing subsystem, when I found myself at what was apparantly the point of a bug: Function A was supposed to call function B, but B never seemed to be called. So surely A was buggy, and I instrumented it to bits with print statements and stuff, and started wondering if the libraries it relied on were somehow breaking it in non-obvious ways before it could call B, or maybe there was a bug in the runtime language that was breaking the call to B.

Going deeper and deeper didn't help, because the thing I was overlooking was up at the top level -- one of the first print statements I inserted showed that all this code was running twice. Why? Didn't seem relevant to the bug so I ignored it. Of course what I was ignoring was a symptom of the real problem: The first run was by another subsystem, that happened to redefine function B temporarily..

Actually, one of the nice things about Haskell is that print statements are not very helpful in debugging pure code. Pure code tends to get loaded up in ghci and tested interactively, and the bug is then clear. Or a quickcheck test case gets written with an invariant that the pure code should satisfy. I spent a whole day a few weeks ago writing an inverse form of a buggy function in git-annex just so I could feed them both into quickcheck and automate debugging. (Most of that time was spent wrestling with unicode decomposition .. ugh.) Being used to getting down in the buggy code with print statements, that at the time felt rather like a waste of time unrelated to getting on with making my program work, but it was very much worth it since I got my program working 100% in even crazy edge cases, and got a test suite for free, too.

Most of my debugging of Haskell code so far has not involved bugs in pure code. The most memorable bug was actually a bug in ghc's IO manager, which I'd have never tracked down without Josh's help. The problem with finding bugs in the runtime environment or compiler is that after you've found enough over the years, you're more likely to go down false paths distrusting runtime environments, like I did with the bug today. The beginner's assumption is that the runtime environment just works, but I by now may have over-challenged that assumption. :)

Posted