10

2 つの日付間の日数を計算する最も効率的な方法は何ですか? 基本的に、お気に入りの日時ライブラリがどのように実装されているかを尋ねています。

4年に1回の反復を実行するため、~O(n)のソリューションをすぐに実装しました。(以下にコードを添付)

これを実装するためにコンピュータークラスでの問題解決の紹介で尋ねられましたが、 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;
} 
4

8 に答える 8

23

O(1) では、日付をユリウス日に変換できます。

2 つのユリウス日を引きます。

于 2012-10-12T15:31:27.267 に答える
11

すべての除算は整数除算であり、演算子 % はモジュラスです。

与えられた整数 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)
于 2012-10-12T16:23:58.543 に答える
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);            
    }
于 2013-10-13T11:30:46.937 に答える
0

オリジンベースのアルゴリズムを使用することもできます。開始日と終了日の前のすべての日を数えて、それらの数の差を見つけることができます。

totalDays = end_date_count - start_date_count

たとえば(Javaコード):

public class Origincount {
public static class Dates {
    private final Integer day;
    private final Integer month;
    private final Integer year;

    public Dates(String date) {
        String[] s = date.split("/");
        this.day = Integer.valueOf(s[0]);
        this.month = Integer.valueOf(s[1]);
        this.year = Integer.valueOf(s[2]);
    }
    public Integer getDay() {
        return day;
    }
    public Integer getMonth() {
        return month;
    }
    public Integer getYear() {
        return year;
    }
}

private static final Map<Integer, Integer> daysOfMonth = new HashMap<Integer, Integer>();

static {
    daysOfMonth.put(1, 31);
    daysOfMonth.put(2, 28);
    daysOfMonth.put(3, 31);
    daysOfMonth.put(4, 30);
    daysOfMonth.put(5, 31);
    daysOfMonth.put(6, 30);
    daysOfMonth.put(7, 31);
    daysOfMonth.put(8, 31);
    daysOfMonth.put(9, 30);
    daysOfMonth.put(10, 31);
    daysOfMonth.put(11, 30);
    daysOfMonth.put(12, 31);
}

public static Integer countLeapYears(Dates date) {
    Integer y = date.getYear();
    if(date.getMonth() <= 2) { y--; }
    return (y/4) - (y/100) + (y/400);
}

public static Integer daysMonth(Dates date) {
    Integer days = 0;
    for(int i=1; i<date.getMonth(); i++) {
        days += daysOfMonth.get(i);
    }
    return days;
}

public static void main(String[] args) {
    Dates start = new Dates("1/1/1901");
    Dates end = new Dates("31/12/2999");
    Integer countStart = (start.getYear()*365) + countLeapYears(start) + daysMonth(start) + start.getDay();
    Integer countEnd = (end.getYear()*365) + countLeapYears(end) + daysMonth(end) + end.getDay();

    System.out.println("Total days: "  + (countEnd-countStart));
}
}
于 2018-09-19T00:57:55.870 に答える
-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;

}

于 2016-06-27T07:51:11.693 に答える