如何在 C++ 中构建 ISO 8601 日期时间?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9527960/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I construct an ISO 8601 datetime in C++?
提问by chikuba
I'm working with the Azure REST API and they are using this to create the request body for table storage:
我正在使用 Azure REST API,他们正在使用它来创建表存储的请求正文:
DateTime.UtcNow.ToString("o")
Which produces:
其中产生:
2012-03-02T04:07:34.0218628Z
2012-03-02T04:07:34.0218628Z
It is called "round-trip" and apparently it's an ISO standard (see http://en.wikipedia.org/wiki/ISO_8601) but I have no idea how to replicate it after reading the wiki article.
它被称为“往返”,显然它是一个 ISO 标准(参见http://en.wikipedia.org/wiki/ISO_8601),但我不知道如何在阅读 wiki 文章后复制它。
Does anyone know if Boosthas support for this, or possibly Qt?
回答by strcat
If the time to the nearest second is precise enough, you can use strftime
:
如果到最接近秒的时间足够精确,您可以使用strftime
:
#include <ctime>
#include <iostream>
int main() {
time_t now;
time(&now);
char buf[sizeof "2011-10-08T07:07:09Z"];
strftime(buf, sizeof buf, "%FT%TZ", gmtime(&now));
// this will work too, if your compiler doesn't support %F or %T:
//strftime(buf, sizeof buf, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now));
std::cout << buf << "\n";
}
If you need more precision, you can use Boost:
如果您需要更高的精度,可以使用 Boost:
#include <iostream>
#include <boost/date_time/posix_time/posix_time.hpp>
int main() {
using namespace boost::posix_time;
ptime t = microsec_clock::universal_time();
std::cout << to_iso_extended_string(t) << "Z\n";
}
回答by Gillespie
Using the datelibrary (C++11):
使用日期库(C++11):
template <class Precision>
string getISOCurrentTimestamp()
{
auto now = chrono::system_clock::now();
return date::format("%FT%TZ", date::floor<Precision>(now));
}
Example usage:
用法示例:
cout << getISOCurrentTimestamp<chrono::seconds>();
cout << getISOCurrentTimestamp<chrono::milliseconds>();
cout << getISOCurrentTimestamp<chrono::microseconds>();
Output:
输出:
2017-04-28T15:07:37Z
2017-04-28T15:07:37.035Z
2017-04-28T15:07:37.035332Z
回答by Rahim Khoja
I should point out I am a C++ newb.
我应该指出我是一个 C++ 新手。
I needed string with a UTC ISO 8601 formatted date and time that included milliseconds. I did not have access to boost.
我需要带有 UTC ISO 8601 格式的日期和时间(包括毫秒)的字符串。我没有权限提升。
This is more of a hack than a solution, but it worked well enough for me.
这与其说是解决方案,不如说是一种黑客攻击,但它对我来说效果很好。
std::string getTime()
{
timeval curTime;
gettimeofday(&curTime, NULL);
int milli = curTime.tv_usec / 1000;
char buf[sizeof "2011-10-08T07:07:09.000Z"];
strftime(buf, sizeof buf, "%FT%T", gmtime(&curTime.tv_sec));
sprintf(buf, "%s.%dZ", buf, milli);
return buf;
}
The output looks like: 2016-04-13T06:53:15.485Z
输出看起来像:2016-04-13T06:53:15.485Z
回答by vines
Boost has a libraryfor this.
Boost 有一个用于此的库。
I.e. posix_timehas the from_iso_string()
and to_iso_string()
functions.
即posix_time具有from_iso_string()
和to_iso_string()
功能。
回答by Chris Browet
In Qt, that would be:
在 Qt 中,这将是:
QDateTime dt = QDateTime::currentDateTime();
dt.setTimeSpec(Qt::UTC); // or Qt::OffsetFromUTC for offset from UTC
qDebug() << QDateTime::currentDateTime().toString(Qt::ISODate);
回答by Danie Bruwer
OK so I've modified a few solutions that I've found as came up with the following :
好的,所以我修改了一些我发现的解决方案,如下所示:
static QString getTimeZoneOffset()
{
QDateTime dt1 = QDateTime::currentDateTime();
QDateTime dt2 = dt1.toUTC();
dt1.setTimeSpec(Qt::UTC);
int offset = dt2.secsTo(dt1) / 3600;
if (offset >= 0)
return QString("%1").arg(offset).rightJustified(2, '0',true).prepend("+");
return QString("%1").arg(offset).rightJustified(2, '0',true);
}
Then to easily format a date ( yyyy-MM-dd'T'HH:mm:ss.SSSZ) :
然后轻松格式化日期(yyyy-MM-dd'T'HH:mm:ss.SSSZ):
static QString toISO8601ExtendedFormat(QDateTime date)
{
QString dateAsString = date.toString(Qt::ISODate);
QString timeOffset = Define::getTimeZoneOffset();
qDebug() << "dateAsString :" << dateAsString;
qDebug() << "timeOffset :" << timeOffset;
timeOffset = QString(".000%1%2").arg(timeOffset).arg("00");
qDebug() << "timeOffset replaced :" << timeOffset;
if(dateAsString.contains("Z",Qt::CaseInsensitive))
dateAsString = dateAsString.replace("Z",timeOffset);
else
dateAsString = dateAsString.append(timeOffset);
qDebug() << "dateAsString :" << dateAsString;
return dateAsString;
}
For example GMT +2 would look like this : 2013-10-14T00:00:00.000+0200
例如 GMT +2 看起来像这样: 2013-10-14T00:00:00.000+0200
回答by Joma
Tested in Visual C++, GNU C++, Emscripten
在 Visual C++、GNU C++、Emscripten 中测试
#include <ctime>
#include <chrono>
#include <iostream>
#include <locale>
#if defined (_WIN32)
#define WINDOWSLIB 1
#elif defined (__APPLE__)//iOS, Mac OS
#define MACOSLIB 1
#elif defined (__LINUX__) || defined(__gnu_linux__) || defined(__linux__) || defined(__linux) || defined(linux)//_Ubuntu - Fedora - Centos - RedHat
#define LINUXLIB 1
#elif defined (__EMSCRIPTEN__)
#define EMSCRIPTENLIB 1
#endif
#define WriteLine(data)std::cout<< data <<std::endl;
typedef std::string String;
String CurrentISO8601DateTime(bool toUTC=true)
{
using namespace std::chrono;
system_clock::time_point now = system_clock::now();
time_t timet = system_clock::to_time_t(now);
std::tm tm{};
String localeStr = setlocale(LC_ALL, nullptr);
setlocale(LC_ALL, u8"");
String format = String(u8"%FT%T.").append(std::to_string(duration_cast<milliseconds>(now.time_since_epoch()).count() % static_cast<long long>(1000)));
if (toUTC)
{
#ifdef WINDOWSLIB
gmtime_s(&tm, &timet);
#elif LINUXLIB
gmtime_r(&timet, &tm);
#elif EMSCRIPTENLIB
gmtime_r(&timet, &tm);
#endif
format = format.append(u8"Z");
}
else
{
#ifdef WINDOWSLIB
localtime_s(&tm, &timet);
#elif LINUXLIB
localtime_r(&timet, &tm);
#elif EMSCRIPTENLIB
localtime_r(&timet, &tm);
#endif
format.append(u8"%z");
}
String result = String(255, 0);
const size_t length = std::strftime(&result[0], result.size(), format.c_str(), &tm);
result.resize(length);
setlocale(LC_ALL, localeStr.c_str());
return result;
}
#define ConsoleWriteLn(data) std::cout<< data <<std::endl;
int main()
{
ConsoleWriteLn(u8"UTC : " + CurrentISO8601DateTime());
ConsoleWriteLn(u8"LOCAL: " + CurrentISO8601DateTime(false));
}
Results结果
UTC : 2020-04-12T17:00:18.632Z
LOCAL: 2020-04-12T12:00:18.633-0500
UTC : 2020-04-12T17:00:18.632Z
本地: 2020-04-12T12:00:18.633-0500
You can deserialize normally with Json.NET
您可以使用Json.NET正常反序列化
回答by chikuba
Did it like this:
是不是这样的:
using namespace boost::posix_time;
ptime t = microsec_clock::universal_time();
qDebug() << QString::fromStdString(to_iso_extended_string(t) + "0Z"); // need 7 digits