<commit_before>{-# LANGUAGE DeriveDataTypeable #-}
-- |
-- Module      : Data.Hourglass.Diff
-- License     : BSD-style
-- Maintainer  : <NAME> <<EMAIL>>
-- Stability   : experimental
-- Portability : unknown
--
-- time arithmetic methods
--
module Data.Hourglass.Diff
    ( Duration(..)
    , Period(..)
    , durationNormalize
    , durationFlatten
    , elapsedTimeAddSeconds
    , elapsedTimeAddSecondsP
    , dateAddPeriod
    ) where

import Data.Data
import Data.Monoid
import Data.Hourglass.Types
import Data.Hourglass.Calendar
import Control.DeepSeq

-- | An amount of conceptual calendar time in terms of years, months and days.
--
-- This allow calendar manipulation, representing things like days and months
-- irrespective on how long those are related to timezone and daylight changes.
--
-- See 'Duration' for the time-based equivalent to this class.
data Period = Period
    { periodYears  :: !Int
    , periodMonths :: !Int
    , periodDays   :: !Int
    } deriving (Read,Eq,Ord,Data,Typeable)

instance NFData Period where
    rnf (Period y m d) = y `seq` m `seq` d `seq` ()
instance Monoid Period where
    mempty = Period 0 0 0
    mappend (Period y1 m1 d1) (Period y2 m2 d2) =
        Period (y1+y2) (m1+m2) (d1+d2)

-- | An amount of time in terms of constant value like hours (3600 seconds),
-- minutes (60 seconds), seconds and nanoseconds.
data Duration = Duration
    { durationHours   :: !Hours       -- ^ number of hours
    , durationMinutes :: !Minutes     -- ^ number of minutes
    , durationSeconds :: !Seconds     -- ^ number of seconds
    , durationNs      :: !NanoSeconds -- ^ number of nanoseconds
    } deriving (Read,Eq,Ord,Data,Typeable)

instance NFData Duration where
    rnf (Duration h m s ns) = h `seq` m `seq` s `seq` ns `seq` ()
instance Monoid Duration where
    mempty = Duration 0 0 0 0
    mappend (Duration h1 m1 s1 ns1) (Duration h2 m2 s2 ns2) =
        Duration (h1+h2) (m1+m2) (s1+s2) (ns1+ns2)
instance TimeInterval Duration where
    fromSeconds s = (durationNormalize (Duration 0 0 s 0), 0)
    toSeconds d   = fst $ durationFlatten d

durationFlatten :: Duration -> (Seconds, NanoSeconds)
durationFlatten (Duration h m s (NanoSeconds ns)) =
    (toSeconds h + toSeconds m + s + Seconds sacc, NanoSeconds ns')
  where (sacc, ns') = ns `divMod` 1000000000

-- | Normalize all fields to represent the same value
-- with the biggest units possible.
--
-- For example, 62 minutes is normalized as 1h 2minutes
durationNormalize :: Duration -> Duration
durationNormalize (Duration (Hours h) (Minutes mi) (Seconds s) (NanoSeconds ns)) =
    Duration (Hours (h+hacc)) (Minutes mi') (Seconds s') (NanoSeconds ns')
  where (hacc, mi') = (mi+miacc) `divMod` 60
        (miacc, s') = (s+sacc) `divMod` 60
        (sacc, ns') = ns `divMod` 1000000000

-- | add a period of time to a date
dateAddPeriod :: Date -> Period -> Date
dateAddPeriod (Date yOrig mOrig dOrig) (Period yDiff mDiff dDiff) =
    loop (yOrig + yDiff + yDiffAcc) mStartPos (dOrig+dDiff)
  where<commit_msg>add a description for durationFlatten<commit_after>{-# LANGUAGE DeriveDataTypeable #-}
-- |
-- Module      : Data.Hourglass.Diff
-- License     : BSD-style
-- Maintainer  : <NAME> <<EMAIL>>
-- Stability   : experimental
-- Portability : unknown
--
-- time arithmetic methods
--
module Data.Hourglass.Diff
    ( Duration(..)
    , Period(..)
    , durationNormalize
    , durationFlatten
    , elapsedTimeAddSeconds
    , elapsedTimeAddSecondsP
    , dateAddPeriod
    ) where

import Data.Data
import Data.Monoid
import Data.Hourglass.Types
import Data.Hourglass.Calendar
import Control.DeepSeq

-- | An amount of conceptual calendar time in terms of years, months and days.
--
-- This allow calendar manipulation, representing things like days and months
-- irrespective on how long those are related to timezone and daylight changes.
--
-- See 'Duration' for the time-based equivalent to this class.
data Period = Period
    { periodYears  :: !Int
    , periodMonths :: !Int
    , periodDays   :: !Int
    } deriving (Read,Eq,Ord,Data,Typeable)

instance NFData Period where
    rnf (Period y m d) = y `seq` m `seq` d `seq` ()
instance Monoid Period where
    mempty = Period 0 0 0
    mappend (Period y1 m1 d1) (Period y2 m2 d2) =
        Period (y1+y2) (m1+m2) (d1+d2)

-- | An amount of time in terms of constant value like hours (3600 seconds),
-- minutes (60 seconds), seconds and nanoseconds.
data Duration = Duration
    { durationHours   :: !Hours       -- ^ number of hours
    , durationMinutes :: !Minutes     -- ^ number of minutes
    , durationSeconds :: !Seconds     -- ^ number of seconds
    , durationNs      :: !NanoSeconds -- ^ number of nanoseconds
    } deriving (Read,Eq,Ord,Data,Typeable)

instance NFData Duration where
    rnf (Duration h m s ns) = h `seq` m `seq` s `seq` ns `seq` ()
instance Monoid Duration where
    mempty = Duration 0 0 0 0
    mappend (Duration h1 m1 s1 ns1) (Duration h2 m2 s2 ns2) =
        Duration (h1+h2) (m1+m2) (s1+s2) (ns1+ns2)
instance TimeInterval Duration where
    fromSeconds s = (durationNormalize (Duration 0 0 s 0), 0)
    toSeconds d   = fst $ durationFlatten d

-- | Flatten a duration to a number of seconds, nanoseconds
durationFlatten :: Duration -> (Seconds, NanoSeconds)
durationFlatten (Duration h m s (NanoSeconds ns)) =
    (toSeconds h + toSeconds m + s + Seconds sacc, NanoSeconds ns')
  where (sacc, ns') = ns `divMod` 1000000000

-- | Normalize all fields to represent the same value
-- with the biggest units possible.
--
-- For example, 62 minutes is normalized as 1h 2minutes
durationNormalize :: Duration -> Duration
durationNormalize (Duration (Hours h) (Minutes mi) (Seconds s) (NanoSeconds ns)) =
    Duration (Hours (h+hacc)) (Minutes mi') (Seconds s') (NanoSeconds ns')
  where (hacc, mi') = (mi+miacc) `divMod` 60
        (miacc, s') = (s+sacc) `divMod` 60
        (sacc, ns') = ns `divMod` 1000000000

-- | add a period of time to a date
dateAddPeriod :: Date -> Period -> Date
dateAddPeriod (Date yOrig mOrig dOrig) (Period yDiff mDiff dDiff) =
    loop (yOrig + yDiff + yDiffAcc) mStartPos (dOrig+dDiff)
  where
{'fraction_non_alphanumeric': 0.11002285341168788, 'fraction_numerical': 0.023832843617368593, 'mean_word_length': 3.1965753424657533, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '773065', 'n_tokens_mistral': 2078, 'n_tokens_neox': 1940, 'n_words': 710}