--- ToDo: should be made thread safe, because localtime uses static storage,
--- or use the localtime_r version.
-clockToCalendarTime :: (Ptr CTime -> IO (Ptr CTm)) -> Bool -> ClockTime
+toUTCTime :: ClockTime -> CalendarTime
+#ifdef __HUGS__
+toUTCTime = unsafePerformIO . toCalTime True
+#elif HAVE_GMTIME_R
+toUTCTime = unsafePerformIO . clockToCalendarTime_reentrant (throwAwayReturnPointer gmtime_r) True
+#else
+toUTCTime = unsafePerformIO . clockToCalendarTime_static gmtime True
+#endif
+
+#ifdef __HUGS__
+toCalTime :: Bool -> ClockTime -> IO CalendarTime
+toCalTime toUTC (TOD s psecs)
+ | (s > fromIntegral (maxBound :: Int)) ||
+ (s < fromIntegral (minBound :: Int))
+ = error ((if toUTC then "toUTCTime: " else "toCalendarTime: ") ++
+ "clock secs out of range")
+ | otherwise = do
+ (sec,min,hour,mday,mon,year,wday,yday,isdst,zone,off) <-
+ toCalTimePrim (if toUTC then 1 else 0) (fromIntegral s)
+ return (CalendarTime{ ctYear=1900+year
+ , ctMonth=toEnum mon
+ , ctDay=mday
+ , ctHour=hour
+ , ctMin=min
+ , ctSec=sec
+ , ctPicosec=psecs
+ , ctWDay=toEnum wday
+ , ctYDay=yday
+ , ctTZName=(if toUTC then "UTC" else zone)
+ , ctTZ=(if toUTC then 0 else off)
+ , ctIsDST=not toUTC && (isdst/=0)
+ })
+#else /* ! __HUGS__ */
+throwAwayReturnPointer :: (Ptr CTime -> Ptr CTm -> IO (Ptr CTm))
+ -> (Ptr CTime -> Ptr CTm -> IO ( ))
+throwAwayReturnPointer fun x y = fun x y >> return ()
+
+#if !HAVE_LOCALTIME_R || !HAVE_GMTIME_R
+clockToCalendarTime_static :: (Ptr CTime -> IO (Ptr CTm)) -> Bool -> ClockTime