为什么mktime()会改变我的tm结构的年份?

问题描述:

我读了两个字符串,一年,朱利安日(年),小时,分钟和观察。为什么mktime()会改变我的tm结构的年份?

我拉了相关变量进行使用的sscanf:

sscanf(tide_str1.c_str(), "%d %d %d %d %Lf", &y1, &j1, &h1, &m1, &obs1); 
sscanf(tide_str2.c_str(), "%d %d %d %d %Lf", &y2, &j2, &h2, &m2, &obs2); 

对于这个特定的数据集,该值是2011 083 23 22 1.1

然后我创建并填充一个TM结构,mktime运行,并在当天之间进行cout呼叫,并且它从083改变到364.

int y1=2011, j1=83, h1=23, m1=22; 
struct tm time_struct = {0, 0, 0, 0, 0, 0, 0, 0, 0}, *time_ptr = &time_struct; 
time_t tv_min; 
time_struct.tm_year = y1 - 1900; 
time_struct.tm_yday = j1; 
cout << time_struct.tm_yday << endl; 
time_struct.tm_hour = h1; 
time_struct.tm_min = m1; 
time_struct.tm_isdst = -1; 
cout << time_struct.tm_yday << endl; 
tv_min = mktime(time_ptr); 
cout << time_struct.tm_yday << endl; 

为什么?是否因为tm_mday和tm_mon设置为0?我最初尝试不将它初始化为零,但然后mktime返回-1。如果我只知道年份而不是月份和月份,我应该做些什么改变?

+0

一年的日子有时是不正确的* *被称为“儒略日”。实际上,[Julian Day](http://en.wikipedia.org/wiki/Julian_day)是自公元前4713年1月1日以来的天数;它用于天文学。 – 2012-03-05 22:52:35

+0

是的,但它在某些行业中被广泛使用(不正确),因此在实践中是正确的。只要一个领域内的每个人都使用相同的jargin ...沟通就会发生。 – RuQu 2012-03-05 23:47:02

mktime()正在做它应该做的事情。

引述C标准:

mktime函数转换毁掉的时候,表示为 本地时间,在该结构指向timeptr与日历 时间值与由 返回的值相同的编码时间函数。 tm_wdaytm_yday该结构的组件被忽略,并且其他组件的原始值不限于上面指出的范围 。在成功完成时, tm_wdaytm_yday结构的部件的值被适当地设置,而另一分量被设置为表示 指定日历时间,但与*以上指出的范围 它们的值; tm_mdayis的最终值未设置,直到tm_montm_year被确定。

mktime()可以计算tm_mday并从其他成员tm_yday值;它不是为了计算这些领域的其他成员的价值而设计的。

但是,您可以执行的操作是使用超出范围的值初始化struct tm。例如,如果您希望tm_yday为200(一年中的第200天),则可以初始化代表1月200日的struct tm。然后mktime()将其归一化到正确的日期,产生一个time_t值,然后您可以输入到gmtime()localtime()

这里有一个简单的例子:

#include <iostream> 
#include <ctime> 

int main() 
{ 
    struct tm t = { 0 }; 
    t.tm_sec = t.tm_min = t.tm_hour = 0; // midnight 
    t.tm_mon = 0;      // January 
    t.tm_year = 2012 - 1900; 
    t.tm_isdst = -1;      // unknown 

    t.tm_mday = 200;      // January 200th? 

    time_t when = mktime(&t); 
    const struct tm *norm = localtime(&when); // Normalized time 

    std::cout << "month=" << norm->tm_mon << ", day=" << norm->tm_mday << "\n"; 
    std::cout << "The 200th day of 2012 starts " << asctime(norm); 
} 

输出是:

month=6, day=18 
The 200th day of 2012 starts Wed Jul 18 00:00:00 2012 
+0

我尝试了你的建议并初始化为这样:struct tm time_struct = {0,0,200,200,0,200,0,0},当我回调时的结果是第77天,应该是83,这比之前的364更接近但仍然关闭。 – RuQu 2012-03-05 23:02:31

+1

该标准不保证'struct tm'成员的顺序,所以像这样初始化它不一定有效。您应该按名称初始化或分配所有成员。但是如果它们按照通常的顺序声明,那么你将'tm_mday'和'tm_mon'初始化为200.我认为你不需要这一年的第200个月,也就是说第201个月。 (并且不要忘记,'struct tm'数字的月份为0到11,而不是1到12.) – 2012-03-05 23:08:10

+0

要清楚,如果我想要第83天,我应该将月份设置为0,并将月份的日期83? – RuQu 2012-03-05 23:10:26