10

我是C的初学者。

  • 日期是否有任何数据类型?
  • 在 C 语言中,我们可以处理时间,是否也有时间处理?
  • 如何计算两个日期之间的差异?
4

8 回答 8

15

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

于 2012-12-18T12:33:02.713 回答
4

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

不,尽管对于“现在加上或减去几十年”范围内的日期,您可以在相关日期的(例如)午夜使用time_t或包含日期时间。struct tm或者,您可以研究一个称为“朱利安日”的事物:计算它并将其存储为您喜欢的任何整数类型。

C也有任何库吗?

标准函数都与日期/时间有关,而不仅仅是日期:mktime, localtime, gmtime.

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

将其放入 a 后,time_t您可以将两者相减并除以 86400。但请注意,由于夏令时的变化,两个不同日子的“当地时间午夜”可能不是 24 小时的精确倍数。

如果您需要一个超出实施范围的日历,time_t那么您基本上只能靠自己了。如果time_t是 64 位,那已经超过了宇宙的年龄,但如果time_t是 32 位,则对历史没有好处。甚至养老金计划。无论如何,历史应用程序对日历都有自己的要求(儒略历,与公历完全无关的日历)。

于 2012-12-18T12:33:44.693 回答
3

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

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

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

你可以试试这个:

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

在 main() 中,您需要为 type 声明三个变量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你有两个日期之间的差异。

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


于 2012-12-18T12:31:59.693 回答
3

日期和时间的标准 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

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

在 C 语言中,我们可以处理时间,是否也有时间处理?

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

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

取决于你想要什么。如果您想要秒数,您可以将 转换struct tmtime_tusingmktime然后使用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));
}

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

很难获得年、月和日的差异,因为一个月中的天数因月和年而异,而且必须标准化。例如,您不会说 2 年,-1 个月,2 天。你会说 1 年 11 个月 29 天(或者可能是 28 天,取决于月份)。出于这个原因,尽可能在儒略日做日期数学。

为了了解所涉及的内容,PHP 将其实现为date_diff. 看看需要多少 C 代码

于 2017-03-21T11:16:04.287 回答
2

您可以创建具有以下字段的struct命名日期

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

它只是您想要的蓝图,现在制作和对象date并相应地工作。要找到差异,请编写一个函数来分别获取两个结构之间的day month差异year

于 2012-12-18T12:24:59.037 回答
2

您必须定义一个日期结构:

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);

}
于 2014-03-14T21:57:20.263 回答
0
/*  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<stdio.h>

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;jj<yy2;jj++){
    bb+=365;
    if(((((jj%400)==0)||((jj%100)!=0))
      &&((jj%4)==0))) bb+=1;
  }
  return(bb);
}// end Godn

//Day of the Year
long rbdug(d,m,y)
{ long a,r[13];
  r[1] = 0; r[2] = 31; r[3] = 59;
  r[4] = 90; r[5] = 120; r[6] = 151;
  r[7] = 181; r[8] = 212; r[9] = 243;
  r[10]= 273; r[11]= 304; r[12]= 334;
  a=r[m]+d;
  if(((((y%400)==0)||((y%100)!=0))
      &&((y%4)==0))&&(m>2)) 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
于 2016-05-06T13:06:08.433 回答
0
/* 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<stdio.h>

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;jj<yy2;jj++){
    bb+=365;
    if(IsLeapG(jj)==1) bb+=1;
  }
  return(bb);
}// end Godn

//Day of the Year
long rbdug(d,m,y)
{ long a,r[13];
  r[1] = 0; r[2] = 31; r[3] = 59; r[4] = 90;
  r[5] = 120; r[6] = 151; r[7] = 181; r[8] = 212;
  r[9] = 243; r[10]= 273; r[11]= 304; r[12]= 334;
  a=r[m]+d;
  if((IsLeapG(y)==1)&&(m>2)) 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
于 2016-05-20T18:20:35.263 回答