在这个答案中,有:
int main()
{
std::string strUTCTime = "2017-03-17T13:20:00Z";
std::wstring wstrUTCTime = std::wstring(strUTCTime.begin(),strUTCTime.end());
time_t utctime = getEpochTime(wstrUTCTime.c_str());
struct tm tm;
/*Convert UTC TIME To Local TIme*/
localtime_s(&tm, &utctime);
char CharLocalTimeofUTCTime[30];
strftime(CharLocalTimeofUTCTime, 30, "%Y-%m-%dT%H:%M:%SZ", &tm);
string strLocalTimeofUTCTime(CharLocalTimeofUTCTime);
std::cout << "\n\nLocal To UTC Time Conversion:::" << strLocalTimeofUTCTime;
}
std::time_t getEpochTime(const std::wstring& dateTime)
{
/* Standard UTC Format*/
static const std::wstring dateTimeFormat{ L"%Y-%m-%dT%H:%M:%SZ" };
std::wistringstream ss{ dateTime };
std::tm dt;
ss >> std::get_time(&dt, dateTimeFormat.c_str()); // (1)
/* Convert the tm structure to time_t value and return Epoch. */
return _mkgmtime(&dt);
}
我从解决方案一开始就心存疑虑,我在另一个问题中提出这个问题,因为该解决方案代表了多个类似的解决方案:首先依赖于
get_time
,然后依赖于mktime
。
我对情况的理解是(看线
(1)
):
stringstream
上的默认区域设置都是与机器对应的区域设置(例如,当地时间)。get_time
考虑流中所灌输的语言环境来解析其“输入”;换句话说:它认为解析的字符串是一个时间点,根据“本地日历”以给定的格式表示;但事实并非如此,它是 UTC 日期(来自“UTC”时区)!解析 UTC 日期时间并认为它是本地日期时间,这不存在任何语义问题吗?我真的不明白这个“逻辑不匹配”是如何解决的。这对我来说毫无意义。
注意: 对于那些向我推荐此解决方案替代方案的人(尽管这不是我的问题),我无法使用 C++20。我最多可以使用 C++17,以及任何 POSIX 和/或 Linux 特定的函数(gcc 8.5、Linux 内核 3.x)。
getEpochTime
对于时区而言可以正确工作。 UTC 和当地时间之间没有实际差异。
更多细节:
问题中的
dateTimeFormat
值"%Y-%m-%dT%H:%M:%SZ"
是较长的ISO 8601格式,如date + "T" + time + time_zone
,其中时区字符串"Z"
表示UTC == GMT。
ss >> std::get_time(..., dateTimeFormat)
仅接受更长的ISO 8601格式(如"Z"
中指定)的UTC字符串(以dateTimeFormat
结尾,如dateTimeFormat
中指定)。它的输出结构体std::tz
不包含任何指示时区的字段。
ss >> std::get_time(..., dateTimeFormat)
调用在解析月份和工作日名称时尊重当前区域设置(例如,如果区域设置是英语,则 "%b"
、"%h"
和 "%B"
转换说明符在输入字符串中接受 October
,并且它们接受Oktober
相反,如果当地人是德国人)。但是,指定的 dateTimeFormat
不使用任何特定于区域设置的转换说明符,因此该特定调用与区域设置无关。
ss >> std::get_time(..., dateTimeFormat)
调用会忽略时区。
在
ss >> std::get_time(&dt, dateTimeFormat)
调用之后,dt
结构体(std::tm
)将填充 6 个字段(年、月、日、时、分、秒)。 (也许其他字段也会被填充。)
_mkgmtime(&dt);
调用将std::dt
的6个字段转换为time_t
类型的有符号整数(假设时区UTC == GMT)。