-----------------------------------------------------------------------------
-- |
-- Module      :  Data.HodaTime.CalendarDate
-- 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
--
-- This is the module for 'CalendarDateTime'.  A 'CalendarDateTime' represents a date and time within the calendar system that is part of its type.  It has no reference to a particular time zone and is therefor not
-- a globally unique value as June 3rd 2020 10:05pm occurred at different 'Instant's around the world.
--
-- === Construction
--
-- To construct one of these types you will need a 'CalendarDate' and a 'LocalTime'
----------------------------------------------------------------------------
module Data.HodaTime.CalendarDateTime
(
  -- * Types
   CalendarDateTime
  ,IsCalendar
  ,HasDate
  ,DoW
  ,MoY
  ,day
  ,month
  ,year
  ,dayOfWeek
  ,next
  ,previous
  ,yearMonthDay
  -- * Constructors
  ,on
  ,at
  ,atStartOfDay
  -- * Conversion
  ,withCalendar
)
where

import Data.HodaTime.CalendarDateTime.Internal
import Data.HodaTime.LocalTime.Internal (midnight)

-- | Returns a 'CalendarDateTime' at 'LocalTime' on the given 'CalendarDate'
on :: LocalTime -> CalendarDate cal -> CalendarDateTime cal
on :: forall cal. LocalTime -> CalendarDate cal -> CalendarDateTime cal
on = (CalendarDate cal -> LocalTime -> CalendarDateTime cal)
-> LocalTime -> CalendarDate cal -> CalendarDateTime cal
forall a b c. (a -> b -> c) -> b -> a -> c
flip CalendarDate cal -> LocalTime -> CalendarDateTime cal
forall calendar.
Date calendar -> LocalTime -> CalendarDateTime calendar
CalendarDateTime

-- | Returns the first valid time in the day specified by 'CalendarDate' within the given 'TimeZone'
atStartOfDay :: CalendarDate cal -> CalendarDateTime cal
atStartOfDay :: forall cal. CalendarDate cal -> CalendarDateTime cal
atStartOfDay =  (CalendarDate cal -> LocalTime -> CalendarDateTime cal)
-> LocalTime -> CalendarDate cal -> CalendarDateTime cal
forall a b c. (a -> b -> c) -> b -> a -> c
flip CalendarDate cal -> LocalTime -> CalendarDateTime cal
forall calendar.
Date calendar -> LocalTime -> CalendarDateTime calendar
at LocalTime
midnight

-- | Re-express a 'CalendarDateTime' in a different calendar, preserving the same instant on the absolute timeline
--   (including the time of day).  The target calendar is chosen by the result type (via @TypeApplications@ or a type
--   annotation).
withCalendar :: (IsCalendarDateTime a, IsCalendarDateTime b) => CalendarDateTime a -> CalendarDateTime b
withCalendar :: forall a b.
(IsCalendarDateTime a, IsCalendarDateTime b) =>
CalendarDateTime a -> CalendarDateTime b
withCalendar = Instant -> CalendarDateTime b
forall cal.
IsCalendarDateTime cal =>
Instant -> CalendarDateTime cal
fromAdjustedInstant (Instant -> CalendarDateTime b)
-> (CalendarDateTime a -> Instant)
-> CalendarDateTime a
-> CalendarDateTime b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CalendarDateTime a -> Instant
forall cal.
IsCalendarDateTime cal =>
CalendarDateTime cal -> Instant
toUnadjustedInstant