C语言 - 日期计算器

#ifndef __INC_PUBLHEAD_H__
    #define __INC_PUBLHEAD_H__
//-----------------------------------------------------------------------------
#include <stdio.h>
#include "PublType.h"
//-----------------------------------------------------------------------------
#endif


#ifndef __INC_PUBLTYPE_H__
    #define __INC_PUBLTYPE_H__
//-----------------------------------------------------------------------------
typedef char                String;         // 字符串型
typedef unsigned int        Boolean;        // 布尔型

typedef unsigned char       UFix08;         // 无符号  8 位
typedef unsigned short int  UFix16;         // 无符号 16 位
typedef unsigned long int   UFix32;         // 无符号 32 位

typedef signed char         SFix08;         // 带符号  8 位
typedef signed short int    SFix16;         // 带符号 16 位
typedef signed long int     SFix32;         // 带符号 32 位

typedef unsigned int        UAuto08;        // 无符号 至少  8 位
typedef unsigned int        UAuto16;        // 无符号 至少 16 位
typedef unsigned long       UAuto32;        // 无符号 至少 32 位

typedef signed char         SAuto08;        // 带符号 至少  8 位
typedef signed int          SAuto16;        // 带符号 至少 16 位
typedef signed long         SAuto32;        // 带符号 至少 32 位
//-----------------------------------------------------------------------------
#endif


#include "PublHead.h"

typedef struct
{
    UAuto32         year;           // 年(0000~65535)
    UAuto08         month;          // 月(1~12)
    UAuto08         day;            // 日(1~31)
} STR_DTTM;

// 判断是否是闰年(公元历法)
// 闰年判断方法: 能被4整除且不能被100整除   或   能被400整除
static Boolean IsLeapYear(UAuto32 y)
{
    return ((((y % 4) == 0) && ((y % 100) != 0)) || ((y % 400) == 0)) ? 1 : 0;
}

static const UAuto16 day_of_month[2][13] =
{
	{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
	{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
};

// 计算与公园1年1月1日在偏移量
static UAuto32 Date_Sub_010101(STR_DTTM const *dt)
{
	UAuto32 year;

	year = dt->year - 1;
	return year * 365 + ((year / 4) - (year / 100) + (year / 400)) + day_of_month[IsLeapYear(dt->year)][dt->month - 1] + (dt->day - 1);
}

// 函数功能: 计算两个日期的差值 dt1 - dt2
// 输入    : dt1: 日期1 ,    dt2: 日期2
// 输出    : dt1 - dt2
static SAuto32 Date_Sub_Date(STR_DTTM const *dt1, STR_DTTM const *dt2)
{
#if 1
	return Date_Sub_010101(dt1) - Date_Sub_010101(dt2);
#else
	UAuto32 i = 0;
	SAuto32 day = 0;
	SAuto16 sign = 0;
	STR_DTTM big_year;
	STR_DTTM small_year;

	if (!IsLegal(dt1)|| !IsLegal(dt2)) {
		return 0;
	}

	sign = dt1->year > dt2->year ? -1:1;
	big_year = dt1->year > dt2->year ? *dt1:*dt2;
	small_year = dt1->year < dt2->year ? *dt1:*dt2;

	for (i = small_year.year; i < big_year.year; i++) {
		if (IsLeapYear(i)) {
			day += 366;
		} else {
			day += 365;
		}
	}

	day = sign*(Cal_Day_Of_Year(&big_year) - Cal_Day_Of_Year(&small_year) + day);

	return day;
#endif

}


#define FOUR_YEARS 1461
#define FOUR_HUNGRED_YEARS	146097
#define ONE_HUNGRED_YEARS 36524
#define THREE_HUNGRED_YEARS 109572
#define ONE_YEARS 365
#define THREE_YEARS 1095


static void Cal_Date_By_Offset(STR_DTTM *dest, UAuto32 days)
{
	UAuto16 i;
	UAuto16 const *tbl;

	dest->year = (days / FOUR_HUNGRED_YEARS) * 400 + 1; // 求经过多少个400年
	days %= FOUR_HUNGRED_YEARS;

	if (days > THREE_HUNGRED_YEARS) {  // 判断剩余年份是在0-300年间 还是 300-400年间
		dest->year += 300;
		days -= THREE_HUNGRED_YEARS;
	} else {
		dest->year += (days / ONE_HUNGRED_YEARS) * 100;
		days %= ONE_HUNGRED_YEARS;
	}

	dest->year += (days / FOUR_YEARS) * 4;
	days %= FOUR_YEARS;

	if (days > THREE_YEARS) { // 判断剩余年份是在0-3年间 还是 3-4年间
		dest->year += 3;
		days -= THREE_YEARS;
	} else {
		dest->year += days / ONE_YEARS;
		days %= ONE_YEARS;
	}

	tbl = day_of_month[IsLeapYear(dest->year)];

	for (i = days/31; i < 13; i++) {
		if ((days >= tbl[i]) && (days < tbl[i + 1])) {
			dest->month = i + 1;
			break;
		}
	}

	dest->day = days - tbl[dest->month - 1] + 1;

}


// 函数功能: 已知源日期src,目标日期与源日期相差的天数days,求目标日期dest = src + hex
// 输入:    src  : 源日期
//          days : 目标日期与源日期相差的天数
// 输出:    dest : 目标日期
static void TranDateHexToDate(STR_DTTM *dest, STR_DTTM const *src, SAuto32 days)
{
#if 1
	Cal_Date_By_Offset(dest, Date_Sub_010101(src) + days);
#else
	UAuto32 i = 0;
	UAuto32 j = 0;
	SAuto16 sign = 0;
	SAuto32 year = 0;
	SAuto32 differ_days = 0;
	SAuto16 one_year_of_day = 0;
	UAuto32 day_of_moth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

	if (!IsLegal(src)) {
		return;
	}

	if (!days) {
		*dest = *src;
		return;
	}

	sign = days > 0 ? 1:-1;
	differ_days = days + Cal_Day_Of_Year(src);
	if (days > 0) {
		one_year_of_day = IsLeapYear(src->year) > 0 ? 366:365;
	} else {
		one_year_of_day = IsLeapYear(src->year - 1) > 0 ? 366:365;
		j = -1;
	}


	 while(differ_days < -1*one_year_of_day || differ_days > one_year_of_day) {


		differ_days -= sign*one_year_of_day;
		year += sign;

		if(IsLeapYear(src->year + year + j)) {
			one_year_of_day = 366;
		} else {
			one_year_of_day = 365;
		}
	}

	if (days < 0) {
		if(IsLeapYear(src->year + year + sign)) {
			differ_days += 366;
		} else {
			differ_days += 365;
		}
		year += sign;
	}

	dest->year = src->year + year;

	if (IsLeapYear(dest->year)) {
		day_of_moth[1]++;
	}


	for(i = 0; differ_days > day_of_moth[i]; i++) {

		differ_days -= day_of_moth[i];
	}

	dest->month = i+1;
	dest->day = differ_days;

#endif
}

void main(void)
{
	STR_UFix64 mlong1 = {0};
	STR_DTTM date1 = {0};
    STR_DTTM date2 = {0};

	date1.year = 2003;
	date1.month = 1;
	date1.day = 1;
    date2.year = 4;
    date2.month = 12;
    date2.day = 31;
    TranDateHexToDate(&date1, &date2, 0);
	printf("010101 days = %ld\n", Date_Sub_010101(&date2));
    printf("year = %ld month = %ld day = %ld\n", date1.year, date1.month, date1.day);



	Cal_U32_Mul_U32(0xfdf52234L, 0x00fed741, &mlong1);
	printf("retv->high = %lx,  ",mlong1.high);
    printf("retv->low = %lx\r\n",mlong1.low);

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值