packages feed

hodatime-1.1.0.0: tests/HodaTime/CalendarDateTimeTest.hs

module HodaTime.CalendarDateTimeTest
(
  calendarDateTimeTests
)
where

import Test.Tasty
import Test.Tasty.QuickCheck as QC
import Test.Tasty.HUnit
import Data.Maybe (fromJust)

import HodaTime.Util (RandomTime(..), CycleYear(..))
import Data.HodaTime.LocalTime (localTime, hour, minute, second)
import Data.HodaTime.CalendarDate (day, next, previous, dayOfWeek)
import Data.HodaTime.Calendar.Gregorian (calendarDate, Month(..))
import Data.HodaTime.CalendarDateTime (on)
import Data.HodaTime.Period (applyPeriod, days, months, hours, minutes, seconds)

calendarDateTimeTests :: TestTree
calendarDateTimeTests = testGroup "CalendarDateTimeTests Tests" [qcProps, unitTests]

qcProps :: TestTree
qcProps = testGroup "(checked by QuickCheck)" [timeAccessorProps, datePeriodProps]

unitTests :: TestTree
unitTests = testGroup "Unit tests" [rolloverUnits]

timeAccessorProps :: TestTree
timeAccessorProps = testGroup "Time accessors"
  [
     QC.testProperty "reads constructed components" $ \(RandomTime h m s) ->
       let value = mkTime h m s in (hour value, minute value, second value) == (h, m, s)
  ]
  where
    mkTime h m s = fromJust $ on <$> localTime h m s 0 <*> calendarDate 1 April 2001

datePeriodProps :: TestTree
datePeriodProps = testGroup "Date periods"
  [
     QC.testProperty "first day not changed by month math" $ testMonthAdd 1
    ,QC.testProperty "mid day not changed by month math" $ testMonthAdd 15
    ,QC.testProperty "dayOfWeek . next n dow $ date == dow" $ testNextDoW
    ,QC.testProperty "next n (dayOfWeek date) date == a positive day period" $ testDirection next id
    ,QC.testProperty "previous n (dayOfWeek date) date == a negative day period" $ testDirection previous negate
  ]
    where
      mkcd d m y = fromJust $ on <$> localTime 10 10 10 0 <*> calendarDate d m y
      testMonthAdd d (CycleYear y) m add = day (applyPeriod (months add) $ mkcd d m (y + 1900)) == d
      testNextDoW dow (Positive n) = (dayOfWeek . next n dow $ epochDay) == dow
      testDirection dir adjust (Positive n) = dir n (dayOfWeek epochDay) epochDay == applyPeriod (days (adjust (n * 7))) epochDay
      epochDay = mkcd 1 March 2000

rolloverUnits :: TestTree
rolloverUnits = testGroup "Rollover"
  [
    testCase "30.Jan.2000 22:57:57 + 2s == 30.Jan.2000 22:57:59" $ applyPeriod (seconds 2) <$> dt @?= mkLT 22 57 59 0
      ,testCase "30.Jan.2000 22:57:57 + 5s == 30.Jan.2000 22:58:02" $ applyPeriod (seconds 5) <$> dt @?= mkLT 22 58 2 0
      ,testCase "30.Jan.2000 22:57:57 + 5m == 30.Jan.2000 23:02:57" $ applyPeriod (minutes 5) <$> dt @?= mkLT 23 02 57 0
      ,testCase "30.Jan.2000 22:57:57 + 3h == 31.Jan.2000 01:57:57" $ applyPeriod (hours 3) <$> dt @?= mkLTWithRolledDate 1 57 57 0
      ,testCase "30.Jan.2000 22:57:57 + 3723s == 31.Jan.2000 00:00:00" $ applyPeriod (seconds 3723) <$> dt @?= mkLTWithRolledDate 0 0 0 0
      ,testCase "30.Jan.2000 22:57:57 + 3725s == 31.Jan.2000 00:00:02" $ applyPeriod (seconds 3725) <$> dt @?= mkLTWithRolledDate 0 0 2 0
      ,testCase "30.Jan.2000 22:57:57 + 48h == 1.Feb.2000 22:57:57" $ applyPeriod (hours 48) <$> dt @?= mkLTWithDate monthRoll 22 57 57 0
  ]
  where
    time = localTime 22 57 57 0
    date = calendarDate 30 January 2000
    rollDate = calendarDate 31 January 2000
    monthRoll = calendarDate 1 February 2000
    dt = on <$> time <*> date
    mkLTWithDate date' h m s n = on <$> localTime h m s n <*> date'
    mkLT = mkLTWithDate date
    mkLTWithRolledDate = mkLTWithDate rollDate