【问题标题】:Is there a reliable way to convert unzoned datetime into UNIX time_t?是否有可靠的方法将未分区的日期时间转换为 UNIX time_t?
【发布时间】:2010-12-21 19:27:17
【问题描述】:

我需要将 (MSSQL) 数据库表中的数据库列转换为 UNIX time_t。问题是该列没有时区,有些日期来自 GMT (+0000),有些来自 BST (+0100)。我正在为英国时报工作。

有没有可靠的方法将未分区的 datetime 转换为 UNIX time_t?我目前正在使用

SELECT *,DATEDIFF(second,'1970-01-01',event_time)

但这似乎受制于当前时区,不适用于日期。

我不介意在 SQL 或代码中进行转换。我在 Perl 工作。

【问题讨论】:

  • 您目前如何判断哪些行是 GMT/UTC 和 BST?
  • 他们的系统没有。因此我的问题。
  • 如何填充此列?
  • 如果您无法区分时区,您的程序将如何区分?
  • 潜在的问题似乎是上面的 DATEDIFF 使用了当前的时间偏移量,而不是适合 event_time 的时间偏移量。可能通过深入研究 SQL Server 管理文档来修复(并且当数据库转移到一些新服务器等时必然会中断),使用 hobbs 代码在代码中处理它更安全。

标签: sql sql-server date timezone


【解决方案1】:

如果您的意思是夏季时间是 BST,冬季时间是 GMT,那么 列中隐含了一个时区,它不是“两个不同的时区”,而是一个时区,称为 @987654322 @ 在 Olson DB 中或 GMT0BST,M3.5.0/1,M10.5.0/2 在 POSIX TZ 格式中。您应该能够使用DateTime 模块轻松转换这些时间,甚至巧妙地使用 POSIX 函数,除了秋季转换前后的模糊时间,除非您存储 BST 是或当时还没有生效。

使用DateTime的示例:

use DateTime::Format::MSSQL;
# In reality you would get this from the DB.
my $input = "2009-11-30 16:13:18.123";
my $dt = DateTime::Format::MSSQL->parse_datetime($input);
$dt->set_time_zone("Europe/London");
print "Unix time is ", $dt->epoch, "\n";

【讨论】:

  • 谢谢。知道它可以解决,但不是一个实际的解决方案,这让人放心。
  • 谢谢。我明天早上试试。
  • 已确认。世界再次安全!非常感谢。
【解决方案2】:

SQL 2008 有一个新的日期时间类型:datetimeoffset,它确实保留时区信息,因此可用于从 Unix 纪元中提取差异。但这需要升级到 SQL 2008,重新访问您的架构并更改列类型并追溯更新所有现有数据以设置正确的时区。

如果您无法升级到 SQL 2008,那么我建议您始终将日期时间信息存储为 UDT,这意味着在将其插入数据库之前先将其转换为客户端。在适当的本地时间向用户显示数据应该再次在客户端完成。

【讨论】:

    【解决方案3】:

    UNIX 时间戳是没有夏令时的 UTC。因此,如果您无法判断日期是 GMT 还是 BST,则无法将其转换为 UNIX 时间戳。

    【讨论】:

    • 你说得对,我假设 BST 是一个时区。显然,这只是夏天的时间。霍布斯的答案应该就是你所需要的
    • 啊,和往常一样,问题出在问题上。我不是指时区,而是时间偏移。谢谢。
    猜你喜欢
    • 2011-03-20
    • 1970-01-01
    • 1970-01-01
    • 2010-10-15
    • 2020-02-05
    • 2016-11-01
    • 2018-02-08
    • 2012-06-28
    • 1970-01-01
    相关资源
    最近更新 更多