关于日期的一些计算

闰年的判断方法

在我们目前使用的格里高利历(Gregorian Calendar)中,闰年的确定遵循着一套精确的规则,具体来说,这些规则如下:

1.任何能被4整除的年份通常被认为是闰年。这意味着每四年,我们会增加一天,即2月29日,使得该年有366天而非常规的365天。

2.第二个规则是:如果一个年份能被100整除,那么它通常不被认定为闰年,但是它既能被100整除,同时也能被400整除,那么它就是闰年。

以2000年和1900年为例,2000年是闰年,因为它能被400整除(2000 ÷ 400 = 5),而1900年虽然能被100整除(1900 ÷ 100 = 19),但不能被400整除(1900 ÷ 400 ≠ 整数),因此1900年不是闰年。

bool isLeapYear(int year) {
	return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}

判断给定的日期是给定年份的第几天

要计算给定的日期是给定年份的第几天,可以遍历从1月到给定月份之前的所有月份,累加每个月的天数到dayOfYear,最后,将给定月份的天数加到dayOfYear上即可。要特别注意2月,因为闰年和平年的天数不同,在累加月份天数时,如果年份是闰年且当前月份是2月,则2月有29天;否则,2月有28天。

int calculateDayOfYear(int year, int month, int day)
{
	int dayOfYear = 0;
	std::array<int, 12> daysPerMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
	if (isLeapYear(year))
		daysPerMonth[1] = 29;

	for (int i = 0; i < month - 1; i++)
		dayOfYear += daysPerMonth[i];
	dayOfYear += day;

	return dayOfYear;
}

判断给定的日期是星期几

基姆拉尔森计算公式是一种用于计算给定日期是星期几的算法,特别适用于编程和日常生活中的日期计算。该公式基于公历日期系统,通过特定的数学运算来确定任何一天是星期几。以下是关于基姆拉尔森计算公式的详细解释和计算步骤:

公式概述

基姆拉尔森计算公式的基本形式如下:
W=(d+2m+3(m+1)/5+y+y/4−y/100+y/400+1)%7
其中:

  • d 表示日期中的日数(1-31)。
  • m 表示月份数(3-14,其中1月和2月被视为上一年的13月和14月)。
  • y 表示年份。
  • W 表示星期几,取值范围为0到6,其中0代表星期日,1代表星期一,依此类推。
int calculateWeekDay(int year, int month, int day) {
	if (month == 1 || month == 2) {
		month += 12;
		year--;
	}
	int w = (day + 2 * month + 3 * (month + 1) / 5 + year + year / 4 - year / 100 + year / 400 + 1) % 7;
	return w;
}

完整代码如下

#include <iostream>
#include <array>
#include <chrono>
#include <cmath>

/**
 * 判断指定年份是否为闰年
 *
 * 闰年的判断条件如下:
 * 1、年份可以被400整除;
 * 2、年份能被4整除,但不能被100整除;
 *
 * @param year 要判断的年份
 * @return 如果年份是闰年则返回true,否则返回false
 */
bool isLeapYear(int year) {
	return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}

/**
 * 计算给定的日期是今年第几天
 *
 * @param year 要判断的年份
 * @param year 要判断的月份
 * @param year 要判断的日期
 * @return 返回该日期是今年第几天
 */
int calculateDayOfYear(int year, int month, int day)
{
	int dayOfYear = 0;
	std::array<int, 12> daysPerMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
	if (isLeapYear(year))
		daysPerMonth[1] = 29;

	for (int i = 0; i < month - 1; i++)
		dayOfYear += daysPerMonth[i];
	dayOfYear += day;

	return dayOfYear;
}

/**
 * 基姆拉尔森公式根据日期判断星期几
 *
 * @param year 要判断的年份
 * @param year 要判断的月份
 * @param year 要判断的日期
 * @return 返回该日期是周几,计算结果的取值范围是0-6,0代表星期日,1-6分别代表星期一到星期六
 */
int calculateWeekDay(int year, int month, int day) {
	if (month == 1 || month == 2) {
		month += 12;
		year--;
	}
	int w = (day + 2 * month + 3 * (month + 1) / 5 + year + year / 4 - year / 100 + year / 400 + 1) % 7;
	return w;
}

/**
 * 计算当前日期为当前年份周数
 *
 * 在中国,周数的计算通常遵循以下规则:
 * 1.每周从星期一开始,到星期日结束;
 * 2.1月1日所在的周通常被认为是第1周;

 * @param year 要判断的年份
 * @param year 要判断的月份
 * @param year 要判断的日期
 * @return 返回该日期是第几周
 */
int calculateWeekNumber(int year, int month, int day) {
	int daysOfRemain = CalculateDayOfYear(year, month, day) - (7 - calculateWeekDay(year, 1, 1));
	if (daysOfRemain == 0)
	{
		return 1;
	}

	int weekNumber = std::ceil(static_cast<double>(daysOfRemain) / 7);
	return weekNumber + 1;
}


int main() {
	auto now = std::chrono::system_clock::now();
	auto today = std::chrono::system_clock::to_time_t(now);
	std::tm date;
#ifdef _WIN32
	::localtime_s(&date, &today);
#else
	::localtime_r(&date, &today);
#endif
	int year = date.tm_year + 1900; // tm_year 是从1900年开始计数的
	int month = date.tm_mon + 1; // tm_mon 是从0开始计数的
	int day = date.tm_mday;

	std::cout << "今天是 " << year << "年" << month << "月" << day << "日" << std::endl;
	std::cout << "今天是今年的第 " << calculateWeekNumber(year, month, day) << " 周" << std::endl;

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值