假设我有一个表示Epoch时间的整数,例如epoch = 1499055085
,我想将它转换为Haskell中的UTCTime
。如何做到这一点?
在其他语言中,这是一个非常简单的任务,为什么在Haskell中却这么困难呢?
假设我有一个表示Epoch时间的整数,例如epoch = 1499055085
,我想将它转换为Haskell中的UTCTime
。如何做到这一点?
在其他语言中,这是一个非常简单的任务,为什么在Haskell中却这么困难呢?
这是一个不错的问题,尽管有些人对它进行了负面评价。那么在这里,相当标准的“strptime”和“strftime”的等效物是什么呢?
你可能会觉得这很复杂,我同意,因为我也花了很多时间来弄清楚这个问题(我是新手),所以这里是我的一些发现。这并不简单,因为:
epoch -> utc
,那么这不是遗漏,而是因为它不存在。在Python中,这更简单,因为datetime
可以从您的环境中推断出“非常好的默认值”。对于Haskell来说,“大多数情况下都足够好的默认参数值”的概念并不适用。
如果纪元值来自某个任意整数,则Willem Van Onsem的epochToUTC
函数可以工作。如果它是来自文件的时间戳(EpochTime
),则我们需要另一个函数,因为它不是整数(它看起来像整数,行为像整数,但它既不是Int
也不是Integer
——这是一些非常深奥的问题)。
至于import
语句,您可以将其简化为仅使用import Data.Time
,这将从该模块中获取所有所需内容,但不包括posixSecondsToUTCTime
,因为……我想它被认为是某种专业化的东西。
import System.Posix.Types(EpochTime)
import Data.Time
import Data.Time.Clock.POSIX(posixSecondsToUTCTime)
epochToUTC :: EpochTime -> UTCTime
epochToUTC = posixSecondsToUTCTime . realToFrac
import System.Posix.Files
fStat <- getFileStatus "."
let someTime = epochToUTC . modificationTime $ fStat
我们可以很好地操作这个时间值。请注意,EpochTime
是特定于 System.Posix
模块的。如果它是从数据库或网页中检索到的时间戳,则可能会有另一个故事(类型安全并非免费)。
就像这个 "strptime" 操作并不是非常熟悉一样,类似的情况也出现在类似 "strftime" 的操作中。这可以通过使用 formatTime
来完成。例如:
formatTime defaultTimeLocale "%Y-%m-%d" someTime
--equivalent
formatTime defaultTimeLocale ( iso8601DateFormat Nothing ) someTime
--whichever dateFmt defined in that TimeLocale
formatTime defaultTimeLocale ( dateFmt defaultTimeLocale ) someTime
--"%a, %_d %b %Y %H:%M:%S %Z"
formatTime defaultTimeLocale rfc822DateFormat someTime
defaultTimeLocale
,则可以优雅地缩写为:formatTime' = formatTime defaultTimeLocale
阅读材料:
Haskell时间库教程(我们需要更多这样的内容!)
谁说这很困难呢?
你可以简单地使用fromIntegral :: (Integral a, Num b) => a -> b
将纪元(一个整数)转换为POSIXTime
。
接下来,我们可以使用posixSecondsToUTCTime :: POSIXTime -> UTCTime
获取UTCTime
,最后我们使用utctDay :: UTCTime -> Day
获取UTCTime
的日期部分。
如果您想要一个(年,月,日)元组,我们可以使用toGregorian :: Day -> (Integer,Int,Int)
方法。
所以我们可以使用以下方法:
import Data.Time.Calendar(toGregorian)
import Data.Time.Clock(utctDay,UTCTime)
import Data.Time.Clock.POSIX(posixSecondsToUTCTime)
epochToUTC :: Integral a => a -> UTCTime
epochToUTC = posixSecondsToUTCTime . fromIntegral
epochToGregorian :: Integral a => a -> (Integer,Int,Int)
epochToGregorian = toGregorian . utctDay . epochToUTC
接下来举个例子:
Main> epochToGregorian 1234567
(1970,1,15)
Main> epochToGregorian 123456789
(1973,11,29)
Main> epochToGregorian 1234567890
(2009,2,13)
import Data.Time
来获取前两个模块。最后,你不必“知道”每个模块包含什么 - 你只需要能够阅读文档(这些文档在本答案中提供了链接!)。 - user2407038