packages feed

fuzzytime 0.3 → 0.4

raw patch · 2 files changed

+165/−74 lines, 2 files

Files

fuzzytime.cabal view
@@ -1,7 +1,7 @@ Name:                fuzzytime-Version:             0.3-Description:         Print current time in a more casual way-Synopsis:            Print current time in a more casual way+Version:             0.4+Description:         Telling the time in a more humane way+Synopsis:            Telling the time in a more humane way Category:            Utils License:             GPL License-file:        LICENSE
fuzzytime.hs view
@@ -8,7 +8,7 @@ ---- Maintainer		: Kamil Stachowski <kamil.stachowski@gmail.com> ---- Stability		: unstable ---- Portability	: unportable----- Prints the current time in a more casual way (the \"ten past six\"-style).+---- Tells the time in a more humane way (the \"ten past six\"-style). -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  module Main (@@ -25,7 +25,7 @@   -- $description--- A small utility to print the current time in a more casual way (the \"ten past six\"-style).+-- A small utility to tell the current time in a more humane way (the \"ten past six\"-style). -- -- The whole thing works like this: the current time is read and turned into CalendarTime. This is fuzzified (i.e. the precision is reduced) and at the same time changed into FuzzyTime. FuzzyTime holds the time as two Ints (hour and min), the target language, the desired clock (12 vs. 24) and an information on whether it is am or pm (needed for the 12-hour clock). Custom functions show FuzzyTime as the \"ten past six\"-style String. --@@ -33,7 +33,7 @@ -- -- To add a new language, two things need to be done: ----- (1) The new language has to be added to FuzzyTimeConf, to the instance of Show FuzzyTime, and to the help message.+-- (1) The new language has to be added to checkFTConf, to the instance of Show FuzzyTime, and to the help message. -- -- (2) An appropriate function has to be created to turn FuzzyTime -> String. @@ -42,6 +42,14 @@ -- TODO -- 		more languages -- 		exit codes+-- 		styles+-- 0.4	2011.01.15+-- 		added --time (thanks Daniel Fischer and Brent Yorgey from beginners@haskell.org!)+-- 		added --style+-- 		added Danish (by M_ller with my modifications)+-- 		removed "południe" from pl+-- 		sorted out the representation of midnight and noon+-- 		added a man page -- 0.3	2011.01.14 -- 		added midnight and noon -- 		added checking cli options@@ -55,82 +63,108 @@ -- 				added cabal  - -- config ===============================================================================  --- | \[config] The default for 12 vs. 24-hour clock.-confDefaultClock :: Int-confDefaultClock = 12+-- | \[config] The default clock (12 vs. 24-hour).+confDefClock :: Int+confDefClock = 12  -- | \[config] The default language.-confDefaultLang :: String-confDefaultLang = "en"+confDefLang :: String+confDefLang = "en" --- | \[config] The default precision in minutes. Should be 1 < precision < 60.-confDefaultPrec :: Int-confDefaultPrec = 5+-- | \[config] The default precision (should be in [1..60]).+confDefPrec :: Int+confDefPrec = 5 +-- | \[config] The default style (see man).+confDefStyle :: Int+confDefStyle = 1 +-- | \[config] The default time (current).+confSetCurrTime :: FuzzyTimeConf -> IO FuzzyTimeConf+confSetCurrTime ft = do+	now <- getClockTime+	return $ ft { time = take 5 . drop 11 $ show now }++ -- main =================================================================================   -- | The main part. Only reads the command line args and the current time, fuzzifies and prints it. main :: IO () main = do-	conf <- cmdArgs ftConf-	if (checkConf conf) /= "ok" then-		putStrLn $ checkConf conf-		else do-		calTime <- getClockTime >>= toCalendarTime-		print $ toFuzzyTime conf calTime+	fullFTConf <- confSetCurrTime getFTConf		-- ^ required to avoid unsafePerformIO+	conf <- cmdArgs fullFTConf+	if (checkFTConf conf) /= "ok" then+		putStrLn $ checkFTConf conf+		else+		print $ toFuzzyTime conf   -- cl args ==============================================================================  --- | Three options can be set via the command line: clock (12 vs. 24), language and precision.+-- | Four options can be set via the command line: clock (12 vs. 24), language, precision and time. data FuzzyTimeConf = FuzzyTimeConf { 	  clock	:: Int 	, lang	:: String 	, prec	:: Int+	, time	:: String+	, style	:: Int 	} deriving (Show, Data, Typeable) -ftConf :: FuzzyTimeConf-ftConf = FuzzyTimeConf {-	  clock	=confDefaultClock	&= help "12 or 24-hour clock; default 12-hour."-	, lang	=confDefaultLang	&= help "Language (currently de, en, fr and pl); default en."-	, prec	=confDefaultPrec	&= help "Precision (1 < prec < 60 [minutes]); default 5."-	}-	&= program "fuzzytime"-	&= summary "Print fuzzy time, e.g. 10:52 -> ten to eleven.\nv0.2, 2011.01.12, kamil.stachowski@gmail.com, GPL3+" --checkConf :: FuzzyTimeConf -> String-checkConf (FuzzyTimeConf clock lang prec)+-- | Check that arguments given at cli are correct.+checkFTConf :: FuzzyTimeConf -> String+checkFTConf (FuzzyTimeConf clock lang prec time style) 	| not (clock `elem` [12, 24])	= "--clock must be either 12 or 24."-	| not (lang `elem` ["de", "en", "fr", "pl"])	= "--lang must be de, en, fr or pl."+	| not (lang `elem` ["da", "de", "en", "fr", "pl"])	= "--lang must be de, en, fr or pl." 	| prec < 1 || prec > 60			= "--prec must be 1 < prec < 60."+	| not checkTimeOk				= "--time must be given as HH:MM, where HH is in [0..23] and MM is in [0..59]"+	| not (style `elem` [1, 2])		= "--style must be either 1 or 2 (see the man page)." 	| otherwise						= "ok"+	where+	checkTimeOk :: Bool+	checkTimeOk = ':' `elem` time && h `elem` [0..23] && m `elem` [0..59]+		where+		h = read $ takeWhile (/=':') time +		m = read $ reverse . takeWhile (/=':') . reverse $ time  +-- | Fill the config with the default values.+getFTConf :: FuzzyTimeConf+getFTConf = FuzzyTimeConf {+	  clock	= confDefClock	&= help "12 or 24-hour clock; default 12-hour."+	, lang	= confDefLang	&= help "Language (currently da, de, en, fr and pl); default en."+	, prec	= confDefPrec	&= help "Precision (1 < prec < 60 [minutes]); default 5."+	, time	= ""			&= help "Time to fuzzify as HH:MM; default current time."			-- ^ time is set via confSetCurrTime to avoid unsafePerformIO+	, style	= confDefStyle	&= help "How the time is told (seem the man page); default 1."+	}+	&= program "fuzzytime"+	&= summary "Tell the time in a more humane way, e.g. 10:52 -> ten to eleven.\nv0.4, 2011.01.15, kamil.stachowski@gmail.com, GPL3+"++ -- FuzzyTime – main =====================================================================  --- | Data for fuzzified time. Only keeps hour, minutes (both as Ints), am (vs. pm), clock (12 vs. 24) and language.+-- | Data for fuzzified time. Only keeps hour, minutes (both as Ints), clock (12 vs. 24-hour), night (Bool) and language. -- Can be created from CalendarTime with toFuzzyTime. The String output (the \"ten past six\"-style) is obtained through Show. data FuzzyTime = FuzzyTime {-	  fzAm		:: Bool-	, fzClock	:: Int+	  fzClock	:: Int 	, fzHour	:: Int 	, fzLang	:: String 	, fzMin		:: Int+	, fzNight	:: Bool+	, fzStyle	:: Int 	} deriving (Eq)  -- | This is where FuzzyTime Int Int String is turned into the time String. -- It is assumed that by the time these functions are called, hour will be in [0..23] and min will be in [0..59]. instance Show FuzzyTime where-	show ft@(FuzzyTime _ _ _ lang _) = case lang of+	show ft@(FuzzyTime _ _ lang _ _ _) = case lang of+		"da" -> showFuzzyTimeDa ft 		"de" -> showFuzzyTimeDe ft 		"en" -> showFuzzyTimeEn ft 		"fr" -> showFuzzyTimeFr ft@@ -139,42 +173,92 @@   -- | Converts CalendarTime to FuzzyTime using the given precision. The language and clock are also set, so that Show knows how to display it.-toFuzzyTime :: FuzzyTimeConf -> CalendarTime -> FuzzyTime-toFuzzyTime (FuzzyTimeConf cClock cLang cPrec) (CalendarTime _ _ _ hour min _ _ _ _ _ _ _) =-	FuzzyTime (hour < 12) cClock fuzzdHour cLang (fuzzdMin min) +toFuzzyTime :: FuzzyTimeConf -> FuzzyTime+toFuzzyTime (FuzzyTimeConf cClock cLang cPrec cTime cStyle) =+	FuzzyTime cClock fuzzdHour cLang (fuzzdMin min) (hour < 10 || hour > 22) cStyle 	where+	hour :: Int+	hour = read $ takeWhile (/=':') cTime+	min :: Int+	min = read $ reverse . takeWhile (/=':') . reverse $ cTime 	fuzzdHour :: Int 	fuzzdHour = 		if cClock==24 then-			hour+			if hour==0 then 24 else hour 			else-			hour `mod` 12+			if hour==12 then hour else hour `mod` 12 	fuzzdMin :: Int -> Int 	fuzzdMin m = 		let 			mf = fromIntegral m 			cf = fromIntegral cPrec 		in-			round(mf/cf) * cPrec+			(round(mf/cf) * cPrec) `mod` 60 +-- | Makes sure that midnight is always represented as 0 or 24, depending on the clock, and noon always as 12.+nextFTHour :: FuzzyTime -> Int+nextFTHour (FuzzyTime clock hour _ _ night _)+	| clock == 12 && hour == 11		= if night then 0 else 12+	| otherwise						= hour + 1+				  -- FuzzyTime – shows ==================================================================== +-- Danish (by M_ller with my modifications) ---------------------------------------------+++showFuzzyTimeDa :: FuzzyTime -> String+showFuzzyTimeDa ft@(FuzzyTime clock hour _ min night style)+	| min == 0	= getHour hour+	| min < 30	= getMin min ++ " over " ++ getHour hour+	| min == 30	= "halv " ++ getHour (nextFTHour ft)+	| min > 30	= getMin (60-min) ++ " i " ++ getHour (nextFTHour ft)+	| otherwise	= "Ups, det ser ud til den er " ++ show hour ++ ":" ++ show min ++ "."+	where+	getHour :: Int -> String+	getHour h+		| h `mod` 12 == 0	= if style==1 then+								if clock==12 then numeralDa 12 else numeralDa h+								else+								if night then+									"midnat"+									else+									if min `elem` [0, 30] then "aften" else numeralDa h+		| otherwise			= numeralDa h+	getMin :: Int -> String+	getMin m+		| m `elem` [15, 45]	= "kvart"+		| otherwise 		= numeralDa m+++numeralDa :: Int -> String+numeralDa n+	| n < 20			= numeralDaHelper1 n+	| n `mod` 10 == 0	= numeralDaHelper10 (n `div` 10)+	| otherwise			= numeralDaHelper1 (n `mod` 10) ++ "og" ++ numeralDaHelper10 (n `div` 10)+	where+	numeralDaHelper1 :: Int -> String+	numeralDaHelper1 i = ["en", "to", "tre", "fire", "fem", "seks", "syv", "otte", "ni", "ti", "elleve", "tolv", "tretten", "fjorten", "femten", "seksten", "sytten", "atten", "nitten"] !! (i-1)+	numeralDaHelper10 :: Int -> String+	numeralDaHelper10 i = ["tyve", "tredive", "fyrre", "halvtreds"] !! (i-2)++ -- English ------------------------------------------------------------------------------   showFuzzyTimeEn :: FuzzyTime -> String-showFuzzyTimeEn (FuzzyTime am clock hour _ min)+showFuzzyTimeEn ft@(FuzzyTime clock hour _ min night style) 	| min == 0	= if (getHour hour) `elem` ["midnight", "noon"] then (getHour hour) else (getHour hour) ++ " o’clock" 	| min <= 30	= getMin min ++ " past " ++ getHour hour-	| min > 30	= getMin (60-min) ++ " to " ++ getHour (hour+1)+	| min > 30	= getMin (60-min) ++ " to " ++ getHour (nextFTHour ft) 	| otherwise	= "Oops, it looks like it's " ++ show hour ++ ":" ++ show min ++ "." 	where 	getHour :: Int -> String 	getHour h-		| h == 0 && am		= "midnight"-		| h == 0 && not am	= if clock==12 then "noon" else "midnight"-		| h == 12			= "noon"+		| h `mod` 12 == 0	= if style==1 then+								if clock==12 then numeralEn 12 else numeralEn h+								else+								if night then "midnight" else "noon" 		| otherwise			= numeralEn h 	getMin :: Int -> String 	getMin m@@ -190,7 +274,7 @@ 	| otherwise			= numeralEnHelper10 (n `div` 10) ++ "-" ++ numeralEnHelper1 (n `mod` 10) 	where 	numeralEnHelper1 :: Int -> String-	numeralEnHelper1 i = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"] !! i+	numeralEnHelper1 i = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"] !! (i-1) 	numeralEnHelper10 :: Int -> String 	numeralEnHelper10 i = ["twenty", "thirty", "forty", "fifty"] !! (i-2) @@ -199,18 +283,22 @@   showFuzzyTimeDe :: FuzzyTime -> String-showFuzzyTimeDe (FuzzyTime am clock hour _ min)+showFuzzyTimeDe ft@(FuzzyTime clock hour _ min night style) 	| min == 0	= if (getHour hour) `elem` ["Mitternacht", "Mittag"] then (getHour hour) else (getHour hour) ++ " Uhr" 	| min < 30	= getMin min ++ " nach " ++ getHour hour-	| min == 30	= "halb " ++ getHour (hour+1)-	| min > 30	= getMin (60-min) ++ " vor " ++ getHour (hour+1)+	| min == 30	= "halb " ++ getHour (nextFTHour ft)+	| min > 30	= getMin (60-min) ++ " vor " ++ getHour (nextFTHour ft) 	| otherwise	= "Oops, es sieht aus, dass es " ++ show hour ++ ":" ++ show min ++ " ist." 	where 	getHour :: Int -> String 	getHour h-		| h == 0 && am		= "Mitternacht"-		| h == 0 && not am	= if clock==12 then "Mittag" else "Mitternacht"-		| h == 12			= "Mittag"+		| h `mod` 12 == 0	= if style==1 then+								if clock==12 then numeralDe 12 else numeralDe h+								else+								if night then+									"Mitternacht"+									else+									if min `elem` [0, 30] then "Mittag" else numeralDe h 		| otherwise			= numeralDe h 	getMin :: Int -> String 	getMin m@@ -234,18 +322,19 @@   showFuzzyTimeFr :: FuzzyTime -> String-showFuzzyTimeFr (FuzzyTime am clock hour _ min)+showFuzzyTimeFr ft@(FuzzyTime clock hour _ min night style) 	| min == 0	= getHour hour 	| min <= 30	= getHour hour ++ " " ++ getMin min-	| min > 30	= getHour (hour+1) ++ " moins " ++ getMin (60-min)+	| min > 30	= getHour (nextFTHour ft) ++ " moins " ++ getMin (60-min) 	| otherwise	= "Oops, il semble qu’il est " ++ show hour ++ ":" ++ show min ++ "." 	where 	getHour :: Int -> String 	getHour h-		| h == 0 && am		= "minuit"-		| h == 0 && not am	= if clock==12 then "midi" else "minuit"-		| h == 12			= "midi"-		| otherwise			= numeralFr h ++ if h==1 then " heure" else " heures"+		| h `mod` 12 == 0	= if style==1 then+								(if clock==12 then numeralFr 12 else numeralFr h) ++ getHourWord h+								else+								if night then "minuit" else "midi"+		| otherwise			= numeralFr h ++ getHourWord h 	getHourWord :: Int -> String 	getHourWord h = if h==1 then " heure" else " heures" 	getMin :: Int -> String@@ -272,24 +361,26 @@   showFuzzyTimePl :: FuzzyTime -> String-showFuzzyTimePl (FuzzyTime am clock hour _ min)+showFuzzyTimePl ft@(FuzzyTime clock hour _ min night style) 	| min == 0	= getHourEven hour-	| min < 30	= getMin min ++ " po " ++ getHourUneven hour-	| min == 30	= "wpół do " ++ getHourUneven (hour+1)-	| min > 30	= "za " ++ getMin (60-min) ++ " " ++ getHourEven (hour+1)+	| min < 30	= getMin min ++ " po " ++ getHourOdd hour+	| min == 30	= "wpół do " ++ getHourOdd (nextFTHour ft)+	| min > 30	= "za " ++ getMin (60-min) ++ " " ++ getHourEven (nextFTHour ft) 	| otherwise	= "Oops, wychodzi, że jest " ++ show hour ++ ":" ++ show min ++ "." 	where 	getHourEven :: Int -> String 	getHourEven h-		| h == 0 && am		= "północ"-		| h == 0 && not am	= if clock==12 then "południe" else "północ"-		| h == 12			= "południe"+		| h `mod` 12 == 0	= if style==1 then+								if clock==12 then numeralPlOrdNom 12 else numeralPlOrdNom h+								else+								if night then "północ" else numeralPlOrdNom h 		| otherwise			= numeralPlOrdNom h-	getHourUneven :: Int -> String-	getHourUneven h-		| h == 0 && am		= "północy"-		| h == 0 && not am	= if clock==12 then "południu" else "północy"-		| h == 12			= "południu"+	getHourOdd :: Int -> String+	getHourOdd h+		| h `mod` 12 == 0	= if style==1 then+								if clock==12 then numeralPlOrdPraep 12 else numeralPlOrdPraep h+								else+								if night && min < 30 then "północy" else numeralPlOrdPraep h 		| otherwise			= numeralPlOrdPraep h 	getMin :: Int -> String 	getMin m