关注

简单快速的算出YYMMDD格式的日期之差

1 杂谈:

   最近在写蓝桥杯嵌入式12届真题,遇见了一个要处理YYMMDDHHmmSS格式的时间之差的问题。起初乍一看感觉很简单啊,不就算个日期差吗?把所有除串口以外的功能写完后,就去写这个日期之差,越写越感觉汗流浃背了,要求了好多细节,导致难度上升很多。其中就属这个算相差多少小时的功能写的最丑陋,一直if else差点给自己写迷了。最后写是写出来了,但是感觉写的太丑陋了,所以静下心研究了一会真就发现了一个比较好算的方法,特意写个博客记录一下,也算帮助一下别人,别人也可以参考一下。

2 内容:

2.1 难点:

      我个人感觉日期难点就在与年份分闰年和非润年,闰年是366天非闰年是365天。而且每一年当中不同的月份中的天数也不同比如1,3,5,7,8,10,12都是31天。4,6,9,11都是30天,其中2月最特殊闰年的时候为29天,平年的时候为28天。这一大堆的限制条件很容易让人写出一堆if else,虽然也能运行但是不优雅。

2.2 解决方法:

       我们不如换个角度想既然月份的太复杂了,我们不如只看一个整体那就是年份,因为年份只有闰年和平年之分,这样判断条件会减少很多。这个时候我们需要引入一个知识那就是前缀和了。前缀和简单来说就是把一个有序的数组的前n项进行相加,形成一个新的数组,这个数组的每一项都是原数组的起始位到此项之和。比如一个数组是arr[5]={1,2,3,4,5},那它的前缀和数组之和就是sum_arr[5]={1,3,6,10,15}。根据这个原理我们也可以将年份也化为前缀和去使用,它会大大降低我们的计算量。

 平年: 原年份数组yaer:

                 31,    28,   31,  30,    31,  30,  31, 31, 30, 31,  30,  31

                1月       2月    3月     4月     5月    6月    7月   8月   9月   10月  11月   12月

 前缀和数组             

                31,    59,   90,  120, 151,181,212,243,273,304 ,334,365  

 润年: 原年份数组yaer:

                 31,    29,   31,  30,    31,  30,  31, 31, 30, 31,  30,  31

                1月       2月    3月     4月     5月    6月    7月   8月   9月   10月  11月   12月

 前缀和数组           

                31,    60,   91,  121, 152,182,213,244,274,305 ,335,366

这张图便是精髓用图像的方式展示出我是如何简便计算的。我们以2020年4月6日到2022年12月11日为例。我们先设一个值dis_day=0.首先我们知道2020年到2022年中间有一个完整的年份就是2021年,我们再判断一下这个2021年是闰年还是平年。2021年是平年所以dis_day+365=365,自可dis_day是365.我们再看起始年份2020年是润年,所以我们需要用到闰年的那个前缀和数组,我们再看月和日是4月6日,可以拆成前三个月的前缀和加上第四月的6天,我们可以查数组3月份的前缀和是91天,再把它加6天就是91+6=97天。但是呢这只是算2020年到起始年份已经经过的天数所以我们要366(闰年)-97=269天,dis_day+269=634天。同理我们再看截止日期2022年是平年所以需要用到平年的前缀和数组,12月11日就是前11个月加上第12个月的11天,11月的前缀和是334,334+11=345天,所以dis_day+345=979天至此我们就算出了相差天数。最终把计算分为了三个部分,起始日期,中间年份,截至日期。

2.3 bug:

     其实这里还是有点小bug的,那就是不能算同一年份的相差日期的,因为我们算起始日期的时候要的是全年-月日(366-97)。这个时候只需做一点小修改就是改成我们要这个97天并且变为负数就像这样dis_day-97天就解决了这个bug。通俗易懂的说如果两个年份是同一年,我们要的是它俩的差。例如2022年4月6日到2022年12月11日,首先判断出这个2022是平年,然后就是前11个月的前缀和加11天-前3个月的前缀和加6天,334+11-90+6=249天。

3 代码:

  

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
bool run_falg(int year)
{ 
  if(year%4==0&&year%100!=0||year%400==0)
  {
   return true;
  }
  return false;
}
int run_year[13]={0,31,60,91,121,152,182,213,244,274,305,335,366};
int year[13]={0,31,59,90,120,151,181,212,243,273,304,334,365};
int disday(int h_yy,int h_mm,int h_dd,int l_yy,int l_mm,int l_dd)
{
   int dis_day=0; 
   for(int i=l_yy+1;i<h_yy;i++)
   {
     if(run_falg(i))
	 {
	  dis_day+=366;
	 }
     else
	 {
	  dis_day+=365;
	 }
   }
   //上半部分
   bool l_flag=run_falg(l_yy);
   if(h_yy!=l_yy)//当两者年份不相同时 
 {   
   if(l_flag)
   {
    dis_day+=366-(run_year[l_mm-1]+l_dd);
   }
   else
   {
    dis_day+=365-(year[l_mm-1]+l_dd);
   }
 }
   //当两者年份相同时 
   else
 {
   if(l_flag)
   {
    dis_day-=(run_year[l_mm-1]+l_dd);
   }
   else
   {
    dis_day-=(year[l_mm-1]+l_dd);
   }
 }
   //下半部分
   bool h_flag=run_falg(h_yy);
   if(h_flag)
   {
    dis_day+=(run_year[h_mm-1]+h_dd);
   }
   else
   {
    dis_day+=(year[h_mm-1]+h_dd);
   }
   return dis_day;
}
int main(void)
{
 	int day=disday(22,12,11,20,4,6);
 	printf("%d",day);
	return 0;
 }

4  结语:

     希望帮到大家。

转载自CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/ne555555/article/details/152167769

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--