C中两个日期之间的差异

我是C的初学者。

  • 日期是否有任何数据类型?
  • 在C我们有时间工作,还有一个日期吗?
  • 如何计算两个日期之间的差异?

日期是否有任何数据类型?

不, C内置数据类型,您必须定义用户定义的数据类型。

如何计算两个日期之间的差异?

你可以试试这个:

 struct dt { int dd; int mm; int yy; }; typedef dt date; 

在main()中,您需要为类型data声明三个变量。
在以下示例today差异,
例如,你想在当前日期( c_date )和出生日期( dob )之间取差异

  date dob,c_date,today; if(c_date.dd>=dob.dd) today.dd = c_date.dd-dob.dd; else { c_date.dd+=30; c_date.mm-=1; today.dd = c_date.dd-dob.dd; } if(c_date.mm>=dob.mm) today.mm = c_date.mm-dob.mm; else { c_date.mm+=12; c_date.yy-=1; today.mm = c_date.dd-dob.mm; } today.yy = c_date.yy-dob.yy; 

today你有两个日期之间的差异。

还有一种方法: double difftime (time_t end, time_t beginning);
阅读此答案:
1. 如何比较格式为“月份日期hh:mm:ss”的两个时间戳
2. 你如何找到C中两个小时之间的差异?

是的,标准库C Time Library包含您想要的结构和function。您可以使用struct tm来存储日期和difftime以获得差异。

是否有保存日期的数据类型?

不,虽然对于“现在加上或减去几十年”范围内的日期,您可以在相关日期的(例如)午夜使用包含日期时间的time_tstruct tm 。 或者你可以看一个叫做“Julian day”的东西:计算它并将它存储在你喜欢的任何整数类型中。

C也有图书馆吗?

标准函数都与日期/时间有关,而不仅仅是日期: mktimelocaltimegmtime

如何计算两个日期之间的差异

一旦你有一个time_t你可以减去两个并除以86400.但是,请注意,因为夏令时的变化,两天之后的“午夜当地时间”可能不会相隔24小时。

如果您需要一个超出time_t范围的日历,那么您基本上可以独立完成。 如果time_t是64位,则超过宇宙的年龄,但如果time_t是32位,则对历史没有好处。 或者甚至是养老金计划。 无论如何,历史应用程序对日历都有自己的要求(儒略历,与格里高利完全无关的日历)。

您可以创建名为datestruct ,其中包含以下字段

 typedef struct { int day; int month; int year; }date; 

这只是你想要的蓝图,现在制作和date对象并相应地工作。 要找到差异,请编写一个函数,分别对两个结构的monthyear进行区分。

您必须定义日期结构:

 typedef struct date { int day; int month; int year; } Date; 

然后定义一个简单的date_compare()方法:

 int date_compare(Date *date1, Date *date2) { if (date1->year != date2->year) return (date1->year - date2->year); if (date1->month != date2->month) return (date1->month - date2->month); return (date1->day - date2->day); } 

日期和时间的标准C库选项非常差,并且存在警告和限制。 如果可能的话,使用像Gnome Lib这样的库来提供GDate和许多有用的日期和时间函数 。 这包括g_date_days_between()用于获取两个日期之间的天数。

本答案的其余部分将限制在标准C库中,但如果您不必限制自己的标准,请不要折磨自己。 日期非常艰难。


日期是否有任何数据类型?

struct tm将服务。 只需将小时,分钟和秒留在0。

确保struct tm所有字段都正确填充的最简单方法是使用strptime

 struct tm date; strptime( "2017-03-21", "%F", &date ); puts( asctime(&date) ); // Mon Mar 21 00:00:00 2017 

但这并不是存储日期的好方法。 事实certificate,使用Julian Days更好(见下文)。

在C我们有时间工作,还有一个日期吗?

如果您指的是time_t ,那也是日期时间。 这是自POSIX系统上1970-01-01 00:00:00 UTC的“纪元”以来的秒数,但不一定是其他。 不幸的是,它的安全范围仅为1970年至2037年,但任何最新版本的操作系统都将大大扩展该范围。

如何计算两个日期之间的差异?

取决于你想要什么。 如果你想要秒数,你可以使用mktimestruct tm转换为time_t然后使用difftime ,但这仅限于1970-2037的time_t安全范围。

 int main() { struct tm date1, date2; strptime( "2017-03-21", "%F", &date1 ); strptime( "2018-01-20", "%F", &date2 ); printf("%.0lf\n", difftime(mktime(&date1), mktime(&date2))); } 

如果您想要天数,您可以将日期转换为儒略日 ,即自公元前4714年11月24日以来的天数,并减去。 虽然这可能看起来很荒谬,但这个相对简单的公式利用了日历周期并且只使用整数数学。

 // The formulas for a and m can be distilled down to these tables. int Julian_A[12] = { 1, 1, 0 }; int Julian_M[12] = { 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int julian_day( struct tm *date ) { int a = Julian_A[date->tm_mon]; int m = Julian_M[date->tm_mon]; int y = date->tm_year + 1900 + 4800 - a; return date->tm_mday + ((153*m + 2) / 5) + 365*y + y/4 - y/100 + y/400 - 32045; } int main() { struct tm date1, date2; strptime( "2017-03-21", "%F", &date1 ); strptime( "2018-01-20", "%F", &date2 ); // 305 days printf("%d days\n", julian_day(&date2) - julian_day(&date1)); } 

还有其他简单的公式可以在Julian日期和日历日期之间进行转换。

由于一个月中的天数因月份和年份而异,并且因为必须进行标准化,因此难以在数年,数月和数天内获得差异。 例如,你不会说2年,-1个月,2天。 你会说1年,11个月,29天(或者28天,取决于月份)。 因此,尽可能在Julian Days中进行日期数学运算。

为了了解所涉及的内容, PHP将其实现为date_diff 。 看看所需的C代码量 。

 /* Version 3 (better) Date Difference between the two dates in days like VBA function DateDiff("d", date1, date2) in case of Gregorian. Same basic principle you can translate in lot of other languages. This is complete C code with date validity control. */ #include void main(){ long d1,m1,y1,d2,m2,y2; printf("Enter first date day, month, year\n"); scanf("%d%d%d",&d1,&m1,&y1); printf("Enter second date day, month, year\n"); scanf("%d%d%d",&d2,&m2,&y2); if((IsValid(d1,m1,y1)==0)||(IsValid(d2,m2,y2)==0)){ printf("Invalid date detected\n"); }else{ d1=DatDif(d1,m1,y1,d2,m2,y2); printf("\n\n Date difference is %d days\n",d1); } }// end main long DatDif(d1,m1,y1,d2,m2,y2) { long suma; suma=rbdug(d2,m2,y2) - rbdug(d1,m1,y1); if(y1 != y2){ if(y1 < y2){ suma+=Godn(y1,y2); }else{ suma-=Godn(y2,y1); } } return(suma); }// end DatDif long Godn(yy1,yy2) { long jj,bb; bb=0; for(jj=yy1;jj2)) a+=1; return(a); }//end rbdug //date validity long IsValid(dd,mm,yy) { long v[13]; if((0 < mm) && (mm < 13)){ v[1] = 32; v[2] = 29; v[3] = 32; v[4] = 31; v[5] = 32; v[6] = 31; v[7] = 32; v[8] = 32; v[9] = 31; v[10]= 32; v[11]= 31; v[12]= 32; if(((((yy%400)==0)||((yy%100)!=0)) &&((yy%4)==0))) v[2]+=1; if((0 < dd) && (dd < v[mm])){ return(1); }else{ return(0); } }else{ return(0); } }//end IsValid 
 /* Version 4 ( 100 % correct): Proleptic Gregorian date difference in days. Date Difference between the two dates in days like VBA function DateDiff("d", date1, date2) and better (without limitations of DateDiff) in case of Gregorian. Same basic principle you can translate in lot of other languages. This is complete C code with date validity control. */ #include void main(){ long d1,m1,y1,d2,m2,y2; printf("Enter first date day, month, year\n"); scanf("%d%d%d",&d1,&m1,&y1); printf("Enter second date day, month, year\n"); scanf("%d%d%d",&d2,&m2,&y2); if((IsValid(d1,m1,y1)==0)||(IsValid(d2,m2,y2)==0)){ printf("Invalid date detected\n"); }else{ d1=DatDif(d1,m1,y1,d2,m2,y2); printf("\n\n Date difference is %d days\n",d1); } }// end main long DatDif(d1,m1,y1,d2,m2,y2) { long suma; suma=rbdug(d2,m2,y2) - rbdug(d1,m1,y1); if(y1 != y2){ if(y1 < y2){ suma+=Godn(y1,y2); }else{ suma-=Godn(y2,y1); } } return(suma); }// end DatDif long Godn(yy1,yy2) { long jj,bb; bb=0; for(jj=yy1;jj2)) a+=1; return(a); }//end rbdug //date validity long IsValid(dd,mm,yy) { long v[13]; if((0 < mm) && (mm < 13)){ v[1] = 32; v[2] = 29; v[3] = 32; v[4] = 31; v[5] = 32; v[6] = 31; v[7] = 32; v[8] = 32; v[9] = 31; v[10]= 32; v[11]= 31; v[12]= 32; if ((mm==2)&&(IsLeapG(yy)==1)) v[2]=30; if((0 < dd) && (dd < v[mm])){ return(1); }else{ return(0); } }else{ return(0); } }//end IsValid //is leap year in Gregorian long IsLeapG(yr){ if(((((yr%400)==0)||((yr%100)!=0))&&((yr%4)==0))){ return(1); }else{ return(0); } }//end IsLeapG