如何在Windows上以ISO 8601格式获取日期时间?

时间:2017-02-22 11:23:09

标签: c++ windows datetime datetime-format iso8601

使用C ++在Windows上以ISO8601格式获取日期时间的标准方法是什么?具体来说,我希望它格式化为:

2017-02-22T10:00:00.123-05:00 2017-02-22T10:00:00.123 >>> -05:00 <<< # how to print the offset?

我正在考虑将GetLocalTimeGetTimeZoneInformation的输出结合起来,但这看起来很神秘。在SO上有类似的问题,但是,我没有找到一个以所需格式打印UTC偏移的问题。有更好的方法吗?

4 个答案:

答案 0 :(得分:1)

也许是这样的。我们调用GetLocalTimeGetTimeZoneInformation然后将其传递给返回格式化字符串的函数。

这是快速写的,除了观察它在我的机器现在上返回正确结果的事实之外没有经过测试。它基于以下事实:SYSTEMTIME有一个成员Bias,其中UTC = Localtime + BiasBias在几分钟内设置。因此,将小时数除以60并取其绝对值。然后我们以类似的方式得到分钟,并根据Bias > 0

设置符号
#include <Windows.h>
#include <string>
#include <sstream>
#include <iomanip>
#include <cmath>

std::string format_system_time(const SYSTEMTIME& sys_time, const TIME_ZONE_INFORMATION& time_zone)
{
    std::ostringstream formatted_date_time;
    formatted_date_time << std::setfill('0');
    formatted_date_time << sys_time.wYear <<  "-" << std::setw(2) << sys_time.wMonth << "-" <<
        std::setw(2) << sys_time.wDay << "T" << std::setw(2) << sys_time.wHour << ":" <<
        std::setw(2) << sys_time.wMinute << ":" << std::setw(2) << sys_time.wSecond << "." <<
        std::setw(3) << sys_time.wMilliseconds;

    //UTC = localtime + bias; bias is in minutes
    int utc_offset_hours = time_zone.Bias / 60;
    int utc_offset_minutes = std::abs(time_zone.Bias - (utc_offset_hours * 60));
    char offset_sign = time_zone.Bias > 0 ? '-' : '+';
    formatted_date_time << offset_sign << std::setw(2) << std::abs(utc_offset_hours) << ":" << utc_offset_minutes;

    return formatted_date_time.str();
}

int main(int argc, char* argv[])
{
    SYSTEMTIME date_and_time;
    GetLocalTime(&date_and_time);

    TIME_ZONE_INFORMATION time_zone;
    GetTimeZoneInformation(&time_zone);

    auto& formatted_date_time = format_system_time(date_and_time, time_zone);

    return 0;
}

答案 1 :(得分:1)

我认为在Windows上没有针对c ++的插件解决方案。您可以获得的最接近的是GetLocalTime,但它仅记录为支持RFC1123。

您可能需要使用GetTimeZoneInformation + wsprintf + GetTimeZoneInformationForYear(或{{1}},如果您不处理当前时间)自行编码。

答案 2 :(得分:0)

使用适用于VS-2013及更高版本的Howard Hinnant's free, open-source timezone library,但需要一些installation

#include "tz.h"
#include <iostream>

int
main()
{
    using namespace std;
    using namespace std::chrono;
    using namespace date;
    auto zt = make_zoned(current_zone(), floor<milliseconds>(system_clock::now()));
    cout << format("%FT%T%Ez\n", zt);
}

这只是我的输出:

2017-02-22T17:29:03.859-05:00

答案 3 :(得分:0)

格式说明符%z为您提供文档中描述的时区偏移量(例如MSDN on strftime),但保留了“:”。您可以像这样使用它来将':'加入到字符串中:

struct tm tmNow;

time_t now = time(NULL);    // Get the current time
_localtime64_s(&tmNow, &now);

char bufferTime[26];
char bufferTimezoneOffset[6];
size_t tsizTime =  strftime(bufferTime, 26, "%Y-%m-%dT%H:%M:%S", &tmNow);   // The current time formatted "2017-02-22T10:00:00"
size_t tsizOffset =  strftime(bufferTimezoneOffset, 6, "%z", &tmNow);       // The timezone offset -0500
strncpy_s(&bufferTime[tsizTime], 26, bufferTimezoneOffset, 3);              // Adds the hour part of the timezone offset
bufferTime[tsizTime + 3] = ':';                                             // insert ':'
strncpy_s(&bufferTime[tsizTime + 4], 26, &bufferTimezoneOffset[3], 3);      // Adds the minutes part of the timezone offset
puts(bufferTime);   // Your output: "2017-02-22T10:00:00-05:00"

我遗漏了毫秒,因为据我所知,他们不属于当地时间。