strftime force输出在同一个本地时区

时间:2014-12-01 20:42:43

标签: c strftime strptime

我当前的电脑给出了CET的时间:

$ date
Mon Dec  1 21:31:41 CET 2014

但我的语言环境是en_US:

$ locale | grep -i time
LC_TIME="en_US.UTF-8"

我想将带有C的纪元字符串格式化为我当前的本地时区,但我不知道如何告诉strptime更改默认的本地时间:

#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int
main(void)
{
   struct tm tm;
   char buf[255];

   memset(&tm, 0, sizeof(struct tm));
   strptime("1412200800", "%s", &tm);
   strftime(buf, sizeof(buf), "%c %Z", &tm);
   puts(buf);
   exit(EXIT_SUCCESS);
}

手册页指出它根据区域设置格式化时间,但似乎忽略了我的设置:

 $ export LC_TIME=de_DE.UTF-8
 $ locale | grep -i time
LC_TIME=de_DE.UTF-8
 $ ./a.out 
Thu Oct  2 00:00:00 2014 CEST

我的期望是:

Wed Thu Oct  1 22:00:00 2014 CET

更新

好的,所以我完全删除了%s并尝试了以下方法,但仍然没有成功:

#define _XOPEN_SOURCE
#include <string.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

int
main(void)
{
   struct tm *tim;
   setlocale(LC_ALL, "");
   char buf[255];
   time_t c;

   c = strtoul("1412200800", NULL, 0);
   tim = localtime(&c);
   strftime(buf, sizeof(buf), "%c" , tim);
   puts(buf);
   printf("%s %s\n", tzname[0], tzname[1]);
   exit(EXIT_SUCCESS);
}

输出现在仍然是我所期望的:

gcc strptime_test.c && ./a.out 
Thu 02 Oct 2014 12:00:00 AM CEST
CET CEST

更新2,解决方案:

而不是使用localtime(&c);我现在使用:

tim = gmtime(&c);
strftime(buf, sizeof(buf), "%c" , tim);

这给出了所需的行为:

Wed 01 Oct 2014 10:00:00 PM GMT

1 个答案:

答案 0 :(得分:1)

您的代码使用strptime的非标准glibc扩展名; %s是纪元以来的秒数。

根据Epoch Converter1412200800Wed, 01 Oct 2014 22:00:00 GMT,因此您的程序行为正常。但是,目前还不清楚时间秒是以UTC还是在当地时区拍摄,因此评论中的loreb音符可能还需要调用时区转换功能。

您必须决定程序中的时间(即time_tstruct tm对象的内容)是UTC时间还是当地时间。

我建议采取以下解决方法:将strptime替换为

time_t c = 1412200800;
tm = *gmtime(&c);     

此处可能使用的另一个功能是gmtime,而不是localtime


BTW我认为你正在混淆语言环境和时区:“语言环境”意味着格式化时间的方式;例如,默认值可能是:

Sun Oct  1 00:00:00 2014

但是语言环境格式的版本是:

Sun, Oct 01, 2014 12:00:00 AM

时区和区域设置是不同的东西。 (一个区域设置可能跨越多个时区,一个时区可能包含多个区域设置)。

NB。在C中,默认语言环境是C语言环境,而不是系统语言环境。要从环境变量中读取区域设置,请执行以下操作:

#include <locale.h>

// in main()
setlocale(LC_ALL, "");