C语言-日历与日期相关问题

1.给出年月日,计算该日是星期几

#include <stdio.h>
#include <Windows.h>

/*
	<程序说明>
	
	1.给出年月日(如:2022 3 6),系统会自动计算出该日的星期(如:星期天)
	
	2.数学公式:
		S = x - 1 + (x - 1)/4 - (x - 1)/100 + (x - 1)/400 + C
		参数说明:
		(1)S%7 --> 计算出来的星期(如:0表示星期天,1表示星期一,...,等) 
		(2)x   --> 该日期(输入的日期)
		(3)C   --> 该日期为这一年的第几天(从元旦到该日,包括元旦与该日期) ===>难点!! 
		
	3.拓展知识:
		(1)闰年计算:
			每4年且不是100的整数,即为闰年(2月29天)
		(2)闰年计算:
			每400年是一个闰年 

*/

int main(){
	
	int year,month,day;//年月日 
	int numberOfDays;//天数
	int week;//星期 
	int num;//公式算出来的结果 
	
	printf("请输入日期(格式:2022 3 6):"); 
	scanf("%d%d%d",&year,&month,&day);//输入日期
		
	//根据月份来计算天数
	switch(month){
		case 12:
			numberOfDays += 30;//加上一个月的总天数,否则会差一天(差的一天是1月份的) 
		case 11:
			numberOfDays += 31;
		case 10:
			numberOfDays += 30;
		case 9:
			numberOfDays += 31;
		case 8:
			numberOfDays += 31;
		case 7:
			numberOfDays += 30;
		case 6:
			numberOfDays += 31;
		case 5:
			numberOfDays += 30;
		case 4:
			numberOfDays += 31;
		case 3:
			//判断是否是闰年 
			if((year % 4 == 0 && year / 100 != 0) || (year % 400 == 0)){
				numberOfDays += 29;
			}else{
				numberOfDays += 28;
			}	
		case 2:
			numberOfDays += 31;	
		case 1:
			numberOfDays += day;
			break;
		default:
			printf("输入年份有误!\n");
			exit(0);//退出程序 
	} 	
	
	//计算公式:S = x - 1 + (x - 1)/4 - (x - 1)/100 + (x - 1)/400 + C 
	num = year - 1 + (year - 1)/4 - (year - 1)/100 + (year - 1)/400 + numberOfDays;
	
	//计算星期几 
	week = num % 7;
	
	printf("\n"); 
	
	switch(week){
		case 0:
			printf("%d年%d月%d日,是星期天\n",year,month,day);
			break;
		case 1:
			printf("%d年%d月%d日,是星期一\n",year,month,day);
			break;
		case 2:
			printf("%d年%d月%d日,是星期二\n",year,month,day);
			break;
		case 3:
			printf("%d年%d月%d日,是星期三\n",year,month,day);
			break;
		case 4:
			printf("%d年%d月%d日,是星期四\n",year,month,day);
			break;
		case 5:
			printf("%d年%d月%d日,是星期五\n",year,month,day);
			break;
		case 6:
			printf("%d年%d月%d日,是星期六\n",year,month,day);
			break;
	} 
			
	return 0;
}

在这里插入图片描述

2.给出年份,计算该年元旦那天是星期几

#include <stdio.h>

/*
	<程序说明>
	
	1.给出年(如:2022),系统会自动计算出该年元旦的星期(如:2022年元旦是星期六)
	
	2.数学公式:
		S = [x + (x - 1)/4 - (x - 1)/100 + (x - 1)/400] % 7
		参数说明:
		(1)S --> 计算出来的星期(如:0表示星期天,1表示星期一,...,等) 
		(2)x --> 该日期(输入的日期)
		
	3.拓展知识:
		(1)闰年计算:
			每4年且不是100的整数,即为闰年(2月29天)
		(2)闰年计算:
			每400年是一个闰年 

*/

int main(){
	
	int year;
	int week; 
	
	printf("请输入年份(如:2022):");
	scanf("%d",&year);
	
	//计算公式: S = [x + (x - 1)/4 - (x - 1)/100 + (x - 1)/400] % 7
	week = (year + (year - 1)/4 - (year - 1)/100 + (year - 1)/400)%7;
	
	switch(week){
		case 0:
			printf("%d年,是星期天\n",year);
			break;
		case 1:
			printf("%d年,是星期一\n",year);
			break;
		case 2:
			printf("%d年,是星期二\n",year);
			break;
		case 3:
			printf("%d年,是星期三\n",year);
			break;
		case 4:
			printf("%d年,是星期四\n",year);
			break;
		case 5:
			printf("%d年,是星期五\n",year);
			break;
		case 6:
			printf("%d年,是星期六\n",year);
			break;
	} 
	
	
	return 0;
}

在这里插入图片描述

3.计算某年某月某日是本年度第几天

#include <stdio.h>
#include <Windows.h>

/*
	<程序说明>
	
	1.给出年月日(如:2022 3 6),系统会自动计算出该日是该年的第几天(如:65天)
	
	2.函数(用函数将其封装起来)
	
		(1)计算天数
			int sumDays(int year,int month,int day);
			利用for循环,将上一个月的天数加起来,即可求解!
			如果是1月份的话,就直接返回day参数
			返回值为int型
			 
		(2)计算该年是否是闰年
			bool isLeap(int year); 
			如果是闰年,返回true;否则返回false. 
		
	3.拓展知识:
		(1)闰年计算:
			每4年且不是100的整数,即为闰年(2月29天)
		(2)闰年计算:
			每400年是一个闰年 
			
*/

int sumDays(int year,int month,int day);//传入参数:month ==> 该年的月份 , day ==> 该年的日数
bool isLeap(int year);//传入参数:year ==> 该年的年份 

int main(){
	
	int year,month,day;//年月日
	int numberOfDays;//计算天数
	
	printf("请输入年月日(如:2022 3 6):");
	scanf("%d%d%d",&year,&month,&day);
	
	numberOfDays = sumDays(year,month,day);//代入函数,求得天数
	
	printf("\n%d年%d月%d日,是%d年的第%d天\n",year,month,day,year,numberOfDays); 
	
	return 0;
}

//计算天数(从该年的元旦开始记起) 
int sumDays(int year,int month,int day){
	
	int daysOfTheMonth[12] = {0,31,28,31,30,31,30,31,31,30,31,30};//并未将12月份的天数加进来 
	bool monthFlag = false;//假设传入的参数有误 
	bool dayFlag = false;//两个传入的参数(month day)都满足才能继续执行程序 
	
	//判断传入的参数,是否有误
	for(int i = 1;i <= 12;i++){
		if(month == i){//传入的月份在1到12数字之间,传入数字正确 
			monthFlag = true;
		}
	}
	if(month == 1 || month == 3 || month == 5 ||
	month == 7 || month == 8 || month == 10 || month == 12){//月份都有31天的情况 
		for(int i = 1; i <= 31;i++){
			if(day == i){  //传入的日份在1到31数字之间,传入数字正确 
				dayFlag = true;
			}
			
		}
	}else if(month == 2){//2月份的情况 
		if(isLeap(year)){
			for(int i = 1; i <= 29;i++){
				if(day == i){  //传入的日份在1到31数字之间,传入数字正确 
					dayFlag = true;
				}
			}
		}else{
			for(int i = 1; i <= 28;i++){
				if(day == i){  //传入的日份在1到31数字之间,传入数字正确 
					dayFlag = true;
				}
			}	
		}
	}else{//其他月份的情况,都为30天 
		for(int i = 1; i <= 30;i++){
			if(day == i){  //传入的日份在1到31数字之间,传入数字正确 
				dayFlag = true;
			}
		}
	}
	
	//情况总结,如果传入参数无误,flag为true,则!flag == false,就不会执行下面语句 
	if(!monthFlag || !dayFlag){
		printf("传入参数有误!请重新检查!\n");
		exit(0);//传入参数有误,并退出程序 
	} 
	
	for(int i = 1; i < month;i++){
		if(i == 2){//添加2月份的全部天数 
			if(isLeap(year)){
				//该年是闰月
				day += 29; 
				continue;//加了29天后,跳出当前循环,进入下一循环! 
			}
		}
		day += daysOfTheMonth[i];
	}
	
	return day;//返回天数
	
}

//判断该年是否是闰年 
bool isLeap(int year){
	return (year % 4 == 0 && year / 100 != 0) || (year % 400 == 0);
}

在这里插入图片描述

4.求指定日期距离出生日期的天数

#include <stdio.h>
#include <windows.h>

/*
	<程序说明>
	
	1.给出"指定年月日"(如:2022 3 6),给出"出生年月日"(如:2000 1 1),
	系统会自动计算出指定年月日到出生日有多少天(如:xxx天)
	
	2.思路 
		
		(1) 计算指定年月日到出生年的1月1日的天数(详细步骤可见上一程序)
		
		(2) 计算出指定年月日与出生年月日的分别在当年的第几天(详见:3.给出年月日,计算出该日是该年的第几天) 
		
		(3) 减去出生年中出生日期之前的天数(见下面的图)
			
			|------birth~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~today| 
			birth:2000-02-01
			today:2022-03-06
			头:2000-01-01 (出生年的元旦)  尾:today
			
			①根据第一步(1)操作后,我们可以计算出这一整条线段
			②根据第二步(2)操作后,我们可以计算出[birth - 头]这一段"短横线"所代表在这一年并未出生的阶段
			③所以[birth - today]这一段,可以通过(1)(2)问相减可得! 
			
	3.拓展知识:
		(1)闰年计算:
			每4年且不是100的整数,即为闰年(2月29天)
			
		(2)闰年计算:
			每400年是一个闰年 
			
		(3)初始化问题
			声明的变量一定要初始化,否则预计的结果会跟预料的结果不一样!(不信?可以试试!) 
			
*/

//定义一个结构体 ==> 表示日期
typedef struct datatime{
	int year;
	int month;
	int day;
}DATETIME; 

int totalDays(DATETIME date,int birth_year);//传入参数:日期 
int currentYearDays(DATETIME date);//计算指定日期在该年是第几天 
bool isLeap(int year);//传入参数:year ==> 该年的年份 
bool isMonthError(int month);//判断月份是否出错(月份应处于[1,12]区间内)
bool isDayError(int year,int month,int day);//判断日期是否出错(day应处于[1,31]之间,根据不同月份而有所不同) 

int main(){
	
	DATETIME specifiedDate;//指定日期
	DATETIME birthday;//出生日期 
	
	printf("请输入现在的日期(如:2022-3-6):");
	scanf("%d-%d-%d",&specifiedDate.year,&specifiedDate.month,&specifiedDate.day);//输入指定日期
	
	printf("\n请输入出生的日期(如:2000-8-21):");
	scanf("%d-%d-%d",&birthday.year,&birthday.month,&birthday.day);//输入出生日期 
	
	int overall_days;//从现在的日期到出生年元旦的总共天数
	
	overall_days = totalDays(specifiedDate,birthday.year); //计算出思路(1)的结果,即整个线段的长度
	
	//计算出生日到出生年有多少天(包括出生日) --> 等价于思路中的短横线阶段,计算思路(2)的步骤 
	int birth_before = currentYearDays(birthday);
	
	//整个线段 - 出生前(短横线的阶段)  ===> 现在年月日到出生日的天数,计算思路(2) 
	int birth_to_today = overall_days - birth_before;
	if(birth_to_today < 0){
		//现在年月日小于出生年月日,说明还未出生 
		printf("还未出生呢~!\n");
		exit(0);
	}
	
	int age = birth_to_today/365;//计算年龄:出生日期到现在日期经历的天数 除以 一年 ==> 年龄 
	
	printf("\n现在%d年%d月%d日,你已经%d岁了!(%d天)\n",specifiedDate.year,specifiedDate.month,
									specifiedDate.day,age,birth_to_today); //打印输出信息 
	
	 
	
	
	return 0;
}

//计算经过了多少天
int totalDays(DATETIME date,int birth_year){
	
	int total_day = 0;
	
	//先计算过了多少年
	for(int oldYear = birth_year;oldYear < date.year;oldYear++){
		if(isLeap(date.year)){
			total_day += 366;
		}else{
			total_day += 365;
		}
	} 
	
	//再计算该日是该年的第几天
	total_day += currentYearDays(date); //包括指定日期的那一天 
	
	return total_day;//返回总的计算天数 
	
} 

//计算天数(从该年的元旦开始记起) 
int currentYearDays(DATETIME date){
	
	int daysOfTheMonth[12] = {0,31,28,31,30,31,30,31,31,30,31,30};//并未将12月份的天数加进来 
	int sum_days = 0;//计算出来的天数 
	
	//判断传入的参数,是否有误
	if(!isMonthError(date.month) || !isDayError(date.year,date.month,date.day)){
		printf("传入参数有误!请重新检查!\n");
		exit(0);//传入参数有误,并退出程序 
	} 
	
	for(int i = 1; i < date.month;i++){
		if(i == 2){//添加2月份的全部天数 
			if(isLeap(date.year)){
				//该年是闰月
				sum_days += 29; 
				continue;//加了29天后,跳出当前循环,进入下一循环! 
			}
		}
		sum_days += daysOfTheMonth[i];
	}
	
	sum_days += date.day;//将当前月份已经经过的天数算上(包括指定日期) 
	 
	return sum_days;//返回计算出来的天数 
	
}

//判断输入的月份是否超过数值范围 
bool isMonthError(int month){
	for(int i = 1;i <= 12;i++){
		if(month == i){
			return true;//传入的月份在1到12数字之间,传入数字正确 
		}
	}
	return false;//传入数字,不在[1,12]区间内,传入参数错误 
} 

//判断输入的日期是否超过数值范围 
bool isDayError(int year,int month,int day){
	
	if(month == 1 || month == 3 || month == 5 ||
	month == 7 || month == 8 || month == 10 || month == 12){//月份都有31天的情况 
		for(int i = 1; i <= 31;i++){
			if(day == i){  
				return true;//传入的日份在1到31数字之间,传入数字正确 
			}
			
		}
	}else if(month == 2){//2月份的情况 
		if(isLeap(year)){
			for(int i = 1; i <= 29;i++){
				if(day == i){  
					return true;//传入的日份在1到31数字之间,传入数字正确 
				}
			}
		}else{
			for(int i = 1; i <= 28;i++){
				if(day == i){  
					return true;//传入的日份在1到31数字之间,传入数字正确 
				}
			}	
		}
	}else{//其他月份的情况,都为30天 
		for(int i = 1; i <= 30;i++){
			if(day == i){  
				return true;//传入的日份在1到31数字之间,传入数字正确 
			}
		}
	}
	
	return false;//传入参数错误,不符合日期规范 
} 
 
//判断是否是闰年 
bool isLeap(int year){
	return (year % 4 == 0 && year / 100 != 0) || (year % 400 == 0);
}

在这里插入图片描述

5.求指定日期距离1970年1月1日的天数

#include <stdio.h>
#include <windows.h>

/*
	<程序说明>
	
	1.给出年月日(如:2022 3 6),系统会自动计算出该日是距离1970年1月1日有多少天(如:xxx天)
	
	2.思路 
	
		(1)计算天数
			totalDays(int year,int month,int day)
			①指定日期与1970年中间的一些年,相加起来
			②通过年月日,计算出指定日期是该年的第几天
			③第一步与第二步相加即可得最终解 
			 
		(2)计算该年是否是闰年
			bool isLeap(int year); 
			如果是闰年,返回true;否则返回false. 
		
	3.拓展知识:
		(1)闰年计算:
			每4年且不是100的整数,即为闰年(2月29天)
		(2)闰年计算:
			每400年是一个闰年 
		(3)初始化问题
			声明的变量一定要初始化,否则预计的结果会跟预料的结果不一样!(不信?可以试试!) 
			
*/

//定义一个结构体 ==> 表示日期
typedef struct datatime{
	int year;
	int month;
	int day;
}DATETIME; 

long long totalDays(DATETIME date);//传入参数:日期 
int currentYearDays(DATETIME date);//计算指定日期在该年是第几天 
bool isLeap(int year);//传入参数:year ==> 该年的年份 
bool isMonthError(int month);//判断月份是否出错(月份应处于[1,12]区间内)
bool isDayError(int year,int month,int day);//判断日期是否出错(day应处于[1,31]之间,根据不同月份而有所不同) 

int main(){
	
	DATETIME specifiedDate;//指定日期
	
	printf("请输入日期(如:2022-3-6):");
	scanf("%d-%d-%d",&specifiedDate.year,&specifiedDate.month,&specifiedDate.day);//输入指定日期
	
	printf("\n%d年%d月%d日距离1970年1月1日,有%lld天\n",specifiedDate.year,
			specifiedDate.month,specifiedDate.day,totalDays(specifiedDate)); 
	
	printf("\n%d年%d月%d日距离1970年1月1日,有%lld毫秒\n",specifiedDate.year,
			specifiedDate.month,specifiedDate.day,totalDays(specifiedDate)*24*60*60*1000);
	
	return 0;
}

//计算经过了多少天
long long totalDays(DATETIME date){
	
	int total_day = 0;
	
	//先计算过了多少年
	for(int oldYear = 1970;oldYear < date.year;oldYear++){
		if(isLeap(date.year)){
			total_day += 366;
		}else{
			total_day += 365;
		}
	} 
	
	//再计算该日是该年的第几天
	total_day += currentYearDays(date); //包括指定日期的那一天 
	
	return total_day;//返回总的计算天数 
	
} 

//计算天数(从该年的元旦开始记起) 
int currentYearDays(DATETIME date){
	
	int daysOfTheMonth[12] = {0,31,28,31,30,31,30,31,31,30,31,30};//并未将12月份的天数加进来 
	int sum_days = 0;//计算出来的天数 
	
	//判断传入的参数,是否有误
	if(!isMonthError(date.month) || !isDayError(date.year,date.month,date.day)){
		printf("传入参数有误!请重新检查!\n");
		exit(0);//传入参数有误,并退出程序 
	} 
	
	for(int i = 1; i < date.month;i++){
		if(i == 2){//添加2月份的全部天数 
			if(isLeap(date.year)){
				//该年是闰月
				sum_days += 29; 
				continue;//加了29天后,跳出当前循环,进入下一循环! 
			}
		}
		sum_days += daysOfTheMonth[i];
	}
	
	sum_days += date.day;//将当前月份已经经过的天数算上(包括指定日期) 
	 
	return sum_days;//返回计算出来的天数 
	
}

//判断输入的月份是否超过数值范围 
bool isMonthError(int month){
	for(int i = 1;i <= 12;i++){
		if(month == i){
			return true;//传入的月份在1到12数字之间,传入数字正确 
		}
	}
	return false;//传入数字,不在[1,12]区间内,传入参数错误 
} 

//判断输入的日期是否超过数值范围 
bool isDayError(int year,int month,int day){
	
	if(month == 1 || month == 3 || month == 5 ||
	month == 7 || month == 8 || month == 10 || month == 12){//月份都有31天的情况 
		for(int i = 1; i <= 31;i++){
			if(day == i){  
				return true;//传入的日份在1到31数字之间,传入数字正确 
			}
			
		}
	}else if(month == 2){//2月份的情况 
		if(isLeap(year)){
			for(int i = 1; i <= 29;i++){
				if(day == i){  
					return true;//传入的日份在1到31数字之间,传入数字正确 
				}
			}
		}else{
			for(int i = 1; i <= 28;i++){
				if(day == i){  
					return true;//传入的日份在1到31数字之间,传入数字正确 
				}
			}	
		}
	}else{//其他月份的情况,都为30天 
		for(int i = 1; i <= 30;i++){
			if(day == i){  
				return true;//传入的日份在1到31数字之间,传入数字正确 
			}
		}
	}
	
	return false;//传入参数错误,不符合日期规范 
} 
 
//判断是否是闰年 
bool isLeap(int year){
	return (year % 4 == 0 && year / 100 != 0) || (year % 400 == 0);
}

在这里插入图片描述

posted @ 2022-03-12 17:10  辰梦starDream  阅读(33)  评论(0编辑  收藏  举报  来源