【问题标题】:c/c++ strptime() does not parse %Z Timezone namec/c++ strptime() 不解析 %Z 时区名称
【发布时间】:2012-11-25 22:31:20
【问题描述】:

我是 C 的新手。当我练习 C 来隐蔽时间刺痛来回构造 tm 时。我注意到了一些不同。请指教我做错了什么。

#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 正确解析时区名称的内容?

提前致谢,

阿尔伯特

【问题讨论】:

  • 这在我看来像 C。为什么要标记它 C++,尤其是 C++11?
  • @Pascal Cuoq 你是对的。是C代码。我用 g++ 编译它。应该没关系吧?
  • 只要您牢记以下差异列表,就不应该这样做。 stackoverflow.com/questions/10461331/… 。而且该页面似乎甚至没有列出我的最爱:在 C++ 中,'c' 的类型为 char,而“c”的类型为 const char*

标签: c timezone strptime timestamp-with-timezone


【解决方案1】:

我不确定你在做什么会奏效。 github 的glibc source code 对此有话说:

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-type 时区。

我在 bugzilla 中找不到任何相关的错误,所以我在 glibc 上提出了一个错误。你可以追踪它here


附录:根据上一段中的错误报告链接和glibc 2.19 release notice,我建议的更改已使代码与文档保持一致。希望它没有错误,否则我看起来很傻,因为它只有五行代码。

【讨论】:

  • 听起来很合理。根据man strptime.3,我期待与 strftime 类似的实现。指定不支持的描述符有那么难吗?
  • 你的期望是非常合理的,我自己也有。正如尤达所说:“支持。或者不支持。没有‘尝试’。”他们要么实现这一点,要么停止假装它存在。当我使用真正的 PC 时(这个 Android 选项卡很难打字),我会考虑提交错误报告。
猜你喜欢
  • 2020-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多