当前位置: 首页 > ai >正文

查漏补缺——与日期有关的字符串

文章目录

  • 一、日期相关的字符串
    • 1.1基础问题
      • 1.1.1判断闰年
      • 1.1.2月份的规律
      • 1.1.3字符串解析出年月日
      • 1.1.4格式化日期格式
    • 1.2进阶问题
      • 1.2.1验证日期的合法性
      • 1.2.2一年过了多少天
      • 1.2.3日期加天数
      • 1.2.4转换日期格式
      • 1.2.3日期之间间隔多少天

一、日期相关的字符串

1.1基础问题

1.1.1判断闰年

闰年 指的是:1、能被400整除,2、或者能被4整除但不能被100整除。

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

要计算某一年的总天数,只需判断该年是否为闰年即可:

  • 闰年有 366 天(2 月有 29 天)
  • 平年有 365 天(2 月有 28 天)
int daysInYear(int year) {return isLeapYear(year) ? 366 : 365;
}

1.1.2月份的规律

月份的规律是:

  • 1、3、5、7、8、10、12 月固定有 31 天
  • 4、6、9、11 月固定有 30 天
  • 2 月特殊:闰年 29 天,平年 28 天(通过isLeapYear函数判断)
int months[12]={31,28/29,31,30,31,30,31,31,30,31,30,31};
if(isLeapYear(year))  months[1]=29;int daysInMonth(int year, int month) {switch (month) {case 2:return isLeapYear(year) ? 29 : 28;case 4: case 6: case 9: case 11:return 30;default:return 31;}
}

1.1.3字符串解析出年月日

给定一个 “YYYY-MM-DD” 格式的日期,将年月日分离出来。

void parseDate(const string& date, int& year, int& month, int& day) {stringstream ss(date);char dash;  // 用于接收分隔符 '-'ss >> year >> dash >> month >> dash >> day;
}

1.1.4格式化日期格式

#include<iomanip>
string formatDate(int year, int month, int day) {stringstream ss;ss << setw(4) << setfill('0') << year << "-"<< setw(2) << setfill('0') << month << "-"<< setw(2) << setfill('0') << day;return ss.str();
}

1.2进阶问题

序号题目链接
1转变日期格式——正规https://leetcode.cn/problems/reformat-date/description/?envType=problem-list-v2&envId=string
2转换日期格式——转换为二进制https://leetcode.cn/problems/convert-date-to-binary/description/?envType=problem-list-v2&envId=string
3一年中的第几天https://leetcode.cn/problems/day-of-the-year/description/?envType=problem-list-v2&envId=string
4日期之间隔多少天https://leetcode.cn/problems/number-of-days-between-two-dates/description/?envType=problem-list-v2&envId=string
5统计共同度过的日子https://leetcode.cn/problems/count-days-spent-together/description/?envType=problem-list-v2&envId=string

1.2.1验证日期的合法性

验证一个日期是否合法,需要检查年、月、日三个部分是否都符合实际规则。

  • 年份范围 [1900, 2100]
  • 月份范围 [01, 12]
  • 日期在当月的有效天数范围内(考虑闰年对 2 月的影响)
bool isValidDate(int year, int month, int day) {if (year < 1) return false;if (month < 1 || month > 12) return false;if (day < 1 || day > daysInMonth(year, month)) return false;return true;
}

1.2.2一年过了多少天

int dayOfYear(string date) {//判断每个月多少天int months[12]={31,28,31,30,31,30,31,31,30,31,30,31};//解析字符串int y,m,d;char dash;stringstream ss(date);ss >> y >> dash >> m >> dash >> d;if((y % 400 == 0) || (y % 4 == 0 && y % 100 != 0))  months[1]=29;//月*天数+dayint sum=0;for(int i=0;i<m-1;i++){sum+=months[i];}return sum+d;
}

1.2.3日期加天数

给定一个 “YYYY-MM-DD” 格式的日期和一个整数 N,计算 N 天后的日期,同样以 “YYYY-MM-DD” 格式返回。

情况输入输出
当月内的简单加法输入日期:2023-10-05,N=3结果:2023-10-08
跨月输入日期:2023-04-25,N=10结果:2023-05-05
跨年输入日期:2023-11-15,N=50结果:2024-01-04

处理的核心逻辑:

  • 判断累加后的日
    • 没有超过当月的最大天数:无需处理
    • 超过了当月的最大天数,跨月:减去当月的天数,进入下一个月
  • 如果月份超过 12(即month>12),则年份加 1,月份重置为 1(进入下一年)。
string addDays(string date, int N) {//将日期分隔出年月日int year, month, day;parseDate(date, year, month, day);// 加上N天day += N;// 处理日期进位(月和年)while (true) {int daysInCurrentMonth = getDaysInMonth(year, month);// 日期在当前月范围内,无需继续进位if (day <= daysInCurrentMonth) {  break;   }// 减去当前月的天数,进入下个月day -= daysInCurrentMonth;month++;// 处理月份进位到年if (month > 12) {month = 1;year++;}}return formatDate(year, month, day);
}

1.2.4转换日期格式

给你一个字符串 date ,它的格式为 Day Month Year ,请你将字符串转变为 YYYY-MM-DD 的格式。其中:

  • Day 是集合 {“1st”, “2nd”, “3rd”, “4th”, …, “30th”, “31st”} 中的一个元素。
  • Month 是集合 {“Jan”, “Feb”, “Mar”, “Apr”, “May”, “Jun”, “Jul”, “Aug”, “Sep”, “Oct”, “Nov”, “Dec”} 中的一个元素。
  • Year 的范围在 ​[1900, 2100] 之间。
string reformatDate(string date) {unordered_map<string,string> mp={{"Jan", "01"},{"Feb", "02"},{"Mar", "03"},{"Apr", "04"},{"May", "05"},{"Jun", "06"},{"Jul", "07"},{"Aug", "08"},{"Sep", "09"},{"Oct", "10"}, {"Nov", "11"},{"Dec", "12"}};//解析字符串string year,month,day;stringstream ss(date);ss >> day >> month >> year;//处理日后面的thday.pop_back();day.pop_back();if(day.size() == 1) day="0"+day;//处理月份month=mp[month];return year+"-"+month+"-"+day;
}

给你一个字符串 date,它的格式为 yyyy-mm-dd,表示一个公历日期。date 可以重写为二进制表示,只需要将年、月、日分别转换为对应的二进制表示(不带前导零)并遵循 year-month-day 的格式。

//十进制转换为二进制
string decimalToBinary(int num) {if (num == 0) { return "0";}string binary;while (num > 0) {binary += (num % 2 == 0) ? '0' : '1'; // 取余数,转换为字符num /= 2;}// 反转字符串得到正确的二进制顺序reverse(binary.begin(), binary.end());return binary;
}
string convertDateToBinary(string date) {//解析字符串int year, month, day;stringstream ss(date);char dash;ss >> year >> dash >> month >> dash >> day;//将数字转换为二进制并连接起来//return decimalToBinary(year) + "-" + decimalToBinary(month) + "-" + decimalToBinary(day);return format("{}-{}-{}", decimalToBinary(year), decimalToBinary(month), decimalToBinary(day));
}

1.2.3日期之间间隔多少天

请你编写一个程序来计算两个日期之间隔了多少天。

  • 将两个日期都转换为从一个固定起始点(如公元 1 年 1 月 1 日)开始的总天数
  • 然后计算差值的绝对值。
// 计算从公元1年1月1日到给定日期的总天数
int totalDaysFromStart(int year, int month, int day) {int days = 0;// 累加完整年份的天数for (int y = 1; y < year; ++y) {days += isLeapYear(y) ? 366 : 365;}// 累加当月之前的月份天数for (int m = 1; m < month; ++m) {days += daysInMonth(year, m);}// 累加当月的天数(1月1日是第1天)days += day;return days;
}
// 计算两个日期之间的天数差
int daysBetweenDates(const string& date1, const string& date2) {int y1, m1, d1;int y2, m2, d2;parseDate(date1, y1, m1, d1);parseDate(date2, y2, m2, d2);int days1 = totalDaysFromStart(y1, m1, d1);int days2 = totalDaysFromStart(y2, m2, d2);return abs(days1 - days2);
}

统计两个人共同度过的日子数。日期都是 “MM-DD” 格式(不包含年份)

  • 所有 “MM-DD” 格式的日期转换为当年的第几天
  • 找到两个区间的重叠部分:重叠开始是两个开始日期的最大值,重叠结束是两个结束日期的最小值
  • 计算重叠区间的天数:如果重叠结束 >= 重叠开始,则天数为重叠结束 - 重叠开始 + 1,否则为 0
    在这里插入图片描述
int days[12]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//计算该日期从01-01开始的总天数
int f(string s){int month,day;stringstream ss(s);char dash;ss >> month >> dash >> day;int sum=0;for(int i=0;i<month-1;i++){sum+=days[i];}sum+=day;return sum;
}
int countDaysTogether(string arriveAlice, string leaveAlice, string arriveBob, string leaveBob) {string a = arriveAlice < arriveBob ? arriveBob : arriveAlice;string b = leaveAlice < leaveBob ? leaveAlice : leaveBob;return max(0,f(b)-f(a)+1);
}

给定两个 “YYYY-MM-DD” 格式的日期,计算它们之间的工作日天数(周一至周五,不含法定节假日)。

  • 基姆拉尔森计算公式【根据年月日计算出星期几】:
    • 由于公式的计算逻辑基于 “1 月、2 月视为上一年的 13 月、14 月”(简化闰年对 2 月的影响)
    • 公式:h = ( D + [13×(M + 1)÷5] + Y + [Y÷4] - [Y÷100] + [Y÷400] ) % 7
    • 公式计算出的 h 并非直接对应 “周一至周日”,需按以下规则转换:
公式结果 h0123456
实际星期
// 计算给定日期是星期几(0=星期日, 1=星期一, ..., 6=星期六)
int getWeekday(int year, int month, int day) {// 基姆拉尔森计算公式if (month < 3) {month += 12;year--;}int h = (day + 13*(month + 1)/5 + year + year/4 - year/100 + year/400) % 7;return (h == 0) ? 6 : h - 1; // 转换为0=星期日, 1=星期一...6=星期六
}// 计算从日期1到日期2的工作日天数(包含起止日期)
int workdaysBetweenDates(const string& date1, const string& date2) {// 解析两个日期int y1, m1, d1;int y2, m2, d2;parseDate(date1, y1, m1, d1);parseDate(date2, y2, m2, d2);// 确保date1 <= date2bool swapped = false;if (y1 > y2 || (y1 == y2 && m1 > m2) || (y1 == y2 && m1 == m2 && d1 > d2)) {swap(y1, y2);swap(m1, m2);swap(d1, d2);swapped = true;}int workdays = 0;int currentY = y1, currentM = m1, currentD = d1;// 遍历两个日期之间的每一天while (true) {// 检查是否到达结束日期if (currentY == y2 && currentM == m2 && currentD == d2) {// 检查当前日期是否为工作日(1-5为周一至周五)int weekday = getWeekday(currentY, currentM, currentD);if (weekday >= 1 && weekday <= 5) { workdays++; }break;}// 检查当前日期是否为工作日int weekday = getWeekday(currentY, currentM, currentD);if (weekday >= 1 && weekday <= 5) { workdays++; }// 移动到下一天currentD++;if (currentD > daysInMonth(currentY, currentM)) {currentD = 1;currentM++;if (currentM > 12) {currentM = 1;currentY++;}}}return workdays;
}
http://www.xdnf.cn/news/19329.html

相关文章:

  • SAP Business One的设计哲学
  • Linux 网络编程:深入理解套接字与通信机制
  • 在Windows系统Docker中使用wsl2、容器、windows文件路径三种不同挂载方式的区别和性能差异
  • 大话 IOT 技术(1) -- 架构篇
  • 【代码随想录day 22】 力扣 39. 组合总和
  • 视频理解与行为识别全景综述
  • Multi-Head RAG: Solving Multi-Aspect Problems with LLMs
  • linux 内核 - 常见的文件系统介绍
  • AIA中断控制器IPI的Linux内核实现
  • Qt-Advanced-Docking-System: 一个基于 Qt 框架的高级停靠窗口系统
  • Spring boot注解介绍
  • Python 2025:AI代理、Rust与异步编程的新时代
  • BigDecimal账户分布式原子操作
  • IOT安全学习之IoT_Sec_Tutorial
  • 历史数据分析——寒武纪
  • Wi-Fi技术——MAC特性
  • 【人工智能99问】Qwen3中的QK归一化是什么?(34/99)
  • LeetCode 3459.最长 V 形对角线段的长度:记忆化搜索——就一步步试
  • 备份压缩存储优化方案:提升效率与节省空间的完整指南
  • 鸿蒙开发入门:ArkTS 运算符与分支循环全解析(含实战案例 + 避坑指南)
  • ES6 面试题及详细答案 80题 (13-21)-- 数组与字符串扩展
  • Zynq开发实践(FPGA之平台免费IP)
  • GitHub Spark深度体验:是革命前夜,还是又一个“大厂玩具”?
  • 浅层与深层语义分析的NLP进化论
  • libmodbus移植
  • spi总线
  • Python 实战:内网渗透中的信息收集自动化脚本(6)
  • 【Unity3D实例-功能-切换武器】切换武器(一)动画配置
  • FPGA CIC抽取滤波器设计
  • HarmonyOS 应用开发:基于API 12及以上的新特性与实践