如何在Haskell HDBC中直接获取SqlUTCTime?
如何通过Haskell HDBC从MariaDB直接获取SqlUTCTime?
我在使用Haskell HDBC查询MariaDB时遇到了问题:数据库的datetime列存储的是UTC时间,但直接执行SELECT查询时,返回的是SqlLocalTime类型,无法直接用fromSql转换为UTCTime;尝试用SQL的DATE_FORMAT()生成带+00:00或Z的ISO8601字符串时,又出现格式兼容错误。最终我通过手动转换解决了问题,但想知道有没有办法直接获取SqlUTCTime?
解决方案
要直接获取SqlUTCTime,可以从连接配置和数据库列类型两个方向处理:
1. 连接时指定UTC时区
HDBC的MariaDB/MySQL驱动支持在创建连接时设置时区参数,将连接时区设为UTC后,驱动会自动把数据库返回的datetime类型值解析为SqlUTCTime。
示例代码:
import Database.HDBC.MySQL main = do conn <- connectMySQL MySQLConnectInfo { mysqlHost = "localhost", mysqlDatabase = "your_database", mysqlUser = "your_user", mysqlPassword = "your_password", mysqlPort = 3306, mysqlOptionGroups = [], mysqlOptions = [("timezone", "UTC")] -- 核心:设置连接时区为UTC } results <- quickQuery conn "SELECT your_datetime_column FROM your_table" [] -- 直接提取SqlUTCTime并转换为UTCTime let utcTime = fromSql (head $ head results) :: UTCTime print utcTime disconnect conn
2. 将列类型改为TIMESTAMP
如果数据库中的时间列使用TIMESTAMP类型而非DATETIME,结合连接时区为UTC的设置,驱动会更稳定地将其映射为SqlUTCTime。这是因为MariaDB的TIMESTAMP本身以UTC格式存储,当连接时区设为UTC时,返回的时间不会经过时区转换,直接对应UTC时间。
补充说明
你当前手动转换SqlLocalTime到UTCTime的方法是有效的,尤其适合无法修改连接配置或表结构的场景:
convertSqlValue :: SqlValue -> Maybe UTCTime convertSqlValue sql = case sql of SqlString s -> iso8601ParseM s SqlUTCTime u -> Just u SqlLocalTime l -> Just $ localTimeToUTC utc l other -> Nothing
但通过上述两种方式,你可以省去手动转换的步骤,直接从查询结果中获取SqlUTCTime并转换为UTCTime。
内容的提问来源于stack exchange,提问作者vkubicki
相关产品推荐
相关产品推荐

