【问题标题】:c++ strptime ignores Timezone when parsingc ++ strptime在解析时忽略时区
【发布时间】:2013-07-23 04:17:51
【问题描述】:

当我运行以下代码时,strptime 似乎忽略了时区值。只需设置本地时区的值(即 +10)。

这是输出,(在 Linux 上运行,使用 gcc 4.6.3 编译):

-----------2013-04-24T9:47:06+400 - %Y-%m-%dT%H:%M:%S%z
TM Break    H:9 is DST:0 GMT Off:0
The epoch value:    1366760826
DateTime in String:     04/24/13 - 09:47AM +1000

-----------2013-04-24T11:47:06+800 - %Y-%m-%dT%H:%M:%S%z
TM Break    H:11 is DST:0 GMT Off:36000
The epoch value:    1366768026
DateTime in String:     04/24/13 - 11:47AM +1000

-----------2013-04-24T9:47:06+0 - %Y-%m-%dT%H:%M:%S%z
TM Break    H:9 is DST:0 GMT Off:36000
The epoch value:    1366760826
DateTime in String:     04/24/13 - 09:47AM +1000

-----------2013-04-24T9:47:06+4 - %Y-%m-%dT%H:%M:%S%z
TM Break    H:9 is DST:0 GMT Off:36000
The epoch value:    1366760826
DateTime in String:     04/24/13 - 09:47AM +1000

这是代码:

void date_Test(){
    string dateStrings[] = {"2013-04-24T9:47:06+400"
                          , "2013-04-24T11:47:06+800"
                          , "2013-04-24T9:47:06+0"
                          , "2013-04-24T9:47:06+4"};
    string formatStrings[] = {"%Y-%m-%dT%H:%M:%S%z"
                            , "%Y-%m-%dT%H:%M:%S%z"
                            , "%Y-%m-%dT%H:%M:%S%z"
                            , "%Y-%m-%dT%H:%M:%S%z"};

process_Timezone(dateStrings, formatStrings);
}

void process_Timezone(string dateStrings[], string formatStrings[]){
    int num = 4; 

    for (int i = 0; i < num; i++) {
        cout << endl << "-----------" << dateStrings[i] << " - " << formatStrings[i] << endl;
        tm *dtm = new tm;
        strptime(dateStrings[i].c_str(), formatStrings[i].c_str(), dtm);
        cout << "TM Break \tH:" << dtm->tm_hour << " is DST:" << dtm->tm_isdst << " GMT Off:"  << dtm->tm_gmtoff << endl;
        time_t ep_dt = mktime(dtm);
        cout << "The epoch value: \t" << ep_dt << endl;
        char buffer[40];
        strftime(buffer, 40,"%x - %I:%M%p %z", dtm);
        cout << "DateTime in String: \t" << buffer << endl;
        delete dtm;
    }
}

【问题讨论】:

    标签: c++ parsing time timezone strptime


    【解决方案1】:

    根据http://en.wikipedia.org/wiki/ISO_8601,您的一位和三位时区偏移量不是有效的 ISO 8601 值(strptime 至少在 Linux 上使用的格式),这需要hh[:][mm] 作为格式。

    【讨论】:

    • 我尝试过 0400、04:00 之类的变体,但都没有奏效,甚至无法在网上找到有人使用它的示例
    • 嘿,祝你好运,我有同样的问题..如何从具有时区的字符串创建 time_t
    【解决方案2】:

    可能会迟到,但strptime 确实正确解析了%z 说明符,它将其存储在tm.tm_gmtoff 变量中。这个变量不在标准中,而是一个 gnu 扩展。 mktime 没有使用这个变量。

    你可以试试

    strptime(<time_string>, dtm);
    std::cout << dtm->tm_gmtoff;
    

    查看解析的时间偏移量。

    注意.tm_gmtoff是秒,所以要得到正确的纪元时间,你可以这样做

    auto offset = dtm->tm_gmtoff;
    auto _epoch = mktime(dtm);
    auto final_epoch = _epoch + offset
    

    来源

    【讨论】:

    • 这对我有帮助,所以请投赞成票,但除非您在 UTC 中运行,否则我认为这不太正确。为了解释原因,我需要更多的空间而不是评论,所以提交了我自己的答案。
    【解决方案3】:

    @Nguyen Ha Kien 的回答对我有帮助,但为了获得正确的纪元时间,我还需要在 mktime 填写本地 UTC 偏移量后将其考虑在内,而不是覆盖 libc 确定 DST 是否处于活动状态在此处指定时间:

            int offset = dtm->tm_gmtoff;
            // Ask libc to work out whether the local timezone is in DST at this time.
            dtm->tm_isdst = -1;
            time_t ep_dt = mktime(dtm);
            ep_dt -= offset - dtm->tm_gmtoff;
    

    int 而不是 auto 只是因为我正在编译 2011 时代的设置,希望像 pt123 最初使用的那样,以表明 Mark B 的答案得到 strptime 来为我解析 tm_gmtoff:

    (ia32)martind@sirius:~/playpen$ ls /lib/libc-2.11.3.so 
    /lib/libc-2.11.3.so
    (ia32)martind@sirius:~/playpen$ gcc -v
    ...
    gcc version 4.4.5 (Debian 4.4.5-8) 
    (ia32)martind@sirius:~/playpen$ g++ c-strptime-ignores-timezone-when-parsing.cpp 
    (ia32)martind@sirius:~/playpen$ ./a.out
    
    -----------2013-04-24T9:47:06+0400 - %Y-%m-%dT%H:%M:%S%z
    TM Break    H:9 is DST:0 GMT Off:14400
    

    唯一的附加代码是:

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    void process_Timezone(string dateStrings[], string formatStrings[]);
    void date_Test();
    int main(){
        date_Test();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-20
      • 1970-01-01
      • 1970-01-01
      • 2011-01-09
      • 2023-03-22
      • 2020-04-08
      • 1970-01-01
      相关资源
      最近更新 更多