2013-06-25 52 views
1

我有一個要求,其中日期時間,區域設置和夏令時作爲固定長度字符串輸入,如YYMMDDHHMMCY,其中圖例在下面提供。構建日期在與當前不同的區域設置

  1. YY(年)
  2. MM(月)
  3. DD(日)
  4. HH(小時)
  5. MM(分鐘)
  6. 時區(C爲中心,P爲太平洋,M代表山區,E代表東部)
  7. 夏令時(Y如果夏令時有效,其他明智N)

所需要的是能夠在指定的時區中構建時間,然後在C/C++中將其轉換爲本地時區。我們不使用Boost,有沒有現有的功能可以滿足要求。我知道strptime,它在一些按摩數據後,我可以使用它,但我想知道是否有如上所述的功能,這將允許我在指定的區域構造一個結構。

回答

1

使用sscanf()strptime()來提取大部分字段。時區字符和DST字符需要自行解碼。由於您僅使用2位數年份,因此您需要定義範圍。下面的例子使用1970-2069。使用提取的時區字符來形成通常的時區名稱。在致電mktime()之前,請將TZ設置爲時區名稱。然後,手中有time_t,轉換爲當地時間。

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

extern time_t mktime_TZ(struct tm *tm, const char *tz); 
extern time_t DecodeTimeString_time_t(const char *time_string); 

void DecodeTimeString_Local(const char *time_string, struct tm *local) { 
    // Various error handling not shown 
    time_t t; 
    t = DecodeTimeString_time_t(time_string); 
    *local = *localtime(&t); 
} 

time_t DecodeTimeString_time_t(const char *time_string /* YYMMDDHHMMCY */) { 
    struct tm tm; 
    char Zone, DST; 
    int result = sscanf(time_string, "%2d%2d%2d%2d%2d%[CEMP]%[NY]", 
     &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &Zone, &DST); 
    if (result != 7) { 
     ; // handle error 
    } 
    // Your need to decide how to handle 2 digits years 
    // Assume 70-99 is 1970-1999 and 0 to 69 is 2000-2069 
    if (tm.tm_year < 70) tm.tm_year += 2000-1900; 
    tm.tm_mon--; // Assume DateString used "01" for January, etc. 
    tm.tm_sec = 0; 
    tm.tm_isdst = Zone == 'Y'; 
    const char *TZ; 
    switch (Zone) { 
     case 'P': TZ = "PST8PDT"; break; // Pacific 
     case 'M': TZ = "MST7MDT"; break; // mountain 
     case 'C': TZ = "CST6CDT"; break; // central 
     case 'E': TZ = "EST5EDT"; break; // eastern 
    } 
    time_t t = mktime_TZ(&tm, TZ); 
    return t; 
    } 

// Form time_t from struct tm given a TZ 
time_t mktime_TZ(struct tm *tm, const char *tz) { 
    time_t t; 
    const char *old_tz = getenv("TZ"); 
    if (setenv("TZ", tz, 1 /* overwrite */)) { 
    return -1; // handle error 
    } 
    tzset(); 
    t = mktime(tm); 
    if (old_tz) { 
    if (setenv("TZ", old_tz, 1 /* overwrite */)) { 
     return -1; // handle error 
    } 
    } 
    else { 
    if (unsetenv("TZ")) { 
     return -1; // handle error 
    } 
    } 
    tzset(); 
    return t; 
} 
+0

將環境變量TZ重新設置回舊變量後,應該調用tzset();再次。 – Jimm

+0

@Jimm發佈的代碼準備好在'return t'之前調用'tzset()'。它不會在錯誤處理中調用'tzset()',因爲該代碼區域需要根據OP進行擴展(現在我注意到了你)。 – chux

相關問題