-----------------------------------------------------------------------------
-- |
-- Module      :  Data.HodaTime.Pattern.Instant
-- Copyright   :  (C) 2017 Jason Johnson
-- License     :  BSD-style (see the file LICENSE)
-- Maintainer  :  Jason Johnson <jason.johnson.081@gmail.com>
-- Stability   :  experimental
-- Portability :  POSIX, Windows
--
-- Patterns for an 'Data.HodaTime.Instant.Instant', rendered as ISO-8601 UTC (@yyyy-MM-ddTHH:mm:ssZ@); @pInstantNano@
-- additionally carries the fractional second down to the nanosecond.
----------------------------------------------------------------------------
{-# LANGUAGE FlexibleContexts #-}
module Data.HodaTime.Pattern.Instant
(
  -- * Standard Patterns
   pInstant
  ,pInstantNano
  -- * Custom Patterns
  --
  -- | Build an 'Instant' pattern from any Gregorian 'CalendarDateTime' pattern, treating the instant as UTC.
  ,instantPattern
)
where

import Data.HodaTime.Pattern.Internal (Pattern, dimapP, (<%), char)
import Data.HodaTime.Pattern.CalendarDateTime (ps, po)
import Data.HodaTime.Instant.Internal (Instant)
import Data.HodaTime.CalendarDateTime.Internal (CalendarDateTime, IsCalendarDateTime(..))
import Data.HodaTime.Calendar.Gregorian (Gregorian)

-- | Adapt a Gregorian 'CalendarDateTime' pattern into an 'Instant' pattern.  The instant is treated as UTC: it is
--   projected to its unadjusted Gregorian 'CalendarDateTime' for formatting, and the parsed 'CalendarDateTime' is
--   taken back to an 'Instant' without any offset.
instantPattern
  :: Pattern (CalendarDateTime Gregorian -> CalendarDateTime Gregorian) (CalendarDateTime Gregorian -> String) String
  -> Pattern (Instant -> Instant) (Instant -> String) String
instantPattern :: Pattern
  (CalendarDateTime Gregorian -> CalendarDateTime Gregorian)
  (CalendarDateTime Gregorian -> String)
  String
-> Pattern (Instant -> Instant) (Instant -> String) String
instantPattern = (Instant -> CalendarDateTime Gregorian)
-> (CalendarDateTime Gregorian -> Instant)
-> Pattern
     (CalendarDateTime Gregorian -> CalendarDateTime Gregorian)
     (CalendarDateTime Gregorian -> String)
     String
-> Pattern (Instant -> Instant) (Instant -> String) String
forall t s.
(t -> s)
-> (s -> t)
-> Pattern (s -> s) (s -> String) String
-> Pattern (t -> t) (t -> String) String
dimapP Instant -> CalendarDateTime Gregorian
forall cal.
IsCalendarDateTime cal =>
Instant -> CalendarDateTime cal
fromAdjustedInstant CalendarDateTime Gregorian -> Instant
forall cal.
IsCalendarDateTime cal =>
CalendarDateTime cal -> Instant
toUnadjustedInstant

-- | The ISO-8601 UTC instant pattern, @yyyy-MM-ddTHH:mm:ssZ@ (the trailing @Z@ marks it as UTC).
pInstant :: Pattern (Instant -> Instant) (Instant -> String) String
pInstant :: Pattern (Instant -> Instant) (Instant -> String) String
pInstant = Pattern
  (CalendarDateTime Gregorian -> CalendarDateTime Gregorian)
  (CalendarDateTime Gregorian -> String)
  String
-> Pattern (Instant -> Instant) (Instant -> String) String
instantPattern (Pattern
  (CalendarDateTime Gregorian -> CalendarDateTime Gregorian)
  (CalendarDateTime Gregorian -> String)
  String
forall dt.
(HasLocalTime dt, HasDate dt, Enum (MoY dt)) =>
Pattern (dt -> dt) (dt -> String) String
ps Pattern
  (CalendarDateTime Gregorian -> CalendarDateTime Gregorian)
  (CalendarDateTime Gregorian -> String)
  String
-> Pattern Char String String
-> Pattern
     (CalendarDateTime Gregorian -> CalendarDateTime Gregorian)
     (CalendarDateTime Gregorian -> String)
     String
forall a b r c. Pattern a b r -> Pattern c r r -> Pattern a b r
<% Char -> Pattern Char String String
char Char
'Z')

-- | Like 'pInstant' but carried down to the nanosecond, @yyyy-MM-ddTHH:mm:ss.fffffffffZ@.
pInstantNano :: Pattern (Instant -> Instant) (Instant -> String) String
pInstantNano :: Pattern (Instant -> Instant) (Instant -> String) String
pInstantNano = Pattern
  (CalendarDateTime Gregorian -> CalendarDateTime Gregorian)
  (CalendarDateTime Gregorian -> String)
  String
-> Pattern (Instant -> Instant) (Instant -> String) String
instantPattern (Pattern
  (CalendarDateTime Gregorian -> CalendarDateTime Gregorian)
  (CalendarDateTime Gregorian -> String)
  String
forall dt.
(HasLocalTime dt, HasDate dt, Enum (MoY dt)) =>
Pattern (dt -> dt) (dt -> String) String
po Pattern
  (CalendarDateTime Gregorian -> CalendarDateTime Gregorian)
  (CalendarDateTime Gregorian -> String)
  String
-> Pattern Char String String
-> Pattern
     (CalendarDateTime Gregorian -> CalendarDateTime Gregorian)
     (CalendarDateTime Gregorian -> String)
     String
forall a b r c. Pattern a b r -> Pattern c r r -> Pattern a b r
<% Char -> Pattern Char String String
char Char
'Z')