最简单的日期计算公式~

文章介绍了如何避免繁琐的闰年和平年判断,使用蔡勒公式计算两个日期之间的天数差,以及如何通过公式确定任意日期是星期几。重点讲解了公式2、3和4的原理以及如何在C++代码中实现intsum_date函数。
摘要由CSDN通过智能技术生成

常规方法

  1. 计算0001-01-01到(xxxx-1)-12-31的公式是
    这里(xxxx-1)指的是去年,比如我们要算2024-02-29那么xxxx-1就代表2023年
                                
    TotalDay=365*y+\frac{y}{4}-\frac{y}{100}+\frac{y}{400}
    公式1

    其中,y:year,

    闰年分为普通闰年(能被4整除但不能被100整除)跟世纪闰年(能被400整除),365*year好理解,就是先算平年的所有天,

    y/4-y/100是计算0001-xxxx年间有多少个普通闰年,

    y/400是计算有多少个世纪闰年(多少个闰年就多多少天)

  2. 接着计算xxxx-01-01到xxxx-xx-xx的天数,执行1.+2.

  3. 如果计算两个日期差的话,就是两个天数相减

上面的计算是否麻烦的一些?还得判断xxxx是闰年还是平年,然后挨个月计算,那么是否有一种公式只需要年月日就可以计算出差多少天?——蔡勒公式

蔡勒公式

首先先给出蔡勒公式的表达式:

TotalDay=365*y+\frac{y}{4}-\frac{y}{100}+\frac{y}{400}+\frac{153*m-457}{5}-306+d
公式2


y:year, m:month, d:day

这是你要计算的日期

公式的前半部分好理解,就是计算0001-01-01到(xxxx-1)-12-31或者0001-01-01到xxxx-12-31的时间,区别这两种计算是因为我们计算月份的时候跨了年份,请看下面的例子。要想无需判断平年闰年就能计算出差多少天,首先一定得迈过2.28/2.29这个坎,其次闰年366天平年365天一定是在这两天变化的,其他月份不管是平年还是闰年都是一样的。于是该公式的起始时间是本年的3.01到明年的2.01此时完美避开了2.28/9,从而可以无需考虑该年是平年还是闰年。

让我们观察一下每个月的1号到3月1号的天数规律

月份该月天数该月1号到3月1号的天数差规律
33100
4303130+1
5316160+1
6309290+2
731122120+2
831153150+3
930184180+4
1031214210+4
1130245240+5
1231275270+5
1331306300+6
14未知337330+7

其中13表示明年的1月份,14表示明年的2月份

你会发现除了个位数,另一个是一个首项是0,公差是30的等差数列
现在的问题就变成找到一个函数拟合个位数的变化1,1,2,2,3,4,4,5,5,6,7
该函数就是
 

num(m)=\lfloor\frac{m*3-7}{5}\rfloor
公式3
m是月份,num值是其个位数

于是就有

(m-3)*30+\lfloor\frac{m*3-7}{5}\rfloor=\lfloor\frac{153m-457}{5}\rfloor
公式4
所以这个公式就是计算我们要求的month所在月的1号到3.01的天数

加上该月所在的天数day,就是总的TotalDay

那么306是哪来的呢, 看上面表格你会发现,306是指3.01-12.31这个时间的总和

那么为何要-306呢?我们来举两个例子

计算2024-02-27和计算2024-05-23(ps:下面说的公式前半部分指的是公式1,后半部分指的是公式4)

首先计算2024-02-27,由于是2月份(小于3月份)于是变成2023-14-27,带入公式得,由于公式的前半部分是计算了2023年一整年,所以这部分就是计算0001-01-01~2023-12-31的总天数,公式后半部分计算的是2023-03-01到2023-14-01(也就是2024-02-01)的总天数,这里也就有了重叠计算了两次2023-03-01到2023-12-31的天数,也就是306,于是公式就有减去306天了,最后在加上2月已过去27天,也就是2024-02-27已过去的天数了。

计算2024-05-23,由于是5月份(大于3月份)于是直接带入公式得,公式前半部分计算0001-01-01到2024-12-31的总天数,减去306天也就是变成0001-01-01到2024-03-01的总天数,公式后半部分计算的是3-01到5-01的总天数,两者相加就是2024-05-23已过去的天数了。

这里给出c++的代码

int sum_date(int y, int m, int d) {
    if (m < 3) {
        m += 12;
        y--;
    }
    return 365 * y + y / 4 - y / 100 + y / 400 + (153 * m - 457) / 5 + d - 306;
}

最后

算出了这个日期已过去多少天就可以秒杀很多题目了,包括但不限于,两个日期差多少天,给定一个日期算出今天是星期几?(totalday%7=0就是星期天,1就是星期一以此类推)

reference

【学习笔记】如何求出任意日期是星期几? - Superlova

  • 19
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 基于Java的日期计算非常简单,可以使用java.util.Calendar类。可以把两个日期转换为毫秒,然后计算它们之间的毫秒差,然后根据工作日的时间(比如8小时)计算出工作日天数: long daysBetween = (date2.getTimeInMillis() - date1.getTimeInMillis())/(1000*60*60*24); long workDaysBetween = daysBetween - (daysBetween/7)*2; ### 回答2: 实现两个日期之间的工作日天数可以使用Java的日期处理类库来进行计算。以下是一个简单的实现: ```java import java.time.DayOfWeek; import java.time.LocalDate; public class WorkingDaysCalculator { public static int calculateWorkingDays(LocalDate startDate, LocalDate endDate) { int workingDays = 0; LocalDate currentDate = startDate; while (!currentDate.isAfter(endDate)) { if (currentDate.getDayOfWeek() != DayOfWeek.SATURDAY && currentDate.getDayOfWeek() != DayOfWeek.SUNDAY) { workingDays++; } currentDate = currentDate.plusDays(1); } return workingDays; } public static void main(String[] args) { LocalDate startDate = LocalDate.of(2022, 1, 1); // 起始日期 LocalDate endDate = LocalDate.of(2022, 1, 10); // 结束日期 int workingDays = calculateWorkingDays(startDate, endDate); System.out.println("工作日天数:" + workingDays); } } ``` 该代码中,首先使用`LocalDate`类来表示起始日期和结束日期。然后通过一个`while`循环,从起始日期依次遍历到结束日期。在循环中,判断当前日期是否为周六或周日,如果不是,则将工作日天数加1。最后返回计算得到的工作日天数。在`main`方法中,我们提供了一个示例来计算2022年1月1日到2022年1月10日之间的工作日天数,并将结果输出到控制台。 该代码的核心思想是使用循环和条件判断来筛选出工作日,并计算其数量。注意,此处假设周六和周日为非工作日。 ### 回答3: 要计算两个日期之间的工作日天数,我们可以按照以下步骤来实现: 1. 首先,创建一个函数,接受两个日期作为参数。假设日期的格式为"yyyy-MM-dd"。 2. 在函数内部,通过Java提供的日期处理类,将传入的日期字符串转换为日期对象。可以使用`SimpleDateFormat`类来实现。 3. 使用日期对象的`getTime()`方法获取日期的毫秒数,并计算两个日期之间的毫秒差。 4. 将毫秒差转换为天数。可以使用以下公式: `天数 = 毫秒差 / (24 * 60 * 60 * 1000)` 5. 创建一个循环,从开始日期循环遍历到结束日期,每次遍历加1天。 6. 在循环中使用`Calendar`类的`get(Calendar.DAY_OF_WEEK)`方法获取当前日期是星期几。根据星期几判断是否为工作日。星期一到星期五为工作日。 7. 统计工作日的天数,使用一个计数器变量。 8. 返回工作日的天数。 以下是具体的实现代码: ```java import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; public class WorkingDaysCalculator { public static int calculateWorkingDays(String startDate, String endDate) { int workingDays = 0; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); try { Date start = sdf.parse(startDate); Date end = sdf.parse(endDate); Calendar startCal = Calendar.getInstance(); startCal.setTime(start); Calendar endCal = Calendar.getInstance(); endCal.setTime(end); while (!startCal.after(endCal)) { int dayOfWeek = startCal.get(Calendar.DAY_OF_WEEK); if (dayOfWeek != Calendar.SATURDAY && dayOfWeek != Calendar.SUNDAY) { workingDays++; } startCal.add(Calendar.DAY_OF_MONTH, 1); } } catch (ParseException e) { e.printStackTrace(); } return workingDays; } public static void main(String[] args) { String startDate = "2022-01-01"; String endDate = "2022-01-10"; int workingDays = calculateWorkingDays(startDate, endDate); System.out.println("工作日天数: " + workingDays); } } ``` 在`main`方法中,我们可以直接调用`calculateWorkingDays`函数,传入起始日期和结束日期的字符串,然后打印工作日天数。在这个例子中,起始日期为"2022-01-01",结束日期为"2022-01-10"。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值