迈出第一步往往是困难的,只愿前路回首,既无风雨也无愁!
这是一份计算工作日天数、自然日天数的代码。编写的起因是前公司经常需要提交项目周期计划给销售,所以经常用到计算工作日的软件,一开始我们都是翻着日历,上网查法定假日,然后将工作日摘出来计算项目交期;后来我找到了一个网站,可以计算工作日间隔、或者根据工作日计算最终交期,于是发给边上同事使用;再后来,我就离职跑路了~
离职后的某天,一个同事找我聊天,说是之前的网站找不到了,于是便萌生了自己写一版的想法,于是乎,下面这份代码就产生了。
思路是建立一个大的数组,内部用0或1标识工作日和非工作日,然后通过给定的条件计算工作日或截止日期,没有用到结构体、指针等高级技巧,因为当时我用的不好,所以就没敢上,使用C-Free软件编写,但是我也试着把它改到VS上跑了一下,也是木有问题的~
写的灰常灰常的挫,请不小心看到的大佬轻喷~
后续有时间再更新,但愿我不会偷懒~(不可能 :)

#include <stdio.h>
#include <string.h>
#include <stddef.h>
int Year_2019_Data[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int Year_2020_Data[]={0,31,29,31,30,31,30,31,31,30,31,30,31};
int OutputDays = 0;//输出天数 
int sumNutureDate(int year1,int month1,int day1,int year2,int month2,int day2); 
void ReleaseLog(void);
void weekendInit(void);
void InsertHoliday(int write2holiday);
void InsertWorkday(int write2workday);
int sum_MONTH_DAYS(int year,int month1,int day1,int month2,int day2);
//定义每一个月初第一周的星期类型
int get_2019_week[]={0, 0x06,0x30,0x30,0x03,0x0C, 0x60,0x03,0x18,0x41,0x06,  0x30,0x41};
int get_2020_week[]={0, 0x0C,0x60,0x41,0x0C,0x30,0x03,0x0C,0x60,0x06,0x18,0x41,0x06};
int weeks2019[13][32]={0};
int weeks2020[13][32]={0};int insert_holiday[] = { 	20190101,//元旦 20190204,20190205,20190206,20190207,20190208,20190209,20190210,//春节 20190405,20190406,20190407,//清明 20190501,20190502,20190503,//劳动20190607,20190608,20190609,//端午节20190913,20190914,20190915,//中秋节 20191001,20191002,20191003,20191004,20191005,20191006,20191007,//国庆节20200101,//元旦 20200124,20200125,20200126,20200127,20200128,20200129,20200130,20200131,20200201,20200202,//春节20200404,20200405,20200406,//清明 20200501,20200502,20200503,20200504,20200505,//劳动节 20200625,20200626,20200627,// 端午节20201001,20201002,20201003,20201004,20201005,20201006,20201007,20201008//国庆&中秋 	 };
int insert_workday[] = {	20190202,20190203,20190428,20190505,20190929,20191012,20200105,20200119,20200426,20200509,20200628,20200927,20201010};
//数据交换函数 
void swap(int a, int b) //引用类型方式  
{  int temp; //辅助变量  temp = a;  a = b;  b = temp;     
}  
//日期解析
int DataAnalysis(int Frist,int End)
{int nuture_date=0;//定义返回值 int year1,month1,day1;//年月日参数,仅支持2019年1月1日-2020年12月31日 int year2,month2,day2;	year1 = Frist/10000;month1 = (Frist/100)%100;day1 = Frist%100;year2 = End/10000;month2 = (End/100)%100;day2 = End%100;	
}
/**节假日初始化,初始化二维数组 
*/
//在weeks数组中插入节假日  
void InsertHoliday(int write2holiday)
{int nuture_date=0;//定义返回值 int year,month,day;//年月日参数,仅支持2019年1月1日-2020年12月31日 year = write2holiday/10000;month = (write2holiday/100)%100;day = write2holiday%100;if(year==2019){weeks2019[month][day]= 1;}if(year==2020){weeks2020[month][day]= 1;}
} 
//在weeks数组中插入调班 
void InsertWorkday(int write2workday)
{int nuture_date=0;//定义返回值 int year,month,day;//年月日参数,仅支持2019年1月1日-2020年12月31日 year = write2workday/10000;month = (write2workday/100)%100;day = write2workday%100;if(year==2019){weeks2019[month][day]= 0;}if(year==2020){weeks2020[month][day]= 0;}
} //节假日初始化 
void weekendInit(void)
{int len;int i,j,k;int m,n,p;int x,y;int temp1[101]={0};int temp2[101]={0};int year=0;//2019年 //标识是否为周末,周末标识为1 for(i=1;i<=12;i++){len=Year_2019_Data[i];//获取每月多少天 for(j=1;j<=len;j++){if(j%7==0)	k = 7 ;else		k = j%7;//获取移位次数 weeks2019[i][j]=!(((get_2019_week[i]<<k)&0x80)==0);//1标识为周末,0标识为工作日 }}//2020年 //标识是否为周末,周末标识为1 for(m=1;m<=12;m++){len=Year_2020_Data[m];//获取每月多少天 for(n=1;n<=len;n++){if(n%7==0)	p = 7 ;else		p = n%7;//获取移位次数 //p =n%7-1;//获取移位次数 weeks2020[m][n]=!(((get_2019_week[m]<<p)&0x80)==0);//1标识为周末,0标识为工作日 }}		//插入节假日for(x=0;x<sizeof(insert_holiday)/sizeof(int);x++){InsertHoliday(insert_holiday[x]);}//插入调班 for(y=0;y<sizeof(insert_workday)/sizeof(int);y++){InsertWorkday(insert_workday[y]);}
} //同一个月内的节假日 
int GetSameMonthHoliday(int year,int tomonth1,int today1,int today2) 
{int j;int res=0;for(j=today1;j<=today2;j++){if(year == 2019) {if(weeks2019[tomonth1][j] == 1)res++;}if(year == 2020) {if(weeks2020[tomonth1][j] == 1)//第一天除去,不算节假日计算 res++;}}	return res;
} 
//计算同一年中的节假日
int GetSameYearHoliday(int year,int tomonth1,int today1,int tomonth2,int today2) 
{int i,j;int result=0;if(year==2019){if(tomonth1==tomonth2){result=GetSameMonthHoliday(year,tomonth1,today1,today2);}if(tomonth1 < tomonth2){//计算day1到月底的间隔节假日 result+=GetSameMonthHoliday(year,tomonth1,today1,Year_2019_Data[tomonth1]);for(i=tomonth1+1;i<tomonth2;i++){//计算中间月份的节假日 result += GetSameMonthHoliday(year,i,1,Year_2019_Data[i]);}//计算尾巴节假日result +=  GetSameMonthHoliday(year,tomonth2,1,today2); }}if(year==2020){if(tomonth1==tomonth2){result=GetSameMonthHoliday(year,tomonth1,today1,today2);}if(tomonth1 < tomonth2){//计算第一天到月底的间隔节假日 result+=GetSameMonthHoliday(year,tomonth1,today1,Year_2020_Data[tomonth1]);for(i=tomonth1+1;i<tomonth2;i++){//计算中间月份的节假日 result += GetSameMonthHoliday(year,i,1,Year_2020_Data[i]);}//计算尾巴节假日result +=  GetSameMonthHoliday(year,tomonth2,1,today2);}return result;}return result;
}
//计算不同年的节假日天数,即总的节假日天数 
int GetHoliday(int tyear1,int tmonth1,int tday1,int tyear2,int tmonth2,int tday2) 
{
//	weeks2019[m][n];
//	weeks2020[m][n]; int result;if(tyear1 < tyear2){result = GetSameYearHoliday(tyear1,tmonth1,tday1,12,31);result += GetSameYearHoliday(tyear2,1,1,tmonth2,tday2);}if(tyear1 == tyear2) result = GetSameYearHoliday(tyear1,tmonth1,tday1,tmonth2,tday2);return result;
} 
//计算同一年内不同月份之间的差值 ,返回差值result 
int sum_MONTH_DAYS(int year,int month1,int day1,int month2,int day2)
{int Data[101]={0};int result=0;//将2019或2020年的日期拷贝至临时数组 Data[] if(year == 2019){memcpy(Data,Year_2019_Data,sizeof(Year_2019_Data));}if(year == 2020){memcpy(Data,Year_2020_Data,sizeof(Year_2020_Data));}//计算同一年中的日期差 int i;for(i=0;(i< (month2-month1));i++){result +=	Data[month1+i];}result = day2+result-day1;return result;
}//计算总的自然日差值,返回自然日差值; 
int sumNutureDate(int year1,int month1,int day1,int year2,int month2,int day2)
{int nuture_date=0;//定义返回值 // 计算总相差日期if(year2 == year1){if(month2 >= month1){nuture_date=	sum_MONTH_DAYS( year1, month1, day1, month2, day2);	}				}if(year2 > year1){int temp1,temp2;//先计算到19年底的天数差 temp1=	sum_MONTH_DAYS( year1, month1, day1, 12, 31);	//再计算到20年初到结束日期的天数差 temp2=	sum_MONTH_DAYS( year2, 1, 1, month2, day2);//两边计算有时间差,故补偿1天 nuture_date = temp1+temp2+1;}return nuture_date; 
}//计算同一年内的最终日期
int calcSameYearEndDate(int year1,int month1,int day1,int days)
{int Data[101]={0};int temp1,temp2,temp3;int lastDate;int LastMonth,LastDay;int i;if(year1 == 2019){memcpy(Data,Year_2019_Data,sizeof(Year_2019_Data));}if(year1 == 2020){memcpy(Data,Year_2020_Data,sizeof(Year_2020_Data));}//计算头部 temp1=Data[month1]-day1;if(days<=temp1){LastMonth = month1; LastDay = day1+days;	}else {temp2=days-temp1;//计算中间月份for(i=1;(temp2>Data[month1+i]);i++){temp2 = temp2-Data[month1+i];}//计算尾部 if(temp2<=Data[month1+i]){LastMonth = month1+i;LastDay	= temp2;}			}lastDate = year1*10000+LastMonth*100+LastDay;return lastDate;	
}//计算不同年的最终日期
int calcEndDate(int year1,int month1,int day1,int days)
{int temp1,temp2;int EndDate;if(year1 == 2019){temp1 = sumNutureDate(year1, month1, day1, 2019, 12, 31);//计算同年剩余自然日 temp2 = days-temp1; if(temp2>0){EndDate = calcSameYearEndDate( 2020, 1, 1, temp2);}else{EndDate = calcSameYearEndDate( year1, month1, day1, days);	}}if(year1 == 2020){EndDate = calcSameYearEndDate( year1, month1, day1, days);	}return EndDate;	
}//假设日期在同一年内计算起始日期加工作日 
int calcSameYear(int year1,int month1,int day1,int Days)
{int temp1,temp2;int i,j,k;int res;if(year1==2019){for(i=month1;i<13;i++){if(i==month1){k=day1+1;	}else{k=1;}for(j=k;j<=Year_2019_Data[i];j++){if(weeks2019[i][j]==0){Days--;}if(Days == 0){res=i*100+j;return res;}}}		} if(year1==2020){for(i=month1;i<13;i++){if(i==month1){k=day1+1;	}else{k=1;}for(j=k;j<=Year_2020_Data[i];j++){if(weeks2020[i][j]==0){Days--;}if(Days == 0){res=i*100+j;return res;}}}	}return 0;
}
//计算起始日期加上工作日最后的日期,可跨年 
int AddWorkingDays_EndDate(int year1,int month1,int day1,int Days)
{int i,j;int EndDate;//EndDate = calcSameYearEndDate( year1, month1, day1, days);if(year1 == 2019){i = sumNutureDate(year1, month1, day1, 2019, 12, 31)\-GetHoliday( year1, month1, day1, 2019, 12, 31);//计算同年剩余工作日 j= Days-i; if(j>0){//	printf("help");EndDate = 2020*10000+calcSameYear(2020,1,1,j);return EndDate;}if(j<=0){//	printf("help2");EndDate = year1*10000+calcSameYear(year1,month1,day1,Days);return EndDate;}		}if(year1==2020){EndDate = year1*10000+calcSameYear(year1,month1,day1,Days);return EndDate;}return 0;
}//主循环 
int main(int argc, char *argv[])
{	int FristDate,EndDate;//输入起始计算日期int InputNutureDays;//输入间隔自然日 int InputWorkingDays;//间隔工作日,输入 int OutputNutureDate  = 0;//自然日日期差 int OutputHoliday	  = 0;//输出节假日 int OutputWorkingDays = 0;//输出工作日int OutputEndDate	  = 0;//输出最终日期 //年月日参数,仅支持2019年1月1日-2020年12月31日 int year1,month1,day1; int year2,month2,day2;	int year3,month3,day3;int Flag = 0; ReleaseLog();weekendInit();//假日初始化while(1){	printf("起始日期:");scanf("%d", &FristDate);//数据输入printf("结束日期:");scanf("%d", &EndDate);//数据输入printf("自然日间隔:");scanf("%d", &InputNutureDays);//数据输入	printf("工作日间隔:");scanf("%d", &InputWorkingDays);//数据输入//日期数据解析  year1 = FristDate/10000;month1 = (FristDate/100)%100;day1 = FristDate%100;year2 = EndDate/10000;month2 = (EndDate/100)%100;day2 = EndDate%100;	//进行间隔天数计算 	if(EndDate>0){Flag = 0;if(FristDate > EndDate){			//支持乱序输入swap(FristDate,EndDate);	}	}if(InputNutureDays> 0)//进行自然日结束日期计算 {//参数检查Flag = 1; }if(InputWorkingDays> 0)//进行工作日结束日期计算 {Flag = 2; } //进行间隔天数计算 if(Flag == 0){//计算间隔天数 OutputNutureDate = sumNutureDate(year1, month1, day1, year2, month2, day2);OutputHoliday = GetHoliday( year1, month1, day1, year2, month2, day2); OutputWorkingDays =  OutputNutureDate - OutputHoliday; printf("间隔自然日天数:%d\n",OutputNutureDate);printf("间隔节假日天数:%d\n",OutputWorkingDays);printf("间隔工作日天数:%d\n\n",OutputWorkingDays);		} //输入自然日,进行最终日期计算 else if(Flag == 1) {OutputEndDate = calcEndDate(year1,month1,day1,InputNutureDays);	printf("自然日最终日期:%d\n\n",OutputEndDate);	}//输入工作日,进行最终日期计算else if(Flag == 2){OutputEndDate =  AddWorkingDays_EndDate(year1,month1,day1,InputWorkingDays);year3 = OutputEndDate/10000;month3 = (OutputEndDate/100)%100;day3 = OutputEndDate%100;	OutputHoliday = GetHoliday( year1, month1, day1, year3, month3, day3); //printf("***************************************************************\n");	printf("工作日最终日期:%d\n",OutputEndDate);		} printf("*****************************THE END**************************************\n");}
}void ReleaseLog(void)
{printf("**************************************************************************\n");printf("本程序仅用于计算两个日期之间的天数间隔\n"); printf("**************************************************************************\n");printf("版本:v0.1\n");printf("发布:2019.11.1\n");printf("仅支持2019年1月1日到2020年12月31日之间的天数计算\n");printf("支持起始日期和结束日期乱序输入\n");
//	printf("Note3:由于目前国务院暂时没有发布2020年的官方放假安排,\n");
//	printf("       本次2020年放假数据来源于百度经验,网址如下:\n https://jingyan.baidu.com/article/f96699bb16ab75894f3c1b7f.html\n");		printf("更新日志:\n");printf("2019.11.1,修复隔月节假日计算异常\n");printf("2019.11.5,增加输入起始日期+工作日,输出最终日期功能\n");printf("2020.8.6,根据法定假日安排,修正2020年放假数据\n");	printf("依次输入起始日期、结束日期、自然日天数、工作日天数\n"); printf("按Enter键结束输入,缺省数据输入0;例:20190101 20190102 0 0 \n\n");
}