[project @ 2001-01-14 15:36:04 by simonmar]
[ghc-hetmet.git] / ghc / lib / std / Time.hsc
index 80d5a61..dc7077d 100644 (file)
@@ -1,5 +1,5 @@
 -- -----------------------------------------------------------------------------
--- $Id: Time.hsc,v 1.1 2001/01/12 16:16:36 simonmar Exp $
+-- $Id: Time.hsc,v 1.5 2001/01/14 15:36:04 simonmar Exp $
 --
 -- (c) The University of Glasgow, 1995-2001
 --
@@ -228,11 +228,19 @@ noTimeDiff = TimeDiff 0 0 0 0 0 0 0
 -- -----------------------------------------------------------------------------
 -- getClockTime returns the current time in its internal representation.
 
-#if defined(_WIN32) && !defined(cygwin32_TARGET_OS)
-  -- 
+#if HAVE_GETTIMEOFDAY
+getClockTime = do
+  allocaBytes (#const sizeof(struct timeval)) $ \ p_timeval -> do
+    throwErrnoIfMinus1_ "getClockTime" $ gettimeofday p_timeval nullPtr
+    sec  <- (#peek struct timeval,tv_sec)  p_timeval :: IO CLong
+    usec <- (#peek struct timeval,tv_usec) p_timeval :: IO CLong
+    return (TOD (fromIntegral sec) ((fromIntegral usec) * 1000))
+#elif HAVE_FTIME && !defined(cygwin32_TARGET_OS)
+  --
   -- ftime() as implemented by cygwin (in B20.1) is
   -- not right, so stay away & use time() there instead.
-  -- 
+  --
 getClockTime = do
   allocaBytes (#const sizeof(struct timeb)) $ \ p_timeb -> do
   ftime p_timeb
@@ -240,14 +248,6 @@ getClockTime = do
   msec <- (#peek struct timeb,millitime) p_timeb :: IO CUShort
   return (TOD (fromIntegral sec) (fromIntegral msec * 1000{-ToDo: correct???-}))
 
-#elif defined(HAVE_GETTIMEOFDAY)
-getClockTime = do
-  allocaBytes (#const sizeof(struct timeval)) $ \ p_timeval -> do
-    throwErrnoIfMinus1_ "getClockTime" $ gettimeofday p_timeval nullPtr
-    sec  <- (#peek struct timeval,tv_sec)  p_timeval :: IO CLong
-    usec <- (#peek struct timeval,tv_usec) p_timeval :: IO CLong
-    return (TOD (fromIntegral sec) ((fromIntegral usec) * 1000))
 #else /* use POSIX time() */
 getClockTime = do
     secs <- time nullPtr -- can't fail, according to POSIX
@@ -327,11 +327,11 @@ normalizeTimeDiff td =
         }
 
 -- -----------------------------------------------------------------------------
--- toCalendarTime t converts t to a local time, modified by
--- the current timezone and daylight savings time settings.  toUTCTime
--- t converts t into UTC time.  toClockTime l converts l into the 
--- corresponding internal ClockTime.  The wday, yday, tzname, and isdst fields
--- are ignored.
+-- How do we deal with timezones on this architecture?
+
+-- The POSIX way to do it is through the global variable tzname[].
+-- But that's crap, so we do it The BSD Way if we can: namely use the
+-- tm_zone and tm_gmtoff fields of struct tm, if they're available.
 
 #if HAVE_TM_ZONE
 zone x      = (#peek struct tm,tm_zone) x   :: IO (Ptr CChar)
@@ -343,44 +343,57 @@ gmtoff x    = (#peek struct tm,tm_gmtoff) x :: IO CLong
 #   define tzname _tzname
 #  endif
 #  ifndef mingw32_TARGET_OS
-extern char *tzname[2];
+foreign label tzname :: Ptr (Ptr CChar)
 #  endif
-#  define ZONE(x)       (((struct tm *)x)->tm_isdst ? tzname[1] : tzname[0])
+zone x = do 
+  dst <- (#peek struct tm,tm_isdst) x
+  if dst then peekArray tzname 1 else peekArray tzname 0
 # else /* ! HAVE_TZNAME */
-/* We're in trouble. If you should end up here, please report this as a bug. */
+-- We're in trouble. If you should end up here, please report this as a bug.
 #  error Dont know how to get at timezone name on your OS.
 # endif /* ! HAVE_TZNAME */
-/* Get the offset in secs from UTC, if (struct tm) doesn't supply it. */
 
+-- Get the offset in secs from UTC, if (struct tm) doesn't supply it. */
 #if defined(mingw32_TARGET_OS) || defined(cygwin32_TARGET_OS)
 #define timezone _timezone
 #endif
 
-#if !defined(HAVE_TIMEZONE) && !defined(mingw32_TARGET_OS)
-extern TYPE_TIMEZONE timezone;
-#endif
-
 # if HAVE_ALTZONE
-extern time_t altzone;
+foreign label altzone  :: Ptr CTime
+foreign label timezone :: Ptr CTime
+gmtoff x = do 
+  dst <- (#peek struct tm,tm_isdst) x
+  tz <- if dst then peek altzone else peek timezone
+  return (fromIntegral tz)
 #  define GMTOFF(x)     (((struct tm *)x)->tm_isdst ? altzone : timezone )
 # else /* ! HAVE_ALTZONE */
-/* Assume that DST offset is 1 hour ... */
-#  define GMTOFF(x) (((struct tm *)x)->tm_isdst ? (timezone - 3600) : timezone )
+-- Assume that DST offset is 1 hour ...
+gmtoff x = do 
+  dst <- (#peek struct tm,tm_isdst) x
+  tz  <- peek timezone
+  if dst then return (fromIngtegral tz - 3600) else return tz
 # endif /* ! HAVE_ALTZONE */
 #endif  /* ! HAVE_TM_ZONE */
 
+-- -----------------------------------------------------------------------------
+-- toCalendarTime t converts t to a local time, modified by
+-- the current timezone and daylight savings time settings.  toUTCTime
+-- t converts t into UTC time.  toClockTime l converts l into the 
+-- corresponding internal ClockTime.  The wday, yday, tzname, and isdst fields
+-- are ignored.
+
 
 toCalendarTime :: ClockTime -> IO CalendarTime
-toCalendarTime =  clockToCalendarTime localtime
+toCalendarTime =  clockToCalendarTime localtime False
 
 toUTCTime      :: ClockTime -> CalendarTime
-toUTCTime      =  unsafePerformIO . clockToCalendarTime gmtime
+toUTCTime      =  unsafePerformIO . clockToCalendarTime gmtime True
 
 -- ToDo: should be made thread safe, because localtime uses static storage,
 -- or use the localtime_r version.
-clockToCalendarTime :: (Ptr CTime -> IO (Ptr CTm)) -> ClockTime
+clockToCalendarTime :: (Ptr CTime -> IO (Ptr CTm)) -> Bool -> ClockTime
         -> IO CalendarTime
-clockToCalendarTime fun (TOD secs psec) = do
+clockToCalendarTime fun is_utc (TOD secs psec) = do
   withObject (fromIntegral secs :: CTime)  $ \ p_timer -> do
     p_tm <- fun p_timer        -- can't fail, according to POSIX
     sec   <-  (#peek struct tm,tm_sec  ) p_tm :: IO CInt
@@ -410,9 +423,9 @@ clockToCalendarTime fun (TOD secs psec) = do
                psec
                (toEnum (fromIntegral wday))
                (fromIntegral yday)
-               tzname 
-               (fromIntegral tz)
-               (isdst /= 0))
+               (if is_utc then "UTC" else tzname)
+               (if is_utc then 0     else fromIntegral tz)
+               (if is_utc then False else isdst /= 0))
 
 
 toClockTime :: CalendarTime -> ClockTime
@@ -455,7 +468,7 @@ toClockTime (CalendarTime year mon mday hour min sec psec
         -- result.
         -- 
         gmtoff <- gmtoff p_tm
-       let res = fromIntegral t + tz + fromIntegral gmtoff
+       let res = fromIntegral t + tz - fromIntegral gmtoff
        return (TOD (fromIntegral res) 0)
 
 -- -----------------------------------------------------------------------------
@@ -603,12 +616,12 @@ foreign import unsafe strftime  :: Ptr CChar -> CSize -> Addr## -> Ptr CTm -> IO
 foreign import unsafe mktime    :: Ptr CTm   -> IO CTime
 foreign import unsafe time      :: Ptr CTime -> IO CTime
 
-#ifdef HAVE_GETTIMEOFDAY
+#if HAVE_GETTIMEOFDAY
 type CTimeVal = ()
 foreign import unsafe gettimeofday :: Ptr CTimeVal -> Ptr () -> IO CInt
 #endif
 
-#if defined(_WIN32) && !defined(cygwin32_TARGET_OS)
-type CTimeB
+#if HAVE_FTIME
+type CTimeB = ()
 foreign import unsafe ftime :: Ptr CTimeB -> IO CInt
 #endif