packages feed

chronologique-0.2.1.0: tests/CheckTimeStamp.hs

--
-- Time to manipulate time
--
-- Copyright © 2013-2016 Operational Dynamics Consulting, Pty Ltd and Others
--
-- The code in this file, and the program it is a part of, is
-- made available to you by its authors as open source software:
-- you can redistribute it and/or modify it under the terms of
-- the 3-clause BSD licence.
--

-- | Test serialisation/deserialiastion for TimeStamp type

{-# LANGUAGE BinaryLiterals #-}
{-# LANGUAGE NegativeLiterals #-}
{-# OPTIONS -fno-warn-orphans #-}

module CheckTimeStamp where

import Test.Hspec
import Test.QuickCheck
import Data.Hourglass

import Chrono.TimeStamp
import Chrono.Compat

checkTimeStamp :: Spec
checkTimeStamp = do
    describe "Smallest valid TimeStamp" $
      let
        t = TimeStamp (-9223372036854775808)
      in do
        it "should be representable" $ do
            t `shouldBe` (minBound :: TimeStamp)

        it "should be match when Shown" $ do
            show t `shouldBe` show (minBound :: TimeStamp)

        it "should equal expected value" $ do
            show t `shouldBe` "1677-09-21T00:12:43.145224192Z"

    describe "Largest valid TimeStamp" $
      let
        t = TimeStamp 9223372036854775807
      in do
        it "should be representable" $ do
            t `shouldBe` (maxBound :: TimeStamp)

        it "should be match when Shown" $ do
            show t `shouldBe` show (maxBound :: TimeStamp)

        it "should equal expected value" $ do
            show t `shouldBe` "2262-04-11T23:47:16.854775807Z"

    describe "Printing and parsing with precise format" $ do
        it "formats a known date correctly" $ do
            timePrint ISO8601_Precise (TimeStamp 1406849015948797001) `shouldBe` "2014-07-31T23:23:35.948797001Z"

        it "uses timeParse effectively" $ do
            timeParse ISO8601_Precise "2014-07-31T23:42:35.948797001Z" `shouldBe`
                Just (DateTime (Date 2014 July 31) (TimeOfDay 23 42 35 948797001))

    describe "Round trip through Read and Show instances" $ do
        it "outputs a correctly formated ISO 8601 timestamp when Shown" $ do
            show (TimeStamp 1406849015948797001) `shouldBe` "2014-07-31T23:23:35.948797001Z"
            show (TimeStamp 1406849015948797001) `shouldBe` "2014-07-31T23:23:35.948797001Z"
            show (TimeStamp 0) `shouldBe` "1970-01-01T00:00:00.000000000Z"

        it "Reads ISO 8601 timestamps" $ do
            read "2014-07-31T23:23:35.948797001Z" `shouldBe` TimeStamp 1406849015948797001
            read "2014-07-31T23:23:35Z" `shouldBe` TimeStamp 1406849015000000000
            read "2014-07-31" `shouldBe` TimeStamp 1406764800000000000

        it "reads the Unix epoch date" $
            read "1970-01-01" `shouldBe` TimeStamp 0

        it "permissively reads various formats" $ do
            show (read "1970-01-01T00:00:00.000000000Z" :: TimeStamp) `shouldBe` "1970-01-01T00:00:00.000000000Z"
            show (read "1970-01-01" :: TimeStamp) `shouldBe` "1970-01-01T00:00:00.000000000Z"
            show (read "0" :: TimeStamp) `shouldBe` "1970-01-01T00:00:00.000000000Z"

        it "permissively reads Posix seconds since epoch" $ do
            show (read "1406849015.948797001" :: TimeStamp) `shouldBe` "2014-07-31T23:23:35.948797001Z"
            show (read "1406849015.948797" :: TimeStamp) `shouldBe` "2014-07-31T23:23:35.948797000Z"
            show (read "1406849015.948" :: TimeStamp) `shouldBe` "2014-07-31T23:23:35.948000000Z"
            show (read "1406849015" :: TimeStamp) `shouldBe` "2014-07-31T23:23:35.000000000Z"
{-
    This is a bit fragile, depending as it does on the serialization to String
    in the Show instance of UTCTime. Not that they're going to change it
    anytime soon.
-}

    describe "Round trip through base time types" $ do
        it "converts to POSIXTime and back again" $ do
            let t = TimeStamp 1406849015948797001
            convertFromPosix (convertToPosix t) `shouldBe` t
            show (convertToPosix t) `shouldBe` "1406849015.948797001s"

        it "converts to UTCTime and back again" $ do
            let t = TimeStamp 1406849015948797001
            convertFromUTC (convertToUTC t) `shouldBe` t
            show (convertToUTC t) `shouldBe` "2014-07-31 23:23:35.948797001 UTC"

        it "behaves when QuickChecked" $ do
            property prop_RoundTrip


instance Arbitrary TimeStamp where
    arbitrary = do
        tick <- arbitrary
        return (TimeStamp tick)

prop_RoundTrip :: TimeStamp -> Bool
prop_RoundTrip t = (read . show) t == t