[Haskell-cafe] GHC 7.0.3 / Win32: Data.Time library?

Yitzchak Gale gale at sefer.org
Wed Jun 15 17:18:43 CEST 2011


Dmitri O.Kondratiev wrote:
> I have:
> ds1 = "10/11/2009 7:04:28 PM"
> ds2 = "10/17/2009 8:48:29 AM"
> t1 = readTime defaultTimeLocale "%m/%d/%Y %l:%M:%S %p" ds1 :: UTCTime
> t2 = readTime defaultTimeLocale "%m/%d/%Y %l:%M:%S %p" ds2 :: UTCTime
> dif = diffUTCTime t2 t1
>
> I need to:
> 1) Find how many complete days elapsed between t1 and t2

It depends what you mean by "complete days". If you just mean
how many periods of 24 hours of UTC, without caring about things
like local clock changes for summer time, then it's just this:

floor $ dif / (24 * 60 * 60)

Otherwise, see below.

> 2) Find UTCTime for a moment 6 days after t1,  in other words time equal to
> t1 + 6 * 24 hours.

addUTCTime (6 * 24 * 60 * 60) t1

> Questions:
> 1) Is there any library function that will convert (diff = diffUTCTime t2
> t1) to a data structure similar to a tuple (days, hours, mins, secs) where
> 'days' is a whole number of days in my 'diff'' interval, and similar for
> 'hours', 'mins' and 'secs' in the tuple above?

If what you mean is amounts of UTC time, then just use the
diffs as floating point numbers. Divide and floor, as above.
You don't need any special functions.

As you can see, things are easy as long as you stay in UTC.
Often that is a little sloppy, but if it is good enough for
your program, use it.

> 2) What is the 'right way' of adding days to UTCTime? Should I add just
> equivalent number of seconds or should I convert UTCTime to
> Data.Time.Calendar.Day type first and then use 'addDays' function?

If what you need is "days", "hours", etc. as concepts of local time,
and you care about things not going wrong in the unusual case of a
change of clock, then yes, you need to convert to local time and do
your calculations there.

> 3) How to convert UTCTime to Data.Time.Calendar.Day and back
> to UTCTime?

If you stay in UTC, it's easy: a UTCTime is made up
of a Day and a DiffTime.

Suppose you need "days" in a certain time zone,
not UTC. If you already know for each of your input
times whether it is standard time or summer time
in that time zone, then here is an outline of how:

1. Create a TimeZone for each of standard time
and summer time.

2. Use utcToLocalTime with the appropriate
TimeZone to convert each input UTCTime to a
LocalTime.

3. Use diffDays. If all you care about is days,
compare the TimeOfDay with < or > to see if
you need to adjust the number of days by one.
Or work with the hours, minutes, and seconds
of the TimeOfDay directly.

If you don't already know whether your input times
are in summer time, then you need the timezone-olson
and timezone-series packages. Here is an outline:

1. Get the Olson time zone file provided by your
operating system for the time zone in question.
On Linux and Mac OS X, it's in /usr/share/zoneinfo.

On Windows it's in a binary format in the registry,
Unfortunately, we don't have a parser for that format
yet, so your best bet for now is to get the Olson files
you need from a non-Windows computer.

2. Use a function in the timezone-olson package to
read the Olson file and get a TimeZoneSeries.

3. Use utcToLocalTime' from the timezone-series
package to get a LocalTime for each of your input
times. Then continue as in #3 above.

Actually, we started out with parsing a time string,
and we have been assuming all along that it
represented UTC. As always, that is the easy case.
You're also OK if the time string has an explicit
offset from UTC, like "-0400" for EDT in the U.S.

Otherwise, you'll have to parse those strings as
LocalTime, not UTCTime. If the LocalTime is
what you need, great. If not, use a TimeZone or
TimeZoneSeries, as above, to get back to UTCTime.

Hope this helps,
Yitz



More information about the Haskell-Cafe mailing list