计算时间差

转载:http://www.aspku.com/kaifa/net/31738.html      C标准库源码解剖:日期与时间函数


struct tm {

   int tm_sec;         /* 秒,范围从 0 59 */

   int tm_min;         /* 分,范围从 0 59 */

   int tm_hour;        /* 小时,范围从 0 23 */

   int tm_mday;        /* 一月中的第几天,范围从 1 31 */

   int tm_mon;         /* 月,范围从 0 11 */

   int tm_year;        /* 1900 年起的年数 */

   int tm_wday;        /* 一周中的第几天,范围从 0 6 */

   int tm_yday;        /* 一年中的第几天,范围从 0 365 */

   int tm_isdst;       /* 夏令时 */

};

 

C 库函数 - difftime()

C 标准库 - <time.h>

描述

C 库函数 double difftime(time_t time1, time_t time2) 返回 time1  time2 之间相差的秒数 (time1 - time2)。这两个时间是在日历时间中指定的,表示了自纪元 Epoch(协调世界时 UTC1970-01-01 00:00:00)起经过的时间。

声明

下面是 difftime() 函数的声明。

double difftime(time_t time1, time_t time2)

参数

time1 -- 这是表示结束时间的 time_t 对象。

time2 -- 这是表示开始时间的 time_t 对象。

返回值

该函数返回以双精度浮点型 double 值表示的两个时间之间相差的秒数 (time2 - time1)

 

/* difftime.cdifftime函数的实现 */  

#include <time.h>  

#include <limits.h>  

#include <float.h>  

#include <stdint.h>  

#define TYPE_BITS(type) (sizeof (type) * CHAR_BIT)  

#define TYPE_FLOATING(type) ((type) 0.5 == 0.5)  

#define TYPE_SIGNED(type) ((type) -1 < 0)  

/* 返回两个时间TIME1TIME0的差值(秒数),这里TIME0<=TIME1time_t众所周知是 

    一个整数类型 */  

static double  

subtract (time_t time1, time_t time0)  

{  

  if (! TYPE_SIGNED (time_t))  

    return time1 - time0;  

  else  

    {  

      /* 对一般的情况进行优化,这里time_t能无损地转换成uintmax_t */  

      uintmax_t dt = (uintmax_t) time1 - (uintmax_t) time0;  

      double delta = dt;  

      if (UINTMAX_MAX / 2 < INTMAX_MAX)  

    {  

      /* 这是一种罕见的情况,uintmax_t有填充位,当把time_t转换成uintmax_t时可能会丢失信息。 

          通过比较dt/2(time1/2-time0/2)检查是否有溢出,如果它们有一个小的差值,则发生溢出 

           

          在下面的代码中,"h"前缀表示一半(half),通过范围分析,我们有: 

                  -0.5 <= ht1 - 0.5*time1 <= 0.5 

                  -0.5 <= ht0 - 0.5*time0 <= 0.5 

                  -1.0 <= dht - 0.5*(time1 - time0) <= 1.0 

                如果溢出没有发生,我们也有: 

                  -0.5 <= hdt - 0.5*(time1 - time0) <= 0 

                  -1.0 <= dht - hdt <= 1.5 

                并且因为dht-hdt是一个整数,我们有: 

                  -1 <= dht - hdt <= 1 

                或者等价的有: 

                  0 <= dht - hdt + 1 <= 2 

                在上面的分析中,所有的运算符都有它们准确的数学语义,而不是C语义。然而, 

             dht-hdt+1C中是无符号的,因此它无需与0比较  */  

      uintmax_t hdt = dt / 2;  

      time_t ht1 = time1 / 2;  

      time_t ht0 = time0 / 2;  

      time_t dht = ht1 - ht0;  

      if (2 < dht - hdt + 1)  

        {  

          /* 修复这个微小的溢出 

             下面的表达式包含一个秒数的舍入,因此结果可能不是与真正答案最接近的。这种 

             情况只在差值非常大时发生 */  

          delta = dt + 2.0L * (UINTMAX_MAX - UINTMAX_MAX / 2);  

        }  

    }  

      return delta;  

    }  

}  

/* 返回TIME1TIME0之间的差值(秒数)  */  

double  

__difftime (time_t time1, time_t time0)  

{  

  /* 如果不会导致double的舍入错误,就转换成double类型,然后做减法 */  

  if (TYPE_BITS (time_t) <= DBL_MANT_DIG  

      || (TYPE_FLOATING (time_t) && sizeof (time_t) < sizeof (long double)))  

    return (double) time1 - (double) time0;  

  /* long double做同样的事  */  

  if (TYPE_BITS (time_t) <= LDBL_MANT_DIG || TYPE_FLOATING (time_t))  

    return (long double) time1 - (long double) time0;  

  /* 调用substract从大的参数中减去小的整数,把差值转换成double,如果需要还要转换成负数  */  

  return time1 < time0 ? - subtract (time0, time1) : subtract (time1, time0);  

}  

/* 把函数命名为标准的difftime */  

strong_alias (__difftime, difftime)  

 

 difftime.c文件源码中

#include <cruntime.h>
#include <time.h>


/***
*double difftime(b, a) - find difference between two times
*
*Purpose:
*       returns difference between two times (b-a)
*
*       Multi-thread version must use pascal calling convention to be re-entrant.
*
*Entry:
*       long a, b - times to difference (actually are time_t values)
*
*Exit:
*       returns a double with the time in seconds between two times
*
*Exceptions:
*
*******************************************************************************/


double __cdecl difftime (
        time_t b,
        time_t a
        )
{
        return( (double)( b - a ) );

}


纯C代码编写(来自网友):

原理年转换成天,月转换成天,天转换成秒。从而计算出时间差。

/*

功能:是否为闰年

参数:

返回:

1----成功

0--失败

修改:

备注:

遵循的规律为: 四年一闰,百年不润,四百年再润.

 

if((year % 400 == 0)|(year % 4 == 0)&(year % 100 != 0))//闰年的计算方法

 

*/

 int Leap_Year(int year)

{

         return  ((year % 400 == 0) || ((year % 4 == 0)&& (year % 100 != 0))) ? 1 : 0;

}

 

/*

功能: 将年转化为天

参数:

返回:

sum---转化的天数

修改:

备注:

*/

 int Year_To_Day(int year_begin, int year_end)

{

         int sum = 0;

         int number = year_begin;

 

         while(number != year_end)

         {

                   sum = sum + 365 + Leap_Year(year_begin);

                   number++;

         }

 

         return sum;

}

/*

功能:将月转化为天数

参数:

返回:

-----转化完成的天数

修改:

备注:

*/

int month[12]={31,28,31,30,31,30,31,31,30,31,30,31};

 int Month_To_Day(date now)

{

         int i, day = 0;

 

         for (i = 0; i < now.month - 1; ++i)

         {

                   day = day + month[i];

         }

 

         return (now.month >= 3) ? day + now.day + Leap_Year(now.year) :  day + now.day;

 

}

 /*

 功能:计算两个日期之间的差值

 参数:

 begin---起始日期

 end----结束日期

 返回:

 ---算出的时间差值天

 修改:

 备注:

 且begin <= end  comcmp

 */

int Calculate(date begin,date end)

 {

          return Year_To_Day(begin.year, end.year) - Month_To_Day(begin) + Month_To_Day(end);

 }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值