<commit_before>{-# OPTIONS_GHC -fno-warn-orphans #-}

module Util where

import Prelude
import Control.Monad (foldM)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.List (groupBy)
import Data.Text (Text)
import Data.Time
import Text.Blaze (ToMarkup(..))


now :: MonadIO m => m UTCTime
now = liftIO getCurrentTime

utcToLocalDay :: TimeZone -> UTCTime -> Day
utcToLocalDay tz = localDay . utcToLocalTime tz

tomorrow :: UTCTime -> UTCTime
tomorrow = addUTCTime oneDay
  where oneDay = 24 * 60 * 60

localEndOfDay :: LocalTime -> LocalTime
localEndOfDay time = time { localTimeOfDay = TimeOfDay 23 59 59 }

locally :: TimeZone -> (LocalTime -> LocalTime) -> UTCTime -> UTCTime
locally tz f = localTimeToUTC tz . f . utcToLocalTime tz

endOfToday :: TimeZone -> IO UTCTime
endOfToday tz = do
  utcNow <- getCurrentTime
  return $ locally tz localEndOfDay utcNow


compareBy :: Ord a => (b -> a) -> b -> b -> Ordering
compareBy f x y = compare (f x) (f y)

eqUnder :: Eq b => (a -> b) -> a -> a -> Bool
eqUnder f a b = f a == f b

groupByEq :: Eq g => (a -> g) -> [a] -> [(g, [a])]
groupByEq f as = zip gs groups where
  groups = groupBy (eqUnder f) as
  gs = map (f . head) groups


instance ToMarkup Day where
  toMarkup = toMarkup . show

-- Mimic Ruby's nil.to_s == ''
instance ToMarkup a => ToMarkup (Maybe a) where
  toMarkup = maybe "" toMarkup


overrideMethodR :: method -> route -> (route, [(Text, method)])
overrideMethodR method route = (route, [("_method", method)])


foldTimesM :: Monad m => Int -> (a -> m a) -> a -> m a
foldTimesM n f initial = foldM f' initial (replicate n ())
  where
    f' intermediate _ = f intermediate


maybeToEither :: String -> Maybe a -> Either String a
maybeToEither msg Nothing = Left msg
maybeToEither _ (Just v) = Right v
<commit_msg>nice time DSL: ago $ weeks 2<commit_after>{-# OPTIONS_GHC -fno-warn-orphans #-}

module Util where

import Prelude
import Control.Monad (foldM)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.List (groupBy)
import Data.Text (Text)
import Data.Time
import Text.Blaze (ToMarkup(..))


now :: MonadIO m => m UTCTime
now = liftIO getCurrentTime


ago, hence :: (Functor m, MonadIO m) => NominalDiffTime -> m UTCTime
ago interval = fmap (earlier interval) now
hence interval = fmap (later interval) now


earlier, later :: NominalDiffTime -> UTCTime -> UTCTime
earlier = addUTCTime . negate
later = addUTCTime


minutes, hours, days, weeks :: Num a => a -> a

minutes = (60 *)
hours = (60 *) . minutes
days = (24 *) . hours
weeks = (7 *) . days


utcToLocalDay :: TimeZone -> UTCTime -> Day
utcToLocalDay tz = localDay . utcToLocalTime tz

tomorrow :: UTCTime -> UTCTime
tomorrow = addUTCTime oneDay
  where oneDay = 24 * 60 * 60

localEndOfDay :: LocalTime -> LocalTime
localEndOfDay time = time { localTimeOfDay = TimeOfDay 23 59 59 }

locally :: TimeZone -> (LocalTime -> LocalTime) -> UTCTime -> UTCTime
locally tz f = localTimeToUTC tz . f . utcToLocalTime tz

endOfToday :: TimeZone -> IO UTCTime
endOfToday tz = do
  utcNow <- getCurrentTime
  return $ locally tz localEndOfDay utcNow


compareBy :: Ord a => (b -> a) -> b -> b -> Ordering
compareBy f x y = compare (f x) (f y)

eqUnder :: Eq b => (a -> b) -> a -> a -> Bool
eqUnder f a b = f a == f b

groupByEq :: Eq g => (a -> g) -> [a] -> [(g, [a])]
groupByEq f as = zip gs groups where
  groups = groupBy (eqUnder f) as
  gs = map (f . head) groups


instance ToMarkup Day where
  toMarkup = toMarkup . show

-- Mimic Ruby's nil.to_s == ''
instance ToMarkup a => ToMarkup (Maybe a) where
  toMarkup = maybe "" toMarkup


overrideMethodR :: method -> route -> (route, [(Text, method)])
overrideMethodR method route = (route, [("_method", method)])


foldTimesM :: Monad m => Int -> (a -> m a) -> a -> m a
foldTimesM n f initial = foldM f' initial (replicate n ())
  where
    f' intermediate _ = f intermediate


maybeToEither :: String -> Maybe a -> Either String a
maybeToEither msg Nothing = Left msg
maybeToEither _ (Just v) = Right v

{'fraction_non_alphanumeric': 0.12703175793948487, 'fraction_numerical': 0.008002000500125032, 'mean_word_length': 3.4150110375275937, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 77, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, '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': '3235714', 'n_tokens_mistral': 1491, 'n_tokens_neox': 1380, 'n_words': 503}