【问题标题】:Qt ISODate formatted date/time including timezoneQt ISODate 格式的日期/时间,包括时区
【发布时间】:2014-03-25 10:29:14
【问题描述】:

有谁知道将时区包含在 QDateTime 的 ISO 字符串表示中的更简洁的方法?

我应该能够使用以下内容:

qDebug() << QDateTime::currentDateTime().toString(Qt::ISODate);

但这总是以 UTC 格式输出:

2014-02-24T01:29:00Z

目前,我解决此问题的方法是通过显式设置偏移量来强制 TimeSpec 为 Qt::offsetFromUtc,这是我最初从 QDateTime 获得的。

QDateTime now = QDateTime::currentDateTime();
int offset = now.offsetFromUtc();
now.setOffsetFromUtc(offset);
qDebug() << now.toString(Qt::ISODate);

这给出了最初的预期:

2014-02-24T01:29:00+02:00

有谁知道如何以更简洁的方式执行此操作,或者必须将其记录为错误?

编辑:我正在使用 Qt5.2.1

更新:

下面的小程序说明了我的意思:

#include <QtCore/QDateTime>
#include <QtCore/QDebug>

int main(int argc, int argv){
    qDebug() << QDateTime::currentDateTime().toString(Qt::ISODate);
    qDebug() << QDateTime::currentDateTime().toTimeSpec(Qt::OffsetFromUTC).toString(Qt::ISODate);

    QDateTime now = QDateTime::currentDateTime();
    int offset = now.offsetFromUtc();
    now.setOffsetFromUtc(offset);
    qDebug() << now.toString(Qt::ISODate);

    return 0;
}

生成以下输出:

"2014-02-24T10:20:49" 
"2014-02-24T08:20:49Z" 
"2014-02-24T10:20:49+02:00"

最后一行是预期的。请注意,第二次已转换为 UTC,这不是我们想要的。

【问题讨论】:

  • 另外,我的机器上的输出不同,所以我自己什至无法重现确切的问题:"2014-02-24T08:51:07" "2014-02-24T08:51:07Z" "2014-02-24T08:51:07Z"
  • 这个问题没有改变它的意思,也许你对这个问题的理解已经改变了。简而言之,我问是否有更简洁的方法来获得所需的结果,或者我是否应该记录一个错误。我认为我对此非常清楚。
  • 您使用的是什么版本的 Qt。我正在使用 5.2.1。我提供的代码是我实际编译和运行的代码,而不仅仅是我脑海中的想法。结果是我的机器生成的实际结果,因此它有资格作为 SSCCE。感谢拉斯洛的意见。我会将您的答案标记为正确。尽管答案对我没有帮助,但我会假设您的代码是 Qt 应该如何工作的,我将使用 Digia 记录一个错误。
  • 是的,我在 Archlinux 上使用相同的,如果这很重要的话。不确定它是否与我的伦敦时区有关,所以没有 +/- 小时差异。
  • 我在 Windows 8 上编译,但我认为这不会有太大的不同。您的时区是伦敦,确实会对您的结果产生很大影响,因为您在 UTC。我的时区是 SAST (UTC+2)。您可以从测试输出中看到 QDateTime::toTimeSpec(Qt::OffsetFromUTC) 将我的本地时间转换为 UTC 时间,即将时间提前 2 小时。对你来说,这种转变不会发生,因为你已经在 UTC 时区。

标签: c++ qt qtcore qdatetime qdate


【解决方案1】:

当我需要时,我使用以下解决方法:

QDateTime::currentDateTime().toOffsetFromUtc(QDateTime::currentDateTime().offsetFromUtc()).toString(Qt::ISODate);

我还没有测试@lpappa 是否正在开发新版本。上述解决方法已在 Qt 5.3 上测试过

【讨论】:

    【解决方案2】:

    这在 5.2 之前不存在,但它已集成在其中。看来您的语法不正确,因为它应该是这样的:

    QDateTime::currentDateTime().toTimeSpec(Qt::OffsetFromUTC).toString(Qt::ISODate)
    

    根据corresponding bugreport。注意toTimeSpec(Qt::OffsetFromUTC)在中间调用。

    【讨论】:

    • 这是我尝试的第一件事。事实证明,每当您将 timespec 设置为 Qt::OffsetFromUTC 时,它会将内部偏移分钟数归零。后来在函数执行中,因为偏移量为0,所以timespec改为Qt::UTC,导致2014-02-24T08:23Z
    • 我最初的问题是询问是否有更简洁的方法来获取包含时区部分的 ISOdate,或者这是否是一个错误。您确实给了我一个更清洁的方法,但这并没有给我正确的输出,它将我的时区转换为 UTC。如果你得到正确的输出,我怀疑我们没有使用相同的次要版本。正如我所说,我使用的是 5.2.1。也许这是一个引入的错误。我会接受你的回答,但我也会将其作为 Digia 的错误记录。
    • @RobbieE:你还没有提供self-contained test case。我想,即使是 Digia 也会要求这样做。通过工作,我的意思是打印该行会在空的 main 函数中提供正确的结果,就像您似乎要求的那样。
    • 抱歉,我以为我说得很清楚。我将举一个完全独立的例子来说明我的意思。
    • FWIW,在基于嵌入式 linux 的系统 Qt 5.3 上,这不能解决问题。我需要使用类似于@rudolf-cardinal answer的自定义方法
    【解决方案3】:

    这似乎可行,具有毫秒精度并保留时区信息:

    #include <QDebug>
    #include <QTimeZone>
    
    QString datetimeToIsoMs(const QDateTime& dt)
    {
        // An ISO-8601 format preserving millisecond accuracy and timezone.
        // Equivalent in moment.js: thing.format("YYYY-MM-DDTHH:mm:ss.SSSZ")
        // Example: '2016-06-02T10:04:03.588+01:00'
        // Here we also allow 'Z' for UTC.
    
        // In Qt, BEWARE:
        //      dt;  // QDateTime(2016-06-02 10:28:06.708 BST Qt::TimeSpec(LocalTime))
        //      dt.toString(Qt::ISODate);  // "2016-06-02T10:28:06" -- DROPS timezone
        QString localtime = dt.toString("yyyy-MM-ddTHH:mm:ss.zzz");
        int offsetFromUtcSec = dt.offsetFromUtc();
        // FOR TESTING: offsetFromUtcSec = -(3600 * 2.5);
        QString tzinfo;
        if (offsetFromUtcSec == 0) {
            tzinfo = "Z";
        } else {
            QString sign = offsetFromUtcSec < 0 ? "-" : "+";
            offsetFromUtcSec = abs(offsetFromUtcSec);
            int hours = offsetFromUtcSec / 3600;
            int minutes = (offsetFromUtcSec % 3600) / 60;
            tzinfo += QString("%1%2:%3").arg(sign)
                .arg(hours, 2, 10, QChar('0'))
                .arg(minutes, 2, 10, QChar('0'));
            // http://stackoverflow.com/questions/2618414/convert-an-int-to-a-qstring-with-zero-padding-leading-zeroes
        }
        return localtime + tzinfo;
    }
    
    QString datetimeToIsoMsUtc(const QDateTime& dt)
    {
        QDateTime utc_dt = dt.toTimeSpec(Qt::UTC);
        return datetimeToIsoMs(utc_dt);
    }
    
    QDateTime isoToDateTime(const QString& iso)
    {
        return QDateTime::fromString(iso, Qt::ISODate);
    }
    

    【讨论】:

      猜你喜欢
      • 2022-06-29
      • 1970-01-01
      • 2018-02-22
      • 1970-01-01
      • 2023-04-09
      • 1970-01-01
      • 2021-05-15
      • 2017-03-28
      • 1970-01-01
      相关资源
      最近更新 更多