prev up next   top/contents search

comp.lang.c FAQ 列表· 问题 13.14

Q我如何给日期加上 N 天?我如何找出两个日期之间的差值?


AANSI/ISO 标准 Cmktimedifftime函数为这两个问题提供了一些(有限的)支持。mktime接受非标准化的日期,因此很容易填写一个struct tm,加减tm_mday字段,然后调用mktime来标准化年、月、日字段(并顺便转换为time_t值)。difftime计算两个time_t值之间的差值(以秒为单位);mktime可用于计算要减去的两个日期的time_t值。

然而,这些解决方案只能保证在可表示的范围内的日期上正确工作time_t[脚注]tm_mday字段是int,因此超过 32,736 天的日偏移量可能会导致溢出。(关于没有这些限制的替代解决方案,请参见下文。)另请注意,在夏令时转换期间,本地日不是 24 小时,因此如果您尝试除以 86,400 秒/天,请小心。

这是一个计算 1994 年 10 月 24 日之后 90 天日期的代码片段

#include <stdio.h>
#include <time.h>

tm1.tm_mon = 10 - 1;
tm1.tm_mday = 24;
tm1.tm_year = 1994 - 1900;
tm1.tm_hour = tm1.tm_min = tm1.tm_sec = 0;
tm1.tm_isdst = -1;

tm1.tm_mday += 90;

if(mktime(&tm1) == -1)
	fprintf(stderr, "mktime failed\n");
else	printf("%d/%d/%d\n",
		tm1.tm_mon+1, tm1.tm_mday, tm1.tm_year+1900);
(设置tm_isdst为 -1 有助于防止夏令时异常;设置tm_hour为 12 也有此作用。)

这是一段代码,用于计算 2000 年 2 月 28 日和 3 月 1 日之间的天数差

	struct tm tm1, tm2;
	time_t t1, t2;

	tm1.tm_mon = 2 - 1;
	tm1.tm_mday = 28;
	tm1.tm_year = 2000 - 1900;
	tm1.tm_hour = tm1.tm_min = tm1.tm_sec = 0;
	tm1.tm_isdst = -1;

	tm2.tm_mon = 3 - 1;
	tm2.tm_mday = 1;
	tm2.tm_year = 2000 - 1900;
	tm2.tm_hour = tm2.tm_min = tm2.tm_sec = 0;
	tm2.tm_isdst = -1;

	t1 = mktime(&tm1);
	t2 = mktime(&tm2);
	
	if(t1 == -1 || t2 == -1)
		fprintf(stderr, "mktime failed\n");
	else {
		long d = (difftime(t2, t1) + 86400L/2) / 86400L;
		printf("%ld\n", d);
	}
(加上86400L/2会将差值四舍五入到最接近的天;另请参见问题 14.6。)

另一种处理这两个问题的方法是使用“儒略日编号”。儒略日编号是从公元前 4013 年 1 月 1 日开始计算的天数。 [脚注] 。使用ToJulFromJul例程声明如下:

/* returns Julian for month, day, year */
long ToJul(int month, int day, int year);

/* returns month, day, year for jul */
void FromJul(long jul, int *monthp, int *dayp, int *yearp);
n天添加到日期可以实现为
	int n = 90;
	int month, day, year;
	FromJul(ToJul(10, 24, 1994) + n, &month, &day, &year);
,两个日期之间的天数是
	ToJul(3, 1, 2000) - ToJul(2, 28, 2000)
处理儒略日编号的代码可以在 Snippets 集合(参见问题 18.15c)、Simtel/Oakland 档案(文件 JULCAL10.ZIP,参见问题 18.16)以及参考文献中提到的“日期转换”文章中找到。

另请参见问题 13.1320.3120.32

额外链接

Mark Brader 的进一步解释

Branko Radovanovic 的日期差和星期几计算的更多代码

参考文献:K&R2 Sec. B10 p. 256
ISO Secs. 7.12.2.2,7.12.2.3
H&S Secs. 18.4,18.5 pp. 401-2
David Burki,“日期转换”


prev up next   contents search
关于此 FAQ 列表   关于 Eskimo   搜索   反馈   版权

Eskimo North 托管