输入年月周星期计算年月日日期

本文详细介绍了如何使用基姆拉尔森计算公式将特定的年、月、周和周几转换为精确的日期。通过判断闰年和平年的不同规则,结合一周的两种定义,文章提供了C++实现的代码示例,帮助读者理解和应用这一算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【要求】

输入年、月、第几周、周几;如:2018 2 2 3(2018年2月第二周的周三)

输出对应的 年、月、日;2018-02-07(输出)

错误的输入输出0

【分析】

  1. 区分任意一年是否为闰年;闰年2月29天,否则是2月有28天;
  2. 一周的定义有2种:周一到周日为一周(1234567);周日到周六为一周(0123456)0为周日
  3. 第一周可能不全,即2018年2月第一周没有周二周三;

【思路】

  • 判断是否为闰年
//判断是否是闰年
int IsLeapYear(int y)
{
	if ((y % 400 == 0) || ((y % 4 == 0) && (y % 100 != 0)))
		return 1;
	else return 0;
}

 

  • 基姆拉尔森计算公式计算某年某月某日对应的星期
int CaculateWeekDay(int yy, int mm, int d)
{
	if (mm == 1 || mm == 2) {
		mm += 12;
		yy--;
	}
	int iWeek = (d + 2 * mm + 3 * (mm + 1) / 5 + yy + yy / 4 - yy / 100 + yy / 400) % 7;
	return iWeek + 1;
}

note:CaculateWeekDay函数返回值即星期几(返回7,星期日;返回2,星期二)

此计算公式可以输入任意日期,求得这个一天的星期

【Code】

#include<iostream>
#include<iomanip>
using namespace std;

//基姆拉尔森计算公式计算某年某月某日对应的星期
int CaculateWeekDay(int yy, int mm, int d)
{
	if (mm == 1 || mm == 2) {
		mm += 12;
		yy--;
	}
	int iWeek = (d + 2 * mm + 3 * (mm + 1) / 5 + yy + yy / 4 - yy / 100 + yy / 400) % 7;
	return iWeek + 1;
}

//注意这里的星期:周日-周六(一周的开始是周日)

int a[][12] = { { 31,28,31,30,31,30,31,31,30,31,30,31 },{ 31,29,31,30,31,30,31,31,30,31,30,31 } };
int b[8] = { 0,1,2,3,4,5,6,0 };
//判断是否是闰年
int IsLeapYear(int y)
{
	if ((y % 400 == 0) || ((y % 4 == 0) && (y % 100 != 0)))
		return 1;
	else return 0;
}

int CaculateDay(int yy, int mm, int w, int n)
{
	//输入判断是否符合条件
	if (mm < 1 || mm > 12)return 0;
	if (w < 1 || w > 6)return 0;
	if (n < 1 || n > 7)return 0;
	//计算每月1号星期几------》为下面判断周几是否有:
	//如2019年7月1号是星期一,那么按照周日为一周的开始,则n=7,return 0;CaculateDay函数 按照此逻辑
	//如果周一为一周开始,参考CaculateDay2函数

	int days;
	int week_day = CaculateWeekDay(yy, mm, 1);//计算每月1号星期
	if (w == 1) {
		//第一周需要检查n是否超过
		if (b[n] < b[week_day])
			return 0;
		else
			days = b[n] - b[week_day] + 1;
	}
	else {
		days = b[6] - b[week_day] + 1;
		days += (w - 2) * 7;
		days += (b[n] + 1);
		if (days <= 0 || days > a[IsLeapYear(yy)][mm - 1])
			return 0;
	}
	return days;
}

int CaculateDay2(int yy, int mm, int w, int n)
{
	//输入判断是否符合条件
	if (mm < 1 || mm > 12)return 0;
	if (w < 1 || w > 6)return 0;
	if (n < 1 || n > 7)return 0;

	int days;
	int week_day = CaculateWeekDay(yy, mm, 1);//计算每月1号星期
	if (w == 1) {
		//第一周需要检查n是否超过
		if (n < week_day)
			return 0;
		else
			days = n - week_day + 1;
	}
	else {
		days = 7 - week_day + 1;
		days += (w - 2) * 7;
		days += n;
		if (days <= 0 || days > a[IsLeapYear(yy)][mm - 1])
			return 0;
	}
	return days;
}

int main()
{
	int yy, mm, w, n;
	while (cin >> yy >> mm >> w >> n) 
	{
		//int day = CaculateDay(yy, mm, w, n);
		int day = CaculateDay2(yy, mm, w, n);
		if (day == 0)
			cout << day << endl;
		else
		{
			cout << yy << "-" << setw(2) << setfill('0') << mm << "-" << setw(2) << setfill('0') << day << endl;
		}
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值