解剖:日期与时间函数标签:int,double,difftime,year,time1,时间差,计算,time From: https://blog.51cto.com/u_6958388/5923276
struct tm {
int tm_sec; /* 秒,范围从 0 到 59 */
分,范围从 0 到 59 */
小时,范围从 0 到 23 */
一月中的第几天,范围从 1 到 31 */
月,范围从 0 到 11 */
自 1900 年起的年数 */
一周中的第几天,范围从 0 到 6 */
一年中的第几天,范围从 0 到 365 */
夏令时 */
};
C 库函数 - difftime()
C 标准库 - <time.h>
描述
C 库函数 double difftime(time_t time1, time_t time2) 返回 time1 和 time2 之间相差的秒数 (time1 - time2)。这两个时间是在日历时间中指定的,表示了自纪元 Epoch(协调世界时 UTC:1970-01-01 00:00:00)起经过的时间。
声明
下面是 difftime() 函数的声明。
double difftime(time_t time1, time_t time2)
参数
time1 -- 这是表示结束时间的 time_t 对象。
time2 -- 这是表示开始时间的 time_t 对象。
返回值
该函数返回以双精度浮点型 double 值表示的两个时间之间相差的秒数 (time2 - time1)。
/* difftime.c:difftime函数的实现 */
#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)
/* 返回两个时间TIME1和TIME0的差值(秒数),这里TIME0<=TIME1,time_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语义。然而,
在C中是无符号的,因此它无需与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;
}
}
/* 返回TIME1和TIME0之间的差值(秒数) */
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 comcmp
*/
int Calculate(date begin,date end)
{
return Year_To_Day(begin.year, end.year) - Month_To_Day(begin) + Month_To_Day(end);
}