That’s not a terribly difficult question to get an answer for with Google. However, there is a much more interesting and nuanced question:
What was the time difference between Bothell, Washington and Haworth, West Yorkshire over time?
To answer this, we’ll use Haskell, of course. Specifically, we’re going to use the following:
for_, which I use for pretty much everything these days
I want to generate a list of every day in a given year along with the effective time zones in both Bothell and Haworth and the corresponding difference in hours and minutes between the times (at midnight) in these two locations.
We can make a single UTC day as follows:
That’s 1 January 2018, just in case you were wondering.
I scratched my head thinking about how to generate a sequence for a little while. At first I was planning to
fromGregorian function over various sequences of numbers. However, this requires knowledge of the number of days in each month in each year and lots of similar nastiness. How else to do this? Well, fortunately for me,
time also exposes an
addDays function. With this, we should be able to generate a list of calendar days by mapping some function of this function and our
startDay over a list of numbers:
These two formulations are equivalent, the first being the point-free style version of the latter.
pointfree.io is your friend for exploring automatic conversions of Haskell expressions into point-free form.
Update: Let’s use
It turns out that
Day has an instance for the
Enum type class which makes generating a sequence of days trivial:
lgastako for this tip.
tz package exposes functions like
diffForPOSIX which sound like they may do what we need. Unfortunately, both functions deal in terms of
Int64 values and the documentation for the package does not explain what this
Int64 is directly. So, I had to take a look at the code. After doing that, I figured out that I need the
Int64 that is the result type of the
utcTimeToInt64 function in the
This leads to the following function:
This function takes a
TZ (which is a time zone database entry for a given geographical location), a
UTCTime (which we can derive from our Gregorian
Day from above) and returns the time difference from UTC in minutes as well as the name of the time zone in effect (encoded using the
Since the hidden
utcTimeToInt64 function is critical to interoperability between
time (I think), I’ll probably file an issue against the package and submit a pull request to make this function part of the public API. If I get time, of course. That was a terrible pun.
Now, all we need to do is apply our
tzOffsetInfo function to a stream of
UTCTime instances deriving from our stream of
Day instances and print the results out. I present the full program here:
There, that was a quick introduction to time and time zones in Haskell.
Content © 2023 Richard Cook. All rights reserved.