我如何正确地将天数添加到给定日期?
How do i correctly add days to given date?
我为存储日期的 class 创建了这个运算符,它应该添加给定的日期天数并将其转换回人类格式
CDate CDate::operator+(const int x)
{
time_t t;
struct tm tmp = {0};
struct tm newtime = {0};
tmp.tm_year = timeinfo.tm_year;
tmp.tm_mon = timeinfo.tm_mon;
tmp.tm_mday = timeinfo.tm_mday + x;
t = mktime(&tmp);
newtime = *(localtime(&t));
return CDate(newtime.tm_year,newtime.tm_mon,newtime.tm_mday);
}
问题是它计算的日期比它应该的高 3 天
具体问题是,我的日期是 2000-01-02(年-月-日),我尝试添加 1500 天,预期结果是 2004-02-10,但我得到的是 2004-02-13
我做错了什么?
这是给日期加上天数的算法。
根据日期计算天数。
function g(y,m,d)
m = (m + 9) % 12
y = y - m/10
return 365*y + y/4 - y/100 + y/400 + (m*306 + 5)/10 + ( d - 1 )
要加号。日期中的天数->
g(y2,m2,d2) + no_of_days
在此之后,您可以将日期转换回日期。
function d(g)
y = (10000*g + 14780)/3652425
ddd = g - (365*y + y/4 - y/100 + y/400)
if (ddd < 0) then
y = y - 1
ddd = g - (365*y + y/4 - y/100 + y/400)
endif
mi = (100*ddd + 52)/3060
mm = (mi + 2)%12 + 1
y = y + (mi + 2)/12
dd = ddd - (mi*306 + 5)/10 + 1
return y, mm, dd
你有两个错误。
首先,传递给 mktime 的 tm
是无效的:年份不应该像 2000
那样是绝对年份,而是与 1900 年的差异,即。 100
表示 2000。更正此问题后,我得到 2004-02-12
作为结果(既不是 2004-02-13
也不是 2004-02-10
)。
(在我的电脑上,程序(没有任何更改)就崩溃了:mktime returns -1,localtime 无法处理它并且 returns 一个无效的指针,用于同一行...)
其次,在同一个结构中,日期可能是1-31
,但月份只有0-11
(而不是1-12
)。您的 2000-01-02
是二月的第二天,而不是一月。
知道这一点,结果是正确的(我会写完整的年份,但月份从 0 开始):
1500 天添加到 2000-01-02
:
2000 年有 366 天(闰年),我们不需要一月和二月的第一天:
2000-01-02
+ (366-31-1) 天= 2001-00-01
, 1166 天加左
再过365天2002-00-01
,还剩801天
再过365天补2003-00-01
,再补436天
再过365天赚2004-00-01
,再赚71天就剩
又一月 31 使 2004-01-01
,还有 40 天加左
闰二月再过292004-02-01
,再剩11天
另外 11 个添加使得 2004-02-12
我为存储日期的 class 创建了这个运算符,它应该添加给定的日期天数并将其转换回人类格式
CDate CDate::operator+(const int x)
{
time_t t;
struct tm tmp = {0};
struct tm newtime = {0};
tmp.tm_year = timeinfo.tm_year;
tmp.tm_mon = timeinfo.tm_mon;
tmp.tm_mday = timeinfo.tm_mday + x;
t = mktime(&tmp);
newtime = *(localtime(&t));
return CDate(newtime.tm_year,newtime.tm_mon,newtime.tm_mday);
}
问题是它计算的日期比它应该的高 3 天
具体问题是,我的日期是 2000-01-02(年-月-日),我尝试添加 1500 天,预期结果是 2004-02-10,但我得到的是 2004-02-13
我做错了什么?
这是给日期加上天数的算法。
根据日期计算天数。
function g(y,m,d)
m = (m + 9) % 12
y = y - m/10
return 365*y + y/4 - y/100 + y/400 + (m*306 + 5)/10 + ( d - 1 )
要加号。日期中的天数->
g(y2,m2,d2) + no_of_days
在此之后,您可以将日期转换回日期。
function d(g)
y = (10000*g + 14780)/3652425
ddd = g - (365*y + y/4 - y/100 + y/400)
if (ddd < 0) then
y = y - 1
ddd = g - (365*y + y/4 - y/100 + y/400)
endif
mi = (100*ddd + 52)/3060
mm = (mi + 2)%12 + 1
y = y + (mi + 2)/12
dd = ddd - (mi*306 + 5)/10 + 1
return y, mm, dd
你有两个错误。
首先,传递给 mktime 的 tm
是无效的:年份不应该像 2000
那样是绝对年份,而是与 1900 年的差异,即。 100
表示 2000。更正此问题后,我得到 2004-02-12
作为结果(既不是 2004-02-13
也不是 2004-02-10
)。
(在我的电脑上,程序(没有任何更改)就崩溃了:mktime returns -1,localtime 无法处理它并且 returns 一个无效的指针,用于同一行...)
其次,在同一个结构中,日期可能是1-31
,但月份只有0-11
(而不是1-12
)。您的 2000-01-02
是二月的第二天,而不是一月。
知道这一点,结果是正确的(我会写完整的年份,但月份从 0 开始):
1500 天添加到 2000-01-02
:
2000 年有 366 天(闰年),我们不需要一月和二月的第一天:
2000-01-02
+ (366-31-1) 天= 2001-00-01
, 1166 天加左
再过365天2002-00-01
,还剩801天
再过365天补2003-00-01
,再补436天
再过365天赚2004-00-01
,再赚71天就剩
又一月 31 使 2004-01-01
,还有 40 天加左
闰二月再过292004-02-01
,再剩11天
另外 11 个添加使得 2004-02-12