@@ -42,7 +42,7 @@ module Database.PostgreSQL.Simple.FromField
4242#include "MachDeps.h"
4343
4444import Control.Applicative
45− ( Applicative, (<|>), (<$>), (<*>), (<*), pure )
45+ ( Applicative, (<|>), (<$>), pure )
4646import Control.Exception (SomeException(..), Exception)
4747import Data.Attoparsec.Char8 hiding (Result)
4848import Data.Bits ((.&.), (.|.), shiftL)
@@ -51,10 +51,8 @@ import qualified Data.ByteString.Char8 as B
5151import Data.Int (Int16, Int32, Int64)
5252import Data.List (foldl')
5353import Data.Ratio (Ratio)
54−import Data.Time.Calendar (Day, fromGregorian)
55−import Data.Time.Clock (UTCTime)
56−import Data.Time.Format (parseTime)
57−import Data.Time.LocalTime (ZonedTime, TimeOfDay, makeTimeOfDayValid)
54+import Data.Time ( UTCTime, ZonedTime, LocalTime, Day, TimeOfDay
55+ , localTimeToUTC, utc )
5856import Data.Typeable (Typeable, typeOf)
5957import Data.Word (Word64)
6058import Database.PostgreSQL.Simple.Internal
@@ -64,7 +62,6 @@ import Database.PostgreSQL.Simple.Types (Binary(..), Null(..))
6462import Database.PostgreSQL.Simple.Time
6563import qualified Database.PostgreSQL.LibPQ as PQ
6664import System.IO.Unsafe (unsafePerformIO)
67−import System.Locale (defaultTimeLocale)
6865import qualified Data.ByteString as SB
6966import qualified Data.ByteString.Char8 as B8
7067import qualified Data.ByteString.Lazy as LB
@@ -197,50 +194,28 @@ instance FromField [Char] where
197194 fromField f dat = ST.unpack <$> fromField f dat
198195
199196instance FromField UTCTime where
200− fromField f =
201− case oid2builtin (typeOid f) of
202− Just Timestamp -> doIt "%F %T%Q" id
203− Just TimestampWithTimeZone -> doIt "%F %T%Q%z" (++ "00")
204− _ -> const $ returnError Incompatible f "types incompatible"
205− where
206− doIt _ _ Nothing = returnError UnexpectedNull f ""
207− doIt fmt preprocess (Just bs) =
208− case parseTime defaultTimeLocale fmt str of
209− Just t -> pure t
210− Nothing -> returnError ConversionFailed f "could not parse"
211− where str = preprocess (B8.unpack bs)
197+ fromField f =
198+ case oid2builtin (typeOid f) of
199+ Just TimestampWithTimeZone -> doIt id parseUTCTime
200+ Just Timestamp -> doIt (localTimeToUTC utc) parseLocalTime -- deprecated
201+ _ -> const $ returnError Incompatible f ""
202+ where
203+ doIt _finish _parse Nothing
204+ = returnError UnexpectedNull f ""
205+ doIt finish parse (Just bs)
206+ = either (returnError ConversionFailed f) (pure . finish) (parse bs)
212207
213208instance FromField ZonedTime where
214− fromField f =
215− case oid2builtin (typeOid f) of
216− Just TimestampWithTimeZone -> doIt "%F %T%Q%z" (++ "00")
217− _ -> const $ returnError Incompatible f "types incompatible"
218− where
219− doIt _ _ Nothing = returnError UnexpectedNull f ""
220− doIt fmt preprocess (Just bs) =
221− case parseTime defaultTimeLocale fmt str of
222− Just t -> pure t
223− Nothing -> returnError ConversionFailed f "could not parse"
224− where str = preprocess (B8.unpack bs)
209+ fromField = ff TimestampWithTimeZone "ZonedTime" parseZonedTime
210+
211+instance FromField LocalTime where
212+ fromField = ff Timestamp "LocalTime" parseLocalTime
225213
226214instance FromField Day where
227− fromField f = atto ok date f
228− where ok = mkCompats [Date]
229− date = fromGregorian <$> (decimal <* char '-')
230− <*> (decimal <* char '-')
231− <*> decimal
215+ fromField = ff Date "Day" parseDay
232216
233217instance FromField TimeOfDay where
234− fromField f = atto' ok time f
235− where ok = mkCompats [Time]
236− time = do
237− hours <- decimal <* char ':'
238− mins <- decimal <* char ':'
239− secs <- decimal :: Parser Int
240− case makeTimeOfDayValid hours mins (fromIntegral secs) of
241− Just t -> return (pure t)
242− _ -> return (returnError ConversionFailed f "could not parse")
243−
218+ fromField = ff Time "TimeOfDay" parseTimeOfDay
244219
245220instance FromField UTCTimestamp where
246221 fromField = ff TimestampWithTimeZone "UTCTimestamp" parseUTCTimestamp
@@ -326,14 +301,3 @@ atto types p0 f dat = doFromField f types (go p0) dat
326301 case parseOnly p s of
327302 Left err -> returnError ConversionFailed f err
328303 Right v -> pure v
329−
330−atto' :: forall a. (Typeable a)
331− => Compat -> Parser (Ok a) -> Field -> Maybe ByteString
332− -> Ok a
333−atto' types p0 f dat = doFromField f types (go p0) dat
334− where
335− go :: Parser (Ok a) -> ByteString -> Ok a
336− go p s =
337− case parseOnly p s of
338− Left err -> returnError ConversionFailed f err
339− Right v -> v