7

我用两个字符串读取年份、儒略日(年日)、小时、分钟和观察。

我使用 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。如果我只知道年日而不知道月日,我应该怎么做?

4

1 回答 1

20

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

引用 C 标准:

mktime函数将timeptr指向的结构中的分解时间,以本地时间表示,转换为与time函数返回的值编码相同的日历时间值。结构的tm_wdaytm_yday组件的原始值被忽略,其他组件的原始值不限于上述范围。成功完成后, tm_wdaytm_yday的值适当设置结构的组件,并设置其他组件以表示指定的日历时间,但它们的值被强制为上述范围;在确定tm_montm_year之前,不会设置tm_mday的最终值。

mktime()可以计算其他成员的值tm_mdaytm_yday来自其他成员的值;它并非旨在计算来自这些字段的其他成员的值。

但是,您可以做的是struct tm用超出范围的值初始化 a 。例如,如果你想tm_yday成为 200(一年中的第 200 天),你可以初始化一个struct tm代表一月的第 200 天的 a。 mktime()然后会将其规范化为正确的日期,产生一个time_t值,然后您可以将其提供给gmtime()or 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
于 2012-03-05T22:47:33.393 回答