2012-11-25 816 views
4

我是C新手。當我練習C來隱藏時間刺激來構造tm來回。我注意到一些差異。請諮詢我做錯了什麼。c/C++ strptime()不解析%Z時區名稱

#include <string.h> 
#include <stdio.h> 
#include <time.h> 

/* 
test different format string to strptime 
" %A, %b %d, %X %z %Y " 
" %A, %b %d, %X %Z %Y " 
*/ 
int main(int argc,char *argv[]) 
{ 

    char date[] = "6 Mar 2001 12:33:45"; 
    char fmt[80]; 
    struct tm tm; 

    if (argc==1) return 0; 
    strcpy(fmt,argv[1]); 
    memset(&tm, 0, sizeof(struct tm)); 
    if (strptime(date,"%d %b %Y %H:%M:%S",&tm)==NULL) printf("error\n"); 
    char buf[128]; 
    strftime(buf, sizeof(buf), fmt, &tm); 
    printf("%s\n", buf); 
    printf("%d\n", tm.tm_isdst); 
    if (strptime(buf,fmt,&tm)==NULL) printf("error\n"); 
    else { 
    printf("year: %d; month: %d; day: %d;\n", 
     tm.tm_year, tm.tm_mon, tm.tm_mday); 
    printf("hour: %d; minute: %d; second: %d\n", 
     tm.tm_hour, tm.tm_min, tm.tm_sec); 
    printf("week day: %d; year day: %d\n", tm.tm_wday, tm.tm_yday); 
    } 
    return 0; 
} 

當我使用 「%A,%B%d,%X%Z%Y」 作爲轉換格式參數,該代碼提供一些結果如下:

~/user$ ./test_time " %A, %b %d, %X %z %Y " 
Tuesday, Mar 06, 12:33:45 +0000 2001 
0 
year: 101; month: 2; day: 6; 
hour: 12; minute: 33; second: 45 
week day: 2; year day: 64 

當我改變參數到「%A,%b%d,%X%Z%Y」,代碼無法解析由strftime生成的時間字符串,其格式完全相同。

~/user$ ./test_time " %A, %b %d, %X %Z %Y " 
    Tuesday, Mar 06, 12:33:45 EET 2001 
0 
error 

我錯過了什麼讓strptime正確解析時區名?

由於提前,

阿爾伯特

+0

這看起來像C給我。爲什麼你要標記C++,特別是C++ 11? –

+0

@Pascal Cuoq你是對的。這是C代碼。我用g ++編譯它。應該沒關係吧? – Albert

+0

只要您牢記以下差異列表,就不應該這樣做。 http://stackoverflow.com/questions/10461331/what-are-the-incompatible-differences-betweeen-c99-and-c11。該頁面甚至沒有列出我的最愛:在C++中,'c'的類型爲'char','c'的類型爲'const char *'。 –

回答

6

我不知道你在做什麼工作。該glibc source code在github上有這樣一段對此事說:

case 'Z': 
    /* XXX How to handle this? */ 
    break 

其次是一些稍微「肉」的小寫'z'東西處理:-)

那麼,什麼是最有可能發生在這裏是字符串當格式字符串爲%Z時,指針不會超過EET,因此當它試圖處理%Y時,它正確地抱怨EET不是有效年份。這是由"%%"的簡單情況下的代碼實際上確實推進輸入字符串的指針rp證實:

case '%': 
    /* Match the `%' character itself. */ 
    match_char ('%', *rp++); 
    break; 

Linux手冊頁還對擴展名(其中'Z'就是其中之一)指出:

由於對稱性原因,glibc嘗試支持strptime()與strftime(3)相同的格式字符。 (在大多數情況下,相應的字段進行解析,但在TM沒有字段被更改。)

此外GNU docs狀態(我的斜體字):

%Z:的時區名稱。注意:目前尚未完全實施。格式被識別,輸入消耗但tm中沒有字段被設置。

所以我實際上認爲這是一個錯誤,雖然可以通過文檔更改輕鬆修復,以防止它假裝可以處理Z類型的時區。

我在bugzilla中找不到任何相關的bug,所以我在那裏提出了一個glibc的bug。您可以跟蹤它here


附錄:按照在上段和bug報告鏈接glibc 2.19 release notice,我建議更改已經作出對準文檔中的代碼。希望它沒有錯誤,或者由於它只有五行代碼,我會看起來非常愚蠢。

+0

聽起來合理。根據[man strptime.3](http://www.kernel.org/doc/man-pages/online/pages/man3/strptime.3.html),我期待與** strftime **類似的實現。指定不支持的描述符是否很難? – Albert

+0

你的期望比合理,我自己做到了。正如Yoda所說:「支持,或者支持,沒有'嘗試'。」他們應該執行這個或停止假裝它存在。當我到達一臺真正的電腦(這個Android標籤是一種很痛苦的打字方式)時,我會考慮提交一份錯誤報告。 – paxdiablo