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

Renzo Carbonara gnuk0001 at gmail.com
Tue Apr 1 01:21:36 UTC 2014

I'm currently a user of the `timezone-olson` and `timezone-series`
libraries, so I can understand the requirement for better time zone
representations than the one offered by `time`. I think it would be
best for the community if your work and the one in `timezone-olson`
and `timezone-series` could be integrated somehow, as there doesn't
seem to be a need to have two different implementations for parsing
the Olson file format. As far as I know, Yitzchak is willing to
improve his libraries, I CC him here.

Given that you are shipping a timezone database with your package, as
a user I'd really prefer `loadTZFromDB` to be `String -> Maybe TZ`
instead of `String -> IO TZ` so that it can be used in pure code.
You'd probably need to hardcode the contents of the `*.zone` files you
are including within a Haskell module, but that could be done
automatically using some script.

Moreover, an idea I've been toying with is writing a program that
parses the tzdata information files and generates a type-safe pure API
for interacting with the tz data in memory. For example, given the
tzdata information files you would generate types, values and pure
functions such as the following:

    data TimeZone
       = Europe__Paris
       | America__Buenos_Aires
       | ...

    timeZoneName :: TimeZone -> Text
    timeZoneName Europe__Paris = "Europe/Paris"
    timeZoneName America__Buenos_Aires = "America/Buenos_Aires"
    timeZoneName ... = ...

    timeZoneFromName :: Text -> Maybe TimeZone
    timeZoneFromName "Europe/Paris" = Just Europe__Paris
    timeZoneFromName "America/Buenos_Aires" = Just America__Buenos_Aires
    timeZoneFromName ... = ...
    timeZoneFromName _ = Nothing

    timeZoneInfo :: TimeZone -> TZ
    timeZoneInfo Europe_Paris = ... some hardcoded value (the `TZ` in
your library) ...
    timeZoneInfo ... = ...

As a minor tidbit: If one is going to do this, I think a good idea is
to devise a package versioning system that's somewhat follows the tz
database versions. This is what I had in mind for the `tzdata` package
I was planning to create (unless someone else does it first):

  The version number of the package is always @YYYYMMDD.B.C@, where
  @YYYYMMDD@ are the year (@YYYY@), the month (@MM@) and the day (@DD@)
  of the @tzdata@ release this particular version was designed for. For
  example, @tzdata 2013i@ was officially released on @2013-12-17@, so a
  version of this package that was designed for @tzdata 2013i@ will
  carry the version number @20131217.B.C at . However, that doesn't mean
  that this library won't work with versions of the @tzdata@ library
  different than @2013i@, it's just that support for new or old data
  (say, the name of a new time zone that was introduced) can be missing.
  The @B@ and @C@ values in the version number of this library as
  treated as the /major/ and /minor/ versions respectively, as suggested
  in the /Haskell Package Version Policy/ page:

Maybe the `timezone-olson`, `timezone-series`, this `tzdata` idea and
`tz` could all live together; with `tz` depending on the others? Just
a thought :)


Renzo Carbonara.

On Mon, Mar 31, 2014 at 3:15 PM, Mihaly Barasz <klao at nilcons.com> wrote:
> I would like to propose reforming the 'time' [1] library.
> Initially, I was just planning to announce my new 'tz' [2] library, but
> realized that I have a more important agenda. Namely: Haskell needs a
> better time library!
> Let me summarize what are ‒ in my view ‒ the biggest deficiencies of
> 'time':
> 1. Inefficient data structures and implementations.
> 2. Ad-hoc API which is hard to remember and frustrating to work with.
> 3. Conceptually wrong representations and/or missing concepts.
> The wonderful thyme [3] package (by Liyang HU) improves a lot on #1 by
> choosing better data structures and careful implementations and on #2
> by lensifying the API.
> But, it was the #3 that caused me the most frustration lately; most
> importantly the time zone handling.
> There is a TimeZone data type in 'time', but it is a misnomer, it
> basically represents a fixed time difference (with a label and a DST
> flag). 'time' basically adapts the broken approach from libc: you can
> work with one time zone at a time, which is defined globally for your
> program (via the TZ environment variable). So, the transformation
> between UTCTime and LocalTime which should have been a pure
> function can only be done in IO now. Like this:
>     do tz <- getTimeZone ut
>        return $ utcToLocalTime tz ut
> Oh, and just to hammer down on the point #1 from the list above. This
> code runs in about 6100 ns on my machine. The drop-in replacement from
> tz: utcToLocalTimeTZ [4] (which is actually pure) runs in 2300 ns.
> While this is a significant improvement, it's easy to miss the point
> where the bulk of the inefficiency comes from the data structures. In
> my main project we represent times as Int64 (raw nanoseconds since
> UNIX epoch; and similar representation for zoned times). And to
> convert those to and from different time zones we need 40 ns. That's
> right, a 150 _times_ improvement!  (There are many other interesting
> benchmark results that I could mention. An exciting bottom line: we
> can actually beat the libc in many use-cases!)
> The 'tz' package is still very much in flux. I will try to solidify
> the API soon, but until then it should be considered more of a proof
> of concept. There is some missing functionality, for example. On the
> other hand, there are the 'timezone-series' [5] and 'timezone-olson'
> [6] packages that together provide about the same functionality as
> 'tz' (minus the efficiency), and I'd like to explore if we could
> remove some of the overlap. But, all kind of suggestions and requests
> are welcome!
> More importantly, I'd like to hear the opinions of the community about
> the general issue of a better time library! Do we need one?  How
> should we proceed about it?  I think, Haskell could potentially have
> one of the best time libraries, but the current de-facto standard is
> mediocre at best. Unfortunately, designing a good time library is very
> far from trivial, as many existing examples demonstrate. And I
> definitely don't know enough for it. (I understand time zone info
> files, now that I wrote tz, but that's just a tiny fraction of what's
> needed.)  So, if you think you can contribute to the design (have
> important use-cases in mind, know good examples of API, have some
> experience working with dates and time, etc. etc.) ‒ speak up!
> Mihaly
> Footnotes:
> [1]  http://hackage.haskell.org/package/time
> [2]  http://hackage.haskell.org/package/tz
> [3]  http://hackage.haskell.org/package/thyme
> [4]  http://hackage.haskell.org/package/tz-
> [5]  http://hackage.haskell.org/package/timezone-series
> [6]  http://hackage.haskell.org/package/timezone-olson
> Version: GnuPG v1.4.6 (GNU/Linux)
> iQEVAwUBUzmwz/i5FOsZqz9DAQJGcAgAhPF4JLWnL4ApJ2qxqAwHqXcIPqRpVb5A
> TH2LERH2A/6b3xXCRYsPgyD43j2CzqZGffRvINSw9fGoJYWuRmis5dCf9hwPiKtg
> UwtoemQSVLUIIRxZyg5pdL+dxadnttm7bGC+UuQJHtSSBRweEh3unr8dcNm4idC3
> nxWOMclbo2hyMdwzDo1bqugugq2xCGPiGrL550aF1lCGD2pf2vQO1feW/5XyMaCR
> Oj6gI+eHo8SuhUx30Dokv1kx8Ssay0aVmmASCJKnR8Bwv1J9AKWo3A==
> =Bp64
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe

More information about the Haskell-Cafe mailing list