haskell / time

A time library
http://hackage.haskell.org/package/time
Other
119 stars 79 forks source link

read cannot parse show of ZonedTime #191

Closed schoettl closed 2 years ago

schoettl commented 2 years ago

I just found #28 which identifies a similar problem (which is already documented at the Read instance).

But my point now is more about the Show instance:

ghci> :m +Data.Time
ghci> tz <- getCurrentTimeZone
ghci> local <- utcToLocalTime tz <$> getCurrentTime
ghci> show tz
"CET"
ghci> show $ ZonedTime local tz
"2021-12-31 21:53:05.271081676 CET"
ghci> read $ show $ ZonedTime local tz
*** Exception: Prelude.read: no parse

If show tz wouldn't display the timezone name but the offset (at least for timezones not supported by read), then read (show zonedTime) would work in such cases, right?

My concrete problem with the current behavior is this: I use persistent and derivePersistField to store a ZonedTime to the database. Persistent uses Show and Read instances and it used to work. But since an update in the last years, my web application is broken now because it tries to restore a ZonedTime with "CEST" or "CET" timezones.

What do you think about changing the Show instance to show +0100 instead of CET?

schoettl commented 2 years ago

For reference the definition of instance Show TimeZone

Another option would be, to add a few more knownTimeZones in the defaultTimeLocale. Maybe Central European Time (CET) and the summer time version are important enough?

schoettl commented 2 years ago

I fixed my app by defining and using this function:

getCurrentTimeZoneFixed :: IO TimeZone
getCurrentTimeZoneFixed = do
  tz <- getCurrentTimeZone
  return $ tz { timeZoneName = "" }

But it would still be good if we could find a solution so that read and show are complementary.

AshleyYakeley commented 2 years ago

show @TimeZone isn't injective, that is, the output String doesn't represent all the information in the input TimeZone, so there's no way to make read @TimeZone a retraction.

AshleyYakeley commented 2 years ago

If you don't care about the time-zone name, you might consider creating a wrapper type. Then you could be sure that show and read use precisely the information you want.

schoettl commented 2 years ago

If you don't care about the time-zone name, you might consider creating a wrapper type. Then you could be sure that show and read use precisely the information you want.

Right, that would probably be the safest solution.

To help others to avoid my wrong assumption, how about adding a note to the documentation of show? Would you accept such a PR?