计算两个日期之间的天数最有效的方法是什么?基本上我在问我们如何实现我们最喜欢的日期时间库。
我快速实施了一个~O(n)的解决方案,因为我每4年进行1次迭代。 (下面附有代码)
我被计算机类解决问题的介绍要求实现这一点,但他们只是每天迭代而不是每4年......所以我不满足于那个解决方案并提出了下面的那个。但是,是否有更有效的解决方案?如果是这样,他们如何实现它?
#include <iostream>
using namespace std;
#define check_leap(year) ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0)))
#define debug(n) cout << n << endl
int get_days(int month, bool leap){
if (month == 2){
if (leap) return 29;
return 28;
} else if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12){
return 31;
} else {
return 30;
}
}
int days[] = {31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
#define days_prior_to_month(n) days[n-2]
int num_days_between(int month1, int day1, int month2, int day2, bool leap){
if (month2 > month1)
return ((days_prior_to_month(month2) - days_prior_to_month(month1+1)) + get_days(month1, leap) - day1 + 1 + day2) + ((leap && month1 <= 2 && 2 <= month2) ? 1 : 0);
else if (month2 == month1)
return day2;
return -1;
}
int main(int argc, char * argv[]){
int year, month, day, year2, month2, day2;
cout << "Year: "; cin >> year;
cout << "Month: "; cin >> month;
cout << "Day: "; cin >> day;
cout << "Year 2: "; cin >> year2;
cout << "Month 2: "; cin >> month2;
cout << "Day 2: "; cin >> day2;
int total = 0;
if (year2 != year){
int leapyears = 0;
total += num_days_between(month, day, 12, 31, check_leap(year));
debug(total);
total += num_days_between(1, 1, month2, day2, check_leap(year2));
debug(total);
int originalyear = year;
year++;
year = year + year % 4;
while (year <= year2-1){
leapyears += check_leap(year) ? 1 : 0;
year += 4;
}
total += leapyears * 366;
debug(total);
total += max(year2 - originalyear - leapyears - 1, 0) * 365;
debug(total);
} else {
total = num_days_between(month, day, month2, day2, check_leap(year));
}
cout << "Total Number of Days In Between: " << total << endl;
system("PAUSE");
return 0;
}
答案 0 :(得分:22)
您可以在O(1)中将日期转换为Julian day number。
减去两个朱利安日数字。
答案 1 :(得分:8)
所有除法均为整数除法,运算符%为模数。
给定整数y,m,d,将天数g计算为:
function g(y,m,d)
m = (m + 9) % 12
y = y - m/10
return 365*y + y/4 - y/100 + y/400 + (m*306 + 5)/10 + ( d - 1 )
Difference between two dates = g(y2,m2,d2) - g(y1,m1,d1)
答案 2 :(得分:8)
Tyler Durden的解决方案最优雅,但可能需要一些解释。
算法的美妙之处在于声明:
(m*306 + 5)/10
返回3月1日到3月之后的第3个月的开始天数。 (如果你想证明它,只记得使用&#39;整数除法&#39;它截断小数部分)
为了将角标准约会惯例转换为此功能,月份和年份的输入值会发生变化,以便日历“开始”#39;三月而不是一月。
m = (m + 9) % 12
y = y - m/10
实现这个可以解决每月计算&#34;天的问题&#34;并且每年只留下&#39;天。要计算。维基百科为该部分提供了充分的解释。
答案 3 :(得分:4)
解决方案是在python中,并且转换为任何其他语言都不难。
def isLeapYear(year):
if year%4 == 0:
if year%100 == 0:
if year%400 == 0:
return True
else:
return False
else:
return True
else:
return False
def daysBetweenDates(year1, month1, day1, year2, month2, day2):
cumDays = [0,31,59,90,120,151,181,212,243,273,304,334] #cumulative Days by month
leapcumDays = [0,31,60,91,121,152,182,213,244,274,305,335] # Cumulative Days by month for leap year
totdays = 0
if year1 == year2:
if isLeapYear(year1):
return (leapcumDays[month2-1] + day2) - (leapcumDays[month1-1] + day1)
else:
return (cumDays[month2-1] + day2) - (cumDays[month1-1] + day1)
if isLeapYear(year1):
totdays = totdays + 366 - (leapcumDays[month1-1] + day1)
else:
totdays = totdays + 365 - (cumDays[month1-1] + day1)
year = year1 + 1
while year < year2:
if isLeapYear(year):
totdays = totdays + 366
else:
totdays = totdays + 365
year = year + 1
if isLeapYear(year2):
totdays = totdays + (leapcumDays[month2-1] + day2)
else:
totdays = totdays + (cumDays[month2-1] + day2)
return totdays
答案 4 :(得分:2)
我根据Doug Currie的建议写了这个公式。我从今天开始测试它直到2147483647天。
static int daysElapsed(int yearOne,int monthOne,int daysOne,int yearTwo,int monthTwo,int daysTwo)
{
return (daysTwo-32075+1461*(yearTwo+4800+(monthTwo-14)/12)/4+367*(monthTwo-2-(monthTwo-14)/12*12)/12-3*((yearTwo+4900+(monthTwo-14)/12)/100)/4)-
(daysOne-32075+1461*(yearOne+4800+(monthOne-14)/12)/4+367*(monthOne-2-(monthOne-14)/12*12)/12-3*((yearOne+4900+(monthOne-14)/12)/100)/4);
}
答案 5 :(得分:0)
您还可以使用基于原点的算法。您可以计算开始日期和结束日期之前的所有天数,然后找出这些计数之间的差额:
url = 'http://httpbin.org/post'
files = {'file': open('report.xls', 'rb')}
r = requests.post(url, files=files)
r.text
例如(Java代码):
totalDays = end_date_count - start_date_count
答案 6 :(得分:-1)
也许这可能会有所帮助:(这个程序是用c编写的)
#include<stdio.h>
int gauss(int y)
{
int r;
r=(1+(5*((y-1)%4))+(4*((y-1)%100))+(6*((y-1)%400)))%7;
return r;
/*
using gauss's algorithm to figure out the first day of the given year
* visit: https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week#Gauss.27s_algorithm
*/
}
int julian(int d,int m,int y){
int j;
j=(d + (((153*m)+2)/5) + (365*y) + (y/4) - (y/100) + (y/400));
return j;
/*
* calculating julian number for a date so that we can calculate number of days passed between the
* first day of that year and the given date
* visit: http://www.had2know.com/society/number-days-between-two-dates.html
*/
}
int main(){
int d1,m1,y1,j1,j2,n,r,n1,abs;
int d,m,y;
/*
* d1= day date
* d=d1
* m1= month given by the user
* m= month required for calculation
* y1= year given by the user
* y=year required for calculation
*/
printf("Enter the day number of date: ");
scanf("%d",&d1);
printf("\nEnter the month number of date: ");
scanf("%d",&m1);
printf("\nEnter the year of date: ");
scanf("%d",&y1);
if(m1<13&&m1>2){
m=m1-3;
d=d1;
y=y1;
j1=julian(1,10,y-1);//did y-1 as for jan and feb we did the same
j2=julian(d,m,y);
}
else if(m1==1 || m1==2)
{
m=m1+9;
d=d1;
y=y1-1;
j1=julian(1,10,y);
j2=julian(d,m,y);
}
printf("\ndate: %d/%d/%d",d1,m1,y1);
r=gauss(y1);
abs=(j1-j2);
if(abs<0){
abs=0-abs;
}
n=(abs)%7;
n1=(n+r)%7;
if(n1==0)
{
printf("\nThe day is: Sunday");
}
else if(n1==1)
{
printf("\nThe day is: Monday");
}
else if(n1==2)
{
printf("\nThe day is: Tuesday");
}
else if(n1==3)
{
printf("\nThe day is: Wednesday");
}
else if(n1==4)
{
printf("\nThe day is: Thursday");
}
else if(n1==5)
{
printf("\nThe day is: Friday");
}
else if(n1==6)
{
printf("\nThe day is: Saturday");
}
return 0;
}
答案 7 :(得分:-1)
使用Python的简单算法:
#Calculate the Days between Two Date
daysOfMonths = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
def isLeapYear(year):
# Pseudo code for this algorithm is found at
# http://en.wikipedia.org/wiki/Leap_year#Algorithm
## if (year is not divisible by 4) then (it is a common Year)
#else if (year is not divisable by 100) then (ut us a leap year)
#else if (year is not disible by 400) then (it is a common year)
#else(it is aleap year)
return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
def Count_Days(year1, month1, day1):
if month1 ==2:
if isLeapYear(year1):
if day1 < daysOfMonths[month1-1]+1:
return year1, month1, day1+1
else:
if month1 ==12:
return year1+1,1,1
else:
return year1, month1 +1 , 1
else:
if day1 < daysOfMonths[month1-1]:
return year1, month1, day1+1
else:
if month1 ==12:
return year1+1,1,1
else:
return year1, month1 +1 , 1
else:
if day1 < daysOfMonths[month1-1]:
return year1, month1, day1+1
else:
if month1 ==12:
return year1+1,1,1
else:
return year1, month1 +1 , 1
def daysBetweenDates(y1, m1, d1, y2, m2, d2,end_day):
if y1 > y2:
m1,m2 = m2,m1
y1,y2 = y2,y1
d1,d2 = d2,d1
days=0
while(not(m1==m2 and y1==y2 and d1==d2)):
y1,m1,d1 = Count_Days(y1,m1,d1)
days+=1
if end_day:
days+=1
return days
# Test Case
def test():
test_cases = [((2012,1,1,2012,2,28,False), 58),
((2012,1,1,2012,3,1,False), 60),
((2011,6,30,2012,6,30,False), 366),
((2011,1,1,2012,8,8,False), 585 ),
((1994,5,15,2019,8,31,False), 9239),
((1999,3,24,2018,2,4,False), 6892),
((1999,6,24,2018,8,4,False),6981),
((1995,5,24,2018,12,15,False),8606),
((1994,8,24,2019,12,15,True),9245),
((2019,12,15,1994,8,24,True),9245),
((2019,5,15,1994,10,24,True),8970),
((1994,11,24,2019,8,15,True),9031)]
for (args, answer) in test_cases:
result = daysBetweenDates(*args)
if result != answer:
print "Test with data:", args, "failed"
else:
print "Test case passed!"
test()