我正在使用strptime(3)解析表示日期的字符串:

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

int main () {
  struct tm t;
  strptime("2015-04-19 12:00:00", "%F %T", &t); /* Sunday */
  printf("%d\n", t.tm_wday); /* Should print 0 */
  return 0;
}

根据cal -y 2015的输出,该日期是星期日。但是,当我在OSX(大概是用clang)上编译它时,它会打印6:
$ gcc timetest.c ; ./a.out
6

而在Debian上,它会打印(正确的)0:
$ gcc timetest.c ; ./a.out
0

有什么区别的解释吗?

更新

这是同一程序,除了t用有效时间初始化并且我正在报告strptime()的返回值:
#include <time.h>
#include <stdio.h>

int main () {
  time_t epoch = 0;
  struct tm t;
  char *ret;
  t = *localtime(&epoch);
  ret = strptime("2015-04-19 12:00:00", "%F %T", &t); /* Sunday */
  printf("%d\n", t.tm_wday); /* Should print 0 */
  printf("strptime() returned %p (%d)\n", ret, *ret);
  return 0;
}

这是输出:
$ gcc timetest.c ; ./a.out
6
strptime() returned 0x10c72af83 (0)

这是我使用的clang版本:
$ clang -v
Apple LLVM version 8.0.0 (clang-800.0.42.1)
Target: x86_64-apple-darwin16.1.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

最佳答案

我认为原因仅仅是设计上的the strptime function only sets the fields that appear in the format。本质上,strptime(3)只是使用提供的格式将给定字符串中的字段解析为引用的结构,并且不执行其他任何计算或逻辑。由于您的代码使用%F %T格式,因此仅修改了与%Y-%m-%d%H:%M:%S(即tm_{year,mon,mday,hour,min,sec})相对应的字段。

您可以通过将t.tm_wday显式设置为strptime不应设置的某个已知值(例如123)进行实验,并验证该调用不会更改它。请注意,您可能应该在使用struct tm之前对其进行初始化,因为这些字段中的任何一个都可能包含随机值,例如struct tm t; memset((void *) &t, 0, sizeof(t));

此外,此Linux strptime(3) man page包含以下注释,这使我相信它描述的特殊行为是非标准的(尽管显然是可取的):

glibc实现不涉及那些未明确指定的字段,只是如果更改了年,月或日元素中的任何一个,它将重新计算tm_wdaytm_yday字段。

This answer shows how您可以使用strptime/mktime/localtime(或gmtime)三重奏为UNIX时代之后的日期填充tm.tm_wday字段。

关于c - 为什么在本例中strptime()不能正确设置tm_wday?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40764356/

10-16 19:11