Qt的ISODate格式化日期/时间,包括时区

10

有人知道在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,这不是所需的。


1
另外,由于我的机器输出不同,所以我甚至无法自己重现确切的问题:”2014-02-24T08:51:07“ ”2014-02-24T08:51:07Z“ ”2014-02-24T08:51:07Z“ - László Papp
问题的意思没有改变,也许是你对问题的理解发生了变化。简而言之,我的问题是,是否有更简洁的方法来获得所需的结果,或者我应该记录一个 bug。我认为我的表述非常清楚。 - RobbieE
我正在Windows 8上编译,但我认为这不会有太大的影响。你所在的伦敦时区对你的结果确实有很大影响,因为你处于UTC时区。我的时区是SAST(UTC+2)。从测试输出中可以看出,QDateTime::toTimeSpec(Qt::OffsetFromUTC)将我的本地时间转换为UTC时间,即使时间提前了2个小时。对于你来说,这种转换不会发生,因为你已经处于UTC时区。 - RobbieE
将系统时区更改为“哈拉雷,普利托里亚或约翰内斯堡(UTC + 2)”,然后重新运行您的代码,您应该得到与我相同的结果。 - RobbieE
我已经尝试过了,但我个人无法重现这个问题。 - László Papp
显示剩余2条评论
3个回答

6

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

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

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


5
这个功能在5.2之前并不存在,但是在那之后被整合了进来。不过看起来你的语法有误,正确的应该是这样的:
QDateTime::currentDateTime().toTimeSpec(Qt::OffsetFromUTC).toString(Qt::ISODate)

根据相应的bug报告。注意中间的toTimeSpec(Qt::OffsetFromUTC)调用。

那是我尝试的第一件事。结果发现,每当你将timespec设置为Qt::OffsetFromUTC时,它会将内部偏移分钟清零。在函数执行后期,由于偏移量为0,timespec被更改为Qt::UTC,导致结果为2014-02-24T08:23Z - RobbieE
1
我的原始问题是询问是否有更干净的方法来获取包含时区部分的ISO日期,或者这是否是一个错误。您确实给了我一种更干净的方法,但这并没有给我正确的输出,它将我的时区转移到了UTC。如果您正在获得正确的输出,则我怀疑我们没有使用相同的次要版本。正如我所说,我正在使用5.2.1。也许这是一个引入的错误。我将接受您的答案,但我也将其记录为Digia的错误。 - RobbieE
@RobbieE:你还没有提供一个自包含测试案例。即使是Digia也会要求这样做,我想。我的意思是,在一个空的主函数中打印出那一行会得到正确的结果,就像你所请求的那样。 - László Papp
非常抱歉,我以为我表达得很清楚。我会提供一个完全自包含的示例来展示我的意思。 - RobbieE
就我所知,在基于嵌入式Linux系统上,Qt 5.3并不能解决这个问题。我需要使用类似@rudolf-cardinal答案的自定义方法。 - Matthew Eshleman
请注意,QDateTime::toTimeSpec()函数将在Qt 6.9中被弃用,因此现在应避免使用此函数。https://doc.qt.io/qt-6/qdatetime-obsolete.html#toTimeSpec - Paul Masri-Stone

4

这似乎可以工作,具有毫秒级准确度和时区信息的保留:

#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'));
        // https://dev59.com/SXE85IYBdhLWcg3wx2j2
    }
    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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接