haskell - 在 Haskell 中显示当地时间
问题描述
我的状态对象将日期存储为UTCTime
. 但我需要将它们作为适当的当地时间显示给用户。
我试过使用getCurrentTimeZone
then utcToLocalTime
,但它不适用于夏季的日期。问题似乎是现在getCurrentTimeZone
返回我的时区,而不是适当的日期。
let time = UTCTime (fromGregorian 2018 08 08) 0
tz <- getCurrentTimeZone -- GMT - my time zone now
utcToLocalTime tz time
-- 2018-08-08 00:00:00 - wrong
如果我将日期传递给getTimeZone
:
let time = UTCTime (fromGregorian 2018 08 08) 0
tz <- getTimeZone time -- BST - the timezone for the date
utcToLocalTime tz time
-- 2018-08-08 01:00:00 - right
问题是,设置/显示时间的代码很深IO
(应该如此),所以当我想显示时间时无法运行此代码。
我看过Olsen 包,但是当我通过它GMT
(使用timeZoneName
)时,它的作用与上面的第一个示例相同 - 无法弄清楚如何告诉它获取数据。
解决方案
使用包执行此操作的预期方法timezone-olson
是使用 a TimeZoneSeries
,它是随时间变化的完整系列时区转换,而不仅仅是 a TimeZone
,它反映了某个时间点的时区。
您通常需要从IO
. 您可以从标准位置加载默认的本地时区系列/etc/localtime
,或者您可以从例如/usr/share/zoneinfo/America/Chicago
或其他位置加载特定系列。不幸的是,似乎没有一种健壮的、独立于平台的方式来指定和加载时区文件。
TimeZoneSeries
读取后,需要将其传递给您的纯计算,您可以在其中使用utcToLocalTime'
该时间点的时区获取正确的本地时间。希望你已经有一个Reader
方便的:
import Control.Monad.Reader
import Data.Time (UTCTime(..), fromGregorian, LocalTime)
import Data.Time.LocalTime.TimeZone.Olson (getTimeZoneSeriesFromOlsonFile)
import Data.Time.LocalTime.TimeZone.Series (TimeZoneSeries, utcToLocalTime')
data R = R { tzs :: TimeZoneSeries }
main :: IO ()
main = do
mytzs <- getTimeZoneSeriesFromOlsonFile "/etc/localtime"
print $ runReader getTimes R { tzs = mytzs }
getTimes :: Reader R LocalTime
getTimes = flip utcToLocalTime' (UTCTime (fromGregorian 2018 08 08) 0) <$> asks tzs
看起来tz
包是一样的,尽管它使用 typeTZ
代替TimeZoneSeries
. 您仍然需要loadTZFromFile
输入IO
并将其传递utcToLocalTimeTZ
给位于纯代码中的调用。有一个方便的函数可以从(或环境变量指定的备用位置)loadLocalTZ
读取;它看起来与平台无关,但和路径在源代码中是硬编码的(除非它使用环境变量代替,如果已设置)。/etc/localtime
TZ
/etc/localtime
/usr/share/zoneinfo
TZDIR
/usr/share/zoneinfo
无论如何,代码看起来像:
import Control.Monad.Reader
import Data.Time (UTCTime(..), fromGregorian, LocalTime)
import Data.Time.Zones (utcToLocalTimeTZ, loadLocalTZ, TZ)
data R = R { tz :: TZ }
main :: IO ()
main = do
mytz <- loadLocalTZ
print $ runReader getTimes R { tz = mytz }
getTimes :: Reader R LocalTime
getTimes = flip utcToLocalTimeTZ (UTCTime (fromGregorian 2018 08 08) 0) <$> asks tz
推荐阅读
- php - Laravel 数据库请求
- windows - 如何过滤掉powershell中的信息?
- r - 按非结构化文本列分组以透视数据
- tensorflow - Keras 与 Tensorflow 估计器
- doxygen - 如何按语言更改 Markdown 文件的标题?
- reporting-services - SSRS 表达式 - 在值之前和之后更改背景颜色
- php - 未捕获的 PDOException:SQLSTATE[HY093]:无效的参数号:没有绑定参数
- haskell - 在 Haskell 中,如何从整数列表中获得平均浮点数?
- python - sns.catplot,缩小条形之间的差距
- javascript - 如何比较格式化的日期字符串