<commit_before>{-# LANGUAGE CPP           #-}
{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE FlexibleInstances   #-}
{-# LANGUAGE GADTs               #-}
{-# LANGUAGE KindSignatures      #-}
{-# LANGUAGE LambdaCase          #-}
{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving  #-}

-- Module      : Network.AWS.Data.Time
-- Copyright   : (c) 2013-2015 <NAME> <<EMAIL>>
-- License     : This Source Code Form is subject to the terms of
--               the Mozilla Public License, v. 2.0.
--               A copy of the MPL can be found in the LICENSE file or
--               you can obtain it at http://mozilla.org/MPL/2.0/.
-- Maintainer  : <NAME> <<EMAIL>>
-- Stability   : experimental
-- Portability : non-portable (GHC extensions)

module Network.AWS.Data.Time
    ( Format (..)
    , Time   (..)
    , _Time

    , UTCTime
    , RFC822
    , ISO8601
    , BasicTime
    , AWSTime
    , POSIX

    , parseTime
    , defaultTimeLocale
    , iso8601DateFormat
    ) where

import           Control.Applicative
import           Control.Lens
import           Data.Aeson
import           Data.Attoparsec.Text        (Parser)
import qualified Data.Attoparsec.Text        as AText
import qualified Data.ByteString.Char8       as BS
import           Data.Scientific
import           Data.Tagged
import qualified Data.Text                   as Text
import           Data.Time                   (UTCTime)
import           Data.Time.Clock.POSIX
import           Data.Time.Format            (formatTime)
import           Network.AWS.Data.ByteString
import           Network.AWS.Data.JSON
import           Network.AWS.Data.Query
import           Network.AWS.Data.Text
import           Network.AWS.Data.XML

#if MIN_VERSION_time(1,5,0)
import           Data.Time.Format (defaultTimeLocale, iso8601DateFormat)
import           Data.Time.Format (ParseTime, TimeLocale, parseTimeM)

parseTime :: ParseTime a => TimeLocale -> String -> String -> Maybe a
parseTime = parseTimeM True
#else
import           Data.Time.Format (parseTime)
import           System.Locale    (defaultTimeLocale, iso8601DateFormat)
#endif

data Format
    = RFC822Format
    | ISO8601Format
    | BasicFormat
    | AWSFormat
    | POSIXFormat
      deriving (Eq, Read, Show)

data Time :: Format -> * where
    Time :: UTCTime -> Time a

deriving instance Eq   (Time a)
deriving instance Ord  (Time a)
deriving instance Read (Time a)
deriving instance Show (Time a)

_Time :: Iso' (Time a) UTCTime
_Time = iso (\(Time t) -> t) Time

convert :: Time a -> Time b
convert (Time t) = Time t

type RFC822    = Time 'RFC822Format
type ISO8601   = Time 'ISO8601Format
type BasicTime = Time 'BasicFormat
type AWSTime   = Time 'AWSFormat
type POSIX     = Time 'POSIXFormat

class TimeFormat a where
    format :: Tagged a String

instance TimeFormat RFC822    where format = Tagged "%a, %d %b %Y %H:%M:%S GMT"
instance TimeFormat ISO8601   where format = Tagged (iso8601DateFormat (Just "%X%QZ"))
instance TimeFormat BasicTime where format = Tagged "%Y%m%d"
instance TimeFormat AWSTime   where format = Tagged "%Y%m%dT%H%M%SZ"

instance FromText BasicTime where parser = parseFormattedTime
instance FromText AWSTime   where parser = parseFormattedTime

instance FromText RFC822 where
    parser = (convert :: ISO8601 -> RFC822) <$> parseFormattedTime
         <|> parseFormattedTime

instance FromText ISO8601 where
    parser = (convert :: RFC822 -> ISO8601) <$> parseFormattedTime
         <|> parseFormattedTime

instance FromText POSIX where
    parser = Time . posixSecondsToUTCTime . realToFrac
        <$> (parser :: Parser Scientific)

parseFormattedTime :: forall a. TimeFormat (Time a) => Parser (Time a)
parseFormattedTime = do
    x <- Text.unpack <$> AText.takeText
    p (parseTime defaultTimeLocale (untag f) x) x
  where
    p :: Maybe UTCTime -> String -> Parser (Time a)
    p Nothing  s = fail   ("Unable to parse " ++ untag f ++ " from " ++ s)
    p (Just x) _ = return (Time x)

    f :: Tagged (Time a) String
    f = format

instance ToText RFC822    where toText = Text.pack . renderFormattedTime
instance ToText ISO8601   where toText = Text.pack . renderFormattedTime
instance ToText BasicTime where toText = Text.pack . renderFormattedTime
instance ToText AWSTime   where toText = Text.pack . renderFormattedTime
<commit_msg>Correcting parsing of TZs and related error messages<commit_after>{-# LANGUAGE CPP           #-}
{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE FlexibleInstances   #-}
{-# LANGUAGE GADTs               #-}
{-# LANGUAGE KindSignatures      #-}
{-# LANGUAGE LambdaCase          #-}
{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving  #-}

-- Module      : Network.AWS.Data.Time
-- Copyright   : (c) 2013-2015 <NAME> <<EMAIL>>
-- License     : This Source Code Form is subject to the terms of
--               the Mozilla Public License, v. 2.0.
--               A copy of the MPL can be found in the LICENSE file or
--               you can obtain it at http://mozilla.org/MPL/2.0/.
-- Maintainer  : <NAME> <<EMAIL>>
-- Stability   : experimental
-- Portability : non-portable (GHC extensions)

module Network.AWS.Data.Time
    ( Format (..)
    , Time   (..)
    , _Time

    , UTCTime
    , RFC822
    , ISO8601
    , BasicTime
    , AWSTime
    , POSIX

    , parseTime
    , defaultTimeLocale
    , iso8601DateFormat
    ) where

import           Control.Applicative
import           Control.Lens
import           Data.Aeson
import           Data.Attoparsec.Text        (Parser)
import qualified Data.Attoparsec.Text        as AText
import qualified Data.ByteString.Char8       as BS
import           Data.Scientific
import           Data.Tagged
import qualified Data.Text                   as Text
import           Data.Time                   (UTCTime)
import           Data.Time.Clock.POSIX
import           Data.Time.Format            (formatTime)
import           Network.AWS.Data.ByteString
import           Network.AWS.Data.JSON
import           Network.AWS.Data.Query
import           Network.AWS.Data.Text
import           Network.AWS.Data.XML

#if MIN_VERSION_time(1,5,0)
import           Data.Time.Format (defaultTimeLocale, iso8601DateFormat)
import           Data.Time.Format (ParseTime, TimeLocale, parseTimeM)

parseTime :: ParseTime a => TimeLocale -> String -> String -> Maybe a
parseTime = parseTimeM True
#else
import           Data.Time.Format (parseTime)
import           System.Locale    (defaultTimeLocale, iso8601DateFormat)
#endif

data Format
    = RFC822Format
    | ISO8601Format
    | BasicFormat
    | AWSFormat
    | POSIXFormat
      deriving (Eq, Read, Show)

data Time :: Format -> * where
    Time :: UTCTime -> Time a

deriving instance Eq   (Time a)
deriving instance Ord  (Time a)
deriving instance Read (Time a)
deriving instance Show (Time a)

_Time :: Iso' (Time a) UTCTime
_Time = iso (\(Time t) -> t) Time

convert :: Time a -> Time b
convert (Time t) = Time t

type RFC822    = Time 'RFC822Format
type ISO8601   = Time 'ISO8601Format
type BasicTime = Time 'BasicFormat
type AWSTime   = Time 'AWSFormat
type POSIX     = Time 'POSIXFormat

class TimeFormat a where
    format :: Tagged a String

instance TimeFormat RFC822    where format = Tagged "%a, %d %b %Y %H:%M:%S GMT"
instance TimeFormat ISO8601   where format = Tagged (iso8601DateFormat (Just "%X%Q%Z"))
instance TimeFormat BasicTime where format = Tagged "%Y%m%d"
instance TimeFormat AWSTime   where format = Tagged "%Y%m%dT%H%M%S%Z"

instance FromText BasicTime where parser = parseFormattedTime
instance FromText AWSTime   where parser = parseFormattedTime

instance FromText RFC822 where
    parser = (convert :: ISO8601 -> RFC822) <$> parseFormattedTime
         <|> parseFormattedTime

instance FromText ISO8601 where
    parser = (convert :: RFC822 -> ISO8601) <$> parseFormattedTime
         <|> parseFormattedTime

instance FromText POSIX where
    parser = Time . posixSecondsToUTCTime . realToFrac
        <$> (parser :: Parser Scientific)

parseFormattedTime :: forall a. TimeFormat (Time a) => Parser (Time a)
parseFormattedTime = do
    x <- Text.unpack <$> AText.takeText
    p (parseTime defaultTimeLocale (untag f) x) x
  where
    p :: Maybe UTCTime -> String -> Parser (Time a)
    p (Just x) _ = return (Time x)
    p Nothing  s = fail $ mconcat
        [ "Failure parsing Date format "
        , untag f
        , " from value: '"
        , s
        , "'"
        ]

    f :: Tagged (Time a) String
    f = format

instance ToText RFC822    where toText = Text.pack . renderFormattedTime
instance ToText ISO8601   where toText = Text.pack . renderFormattedTime
instance ToText BasicTime where toText = Text.pack . renderFormattedTime
instance ToText AWSTime   where toText = Text.pack . renderFormattedTime

{'fraction_non_alphanumeric': 0.0942889137737962, 'fraction_numerical': 0.02127659574468085, 'mean_word_length': 2.5216876971608833, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '798707', 'n_tokens_mistral': 2933, 'n_tokens_neox': 2752, 'n_words': 834}