1

[更新] 我正在尝试找到将 UTC 时间戳转换为不同时区的正确方法。

确切的问题:我的程序中有时间戳,它总是存储在 UTC 中,所以很好。但是,我必须能够根据用户偏好在不同的时区显示它们(实际上将它们写入文件)。

我正在使用 linux,但我想编写与 pateform 无关的代码。我不想使用 boost 库(我们已经在使用 Qt,它没有提供与 boost 日期一样多的功能)。我想编写线程安全代码我想识别像美国/东部这样的时区以简化配置(这是由用户完成的,我不太相信他们会正确使用 EST、CET、CEST 等缩写...)。

我已经在 Internet 上查看并发现了一些或多或少的工作代码,但是

  • 大多数时候它使用TZ环境变量,据说这是一种非线程安全的方法。
  • 它使用时区的缩写(如 EST、CET ...)。

有人可以告诉我一个好方法吗?

这是我现在所拥有的(几天前在 Internet 上找到并在此示例中修改为使用我的 Qt 库)。此代码可能不是线程安全的。

新版本: 仍然不是线程安全的,但它或多或少地完成了这项工作。可能不容易移植到窗口环境。

它处理日光变化见下面的例子(巴黎的日光变化发生在 2012 年 3 月 25 日 01H00 UTC(从当地时间 02H00 到当地时间 03H00 传递)。这是将时间戳从 UTC 转换为巴黎(有日光变化)和 Kuala_Lumpur(没有日光变化)。

#include <QtCore/QCoreApplication>
#include <QDateTime>
#include <stdio.h>
#include <stdlib.h>
#include <QDebug>

void treatTimestamp(QString timestamp,QString format);

int main(int argc, char *argv[])
{
    QString format = "MM:dd:yyyy hh:mm:ss";
    treatTimestamp("03:25:2012 00:59:59",format);
    qDebug()<<"---------------------";
    treatTimestamp("03:25:2012 01:00:00",format);
    return 0;
}

void treatTimestamp(QString timestamp_s,QString format)
{
    unsetenv("TZ");
    setenv("TZ", "UTC", 1);
    QDateTime timestamp = QDateTime::fromString(timestamp_s, format);
    qDebug()<<"CUSTOM TS UTC:"<<timestamp.toUTC().toString(format).toStdString().c_str();;
    time_t tmp = timestamp.toUTC().toTime_t();
    setenv("TZ", ":Asia/Kuala_Lumpur", 1);
    qDebug()<<"CUSTOM TS KL:"<<QDateTime::fromTime_t(tmp).toString(format);
    setenv("TZ", "Europe/Paris", 1);
    qDebug()<<"CUSTOM TS Paris:"<<QDateTime::fromTime_t(tmp).toString(format);
    unsetenv("TZ");
}

输出(第一:时间变化前一秒,第二:后一秒)。

自定义 TS LOC:03:25:2012 01:00:00

自定义 TS UTC:03:25:2012 01:00:00

自定义 TS KL:“03:25:2012 09:00:00”

定制 TS 巴黎:“03:25:2012 03:00:00”


自定义 TS LOC:03:25:2012 03:00:00

自定义 TS UTC:03:25:2012 03:00:00

自定义 TS KL:“03:25:2012 11:00:00”

定制 TS 巴黎:“03:25:2012 05:00:00”

4

2 回答 2

1

根据这个线程,使用 QDateTime 可以dateTime.addSecs(3600*timeZoneOffset);在 dateTime 是 QDateTime 的地方做。

根据gmtime reference,C 库中没有内置的时区支持,但您可以通过在tm->tm_hour. 顺便说一句,它不会正确调整日期(与 QDateTime 方法不同)。

根据mktime参考,mktime 将“标准化”日期时间值,因此您可以将时间偏移添加到 tm_hour,调用 mktime。但是,没有指定 mktime 如何调整 struct tm 的字段 - 如果您说,将 tm_hour 设置为 27,它会将 tm_hour 设置为 23 还是将 tm_hour 设置为 3,从而增加 tm_day(可能还有月/年)?

如果我是你,我会简单地使用QDateTime::addSecs方法。

于 2012-04-30T10:22:59.780 回答
0

我给 SigTerm +1,因为他的回答很有建设性。最后,我与用户验证一个正在运行的进程只需要 2 个时区:一个指定的时区和一个 UTC 时区(主要用于日志记录)。所以最后我在程序的顶部使用它 unsetenv("TZ"); setenv("TZ", "", 1);

然后在我需要 UTC 时间的特定部分,我总是调用 Qt toUTC 方法。这真的不令人满意,但完整的软件是关于数据采集的,时间戳是其中的重要部分,所以我不想在代码中进行自己的计算。我听说 Qt5 将实现类似于 boost 库中的时区操作。可能会在代码发布时重构代码。

于 2012-07-08T11:13:54.757 回答