No instance for (Read POSIXTime)

Hi, I need to read / write epoch seconds from / to plain text files. When I try to read POSIXTime that I use in my own data type: data TimedClassRecT = TCR {timeStamp :: POSIXTime, classCosMap :: Map.Map String Float} deriving (Eq, Read, Show) I get the following error: No instance for (Read POSIXTime) arising from the 'deriving' clause of a data type declaration Possible fix: add an instance declaration for (Read POSIXTime) or use a standalone 'deriving instance' declaration, so you can specify the instance context yourself When deriving the instance for (Read TimedClassRecT) What should I do to provide Read instance for POSIXTime? I would rather not implement it myself. Thanks!

dokondr wrote:
When I try to read POSIXTime... No instance for (Read POSIXTime)... What should I do to provide Read instance for POSIXTime?
Short answer: if you are thinking about this as a moment in time that could be parsed from the usual kind of string representation for that, you probably want to use UTCTime in your data type, not POSIXTime. If you really, really want to represent it internally as POSIXTime, then you should read those strings as UTCTime and then convert them to POSIXTime to store in your data type. I.e., in that case don't make your data type an instance of Read. POSIXTime is just a type alias for NominalDiffTime, i.e., a quantity of time between two moments. This is what the Show instance looks like: Prelude Data.Time> realToFrac 1000000 :: NominalDiffTime 1000000s By convention, the Read instance would expect a string in that format. Generally people aren't interested in that, so there is no Read instance. Even if you did want to parse that, you would just parse it as a number and then use realToFrac, as I did above. The rule of thumb is: always represent moments in time as a UTCTime. Regards, Yitz

Yitz, thanks for the detailed answer!
May be I should have formulated my question differently. All I actually
need is some way to get *seconds* since epoch from the system, so I could
manipulate them as integers.
Correct me if I am wrong, but UTCTime does not help here.
The only way I found to get seconds form epoch using existing today GHC
libraries is that:
utcStr = "Wed, 07 Dec 2011 10:10:05 +0000"
posixSecondsIntg = read posixSecondsStr :: Integer
posixSecondsStr = init $ show (cvtUTCtoSec utcStr) -- throw away 's' from
posix seconds string, s\
uch as "1235657s"
cvtUTCtoSec utcTimeStr = utcTimeToPOSIXSeconds utcTime where
utcTime = fromJust $ tryParseTime utcTimeStr
timeFormat1 = "%a, %d %b %Y %T %z"
timeFormat2 = "%m/%e/%Y %l:%M:%S %p"
tryParseTime :: String -> Maybe UTCTime
tryParseTime timeStr = tryFormat (parseTime defaultTimeLocale timeFormat1
timeStr :: Maybe UTCTime)
where
tryFormat time
| time == Nothing = parseTime defaultTimeLocale timeFormat2 timeStr
:: Maybe UTCTime
| otherwise = time
Not a very easy way, isn't it?
On Sun, Dec 11, 2011 at 9:22 PM, Yitzchak Gale
dokondr wrote:
When I try to read POSIXTime... No instance for (Read POSIXTime)... What should I do to provide Read instance for POSIXTime?
Short answer: if you are thinking about this as a moment in time that could be parsed from the usual kind of string representation for that, you probably want to use UTCTime in your data type, not POSIXTime.
If you really, really want to represent it internally as POSIXTime, then you should read those strings as UTCTime and then convert them to POSIXTime to store in your data type. I.e., in that case don't make your data type an instance of Read.
POSIXTime is just a type alias for NominalDiffTime, i.e., a quantity of time between two moments.
This is what the Show instance looks like:
Prelude Data.Time> realToFrac 1000000 :: NominalDiffTime 1000000s
By convention, the Read instance would expect a string in that format. Generally people aren't interested in that, so there is no Read instance. Even if you did want to parse that, you would just parse it as a number and then use realToFrac, as I did above.
The rule of thumb is: always represent moments in time as a UTCTime.
Regards, Yitz

dokondr wrote:
All I actually need is some way to get *seconds* since epoch from the system, so I could manipulate them as integers.
Well, you already have that - that's exactly what POSIXTime is. It is a numerical type, an instance of the RealFrac class. So perhaps you can do all of your calculations within that type itself, without converting it to anything else. If you really do need to convert it, *please* don't do that by going all the way to String and back! Just cast it or convert like you would any other numerical type. To make it a Fractional, like Float, Double, or Rational, use realToFrac. Since POSIX allows time to be specified with granularity much finer than seconds, the POSIXTime type is not an instance of Integral. (Even on operating systems where POSIX does happen to be counted in whole seconds.) So to get to an Integral type, you'll need to use some kind of rounding function, like round, floor, or ceiling. Regards, Yitz
participants (2)
-
dokondr
-
Yitzchak Gale