module System.Win32.Time where
import System.Win32.Types ( DWORD, WORD, LONG, BOOL, failIf, failIf_, HANDLE
, peekTStringLen, LCID, LPTSTR, LPCTSTR, DDWORD
, LARGE_INTEGER, ddwordToDwords, dwordsToDdword )
import Control.Monad ( when, liftM3, liftM )
import Data.Word ( Word8 )
import Foreign ( Storable(sizeOf, alignment, peekByteOff, peek,
pokeByteOff, poke)
, Ptr, nullPtr, castPtr, plusPtr, advancePtr
, with, alloca, allocaBytes, copyArray )
import Foreign.C ( CInt(..), CWchar(..)
, peekCWString, withCWStringLen, withCWString )
#include "windows_cconv.h"
newtype FILETIME = FILETIME DDWORD deriving (Show, Eq, Ord)
data SYSTEMTIME = SYSTEMTIME {
wYear, wMonth, wDayOfWeek, wDay, wHour, wMinute, wSecond, wMilliseconds :: WORD }
deriving (Show, Eq, Ord)
data TIME_ZONE_INFORMATION = TIME_ZONE_INFORMATION
{ tziBias :: LONG
, tziStandardName :: String
, tziStandardDate :: SYSTEMTIME
, tziStandardBias :: LONG
, tziDaylightName :: String
, tziDaylightDate :: SYSTEMTIME
, tziDaylightBias :: LONG
} deriving (Show,Eq,Ord)
data TimeZoneId = TzIdUnknown | TzIdStandard | TzIdDaylight
deriving (Show, Eq, Ord)
instance Storable FILETIME where
sizeOf = const ((8))
alignment = sizeOf
poke buf (FILETIME n) = do
((\hsc_ptr -> pokeByteOff hsc_ptr 0)) buf low
((\hsc_ptr -> pokeByteOff hsc_ptr 4)) buf hi
where (hi,low) = ddwordToDwords n
peek buf = do
low <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) buf
hi <- ((\hsc_ptr -> peekByteOff hsc_ptr 4)) buf
return $ FILETIME $ dwordsToDdword (hi,low)
instance Storable SYSTEMTIME where
sizeOf _ = (16)
alignment = sizeOf
poke buf st = do
((\hsc_ptr -> pokeByteOff hsc_ptr 0)) buf (wYear st)
((\hsc_ptr -> pokeByteOff hsc_ptr 2)) buf (wMonth st)
((\hsc_ptr -> pokeByteOff hsc_ptr 4)) buf (wDayOfWeek st)
((\hsc_ptr -> pokeByteOff hsc_ptr 6)) buf (wDay st)
((\hsc_ptr -> pokeByteOff hsc_ptr 8)) buf (wHour st)
((\hsc_ptr -> pokeByteOff hsc_ptr 10)) buf (wMinute st)
((\hsc_ptr -> pokeByteOff hsc_ptr 12)) buf (wSecond st)
((\hsc_ptr -> pokeByteOff hsc_ptr 14)) buf (wMilliseconds st)
peek buf = do
year <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) buf
month <- ((\hsc_ptr -> peekByteOff hsc_ptr 2)) buf
dow <- ((\hsc_ptr -> peekByteOff hsc_ptr 4)) buf
day <- ((\hsc_ptr -> peekByteOff hsc_ptr 6)) buf
hour <- ((\hsc_ptr -> peekByteOff hsc_ptr 8)) buf
min <- ((\hsc_ptr -> peekByteOff hsc_ptr 10)) buf
sec <- ((\hsc_ptr -> peekByteOff hsc_ptr 12)) buf
ms <- ((\hsc_ptr -> peekByteOff hsc_ptr 14)) buf
return $ SYSTEMTIME year month dow day hour min sec ms
instance Storable TIME_ZONE_INFORMATION where
sizeOf _ = ((172))
alignment = sizeOf
poke buf tzi = do
((\hsc_ptr -> pokeByteOff hsc_ptr 0)) buf (tziBias tzi)
((\hsc_ptr -> pokeByteOff hsc_ptr 68)) buf (tziStandardDate tzi)
((\hsc_ptr -> pokeByteOff hsc_ptr 84)) buf (tziStandardBias tzi)
((\hsc_ptr -> pokeByteOff hsc_ptr 152)) buf (tziDaylightDate tzi)
((\hsc_ptr -> pokeByteOff hsc_ptr 168)) buf (tziDaylightBias tzi)
write buf ((4)) (tziStandardName tzi)
write buf ((88)) (tziDaylightName tzi)
where
write buf offset str = withCWStringLen str $ \(str,len) -> do
when (len>31) $ fail "Storable TIME_ZONE_INFORMATION.poke: Too long string."
let start = (advancePtr (castPtr buf) offset)
end = advancePtr start len
copyArray (castPtr str :: Ptr Word8) start len
poke end 0
peek buf = do
bias <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) buf
sdat <- ((\hsc_ptr -> peekByteOff hsc_ptr 68)) buf
sbia <- ((\hsc_ptr -> peekByteOff hsc_ptr 84)) buf
ddat <- ((\hsc_ptr -> peekByteOff hsc_ptr 152)) buf
dbia <- ((\hsc_ptr -> peekByteOff hsc_ptr 168)) buf
snam <- peekCWString (plusPtr buf ((4)))
dnam <- peekCWString (plusPtr buf ((88)))
return $ TIME_ZONE_INFORMATION bias snam sdat sbia dnam ddat dbia
foreign import WINDOWS_CCONV "windows.h GetSystemTime"
c_GetSystemTime :: Ptr SYSTEMTIME -> IO ()
getSystemTime :: IO SYSTEMTIME
getSystemTime = alloca $ \res -> do
c_GetSystemTime res
peek res
foreign import WINDOWS_CCONV "windows.h SetSystemTime"
c_SetSystemTime :: Ptr SYSTEMTIME -> IO BOOL
setSystemTime :: SYSTEMTIME -> IO ()
setSystemTime st = with st $ \st -> failIf_ not "setSystemTime: SetSystemTime" $
c_SetSystemTime st
foreign import WINDOWS_CCONV "windows.h GetSystemTimeAsFileTime"
c_GetSystemTimeAsFileTime :: Ptr FILETIME -> IO ()
getSystemTimeAsFileTime :: IO FILETIME
getSystemTimeAsFileTime = alloca $ \ret -> do
c_GetSystemTimeAsFileTime ret
peek ret
foreign import WINDOWS_CCONV "windows.h GetLocalTime"
c_GetLocalTime :: Ptr SYSTEMTIME -> IO ()
getLocalTime :: IO SYSTEMTIME
getLocalTime = alloca $ \res -> do
c_GetLocalTime res
peek res
foreign import WINDOWS_CCONV "windows.h SetLocalTime"
c_SetLocalTime :: Ptr SYSTEMTIME -> IO BOOL
setLocalTime :: SYSTEMTIME -> IO ()
setLocalTime st = with st $ \st -> failIf_ not "setLocalTime: SetLocalTime" $
c_SetLocalTime st
foreign import WINDOWS_CCONV "windows.h GetSystemTimeAdjustment"
c_GetSystemTimeAdjustment :: Ptr DWORD -> Ptr DWORD -> Ptr BOOL -> IO BOOL
getSystemTimeAdjustment :: IO (Maybe (Int, Int))
getSystemTimeAdjustment = alloca $ \ta -> alloca $ \ti -> alloca $ \enabled -> do
failIf_ not "getSystemTimeAdjustment: GetSystemTimeAdjustment" $
c_GetSystemTimeAdjustment ta ti enabled
enabled <- peek enabled
if enabled
then do
ta <- peek ta
ti <- peek ti
return $ Just (fromIntegral ta, fromIntegral ti)
else return Nothing
foreign import WINDOWS_CCONV "windows.h GetTickCount" getTickCount :: IO DWORD
foreign import WINDOWS_CCONV "windows.h SetSystemTimeAdjustment"
c_SetSystemTimeAdjustment :: DWORD -> BOOL -> IO BOOL
setSystemTimeAdjustment :: Maybe Int -> IO ()
setSystemTimeAdjustment ta =
failIf_ not "setSystemTimeAjustment: SetSystemTimeAdjustment" $
c_SetSystemTimeAdjustment time disabled
where
(time,disabled) = case ta of
Nothing -> (0,True)
Just x -> (fromIntegral x,False)
foreign import WINDOWS_CCONV "windows.h GetTimeZoneInformation"
c_GetTimeZoneInformation :: Ptr TIME_ZONE_INFORMATION -> IO DWORD
getTimeZoneInformation :: IO (TimeZoneId, TIME_ZONE_INFORMATION)
getTimeZoneInformation = alloca $ \tzi -> do
tz <- failIf (==(4294967295)) "getTimeZoneInformation: GetTimeZoneInformation" $
c_GetTimeZoneInformation tzi
tzi <- peek tzi
return . flip (,) tzi $ case tz of
(0) -> TzIdUnknown
(1) -> TzIdStandard
(2) -> TzIdDaylight
_ -> TzIdUnknown
foreign import WINDOWS_CCONV "windows.h SystemTimeToFileTime"
c_SystemTimeToFileTime :: Ptr SYSTEMTIME -> Ptr FILETIME -> IO BOOL
systemTimeToFileTime :: SYSTEMTIME -> IO FILETIME
systemTimeToFileTime s = with s $ \s -> alloca $ \ret -> do
failIf_ not "systemTimeToFileTime: SystemTimeToFileTime" $
c_SystemTimeToFileTime s ret
peek ret
foreign import WINDOWS_CCONV "windows.h FileTimeToSystemTime"
c_FileTimeToSystemTime :: Ptr FILETIME -> Ptr SYSTEMTIME -> IO BOOL
fileTimeToSystemTime :: FILETIME -> IO SYSTEMTIME
fileTimeToSystemTime s = with s $ \s -> alloca $ \ret -> do
failIf_ not "fileTimeToSystemTime: FileTimeToSystemTime" $
c_FileTimeToSystemTime s ret
peek ret
foreign import WINDOWS_CCONV "windows.h GetFileTime"
c_GetFileTime :: HANDLE -> Ptr FILETIME -> Ptr FILETIME -> Ptr FILETIME -> IO BOOL
getFileTime :: HANDLE -> IO (FILETIME,FILETIME,FILETIME)
getFileTime h = alloca $ \crt -> alloca $ \acc -> alloca $ \wrt -> do
failIf_ not "getFileTime: GetFileTime" $ c_GetFileTime h crt acc wrt
liftM3 (,,) (peek crt) (peek acc) (peek wrt)
foreign import WINDOWS_CCONV "windows.h SetFileTime"
c_SetFileTime :: HANDLE -> Ptr FILETIME -> Ptr FILETIME -> Ptr FILETIME -> IO BOOL
setFileTime :: HANDLE -> FILETIME -> FILETIME -> FILETIME -> IO ()
setFileTime h crt acc wrt = with crt $ \crt -> with acc $ \acc -> with wrt $ \wrt -> do
failIf_ not "setFileTime: SetFileTime" $ c_SetFileTime h crt acc wrt
foreign import WINDOWS_CCONV "windows.h FileTimeToLocalFileTime"
c_FileTimeToLocalFileTime :: Ptr FILETIME -> Ptr FILETIME -> IO BOOL
fileTimeToLocalFileTime :: FILETIME -> IO FILETIME
fileTimeToLocalFileTime ft = with ft $ \ft -> alloca $ \res -> do
failIf_ not "fileTimeToLocalFileTime: FileTimeToLocalFileTime"
$ c_FileTimeToLocalFileTime ft res
peek res
foreign import WINDOWS_CCONV "windows.h LocalFileTimeToFileTime"
c_LocalFileTimeToFileTime :: Ptr FILETIME -> Ptr FILETIME -> IO BOOL
localFileTimeToFileTime :: FILETIME -> IO FILETIME
localFileTimeToFileTime ft = with ft $ \ft -> alloca $ \res -> do
failIf_ not "localFileTimeToFileTime: LocalFileTimeToFileTime"
$ c_LocalFileTimeToFileTime ft res
peek res
foreign import WINDOWS_CCONV "windows.h QueryPerformanceFrequency"
c_QueryPerformanceFrequency :: Ptr LARGE_INTEGER -> IO BOOL
queryPerformanceFrequency :: IO Integer
queryPerformanceFrequency = alloca $ \res -> do
failIf_ not "queryPerformanceFrequency: QueryPerformanceFrequency" $
c_QueryPerformanceFrequency res
liftM fromIntegral $ peek res
foreign import WINDOWS_CCONV "windows.h QueryPerformanceCounter"
c_QueryPerformanceCounter:: Ptr LARGE_INTEGER -> IO BOOL
queryPerformanceCounter:: IO Integer
queryPerformanceCounter= alloca $ \res -> do
failIf_ not "queryPerformanceCounter: QueryPerformanceCounter" $
c_QueryPerformanceCounter res
liftM fromIntegral $ peek res
type GetTimeFormatFlags = DWORD
lOCALE_NOUSEROVERRIDE :: GetTimeFormatFlags
lOCALE_NOUSEROVERRIDE = 2147483648
lOCALE_USE_CP_ACP :: GetTimeFormatFlags
lOCALE_USE_CP_ACP = 1073741824
tIME_NOMINUTESORSECONDS :: GetTimeFormatFlags
tIME_NOMINUTESORSECONDS = 1
tIME_NOSECONDS :: GetTimeFormatFlags
tIME_NOSECONDS = 2
tIME_NOTIMEMARKER :: GetTimeFormatFlags
tIME_NOTIMEMARKER = 4
tIME_FORCE24HOURFORMAT :: GetTimeFormatFlags
tIME_FORCE24HOURFORMAT = 8
foreign import WINDOWS_CCONV "windows.h GetTimeFormatW"
c_GetTimeFormat :: LCID -> GetTimeFormatFlags -> Ptr SYSTEMTIME -> LPCTSTR -> LPTSTR -> CInt -> IO CInt
getTimeFormat :: LCID -> GetTimeFormatFlags -> SYSTEMTIME -> String -> IO String
getTimeFormat locale flags st fmt =
with st $ \st ->
withCWString fmt $ \fmt -> do
size <- c_GetTimeFormat locale flags st fmt nullPtr 0
allocaBytes ((fromIntegral size) * (sizeOf (undefined::CWchar))) $ \out -> do
size <- failIf (==0) "getTimeFormat: GetTimeFormat" $
c_GetTimeFormat locale flags st fmt (castPtr out) size
peekTStringLen (out,fromIntegral size)