{-# LINE 1 "Data/Text/ICU/Calendar.hsc" #-}
{-# LANGUAGE RankNTypes, BangPatterns, ForeignFunctionInterface, RecordWildCards #-}
-- |
-- Module      : Data.Text.ICU.Calendar
-- Copyright   : (c) 2021 Torsten Kemps-Benedix
--
-- License     : BSD-style
-- Maintainer  : bos@serpentine.com
-- Stability   : experimental
-- Portability : GHC
--
-- Calendar functions implemented as bindings to
-- the International Components for Unicode (ICU) libraries.

module Data.Text.ICU.Calendar
    (
      -- * Data
      Calendar(..), CalendarType(..), SystemTimeZoneType(..), CalendarField(..), UCalendar,
      -- * High-level interface
      -- ** Operations on calendars
      roll, add, set1, set, get,
      -- ** Calendar field getters
      era, year, month,
      dayOfMonth, dayOfYear, dayOfWeek, dayOfWeekInMonth, amPm,
      hour, hourOfDay, minute, second, millisecond, zoneOffset, dstOffset, yearWoY, doWLocal, extendedYear, julianDay,
      millisecondsInDay, isLeapMonth, day, utcTime,
      -- ** Calendar field setters
      setEra, setYear, setMonth,
      setDayOfMonth, setDayOfYear, setDayOfWeek, setDayOfWeekInMonth, setAmPm,
      setHour, setHourOfDay, setMinute, setSecond, setMillisecond, setZoneOffset, setDstOffset, setYearWoY, setDoWLocal, setExtendedYear, setJulianDay,
      setMillisecondsInDay, setDay,
      -- ** Lenses
      _era, _year, _month,
      _dayOfMonth, _dayOfYear, _dayOfWeek, _dayOfWeekInMonth, _amPm,
      _hour, _hourOfDay, _minute, _second, _millisecond, _zoneOffset, _dstOffset, _day,
      -- ** Time zone functions
      timeZoneIDs, timeZones,
      -- * Low-level interface
      calendar, openTimeZoneIDEnumeration, openTimeZones, getField, setField, setDate, setDateTime, rollField, addField, setTimeZone,
    ) where



import Control.Monad (forM_)
import Data.Int (Int32)
import Data.Text (Text, pack)
import Data.Text.Foreign (withCStringLen)
import Data.Text.ICU.Enumerator
import Data.Text.ICU.Error.Internal (UErrorCode, handleError)
import Data.Text.ICU.Internal (LocaleName(..), UChar, withLocaleName, newICUPtr, useAsUCharPtr)
import qualified Data.Time.Calendar as Cal
import qualified Data.Time.Clock as Clock
import Foreign.C.String (CString)
import Foreign.C.Types (CInt(..))
import Foreign.ForeignPtr (withForeignPtr, ForeignPtr)
import Foreign.Ptr (FunPtr, Ptr)
import Prelude hiding (last)
import System.IO.Unsafe (unsafePerformIO)

type UCalendar = CInt

-- A 'Calendar' is an abstract data type that contains a foreign pointer to the ICU internal data structure.
data Calendar = Calendar {Calendar -> ForeignPtr USystemTimeZoneType
calendarForeignPtr :: ForeignPtr UCalendar}

-- | All the fields that comprise a 'Calendar'.
data CalendarField =
  Era -- ^ Field indicating the era, e.g., AD or BC in the Gregorian (Julian) calendar. This is a calendar-specific value.
  | Year -- ^ Field indicating the year. This is a calendar-specific value.
  | Month -- ^ Field indicating the month. This is a calendar-specific value. The first month of the year is JANUARY; the last depends on the number of months in a year. Note: Calendar month is 0-based.
  | WeekOfYear -- ^ Field indicating the week number within the current year. The first week of the year, as defined by UCAL_FIRST_DAY_OF_WEEK and UCAL_MINIMAL_DAYS_IN_FIRST_WEEK attributes, has value 1. Subclasses define the value of UCAL_WEEK_OF_YEAR for days before the first week of the year.
  | WeekOfMonth -- ^ Field indicating the week number within the current month. The first week of the month, as defined by UCAL_FIRST_DAY_OF_WEEK and UCAL_MINIMAL_DAYS_IN_FIRST_WEEK attributes, has value 1. Subclasses define the value of WEEK_OF_MONTH for days before the first week of the month.
  | DayOfMonth -- ^ Field indicating the day of the month. This is a synonym for DAY_OF_MONTH. The first day of the month has value 1.
  | DayOfYear -- ^ Field indicating the day number within the current year. The first day of the year has value 1.
  | DayOfWeek -- ^ Field indicating the day of the week. This field takes values SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, and SATURDAY. Note: Calendar day-of-week is 1-based. Clients who create locale resources for the field of first-day-of-week should be aware of this. For instance, in US locale, first-day-of-week is set to 1, i.e., UCAL_SUNDAY.
  | DayOfWeekInMonth -- ^ Field indicating the ordinal number of the day of the week within the current month. Together with the DAY_OF_WEEK field, this uniquely specifies a day within a month. Unlike WEEK_OF_MONTH and WEEK_OF_YEAR, this field's value does not depend on getFirstDayOfWeek() or getMinimalDaysInFirstWeek(). DAY_OF_MONTH 1 through 7 always correspond to DAY_OF_WEEK_IN_MONTH 1; 8 through 15 correspond to DAY_OF_WEEK_IN_MONTH 2, and so on. DAY_OF_WEEK_IN_MONTH 0 indicates the week before DAY_OF_WEEK_IN_MONTH 1. Negative values count back from the end of the month, so the last Sunday of a month is specified as DAY_OF_WEEK = SUNDAY, DAY_OF_WEEK_IN_MONTH = -1. Because negative values count backward they will usually be aligned differently within the month than positive values. For example, if a month has 31 days, DAY_OF_WEEK_IN_MONTH -1 will overlap DAY_OF_WEEK_IN_MONTH 5 and the end of 4.
  | AmPm -- ^ Field indicating whether the HOUR is before or after noon. E.g., at 10:04:15.250 PM the AM_PM is PM.
  | Hour -- ^ Field indicating the hour of the morning or afternoon. HOUR is used for the 12-hour clock. E.g., at 10:04:15.250 PM the HOUR is 10.
  | HourOfDay -- ^ Field indicating the hour of the day. HOUR_OF_DAY is used for the 24-hour clock. E.g., at 10:04:15.250 PM the HOUR_OF_DAY is 22.
  | Minute -- ^ Field indicating the minute within the hour. E.g., at 10:04:15.250 PM the UCAL_MINUTE is 4.
  | Second -- ^ Field indicating the second within the minute. E.g., at 10:04:15.250 PM the UCAL_SECOND is 15.
  | Millisecond -- ^ Field indicating the millisecond within the second. E.g., at 10:04:15.250 PM the UCAL_MILLISECOND is 250.
  | ZoneOffset -- ^ Field indicating the raw offset from GMT in milliseconds.
  | DstOffset -- ^ Field indicating the daylight savings offset in milliseconds.
  | YearWoY -- ^ Field indicating the extended year corresponding to the UCAL_WEEK_OF_YEAR field. This may be one greater or less than the value of UCAL_EXTENDED_YEAR.
  | DoWLocal -- ^ Field indicating the localized day of week. This will be a value from 1 to 7 inclusive, with 1 being the localized first day of the week.
  | ExtendedYear -- ^ Year of this calendar system, encompassing all supra-year fields. For example, in Gregorian/Julian calendars, positive Extended Year values indicate years AD, 1 BC = 0 extended, 2 BC = -1 extended, and so on.
  | JulianDay -- ^ Field indicating the modified Julian day number. This is different from the conventional Julian day number in two regards. First, it demarcates days at local zone midnight, rather than noon GMT. Second, it is a local number; that is, it depends on the local time zone. It can be thought of as a single number that encompasses all the date-related fields.
  | MillisecondsInDay -- ^ Ranges from 0 to 23:59:59.999 (regardless of DST). This field behaves exactly like a composite of all time-related fields, not including the zone fields. As such, it also reflects discontinuities of those fields on DST transition days. On a day of DST onset, it will jump forward. On a day of DST cessation, it will jump backward. This reflects the fact that it must be combined with the DST_OFFSET field to obtain a unique local time value.
  | IsLeapMonth -- ^ Whether or not the current month is a leap month (0 or 1). See the Chinese calendar for an example of this.
  deriving (Int -> CalendarField -> ShowS
[CalendarField] -> ShowS
CalendarField -> String
(Int -> CalendarField -> ShowS)
-> (CalendarField -> String)
-> ([CalendarField] -> ShowS)
-> Show CalendarField
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CalendarField] -> ShowS
$cshowList :: [CalendarField] -> ShowS
show :: CalendarField -> String
$cshow :: CalendarField -> String
showsPrec :: Int -> CalendarField -> ShowS
$cshowsPrec :: Int -> CalendarField -> ShowS
Show, ReadPrec [CalendarField]
ReadPrec CalendarField
Int -> ReadS CalendarField
ReadS [CalendarField]
(Int -> ReadS CalendarField)
-> ReadS [CalendarField]
-> ReadPrec CalendarField
-> ReadPrec [CalendarField]
-> Read CalendarField
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [CalendarField]
$creadListPrec :: ReadPrec [CalendarField]
readPrec :: ReadPrec CalendarField
$creadPrec :: ReadPrec CalendarField
readList :: ReadS [CalendarField]
$creadList :: ReadS [CalendarField]
readsPrec :: Int -> ReadS CalendarField
$creadsPrec :: Int -> ReadS CalendarField
Read, CalendarField -> CalendarField -> Bool
(CalendarField -> CalendarField -> Bool)
-> (CalendarField -> CalendarField -> Bool) -> Eq CalendarField
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CalendarField -> CalendarField -> Bool
$c/= :: CalendarField -> CalendarField -> Bool
== :: CalendarField -> CalendarField -> Bool
$c== :: CalendarField -> CalendarField -> Bool
Eq)

type UCalendarDateFields = CInt

toUCalendarDateFields :: CalendarField -> UCalendarDateFields
toUCalendarDateFields :: CalendarField -> USystemTimeZoneType
toUCalendarDateFields CalendarField
Era = USystemTimeZoneType
0
{-# LINE 95 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields Year = 1
{-# LINE 96 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields Month = 2
{-# LINE 97 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields WeekOfYear = 3
{-# LINE 98 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields WeekOfMonth = 4
{-# LINE 99 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields DayOfMonth = 5
{-# LINE 100 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields DayOfYear = 6
{-# LINE 101 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields DayOfWeek = 7
{-# LINE 102 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields DayOfWeekInMonth = 8
{-# LINE 103 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields AmPm = 9
{-# LINE 104 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields Hour = 10
{-# LINE 105 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields HourOfDay = 11
{-# LINE 106 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields Minute = 12
{-# LINE 107 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields Second = 13
{-# LINE 108 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields Millisecond = 14
{-# LINE 109 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields ZoneOffset = 15
{-# LINE 110 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields DstOffset = 16
{-# LINE 111 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields YearWoY = 17
{-# LINE 112 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields DoWLocal = 18
{-# LINE 113 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields ExtendedYear = 19
{-# LINE 114 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields JulianDay = 20
{-# LINE 115 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields MillisecondsInDay = 21
{-# LINE 116 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarDateFields IsLeapMonth = 22
{-# LINE 117 "Data/Text/ICU/Calendar.hsc" #-}

data CalendarType = TraditionalCalendarType | DefaultCalendarType | GregorianCalendarType
  deriving (Int -> CalendarType -> ShowS
[CalendarType] -> ShowS
CalendarType -> String
(Int -> CalendarType -> ShowS)
-> (CalendarType -> String)
-> ([CalendarType] -> ShowS)
-> Show CalendarType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CalendarType] -> ShowS
$cshowList :: [CalendarType] -> ShowS
show :: CalendarType -> String
$cshow :: CalendarType -> String
showsPrec :: Int -> CalendarType -> ShowS
$cshowsPrec :: Int -> CalendarType -> ShowS
Show, ReadPrec [CalendarType]
ReadPrec CalendarType
Int -> ReadS CalendarType
ReadS [CalendarType]
(Int -> ReadS CalendarType)
-> ReadS [CalendarType]
-> ReadPrec CalendarType
-> ReadPrec [CalendarType]
-> Read CalendarType
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [CalendarType]
$creadListPrec :: ReadPrec [CalendarType]
readPrec :: ReadPrec CalendarType
$creadPrec :: ReadPrec CalendarType
readList :: ReadS [CalendarType]
$creadList :: ReadS [CalendarType]
readsPrec :: Int -> ReadS CalendarType
$creadsPrec :: Int -> ReadS CalendarType
Read, CalendarType -> CalendarType -> Bool
(CalendarType -> CalendarType -> Bool)
-> (CalendarType -> CalendarType -> Bool) -> Eq CalendarType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CalendarType -> CalendarType -> Bool
$c/= :: CalendarType -> CalendarType -> Bool
== :: CalendarType -> CalendarType -> Bool
$c== :: CalendarType -> CalendarType -> Bool
Eq)

type UCalendarType = CInt

toUCalendarType :: CalendarType -> UCalendarType
toUCalendarType :: CalendarType -> USystemTimeZoneType
toUCalendarType CalendarType
TraditionalCalendarType = USystemTimeZoneType
0
{-# LINE 125 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarType DefaultCalendarType = 0
{-# LINE 126 "Data/Text/ICU/Calendar.hsc" #-}
toUCalendarType GregorianCalendarType = 1
{-# LINE 127 "Data/Text/ICU/Calendar.hsc" #-}

data SystemTimeZoneType = AnyTimeZone | CanonicalTimeZone | CanonicalLocationTimeZone
  deriving (Int -> SystemTimeZoneType -> ShowS
[SystemTimeZoneType] -> ShowS
SystemTimeZoneType -> String
(Int -> SystemTimeZoneType -> ShowS)
-> (SystemTimeZoneType -> String)
-> ([SystemTimeZoneType] -> ShowS)
-> Show SystemTimeZoneType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SystemTimeZoneType] -> ShowS
$cshowList :: [SystemTimeZoneType] -> ShowS
show :: SystemTimeZoneType -> String
$cshow :: SystemTimeZoneType -> String
showsPrec :: Int -> SystemTimeZoneType -> ShowS
$cshowsPrec :: Int -> SystemTimeZoneType -> ShowS
Show, ReadPrec [SystemTimeZoneType]
ReadPrec SystemTimeZoneType
Int -> ReadS SystemTimeZoneType
ReadS [SystemTimeZoneType]
(Int -> ReadS SystemTimeZoneType)
-> ReadS [SystemTimeZoneType]
-> ReadPrec SystemTimeZoneType
-> ReadPrec [SystemTimeZoneType]
-> Read SystemTimeZoneType
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [SystemTimeZoneType]
$creadListPrec :: ReadPrec [SystemTimeZoneType]
readPrec :: ReadPrec SystemTimeZoneType
$creadPrec :: ReadPrec SystemTimeZoneType
readList :: ReadS [SystemTimeZoneType]
$creadList :: ReadS [SystemTimeZoneType]
readsPrec :: Int -> ReadS SystemTimeZoneType
$creadsPrec :: Int -> ReadS SystemTimeZoneType
Read, SystemTimeZoneType -> SystemTimeZoneType -> Bool
(SystemTimeZoneType -> SystemTimeZoneType -> Bool)
-> (SystemTimeZoneType -> SystemTimeZoneType -> Bool)
-> Eq SystemTimeZoneType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SystemTimeZoneType -> SystemTimeZoneType -> Bool
$c/= :: SystemTimeZoneType -> SystemTimeZoneType -> Bool
== :: SystemTimeZoneType -> SystemTimeZoneType -> Bool
$c== :: SystemTimeZoneType -> SystemTimeZoneType -> Bool
Eq)

toUSystemTimeZoneType :: SystemTimeZoneType -> USystemTimeZoneType
toUSystemTimeZoneType :: SystemTimeZoneType -> USystemTimeZoneType
toUSystemTimeZoneType SystemTimeZoneType
AnyTimeZone = USystemTimeZoneType
0
{-# LINE 133 "Data/Text/ICU/Calendar.hsc" #-}
toUSystemTimeZoneType CanonicalTimeZone = 1
{-# LINE 134 "Data/Text/ICU/Calendar.hsc" #-}
toUSystemTimeZoneType CanonicalLocationTimeZone = 2
{-# LINE 135 "Data/Text/ICU/Calendar.hsc" #-}

type USystemTimeZoneType = CInt

-- | Open a Calendar.
--
-- A Calendar may be used to convert a millisecond value to a year,
-- month, and day.
--
-- Note: When unknown TimeZone ID is specified or if the TimeZone ID
-- specified is "Etc/Unknown", the Calendar returned by the function
-- is initialized with GMT zone with TimeZone ID UCAL_UNKNOWN_ZONE_ID
-- ("Etc/Unknown") without any errors/warnings. If you want to check
-- if a TimeZone ID is valid prior to this function, use
-- ucal_getCanonicalTimeZoneID.
--
-- >>> import qualified Data.Text as T
-- >>> c <- calendar (T.pack "CET") (Locale "de_DE") TraditionalCalendarType
-- >>> show c
-- 2021-10-12 17:37:43
calendar :: Text -> LocaleName -> CalendarType -> IO Calendar
calendar :: Text -> LocaleName -> CalendarType -> IO Calendar
calendar Text
zoneId LocaleName
loc CalendarType
typ =
  LocaleName -> (CString -> IO Calendar) -> IO Calendar
forall a. LocaleName -> (CString -> IO a) -> IO a
withLocaleName LocaleName
loc ((CString -> IO Calendar) -> IO Calendar)
-> (CString -> IO Calendar) -> IO Calendar
forall a b. (a -> b) -> a -> b
$ \CString
locale ->
    Text -> (Ptr UChar -> I16 -> IO Calendar) -> IO Calendar
forall a. Text -> (Ptr UChar -> I16 -> IO a) -> IO a
useAsUCharPtr Text
zoneId ((Ptr UChar -> I16 -> IO Calendar) -> IO Calendar)
-> (Ptr UChar -> I16 -> IO Calendar) -> IO Calendar
forall a b. (a -> b) -> a -> b
$ \Ptr UChar
zoneIdPtr I16
zoneIdLen ->
      (ForeignPtr USystemTimeZoneType -> Calendar)
-> FinalizerPtr USystemTimeZoneType
-> IO (Ptr USystemTimeZoneType)
-> IO Calendar
forall a i.
(ForeignPtr a -> i) -> FinalizerPtr a -> IO (Ptr a) -> IO i
newICUPtr ForeignPtr USystemTimeZoneType -> Calendar
Calendar FinalizerPtr USystemTimeZoneType
ucal_close (IO (Ptr USystemTimeZoneType) -> IO Calendar)
-> IO (Ptr USystemTimeZoneType) -> IO Calendar
forall a b. (a -> b) -> a -> b
$
        (Ptr USystemTimeZoneType -> IO (Ptr USystemTimeZoneType))
-> IO (Ptr USystemTimeZoneType)
forall a. (Ptr USystemTimeZoneType -> IO a) -> IO a
handleError ((Ptr USystemTimeZoneType -> IO (Ptr USystemTimeZoneType))
 -> IO (Ptr USystemTimeZoneType))
-> (Ptr USystemTimeZoneType -> IO (Ptr USystemTimeZoneType))
-> IO (Ptr USystemTimeZoneType)
forall a b. (a -> b) -> a -> b
$ Ptr UChar
-> Int32
-> CString
-> USystemTimeZoneType
-> Ptr USystemTimeZoneType
-> IO (Ptr USystemTimeZoneType)
ucal_open Ptr UChar
zoneIdPtr (I16 -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral I16
zoneIdLen) CString
locale (CalendarType -> USystemTimeZoneType
toUCalendarType CalendarType
typ)

setTimeZone :: Calendar -> Text -> IO ()
setTimeZone :: Calendar -> Text -> IO ()
setTimeZone Calendar
cal Text
zoneId =
  ForeignPtr USystemTimeZoneType
-> (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr (Calendar -> ForeignPtr USystemTimeZoneType
calendarForeignPtr Calendar
cal) ((Ptr USystemTimeZoneType -> IO ()) -> IO ())
-> (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr USystemTimeZoneType
calPtr -> do
    Text -> (CStringLen -> IO ()) -> IO ()
forall a. Text -> (CStringLen -> IO a) -> IO a
withCStringLen Text
zoneId ((CStringLen -> IO ()) -> IO ()) -> (CStringLen -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \(CString
zoneIdPtr, Int
zoneIdLen) -> do
      (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a. (Ptr USystemTimeZoneType -> IO a) -> IO a
handleError ((Ptr USystemTimeZoneType -> IO ()) -> IO ())
-> (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ Ptr USystemTimeZoneType
-> CString -> Int32 -> Ptr USystemTimeZoneType -> IO ()
ucal_setTimeZone Ptr USystemTimeZoneType
calPtr CString
zoneIdPtr (Int -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
zoneIdLen)

clone :: Calendar -> IO Calendar
clone :: Calendar -> IO Calendar
clone Calendar
cal =
  ForeignPtr USystemTimeZoneType
-> (Ptr USystemTimeZoneType -> IO Calendar) -> IO Calendar
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr (Calendar -> ForeignPtr USystemTimeZoneType
calendarForeignPtr Calendar
cal) ((Ptr USystemTimeZoneType -> IO Calendar) -> IO Calendar)
-> (Ptr USystemTimeZoneType -> IO Calendar) -> IO Calendar
forall a b. (a -> b) -> a -> b
$ \Ptr USystemTimeZoneType
calPtr -> do
    (ForeignPtr USystemTimeZoneType -> Calendar)
-> FinalizerPtr USystemTimeZoneType
-> IO (Ptr USystemTimeZoneType)
-> IO Calendar
forall a i.
(ForeignPtr a -> i) -> FinalizerPtr a -> IO (Ptr a) -> IO i
newICUPtr ForeignPtr USystemTimeZoneType -> Calendar
Calendar FinalizerPtr USystemTimeZoneType
ucal_close (IO (Ptr USystemTimeZoneType) -> IO Calendar)
-> IO (Ptr USystemTimeZoneType) -> IO Calendar
forall a b. (a -> b) -> a -> b
$ (Ptr USystemTimeZoneType -> IO (Ptr USystemTimeZoneType))
-> IO (Ptr USystemTimeZoneType)
forall a. (Ptr USystemTimeZoneType -> IO a) -> IO a
handleError ((Ptr USystemTimeZoneType -> IO (Ptr USystemTimeZoneType))
 -> IO (Ptr USystemTimeZoneType))
-> (Ptr USystemTimeZoneType -> IO (Ptr USystemTimeZoneType))
-> IO (Ptr USystemTimeZoneType)
forall a b. (a -> b) -> a -> b
$ Ptr USystemTimeZoneType
-> Ptr USystemTimeZoneType -> IO (Ptr USystemTimeZoneType)
ucal_clone Ptr USystemTimeZoneType
calPtr

-- | List of all time zones.
timeZones :: IO [Text]
timeZones :: IO [Text]
timeZones = do
  Enumerator
tzEnum <- IO Enumerator
openTimeZones
  [Text]
tzs <- Enumerator -> IO [Text]
toList Enumerator
tzEnum
  [Text] -> IO [Text]
forall (f :: * -> *) a. Applicative f => a -> f a
pure [Text]
tzs

timeZoneIDs :: SystemTimeZoneType -> IO [Text]
timeZoneIDs :: SystemTimeZoneType -> IO [Text]
timeZoneIDs SystemTimeZoneType
typ = do
  Enumerator
tzEnum <- SystemTimeZoneType -> IO Enumerator
openTimeZoneIDEnumeration SystemTimeZoneType
typ
  [Text]
tzs <- Enumerator -> IO [Text]
toList Enumerator
tzEnum
  [Text] -> IO [Text]
forall (f :: * -> *) a. Applicative f => a -> f a
pure [Text]
tzs

openTimeZoneIDEnumeration :: SystemTimeZoneType -> IO Enumerator
openTimeZoneIDEnumeration :: SystemTimeZoneType -> IO Enumerator
openTimeZoneIDEnumeration SystemTimeZoneType
typ = IO (Ptr UEnumerator) -> IO Enumerator
createEnumerator (IO (Ptr UEnumerator) -> IO Enumerator)
-> IO (Ptr UEnumerator) -> IO Enumerator
forall a b. (a -> b) -> a -> b
$
  (Ptr USystemTimeZoneType -> IO (Ptr UEnumerator))
-> IO (Ptr UEnumerator)
forall a. (Ptr USystemTimeZoneType -> IO a) -> IO a
handleError ((Ptr USystemTimeZoneType -> IO (Ptr UEnumerator))
 -> IO (Ptr UEnumerator))
-> (Ptr USystemTimeZoneType -> IO (Ptr UEnumerator))
-> IO (Ptr UEnumerator)
forall a b. (a -> b) -> a -> b
$ USystemTimeZoneType
-> Ptr USystemTimeZoneType -> IO (Ptr UEnumerator)
ucal_openTimeZoneIDEnumeration (SystemTimeZoneType -> USystemTimeZoneType
toUSystemTimeZoneType SystemTimeZoneType
typ)

-- | Create an enumeration over all time zones.
openTimeZones :: IO Enumerator
openTimeZones :: IO Enumerator
openTimeZones = IO (Ptr UEnumerator) -> IO Enumerator
createEnumerator (IO (Ptr UEnumerator) -> IO Enumerator)
-> IO (Ptr UEnumerator) -> IO Enumerator
forall a b. (a -> b) -> a -> b
$ (Ptr USystemTimeZoneType -> IO (Ptr UEnumerator))
-> IO (Ptr UEnumerator)
forall a. (Ptr USystemTimeZoneType -> IO a) -> IO a
handleError ((Ptr USystemTimeZoneType -> IO (Ptr UEnumerator))
 -> IO (Ptr UEnumerator))
-> (Ptr USystemTimeZoneType -> IO (Ptr UEnumerator))
-> IO (Ptr UEnumerator)
forall a b. (a -> b) -> a -> b
$ Ptr USystemTimeZoneType -> IO (Ptr UEnumerator)
ucal_openTimeZones

-- | Get the value of a specific calendar field.
--
-- >>> import qualified Data.Text as T
-- >>> c <- calendar (T.pack "CET") (Locale "de_DE") TraditionalCalendarType
-- >>> getField c Year
-- 2021
getField :: Calendar -> CalendarField -> IO Int
getField :: Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
fld = ForeignPtr USystemTimeZoneType
-> (Ptr USystemTimeZoneType -> IO Int) -> IO Int
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr (Calendar -> ForeignPtr USystemTimeZoneType
calendarForeignPtr Calendar
cal) ((Ptr USystemTimeZoneType -> IO Int) -> IO Int)
-> (Ptr USystemTimeZoneType -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$ \Ptr USystemTimeZoneType
calPtr -> do
  Int32
n <- (Ptr USystemTimeZoneType -> IO Int32) -> IO Int32
forall a. (Ptr USystemTimeZoneType -> IO a) -> IO a
handleError ((Ptr USystemTimeZoneType -> IO Int32) -> IO Int32)
-> (Ptr USystemTimeZoneType -> IO Int32) -> IO Int32
forall a b. (a -> b) -> a -> b
$ Ptr USystemTimeZoneType
-> USystemTimeZoneType -> Ptr USystemTimeZoneType -> IO Int32
ucal_get Ptr USystemTimeZoneType
calPtr (CalendarField -> USystemTimeZoneType
toUCalendarDateFields CalendarField
fld)
  Int -> IO Int
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
n)

setField :: Calendar -> CalendarField -> Int -> IO ()
setField :: Calendar -> CalendarField -> Int -> IO ()
setField Calendar
cal CalendarField
fld Int
n = ForeignPtr USystemTimeZoneType
-> (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr (Calendar -> ForeignPtr USystemTimeZoneType
calendarForeignPtr Calendar
cal) ((Ptr USystemTimeZoneType -> IO ()) -> IO ())
-> (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr USystemTimeZoneType
calPtr ->
  Ptr USystemTimeZoneType -> USystemTimeZoneType -> Int32 -> IO ()
ucal_set Ptr USystemTimeZoneType
calPtr (CalendarField -> USystemTimeZoneType
toUCalendarDateFields CalendarField
fld) (Int -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n)

setDate :: Calendar -> Int -> Int -> Int -> IO ()
setDate :: Calendar -> Int -> Int -> Int -> IO ()
setDate Calendar
cal Int
y Int
m Int
d = ForeignPtr USystemTimeZoneType
-> (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr (Calendar -> ForeignPtr USystemTimeZoneType
calendarForeignPtr Calendar
cal) ((Ptr USystemTimeZoneType -> IO ()) -> IO ())
-> (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr USystemTimeZoneType
calPtr ->
  (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a. (Ptr USystemTimeZoneType -> IO a) -> IO a
handleError ((Ptr USystemTimeZoneType -> IO ()) -> IO ())
-> (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ Ptr USystemTimeZoneType
-> Int32 -> Int32 -> Int32 -> Ptr USystemTimeZoneType -> IO ()
ucal_setDate Ptr USystemTimeZoneType
calPtr (Int -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
y) (Int -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
m) (Int -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
d)

setDateTime :: Calendar -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()
setDateTime :: Calendar -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()
setDateTime Calendar
cal Int
y Int
m Int
d Int
hr Int
mn Int
sec = ForeignPtr USystemTimeZoneType
-> (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr (Calendar -> ForeignPtr USystemTimeZoneType
calendarForeignPtr Calendar
cal) ((Ptr USystemTimeZoneType -> IO ()) -> IO ())
-> (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr USystemTimeZoneType
calPtr ->
  (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a. (Ptr USystemTimeZoneType -> IO a) -> IO a
handleError ((Ptr USystemTimeZoneType -> IO ()) -> IO ())
-> (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ Ptr USystemTimeZoneType
-> Int32
-> Int32
-> Int32
-> Int32
-> Int32
-> Int32
-> Ptr USystemTimeZoneType
-> IO ()
ucal_setDateTime Ptr USystemTimeZoneType
calPtr (Int -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
y) (Int -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
m) (Int -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
d) (Int -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
hr) (Int -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
mn) (Int -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
sec)

-- | Add a specified signed amount to a particular field in a Calendar.
--
-- This will not modify more significant fields in the calendar. Rolling by a
-- positive value always means moving forward in time (unless the limit of the
-- field is reached, in which case it may pin or wrap), so for Gregorian
-- calendar, starting with 100 BC and rolling the year by +1 results in 99 BC.
-- When eras have a definite beginning and end (as in the Chinese calendar, or
-- as in most eras in the Japanese calendar) then rolling the year past either
-- limit of the era will cause the year to wrap around. When eras only have a
-- limit at one end, then attempting to roll the year past that limit will
--result in pinning the year at that limit. Note that for most calendars in
-- which era 0 years move forward in time (such as Buddhist, Hebrew, or Islamic),
-- it is possible for add or roll to result in negative years for era 0 (that
-- is the only way to represent years before the calendar epoch).
rollField :: Calendar -> CalendarField -> Int -> IO ()
rollField :: Calendar -> CalendarField -> Int -> IO ()
rollField Calendar
cal CalendarField
fld Int
n = ForeignPtr USystemTimeZoneType
-> (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr (Calendar -> ForeignPtr USystemTimeZoneType
calendarForeignPtr Calendar
cal) ((Ptr USystemTimeZoneType -> IO ()) -> IO ())
-> (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr USystemTimeZoneType
calPtr ->
  (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a. (Ptr USystemTimeZoneType -> IO a) -> IO a
handleError ((Ptr USystemTimeZoneType -> IO ()) -> IO ())
-> (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ Ptr USystemTimeZoneType
-> USystemTimeZoneType -> Int32 -> Ptr USystemTimeZoneType -> IO ()
ucal_roll Ptr USystemTimeZoneType
calPtr (CalendarField -> USystemTimeZoneType
toUCalendarDateFields CalendarField
fld) (Int -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n)

-- | Add a specified signed amount to a particular field in a Calendar.
--
-- See 'rollField' for further details.
--
-- >>> import qualified Data.Text as T
-- >>> c1 <- calendar (T.pack "CET") (Locale "de_DE") TraditionalCalendarType
-- >>> show c1
-- 2021-10-12 17:53:26
-- >>> let c2 = roll c1 [(Hour, 2)]
-- >>> show c2
-- 2021-10-12 19:53:26
-- >>> let c3 = roll c1 [(Hour, 12)]
-- >>> show c3
-- 2021-10-12 17:53:26
-- >>> let c4 = add c1 [(Hour, 12)]
-- >>> show c4
-- 2021-10-13 5:53:26
roll ::
  Calendar
  -> [(CalendarField, Int)] -- ^ The field and the signed amount to add to this field. If the amount causes the value to exceed to maximum or minimum values for that field, the field is pinned to a permissible value.
  -> Calendar
roll :: Calendar -> [(CalendarField, Int)] -> Calendar
roll Calendar
cal [(CalendarField, Int)]
lst = IO Calendar -> Calendar
forall a. IO a -> a
unsafePerformIO (IO Calendar -> Calendar) -> IO Calendar -> Calendar
forall a b. (a -> b) -> a -> b
$ do
  Calendar
cal' <- Calendar -> IO Calendar
clone Calendar
cal
  [(CalendarField, Int)] -> ((CalendarField, Int) -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(CalendarField, Int)]
lst (\(CalendarField
fld,Int
n) -> Calendar -> CalendarField -> Int -> IO ()
rollField Calendar
cal' CalendarField
fld Int
n)
  Calendar -> IO Calendar
forall (f :: * -> *) a. Applicative f => a -> f a
pure Calendar
cal'

-- | Add a specified signed amount to a particular field in a Calendar.
--
-- This can modify more significant fields in the calendar. Adding a positive
-- value always means moving forward in time, so for the Gregorian calendar,
-- starting with 100 BC and adding +1 to year results in 99 BC (even though
-- this actually reduces the numeric value of the field itself).
addField :: Calendar -> CalendarField -> Int -> IO ()
addField :: Calendar -> CalendarField -> Int -> IO ()
addField Calendar
cal CalendarField
fld Int
n = ForeignPtr USystemTimeZoneType
-> (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr (Calendar -> ForeignPtr USystemTimeZoneType
calendarForeignPtr Calendar
cal) ((Ptr USystemTimeZoneType -> IO ()) -> IO ())
-> (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr USystemTimeZoneType
calPtr ->
  (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a. (Ptr USystemTimeZoneType -> IO a) -> IO a
handleError ((Ptr USystemTimeZoneType -> IO ()) -> IO ())
-> (Ptr USystemTimeZoneType -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ Ptr USystemTimeZoneType
-> USystemTimeZoneType -> Int32 -> Ptr USystemTimeZoneType -> IO ()
ucal_add Ptr USystemTimeZoneType
calPtr (CalendarField -> USystemTimeZoneType
toUCalendarDateFields CalendarField
fld) (Int -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n)

-- | Add a specified signed amount to a particular field in a Calendar.
--
-- See 'addField' for further details and see 'rollField' for examples and differences
-- compared to rolling.
add ::
  Calendar -- ^ The 'Calendar' to which to add.
  -> [(CalendarField, Int)] -- ^ Field type and the signed amount to add to field. If the amount causes the value to exceed to maximum or minimum values for that field, other fields are modified to preserve the magnitude of the change.
  -> Calendar
add :: Calendar -> [(CalendarField, Int)] -> Calendar
add Calendar
cal [(CalendarField, Int)]
lst = IO Calendar -> Calendar
forall a. IO a -> a
unsafePerformIO (IO Calendar -> Calendar) -> IO Calendar -> Calendar
forall a b. (a -> b) -> a -> b
$ do
  Calendar
cal' <- Calendar -> IO Calendar
clone Calendar
cal
  [(CalendarField, Int)] -> ((CalendarField, Int) -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(CalendarField, Int)]
lst (\(CalendarField
fld,Int
n) -> Calendar -> CalendarField -> Int -> IO ()
addField Calendar
cal' CalendarField
fld Int
n)
  Calendar -> IO Calendar
forall (f :: * -> *) a. Applicative f => a -> f a
pure Calendar
cal'

-- | Set the value of one field of a calendar to a certain value. All fields are
-- represented as 32-bit integers.
set1 :: Calendar -> CalendarField -> Int -> Calendar
set1 :: Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
fld Int
n = IO Calendar -> Calendar
forall a. IO a -> a
unsafePerformIO (IO Calendar -> Calendar) -> IO Calendar -> Calendar
forall a b. (a -> b) -> a -> b
$ do
  Calendar
cal' <- Calendar -> IO Calendar
clone Calendar
cal
  Calendar -> CalendarField -> Int -> IO ()
setField Calendar
cal' CalendarField
fld Int
n
  Calendar -> IO Calendar
forall (f :: * -> *) a. Applicative f => a -> f a
pure Calendar
cal'

-- | Set the value of a list of fields of a calendar to certain values. All fields are
-- represented as 32-bit integers.
set :: Calendar -> [(CalendarField, Int)] -> Calendar
set :: Calendar -> [(CalendarField, Int)] -> Calendar
set Calendar
cal [(CalendarField, Int)]
lst = IO Calendar -> Calendar
forall a. IO a -> a
unsafePerformIO (IO Calendar -> Calendar) -> IO Calendar -> Calendar
forall a b. (a -> b) -> a -> b
$ do
  Calendar
cal' <- Calendar -> IO Calendar
clone Calendar
cal
  [(CalendarField, Int)] -> ((CalendarField, Int) -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(CalendarField, Int)]
lst (\(CalendarField
fld,Int
n) -> Calendar -> CalendarField -> Int -> IO ()
setField Calendar
cal' CalendarField
fld Int
n)
  Calendar -> IO Calendar
forall (f :: * -> *) a. Applicative f => a -> f a
pure Calendar
cal'

-- | Convert the day part of the calendar to a 'Day'.
--
-- >>> import qualified Data.Text as T
-- >>> c1 <- calendar (T.pack "CET") (Locale "de_DE") TraditionalCalendarType
-- >>> show c1
-- 2021-10-12 18:00:50
-- >>> day c1
-- 2021-10-12
day :: Calendar -> Cal.Day
day :: Calendar -> Day
day Calendar
cal = IO Day -> Day
forall a. IO a -> a
unsafePerformIO (IO Day -> Day) -> IO Day -> Day
forall a b. (a -> b) -> a -> b
$ do
  Int
y <- Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
Year
  Int
m <- Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
Month
  Int
d <- Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
DayOfMonth
  Day -> IO Day
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Year -> Int -> Int -> Day
Cal.fromGregorian (Int -> Year
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
y) (Int
mInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int
d)

-- | Set the day part of the calendar from a 'Day'.
setDay :: Calendar -> Cal.Day -> Calendar
setDay :: Calendar -> Day -> Calendar
setDay Calendar
cal Day
aDay = IO Calendar -> Calendar
forall a. IO a -> a
unsafePerformIO (IO Calendar -> Calendar) -> IO Calendar -> Calendar
forall a b. (a -> b) -> a -> b
$ do
  Calendar
cal' <- Calendar -> IO Calendar
clone Calendar
cal
  let (Year
y,Int
m,Int
d) = Day -> (Year, Int, Int)
Cal.toGregorian Day
aDay
  Calendar -> Int -> Int -> Int -> IO ()
setDate Calendar
cal' (Year -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Year
y) (Int
mInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) Int
d
  Calendar -> IO Calendar
forall (f :: * -> *) a. Applicative f => a -> f a
pure Calendar
cal'

-- | Convert the day and time part of the calendar to a 'UTCTime'.
--
-- >>> import qualified Data.Text as T
-- >>> c1 <- calendar (T.pack "CET") (Locale "de_DE") TraditionalCalendarType
-- >>> show c1
-- 2021-10-12 18:00:50
-- >>> utcTime c1
-- 2021-10-12 16:00:50.544999999998 UTC
utcTime :: Calendar -> Clock.UTCTime
utcTime :: Calendar -> UTCTime
utcTime Calendar
cal = IO UTCTime -> UTCTime
forall a. IO a -> a
unsafePerformIO (IO UTCTime -> UTCTime) -> IO UTCTime -> UTCTime
forall a b. (a -> b) -> a -> b
$ do
  Calendar
cal' <- Calendar -> IO Calendar
clone Calendar
cal
  Calendar -> Text -> IO ()
setTimeZone Calendar
cal' (String -> Text
pack String
"UTC")
  Int
y <- Calendar -> CalendarField -> IO Int
getField Calendar
cal' CalendarField
Year
  Int
m <- Calendar -> CalendarField -> IO Int
getField Calendar
cal' CalendarField
Month
  Int
d <- Calendar -> CalendarField -> IO Int
getField Calendar
cal' CalendarField
DayOfMonth
  let day' :: Day
day' = Year -> Int -> Int -> Day
Cal.fromGregorian (Int -> Year
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
y) (Int
mInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int
d
  Int
ms <- Calendar -> CalendarField -> IO Int
getField Calendar
cal' CalendarField
MillisecondsInDay
  let dt :: DiffTime
dt = Double -> DiffTime
forall a b. (Real a, Fractional b) => a -> b
realToFrac ((Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ms :: Double) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000)
  UTCTime -> IO UTCTime
forall (f :: * -> *) a. Applicative f => a -> f a
pure (UTCTime -> IO UTCTime) -> UTCTime -> IO UTCTime
forall a b. (a -> b) -> a -> b
$ Day -> DiffTime -> UTCTime
Clock.UTCTime Day
day' DiffTime
dt

-- | Get the value of a specific field in the calendar.
get :: Calendar -> CalendarField -> Int
get :: Calendar -> CalendarField -> Int
get Calendar
cal CalendarField
fld = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
fld

-- | Return the era of the calendar. The values are calendar specific and are usually 0 (some ancient era) and 1 (current era).
--
-- >>> import qualified Data.Text as T
-- >>> c1 <- calendar (T.pack "CET") (Locale "de_DE") TraditionalCalendarType
-- >>> era c1
-- 1
era :: Calendar -> Int
era :: Calendar -> Int
era Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
Era

setEra :: Calendar -> Int -> Calendar
setEra :: Calendar -> Int -> Calendar
setEra Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
Era

-- | Return the year of the calendar. The values are calendar specific.
--
-- >>> import qualified Data.Text as T
-- >>> c1 <- calendar (T.pack "CET") (Locale "de_DE") TraditionalCalendarType
-- >>> year c1
-- 2021
year :: Calendar -> Int
year :: Calendar -> Int
year Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
Year

setYear :: Calendar -> Int -> Calendar
setYear :: Calendar -> Int -> Calendar
setYear Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
Year

-- | Return the month of the calendar. The values are calendar specific and 0-based.
--
-- >>> import qualified Data.Text as T
-- >>> c1 <- calendar (T.pack "CET") (Locale "de_DE") TraditionalCalendarType
-- >>> month c1
-- 9
-- >>> day c1
-- 2021-10-12
month :: Calendar -> Int
month :: Calendar -> Int
month Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
Month

setMonth :: Calendar -> Int -> Calendar
setMonth :: Calendar -> Int -> Calendar
setMonth Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
Month

dayOfMonth :: Calendar -> Int
dayOfMonth :: Calendar -> Int
dayOfMonth Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
DayOfMonth

setDayOfMonth :: Calendar -> Int -> Calendar
setDayOfMonth :: Calendar -> Int -> Calendar
setDayOfMonth Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
DayOfMonth

dayOfYear :: Calendar -> Int
dayOfYear :: Calendar -> Int
dayOfYear Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
DayOfYear

setDayOfYear :: Calendar -> Int -> Calendar
setDayOfYear :: Calendar -> Int -> Calendar
setDayOfYear Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
DayOfYear

dayOfWeek :: Calendar -> Int
dayOfWeek :: Calendar -> Int
dayOfWeek Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
DayOfWeek

setDayOfWeek :: Calendar -> Int -> Calendar
setDayOfWeek :: Calendar -> Int -> Calendar
setDayOfWeek Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
DayOfWeek

dayOfWeekInMonth :: Calendar -> Int
dayOfWeekInMonth :: Calendar -> Int
dayOfWeekInMonth Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
DayOfWeekInMonth

setDayOfWeekInMonth :: Calendar -> Int -> Calendar
setDayOfWeekInMonth :: Calendar -> Int -> Calendar
setDayOfWeekInMonth Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
DayOfWeekInMonth

amPm :: Calendar -> Int
amPm :: Calendar -> Int
amPm Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
AmPm

setAmPm :: Calendar -> Int -> Calendar
setAmPm :: Calendar -> Int -> Calendar
setAmPm Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
AmPm

hour :: Calendar -> Int
hour :: Calendar -> Int
hour Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
Hour

setHour :: Calendar -> Int -> Calendar
setHour :: Calendar -> Int -> Calendar
setHour Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
Hour

hourOfDay :: Calendar -> Int
hourOfDay :: Calendar -> Int
hourOfDay Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
HourOfDay

setHourOfDay :: Calendar -> Int -> Calendar
setHourOfDay :: Calendar -> Int -> Calendar
setHourOfDay Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
HourOfDay

minute :: Calendar -> Int
minute :: Calendar -> Int
minute Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
Minute

setMinute :: Calendar -> Int -> Calendar
setMinute :: Calendar -> Int -> Calendar
setMinute Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
Minute

second :: Calendar -> Int
second :: Calendar -> Int
second Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
Second

setSecond :: Calendar -> Int -> Calendar
setSecond :: Calendar -> Int -> Calendar
setSecond Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
Second

millisecond :: Calendar -> Int
millisecond :: Calendar -> Int
millisecond Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
Millisecond

setMillisecond :: Calendar -> Int -> Calendar
setMillisecond :: Calendar -> Int -> Calendar
setMillisecond Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
Millisecond

zoneOffset :: Calendar -> Int
zoneOffset :: Calendar -> Int
zoneOffset Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
ZoneOffset

setZoneOffset :: Calendar -> Int -> Calendar
setZoneOffset :: Calendar -> Int -> Calendar
setZoneOffset Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
ZoneOffset

dstOffset :: Calendar -> Int
dstOffset :: Calendar -> Int
dstOffset Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
DstOffset

setDstOffset :: Calendar -> Int -> Calendar
setDstOffset :: Calendar -> Int -> Calendar
setDstOffset Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
DstOffset

yearWoY :: Calendar -> Int
yearWoY :: Calendar -> Int
yearWoY Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
YearWoY

setYearWoY :: Calendar -> Int -> Calendar
setYearWoY :: Calendar -> Int -> Calendar
setYearWoY Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
YearWoY

doWLocal :: Calendar -> Int
doWLocal :: Calendar -> Int
doWLocal Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
DoWLocal

setDoWLocal :: Calendar -> Int -> Calendar
setDoWLocal :: Calendar -> Int -> Calendar
setDoWLocal Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
DoWLocal

extendedYear :: Calendar -> Int
extendedYear :: Calendar -> Int
extendedYear Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
ExtendedYear

setExtendedYear :: Calendar -> Int -> Calendar
setExtendedYear :: Calendar -> Int -> Calendar
setExtendedYear Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
ExtendedYear

julianDay :: Calendar -> Int
julianDay :: Calendar -> Int
julianDay Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
JulianDay

setJulianDay :: Calendar -> Int -> Calendar
setJulianDay :: Calendar -> Int -> Calendar
setJulianDay Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
JulianDay

millisecondsInDay :: Calendar -> Int
millisecondsInDay :: Calendar -> Int
millisecondsInDay Calendar
cal = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
MillisecondsInDay

setMillisecondsInDay :: Calendar -> Int -> Calendar
setMillisecondsInDay :: Calendar -> Int -> Calendar
setMillisecondsInDay Calendar
cal = Calendar -> CalendarField -> Int -> Calendar
set1 Calendar
cal CalendarField
MillisecondsInDay

isLeapMonth :: Calendar -> Bool
isLeapMonth :: Calendar -> Bool
isLeapMonth Calendar
cal = Int
0 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= (IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ Calendar -> CalendarField -> IO Int
getField Calendar
cal CalendarField
IsLeapMonth)

-- Copied from the lens package in order not to generate a dependency.
type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t
type Lens' s a = Lens s s a a

lens :: (s -> a) -> (s -> b -> t) -> Lens s t a b
lens :: forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens s -> a
sa s -> b -> t
sbt a -> f b
afb s
s = s -> b -> t
sbt s
s (b -> t) -> f b -> f t
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> f b
afb (s -> a
sa s
s)
{-# INLINE lens #-}

_era :: Lens' Calendar Int
_era :: Lens' Calendar Int
_era = (Calendar -> Int)
-> (Calendar -> Int -> Calendar) -> Lens' Calendar Int
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Calendar -> Int
era Calendar -> Int -> Calendar
setEra

_year :: Lens' Calendar Int
_year :: Lens' Calendar Int
_year = (Calendar -> Int)
-> (Calendar -> Int -> Calendar) -> Lens' Calendar Int
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Calendar -> Int
year Calendar -> Int -> Calendar
setYear

_month :: Lens' Calendar Int
_month :: Lens' Calendar Int
_month = (Calendar -> Int)
-> (Calendar -> Int -> Calendar) -> Lens' Calendar Int
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Calendar -> Int
month Calendar -> Int -> Calendar
setMonth

_dayOfYear :: Lens' Calendar Int
_dayOfYear :: Lens' Calendar Int
_dayOfYear = (Calendar -> Int)
-> (Calendar -> Int -> Calendar) -> Lens' Calendar Int
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Calendar -> Int
dayOfYear Calendar -> Int -> Calendar
setDayOfYear

_dayOfMonth :: Lens' Calendar Int
_dayOfMonth :: Lens' Calendar Int
_dayOfMonth = (Calendar -> Int)
-> (Calendar -> Int -> Calendar) -> Lens' Calendar Int
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Calendar -> Int
dayOfMonth Calendar -> Int -> Calendar
setDayOfMonth

_dayOfWeek :: Lens' Calendar Int
_dayOfWeek :: Lens' Calendar Int
_dayOfWeek = (Calendar -> Int)
-> (Calendar -> Int -> Calendar) -> Lens' Calendar Int
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Calendar -> Int
dayOfWeek Calendar -> Int -> Calendar
setDayOfWeek

_dayOfWeekInMonth :: Lens' Calendar Int
_dayOfWeekInMonth :: Lens' Calendar Int
_dayOfWeekInMonth = (Calendar -> Int)
-> (Calendar -> Int -> Calendar) -> Lens' Calendar Int
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Calendar -> Int
dayOfWeekInMonth Calendar -> Int -> Calendar
setDayOfWeekInMonth

_amPm :: Lens' Calendar Int
_amPm :: Lens' Calendar Int
_amPm = (Calendar -> Int)
-> (Calendar -> Int -> Calendar) -> Lens' Calendar Int
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Calendar -> Int
amPm Calendar -> Int -> Calendar
setAmPm

_hour :: Lens' Calendar Int
_hour :: Lens' Calendar Int
_hour = (Calendar -> Int)
-> (Calendar -> Int -> Calendar) -> Lens' Calendar Int
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Calendar -> Int
hour Calendar -> Int -> Calendar
setHour

_hourOfDay :: Lens' Calendar Int
_hourOfDay :: Lens' Calendar Int
_hourOfDay = (Calendar -> Int)
-> (Calendar -> Int -> Calendar) -> Lens' Calendar Int
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Calendar -> Int
hour Calendar -> Int -> Calendar
setHourOfDay

_minute :: Lens' Calendar Int
_minute :: Lens' Calendar Int
_minute = (Calendar -> Int)
-> (Calendar -> Int -> Calendar) -> Lens' Calendar Int
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Calendar -> Int
minute Calendar -> Int -> Calendar
setMinute

_second :: Lens' Calendar Int
_second :: Lens' Calendar Int
_second = (Calendar -> Int)
-> (Calendar -> Int -> Calendar) -> Lens' Calendar Int
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Calendar -> Int
second Calendar -> Int -> Calendar
setSecond

_millisecond :: Lens' Calendar Int
_millisecond :: Lens' Calendar Int
_millisecond = (Calendar -> Int)
-> (Calendar -> Int -> Calendar) -> Lens' Calendar Int
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Calendar -> Int
millisecond Calendar -> Int -> Calendar
setMillisecond

_zoneOffset :: Lens' Calendar Int
_zoneOffset :: Lens' Calendar Int
_zoneOffset = (Calendar -> Int)
-> (Calendar -> Int -> Calendar) -> Lens' Calendar Int
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Calendar -> Int
zoneOffset Calendar -> Int -> Calendar
setZoneOffset

_dstOffset :: Lens' Calendar Int
_dstOffset :: Lens' Calendar Int
_dstOffset = (Calendar -> Int)
-> (Calendar -> Int -> Calendar) -> Lens' Calendar Int
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Calendar -> Int
dstOffset Calendar -> Int -> Calendar
setDstOffset

_day :: Lens' Calendar Cal.Day
_day :: Lens' Calendar Day
_day = (Calendar -> Day)
-> (Calendar -> Day -> Calendar) -> Lens' Calendar Day
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Calendar -> Day
day Calendar -> Day -> Calendar
setDay

instance Show Calendar where
  show :: Calendar -> String
show Calendar
cal = UTCTime -> String
forall a. Show a => a -> String
show (Calendar -> UTCTime
utcTime Calendar
cal)

foreign import ccall unsafe "hs_text_icu.h __hs_ucal_open" ucal_open
    :: Ptr UChar -> Int32 -> CString -> UCalendar -> Ptr UErrorCode
    -> IO (Ptr UCalendar)
foreign import ccall unsafe "hs_text_icu.h __hs_ucal_clone" ucal_clone
    :: Ptr UCalendar -> Ptr UErrorCode
    -> IO (Ptr UCalendar)
foreign import ccall unsafe "hs_text_icu.h &__hs_ucal_close" ucal_close
    :: FunPtr (Ptr UCalendar -> IO ())
foreign import ccall unsafe "hs_text_icu.h __hs_ucal_get" ucal_get
    :: Ptr UCalendar -> UCalendarDateFields -> Ptr UErrorCode
    -> IO Int32
foreign import ccall unsafe "hs_text_icu.h __hs_ucal_set" ucal_set
    :: Ptr UCalendar -> UCalendarDateFields -> Int32
    -> IO ()
foreign import ccall unsafe "hs_text_icu.h __hs_ucal_setDate" ucal_setDate
    :: Ptr UCalendar -> Int32 -> Int32 -> Int32
    -> Ptr UErrorCode -> IO ()
foreign import ccall unsafe "hs_text_icu.h __hs_ucal_setDateTime" ucal_setDateTime
    :: Ptr UCalendar -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32
    -> Ptr UErrorCode -> IO ()
foreign import ccall unsafe "hs_text_icu.h __hs_ucal_add" ucal_add
    :: Ptr UCalendar -> UCalendarDateFields -> Int32 -> Ptr UErrorCode
    -> IO ()
foreign import ccall unsafe "hs_text_icu.h __hs_ucal_roll" ucal_roll
    :: Ptr UCalendar -> UCalendarDateFields -> Int32 -> Ptr UErrorCode
    -> IO ()
foreign import ccall unsafe "hs_text_icu.h _hs__ucal_openTimeZoneIDEnumeration" ucal_openTimeZoneIDEnumeration
    :: USystemTimeZoneType -> Ptr UErrorCode
    -> IO (Ptr UEnumerator)
foreign import ccall unsafe "hs_text_icu.h __hs_ucal_openTimeZones" ucal_openTimeZones
    :: Ptr UErrorCode
    -> IO (Ptr UEnumerator)
foreign import ccall unsafe "hs_text_icu.h __hs_ucal_setTimeZone" ucal_setTimeZone
    :: Ptr UCalendar -> CString -> Int32 -> Ptr UErrorCode
    -> IO ()