C 向tm结构添加一些间隔

C 向tm结构添加一些间隔,c,time-t,ctime,C,Time T,Ctime,我有一个struct tm。 我需要增加一些固定的时间间隔(以xx年,xx月,xx天为单位) 到tm结构。 有没有标准的函数来实现这一点 我使用的编译器是Windows XP上的MSVC 2005。标准加法运算符可以工作 struct tm x; /* add 2 years and 3 days to x */ x.tm_year += 2; x.tm_mday += 3; 编辑:您可以轻松创建函数 struct tm addinterval(struct tm x, int y, int

我有一个struct tm。
我需要增加一些固定的时间间隔(以xx年,xx月,xx天为单位) 到tm结构。
有没有标准的函数来实现这一点


我使用的编译器是Windows XP上的MSVC 2005。

标准加法运算符可以工作

struct tm x;
/* add 2 years and 3 days to x */
x.tm_year += 2;
x.tm_mday += 3;

编辑:您可以轻松创建函数

struct tm addinterval(struct tm x, int y, int m, int d) {
    x.tm_year += y;
    x.tm_mon += m;
    x.tm_mday += d;
    mktime(&x); /* normalize result */
    return x;
}

编辑:添加了
mktime
以规范化结果

有两个转换时间格式的函数:

  • mktime()
    它将
    struct tm
    (表示本地时间)转换为
    time\t
  • localtime()
    它在
    struct tm
    中将
    time
    转换为本地时间
  • 有趣的是第一个,它接受超出范围的结构成员值,并作为转换的副产品适当地设置它们(和所有其他值)。这可用于在算术运算后更正字段数据值。然而,字段的类型是int,所以如果e。G在一年中添加秒数

    所以,如果你想知道实际日期,这段代码会有所帮助(来自@pmg的答案的修改副本):


    另请注意
    tm_isdst
    会员,请关注它。当您跳过夏时制切换日期时,其值可能会导致时间前后移动。

    我建议先将当前日期转换为天数。那么,添加一个间隔就很简单了。然后,将数字转换回日期

    您可以找到将日期转换为若干天并返回的算法,例如

    其他答案会导致非常不稳定的结果,具体取决于系统初始化struct tm的方式以及是否正确初始化了中午时间值。 如果您感兴趣的只是日期的更改,而时间保持不变,则在传递到
    mktime
    之前,将
    tm_isdst
    tm_hour
    tm_sec
    全部设置为0。更好的方法是,在之前获取它们的值,并在之后重置它们以保持一致性(如果它们以前不一致,它们将始终保持一致)。重用来自其他答案的代码:

    tm addinterval(tm t, int y, int m, int d)
    {
        auto hour = t.tm_hour;
        auto min = t.tm_min;
        auto sec = t.tm_sec;
    
        // First we discover the DST Flag. By setting hour to 12
        //   we can assure the mktime does not shift the date
        //   because it will shift the hour!
        t.tm_isdst = 0;
        t.tm_hour = 12;
        t.tm_min = 0;
        t.tm_sec = 0;
        mktime(&t);
    
        // Now we can add the interval
        t.tm_year += y;
        t.tm_mon += m;
        t.tm_mday += d;
        mktime(&t);
    
        // Now reset the mid-day time values
        t.tm_hour = hour;
        t.tm_min = min;
        t.tm_sec = sec;
    
        // Return struct tm while keeping mid-day time the same
        //   while the only values that changed are the date and perhaps isdst.
        return t;
    }
    

    我希望它更简单,但这正是它必须做到的。

    +1但要注意溢出,例如,将3个月添加到10个月不会得到13个月,而是得到1年1个月。。。护理是强制性的。“2012-02-29+1年是2013-03-01”非常感谢,简单的添加注意闰耳和月长的差异?例如,如果我将31天的月与28天的月相加,那么这个增加的月在1,天字段在3?@StNickolay:如果你在应用相加后调用
    mktime(&x)
    ,它将使结构正常化(例如10月40日变为11月9日)。我找到了正确的解决方案,谢谢大家。主题结束了。我以前写过,那个修正不起作用。mktime(&x)return-1我认为(希望)DST不会更改结果,因为我们处理的是天,而不是小时。对不起,我在写我的文章时没有看到您的评论。但是
    mktime
    适用于我的GCC。如果编译器不支持c99标准,您的代码可能会失败。@pmg:如果mk time看到时间
    13:17 Dec,7
    with
    tm_isdst
    设置为1,它将尝试设置更正此标志,这将导致时间(可能还有日期)发生更改。如果在
    mktime()
    之前将
    tm_isdst
    设置为-1,则不会发生更改。我对此进行了测试。
    mktime()
    在标准C中始终具有规范化行为,它不需要C99。请告诉我们您使用的编译器和平台(以及它支持的标准,如果您知道的话)。这是为了澄清为什么
    mk_time
    不适合您。即使你已经找到了一个解决方案,它也会帮助其他人。Windows XP,MSVC 2005,我尝试从pmg复制粘贴的代码,无论是否使用MKTIME,它都无法工作请将你的完整测试代码粘贴到这里!
    tm addinterval(tm t, int y, int m, int d)
    {
        auto hour = t.tm_hour;
        auto min = t.tm_min;
        auto sec = t.tm_sec;
    
        // First we discover the DST Flag. By setting hour to 12
        //   we can assure the mktime does not shift the date
        //   because it will shift the hour!
        t.tm_isdst = 0;
        t.tm_hour = 12;
        t.tm_min = 0;
        t.tm_sec = 0;
        mktime(&t);
    
        // Now we can add the interval
        t.tm_year += y;
        t.tm_mon += m;
        t.tm_mday += d;
        mktime(&t);
    
        // Now reset the mid-day time values
        t.tm_hour = hour;
        t.tm_min = min;
        t.tm_sec = sec;
    
        // Return struct tm while keeping mid-day time the same
        //   while the only values that changed are the date and perhaps isdst.
        return t;
    }