在Haskell中打印NominalDiffTime

3

我在我的 Haskell 程序中有这样的一段代码:

...
start <- getCurrentTime
...
end <- getCurrentTime
...
delta = end `diffUTCTime` start
...

在此之后,delta 的类型为 NominalDiffTime。正如文档所述,此类型继承自 Num,我想以小数点后3位的形式打印它。然而,使用类似于 printf "%.3f" delta 的方法行不通:No instance for (PrintfArg NominalDiffTime)

如何正确实现这个功能呢?


2
请注意,delta 不一定是两者之间经过的时间 - 例如,NominalDiffTime 忽略了闰秒。 - Ben Millwood
这是真的,但我认为它在几乎所有程序中都可以安全地忽略。 - aplavin
你这么说是没错,但上次有一次尴尬的闰秒时出了多少问题令人沮丧...我记得作为系统管理员的我所管理的一个服务器不得不重新启动 两次 - Ben Millwood
2
如果你非常不幸的话,比如说,我认为“delta”可能是负数……(或者正数,或者任何它不应该是的数)。 - Ben Millwood
2个回答

6
你可以将其转换为PrintfArg类型,以所需的格式进行打印,例如。
printf "%.3f" (realToFrac delta :: Double)

它行吗。


6
如果您想得到格式良好的差异时间,可以使用 System.Time.Utils (renderSecs)round
 ghci> import Data.Time.Clock
 ghci> import System.Time.Utils (renderSecs)
 ghci> 
 ghci> let renderS = renderSecs . round :: NominalDiffTime -> String
 ghci> t1 <- getCurrentTime
 ghci> -- wait a little :-P
 ghci> t2 <- getCurrentTime
 ghci> renderS $ t2 `diffUTCTime` t1
 "2m15s"

它还可以将天数表示为d,小时表示为h。请注意,由于ghci会默认使用Double类型,因此类型签名是必需的,否则您将无法输入NominalDiffTime值。


如果你使用一个参数定义它,例如 let renderS d = renderSecs (round d),或者关闭 MR(:set -XNoMonomorphismRestriction),你就不需要类型签名。 - Daniel Fischer
它只适用于打印整数秒,还是可以修改为小数部分?我尝试使用相同的 System.Time.Utils 中的 renderTD,但没有成功。 - aplavin
@DanielFischer,是的,这也是可能的。感谢您指出这一点。 - Aleksandar Dimitrov
@chersanya:不,看签名:renderSecs :: Integer -> String。我认为你需要编写自己的漂亮打印函数来完成这个任务。你也可以直接使用 renderSecs,然后从 DiffTime 中减去整数部分以获取小数部分,然后将其附加到渲染函数中。丑陋,我知道,但除了重新实现 renderTD,我看不到其他方法。 - Aleksandar Dimitrov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接