【问题标题】:construct date in a different locale than current在与当前不同的语言环境中构建日期
【发布时间】:2013-06-26 10:37:50
【问题描述】:

我有一个要求,将日期时间、语言环境和夏令时作为固定长度字符串输入,例如YYMMDDHHMMCY,下面提供了图例。

  1. YY(年)
  2. MM(月)
  3. DD(天)
  4. HH(小时)
  5. MM(分钟)
  6. 时区(C 代表中部,P 代表太平洋,M 代表山区,E 代表东部)
  7. 夏令时(如果夏令时生效,则为 Y,否则为 N)

需要的是能够在指定时区中构造时间,然后在 C/C++ 中将其转换为本地时区。我们不使用 Boost,是否有现有的功能可以满足要求。我知道strptime,在对数据进行一些按摩后,我可以使用它,但我想知道是否有如上所述的函数可以让我在指定的语言环境中构造一个结构。

【问题讨论】:

    标签: c++ c


    【解决方案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;
    }
    

    【讨论】:

    • 重新设置环境变量TZ后,回到旧变量,应该调用tzset();再次。
    • @Jimm 发布的代码都准备好了确实调用tzset(),就在return t 之前。它不会在错误处理时调用 tzset(),因为需要根据 OP 扩展该代码区域(我现在注意到的是你)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-11
    • 2021-05-20
    • 1970-01-01
    • 1970-01-01
    • 2021-10-29
    • 1970-01-01
    相关资源
    最近更新 更多