[Haskell-cafe] Time zones and IO
Recently I've been working on an iCalendar parser implementation with support for recurrence rules. For the recurrence logic, I've been relying on Chris Heller's excellent time-recurrence package. Unfortunately, it seems we have both encountered great difficulty in cleanly handling time zones. For example, as seen in the case of the CalendarTime LocalTime instance[1], Chris does the following, instance CalendarTimeConvertible LocalTime where toCalendarTime (LocalTime day t) = CalendarTime (fromEnum $ todSec t) (todMin t) (todHour t) d (toEnum m) y weekDay yearDay tz where (y, m, d, weekDay, yearDay) = dayInfo day tz = unsafePerformIO getCurrentTimeZone Ouch. Unfortunately, I have been entirely unable to come up with any better way to deal with timezones in a referentially transparent way. Passing the current timezone as an argument seems heavy-handed and reveals the leakiness of the CalendarTimeConvertible abstraction. Short of making toCalendarTime an action, can anyone see a suitable way of refactoring CalendarTimeConvertible to avoid unsafe IO? Perhaps a TimeZoneInfo monad is in order, exposing lookup of arbitrary (through timezone-olson) as well the current timezone? It seems like this would be inconvenient and overkill, however. Ideas? - Ben [1] https://github.com/hellertime/time-recurrence/blob/master/src/Data/Time/CalendarTime/CalendarTime.hs#L92 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Time zones and IO
Ben Gamari wrote: > Recently I've been working on an iCalendar parser implementation with > support for recurrence rules. > For the recurrence logic, I've been > relying on Chris Heller's excellent time-recurrence > package. > Unfortunately, it seems we have both encountered great > difficulty in cleanly handling time zones... > tz = unsafePerformIO getCurrentTimeZone > Ouch... > Passing the current timezone as an argument seems heavy-handed and > reveals the leakiness of the CalendarTimeConvertible abstraction. > Short of making toCalendarTime an action, can anyone see a > suitable way of refactoring CalendarTimeConvertible to avoid > unsafe IO? Well, timezone info definitely is something from the outside world, and it even changes over time (very slowly). So it's IO. Yet just about all of what your library does is pure. So passing timezone info as a parameter to pure functions is the most straightforward approach. You would pass the timezone as a parameter to all pure functions that need it. If the need for the tz parameter is ubiquitous, it might then be worth it to use a pure reader monad of some kind. As a convenience, you might provide one or more functions that do the timezone lookup, do the pure calculation, and return the result in IO. All of that does require refactoring CalendarTimeConvertible though, yes. I think the use of unsafePerformIO is a pretty sure sign that the design of CalendarTimeConvertible could use some improvement. > Perhaps a TimeZoneInfo monad is in order, exposing lookup of arbitrary > (through timezone-olson) as well the current timezone? It seems like > this would be inconvenient and overkill, however. I agree. This whole calculation is pure, really. It would be a shame to force the entire thing into an impure monad just because of timezones. Regards, Yitz ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Time zones and IO
Glad to hear you have found use for my library, always nice to see something you produce find purpose other than your own. I rationalized the use of unsafePerformIO in the library by deciding that it was only being used in the case of a LocalTime instance (a user could always stick to UTCTime and avoid the issues) and that unless the machine running the program using time-recurrence was traveling across timezones (and the system was updating that fact) the program would essentially be referentially transparent :) That said, I'm curious to hear what opinions those with more Haskell knowledge than myself have so add to this question. -Chris On Nov 6, 2011, at 2:42 PM, Ben Gamari wrote: > Recently I've been working on an iCalendar parser implementation with > support for recurrence rules. For the recurrence logic, I've been > relying on Chris Heller's excellent time-recurrence > package. Unfortunately, it seems we have both encountered great > difficulty in cleanly handling time zones. For example, as seen in the > case of the CalendarTime LocalTime instance[1], Chris does the following, > > instance CalendarTimeConvertible LocalTime where > toCalendarTime (LocalTime day t) = CalendarTime (fromEnum $ todSec t) > (todMin t) (todHour t) d (toEnum m) y weekDay yearDay tz > where > (y, m, d, weekDay, yearDay) = dayInfo day > tz = unsafePerformIO getCurrentTimeZone > > Ouch. Unfortunately, I have been entirely unable to come up with any > better way to deal with timezones in a referentially transparent > way. Passing the current timezone as an argument seems heavy-handed and > reveals the leakiness of the CalendarTimeConvertible abstraction. Short > of making toCalendarTime an action, can anyone see a suitable way of > refactoring CalendarTimeConvertible to avoid unsafe IO? > > Perhaps a TimeZoneInfo monad is in order, exposing lookup of arbitrary > (through timezone-olson) as well the current timezone? It seems like > this would be inconvenient and overkill, however. > > Ideas? > > - Ben > > > [1] > https://github.com/hellertime/time-recurrence/blob/master/src/Data/Time/CalendarTime/CalendarTime.hs#L92 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Time zones and IO
On Sun, Nov 6, 2011 at 17:25, Heller Time wrote: > I rationalized the use of unsafePerformIO in the library by deciding that > it was only being used in the case of a LocalTime instance (a user could > always stick to UTCTime and avoid the issues) and that unless the machine > running the program using time-recurrence was traveling across timezones > (and the system was updating that fact) the program would essentially be > referentially transparent :) > There's also late-night hackers doing stuff when DST changes (as it did in the US last night and Europe a week ago). -- brandon s allbery allber...@gmail.com wandering unix systems administrator (available) (412) 475-9364 vm/sms ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Time zones and IO
An all to real point that I had overlooked inadvertently. I think adding a timezone parameter would be a fine change to the API. I'll look at it this evening, I've been meaning t Chris Heller SAS - Advanced Analytics Teragram Research & Development phone: 1-617-576-6800 x54237 mobile: 1-617-460-3643 email: hel...@teragram.com On Nov 6, 2011, at 5:28 PM, Brandon Allbery wrote: > On Sun, Nov 6, 2011 at 17:25, Heller Time wrote: > I rationalized the use of unsafePerformIO in the library by deciding that it > was only being used in the case of a LocalTime instance (a user could always > stick to UTCTime and avoid the issues) and that unless the machine running > the program using time-recurrence was traveling across timezones (and the > system was updating that fact) the program would essentially be referentially > transparent :) > > There's also late-night hackers doing stuff when DST changes (as it did in > the US last night and Europe a week ago). > > -- > brandon s allbery allber...@gmail.com > wandering unix systems administrator (available) (412) 475-9364 vm/sms > ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Time zones and IO
On Sun, 2011-11-06 at 17:25 -0500, Heller Time wrote: > unless the machine running the program using time-recurrence was traveling > across timezones (and the system was updating that fact) Note that this is *not* an unusual situation at all these days. DST was already mentioned, but also note that more and more software is running on mobile devices that do frequently update their time zone information. Unpredictably breaking code when this occurs is going to get a lot worse when people starting building Haskell for their Android and iOS phones, as we're very very close to seeing happen. -- Chris ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Time zones and IO
Last night I modified the CalendarTimeConvertible type class. I added a function toCalendarTimeWithTimeZone, which adds a time-zone parameter, and eliminates the need for the unsafePerformIO in the LocalTime derivation. However this morning I realized that this was not the right approach. The problem is that LocalTime is under-defined, and the correct solution is to in fact not derive CalendarTimeConvertible for the LocalTime type. Instead one should think of a CalendarTime as meaningless without a time-zone, and therefore you cannot derive from CalendarTimeConvertible without one. This means users should stick to either the UTCTime derivation of CalendarTimeConvertible, or the ZonedTime derivation (which is in fact a LocalTime plus a TimeZone as desired). -Chris On Mon, Nov 7, 2011 at 2:56 AM, Chris Smith wrote: > On Sun, 2011-11-06 at 17:25 -0500, Heller Time wrote: >> unless the machine running the program using time-recurrence was traveling >> across timezones (and the system was updating that fact) > > Note that this is *not* an unusual situation at all these days. DST was > already mentioned, but also note that more and more software is running > on mobile devices that do frequently update their time zone information. > Unpredictably breaking code when this occurs is going to get a lot worse > when people starting building Haskell for their Android and iOS phones, > as we're very very close to seeing happen. > > -- > Chris > > ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe