
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@. 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:
http://www.haskell.org/haskellwiki/Package_versioning_policy
Maybe the `timezone-olson`, `timezone-series`, this `tzdata` idea and
`tz` could all live together; with `tz` depending on the others? Just
a thought :)
Regards,
Renzo Carbonara.
On Mon, Mar 31, 2014 at 3:15 PM, Mihaly Barasz
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-0.0.0.1/docs/Data-Time-Zones.html#v:ut... [5] http://hackage.haskell.org/package/timezone-series [6] http://hackage.haskell.org/package/timezone-olson
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux)
iQEVAwUBUzmwz/i5FOsZqz9DAQJGcAgAhPF4JLWnL4ApJ2qxqAwHqXcIPqRpVb5A TH2LERH2A/6b3xXCRYsPgyD43j2CzqZGffRvINSw9fGoJYWuRmis5dCf9hwPiKtg hK1wUCz9AsKlKBZztR9eLxROqM/xXMH4HaFydr/YOVffDVY6fUIK9fPbRFJBVCBq UwtoemQSVLUIIRxZyg5pdL+dxadnttm7bGC+UuQJHtSSBRweEh3unr8dcNm4idC3 nxWOMclbo2hyMdwzDo1bqugugq2xCGPiGrL550aF1lCGD2pf2vQO1feW/5XyMaCR Oj6gI+eHo8SuhUx30Dokv1kx8Ssay0aVmmASCJKnR8Bwv1J9AKWo3A== =Bp64 -----END PGP SIGNATURE-----
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe