我尝试向使用时间C函数生成的日期添加时间偏移。 根据偏移值计算错误。如果我增加偏移值,则计算将变为错误!
我在CentOS 5.11上使用gcc
#include <stdio.h>
#include <time.h>
#define MAX_SIZE 80
int main( int argc, char * argv[] ) {
time_t timestamp, offset;
struct tm *pTime;
char buffer[ MAX_SIZE ];
//timestamp = time( NULL );
timestamp = 1470356033L;
printf("timestamp = %ld\n", timestamp);
// offset calculation
offset = atol(argv[1]) * (24L * 60L * 60L);
printf("offset = %ld\n", offset);
timestamp += offset;
printf("timestamp = %ld\n", timestamp);
pTime = localtime( & timestamp );
strftime( buffer, MAX_SIZE, "%d/%m/%Y %H:%M:%S", pTime );
printf( "Date and french time : %s\n", buffer );
return 0;
}
./testDate 0
timestamp = 1470356033
offset = 0
timestamp = 1470356033
Date and french time : 05/08/2016 02:13:53
This Result is OK, it is reference date without offset
./testDate 4
timestamp = 1470356033
offset = 345600
timestamp = 1470701633
Date and french time : 09/08/2016 02:13:53
This Result is also OK, it is reference date with 4 days offset
./testDate 90
timestamp = 1470356033
offset = 7776000
timestamp = 1478132033
Date and french time : 03/11/2016 01:13:53
This Result is wrong, it is reference date with 90 days offset.
Date is OK but 1 hour is missing, it should be 02:13:53 but actual output is 01:13:53
答案 0 :(得分:3)
time_t
类型代表Unix time,即自1970年1月1日星期四00:00:00 UTC以来的秒数,减去leap秒。
(POSIX clock_gettime()
界面可能会增加对CLOCK_TAI
的支持,除了包括 leap秒外,其他支持都将是相同的。)
对于日期处理,最好使用localtime()
或gmtime()
提供的标准C分解时间struct tm
。
localtime()
使用当前时区。 (Linux系统在/etc/timezone
中设置了默认时区,但是每个用户都可以通过设置TZ
环境变量来覆盖它。有关如何执行此操作的详细信息,请参见tzset()
POSIX.1函数。 )gmtime()
使用UTC。
“技巧”是,如果您在描述当前时区中日期和时间的struct tm
上调用mktime()
,则 first 首先将字段标准化,然后返回Unix时间,作为与该日期和本地时间相对应的time_t
。例如,如果一个月中的某天是45,它将调整日,月和年(及相关字段)以反映实际日期。
因此,如果您想从现在起五天零六个小时找出日期和时间:
time_t now, then;
struct tm *t;
now = time(NULL);
t = localtime(&now);
printf("Now is %llu = %04d-%02d-%02d %02d:%02d%02d\n",
(unsigned long long)now,
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec);
t->tm_hour += 6;
t->tm_mday += 5;
t->tm_isdst = -1; /* Don't know if DST or not; please guess. */
then = mktime(t);
printf("Then is %llu = %04d-%02d-%02d %02d:%02d:%02d\n",
(unsigned long long)then,
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec);
如果我们省略打印now
和then
的值,那么上面的代码就是完全标准的C代码,并且可以在所有当前操作系统上使用。
如果您使用Linux或其他POSIXy系统(Mac,BSD),则最好使用
time_t now, then;
struct tm tbuffer, *t;
now = time(NULL);
t = localtime_r(&now, &tbuffer);
printf("Now is %llu = %04d-%02d-%02d %02d:%02d%02d\n",
(unsigned long long)now,
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec);
t->tm_hour += 6;
t->tm_mday += 5;
t->tm_isdst = -1; /* Don't know if DST or not; please guess. */
then = mktime(t);
printf("Then is %llu = %04d-%02d-%02d %02d:%02d:%02d\n",
(unsigned long long)then,
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec);
区别在于localtime()
返回指向静态分配缓冲区的指针,并且对该缓冲区的另一个调用(即使在另一个线程中)也将覆盖其内容。 POSIX.1 localtime_r()
带有第二个参数,即指向struct tm
的指针,取而代之的是存储结果。