[Haskell-cafe] Towards a better time library (announcing tz)

Mihaly Barasz klao at nilcons.com
Mon Apr 7 17:45:12 UTC 2014

On Mon, Apr 7, 2014 at 6:20 PM, Renzo Carbonara <gnuk0001 at gmail.com> wrote:
> On Mon, Apr 7, 2014 at 12:49 PM, Mihaly Barasz <klao at nilcons.com> wrote:
>> Hello Renzo and list,
>> Since my last email I have implemented the two things that I mentioned:
>> * a Template Haskell function with which you can include a few needed
>> `TZ`s in your binary at compile time
>> * a module which contains all of the time zones shipped in a pure way.
>> So, if you use this module, all of the zone files will be compiled
>> into your binary, so you can use them completely independently from
>> the platform/machine you are running on. (This is appropriate for a
>> webapp for example, where you need to display times to many users in
>> many different time zones.)
>> Renzo, please take a look at the Data.Time.Zones.All module
>> (http://hackage.haskell.org/package/tz-
>> I tried to implement it with your comments in mind.
> Yes! This is precisely what I had in mind, thanks so much for working
> on this. Tools like these will allow us at work to deal with timezones
> in a type-safe manner, purely within a closed world (the tz database
> being used), avoiding any IO interactions, which is quite welcome when
> building a piece of software that needs to deal with timezones
> constantly like a web application attending users from different time
> zones, just like you said. This same approach of including a full tz
> database for internal use is done by other programs that need to
> operate with timezones quite frequently; PostgreSQL comes to mind.
> I particularly like that you are removing timezone names that are
> links from the `TZLabel` constructors, yet allowing the link names to
> be looked up when using `tzByName` (that is, both
> `"America/Buenos_Aires"` and `"America/Argentina/Buenos_Aires"` point
> to the canonical `America__Argentina__Buenos_Aires`).

You are giving me too much credit!
This is not how it was implemented, but you are right, this makes much
more sense! I rewrote it to be like that.

> I have two recommendations, both related to performance: First, I'd
> prefer if instead of using `String` you used `ByteString` or `Text`.
> `String` seems like an unnecessary cost to pay, even more so when one
> of the purposes of this module is to avoid expensive lookups (in our
> particular use case at work, we already have stored strings such as
> `Europe/Rome` in the database, so reading them as `Text` or
> `ByteString` will be cheaper than reading them as `String`). And the
> second one, is that you could probably benefit from making
> `tzDescriptions` be a `Data.Map.Map` from the time zone name to the
> (either a `Text` or a `ByteString`) to the rest of the `TZDescription`
> information. That'll certainly speed up the lookups by name (though by
> looking at the definition of `tzByName`, maybe there are some
> memoization tricks into play already which I can't immediately
> recognize).

I changed the names to be (strict) ByteStrings. Maybe I'll add some
convenience functions to also work with Strings and Text. (Or maybe
not, because there are also the lazy versions of ByteString and Text
and I don't want to add functions for all of them.)

For the second part: all of the lookups are done either from Data.Map
or from Data.Vector. I only export the `tzDescriptions` list because
maybe someone is interested, I never do lookups in it. (All three
lookup functions have a constant vector or map produced from
`tzDescriptions` and do lookups in those.)

>> If you think that
>> this is something like what you need, something like what you were
>> thinking about, I can release it as a separate package with your
>> versioning scheme.
> I don't think you really need to do this, it was just a minor
> suggestion I made. As long as it's mentioned in the package and module
> documentation what tz database version is being used, it should be
> fine.

I might do it anyway. It's a nice separation, and also others who
don't want to use `TZ` (like `timezone-olson`) might benefit from it

> Regards,
> Renzo Carbonara.

More information about the Haskell-Cafe mailing list