2013-06-25 54 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

相关问题