2010-02-26 7 views
15

저는 C++을 배우려고 Date 클래스를 작성하려고합니다.날짜에서 날짜를 더하거나 뺍니까?

일을 1에서 시작하고 1이 1에서 시작하는 날짜에 날짜를 더하거나 뺍니다 알고리즘을 찾으려고합니다. 매우 복잡하고 Google이 많이 나타나지 않습니다.

누구든지이 작업을 수행하는 알고리즘을 알고 있습니까?

+0

문서에 대한 링크가있는 "부스트 사용"답변이 없으면이 질문에 대한 놀라움이 있습니다. – jww

답변

16

가장 쉬운 방법은 실제로 주어진 시작 날짜로부터 일 수를 변환 한 다음 다시 날짜로 변환하는 두 가지 함수를 작성하는 것입니다. 날짜가 일 수로 표시되면 더하거나 뺄 수 있습니다.

여기 알고리즘을 찾을 수 있습니다 : http://alcor.concordia.ca/~gpkatch/gdate-algorithm.html

+0

감사합니다, 이것은 내가 뭘 찾고 있었는지, 그물을 검색하는 동안 알고리즘을 찾을 수없는 몇 가지 이유가 있습니다! – bcoughlan

+0

불행히도 이러한 함수는 매우 정확하지 않습니다 ... 적어도 내 결과를 wolfram alpha와 비교했을 때, 나는 하루 정도 벗어났습니다. – aimango

+0

여기 : http://home.roadrunner.com/~hinnant/date_algorithms.html 정확한 알고리즘입니다. 이들의 타당성은 32 비트 산술을 사용하여 +/- 5.8 백만 년의 예측 가능한 그레고리력에 대해 정확한 것으로 테스트되었습니다. 그들은 1970-01-01 전후의 날짜를 계산합니다. –

3

나는 어떤 종류의 운동을한다고 가정하고 있습니다. 그렇지 않으면 이미 제공되는 시간 수업을 사용하게됩니다.

특정 날짜 이후 시간을 밀리 초로 저장할 수 있습니다. 그런 다음 적절한 값을 추가하고 클래스의 접근자를 호출 할 때 해당 값을 날짜로 변환 할 수 있습니다.

+0

왜 밀리 초입니까? 그는 날짜뿐 아니라 시간, 그리고 확실히 밀리 초의 정확성을 원하지 않는 것 같습니다. 심지어 윤초를 계산하는 데 도움이됩니다. – Steve314

1

하나의 접근법은 날짜를 줄리안 숫자로 매핑하고 정수 연산을 수행 한 다음 다시 변환하는 것입니다.

줄리안 기능을위한 많은 리소스를 찾을 수 있습니다.

0

가 처음 1.01.01 이후, 고정 된 날짜, 말 이후 일 수에 년 - 월 - 일을 변환하는 루틴을 작성 건의 할 것입니다. 그리고 그것을 다시 변환 할 대칭 루틴.

윤년을 올바르게 처리하는 것을 잊지 마세요!

두 가지가 있다면, 당신의 작업은 사소한 것입니다.

2

다음은 매우 간단한 방법입니다. 아이디어의 단순화를 위해 나는 덧셈하는 일수가 양수라는 것을 d으로 가정 할 것입니다. d이 음수 인 경우 아래로 쉽게 확장 할 수 있습니다.

while(d >= 365) { 
    d -= 365; 
    if(isLeapYear(y)) { 
     d -= 1; 
    } 
    y++; 
} 
// now use the case where d is less than 365 
:

m = 1; 
while(d > numberOfDaysInMonth(m, y)) { 
    d -= numberOfDaysInMonth(m, y); 
    m++; 
} 
return date with year = y, month = m, day = d; 

d 경우 초과 365이다

어느 d 미만 365 또는 d 미만 365 초과 d 경우 365

이상인이고

또는, 예를 들어 Julian form으로 날짜를 표현한 다음 줄리안 형식에 추가하고 ymd 형식으로 변환하기 만하면됩니다.

+0

이 나를 위해 일합니다. 고마워요! – aimango

7

알고리즘은 정말 필요하지 않습니다. (적어도 이름에 걸맞지는 않습니다.) 표준 라이브러리는 무거운 짐을 덜어줍니다. 캘린더 계산은 악명이 높습니다.

#include <ctime> 

// Adjust date by a number of days +/- 
void DatePlusDays(struct tm* date, int days) 
{ 
    const time_t ONE_DAY = 24 * 60 * 60 ; 

    // Seconds since start of epoch 
    time_t date_seconds = mktime(date) + (days * ONE_DAY) ; 

    // Update caller's date 
    // Use localtime because mktime converts to UTC so may change date 
    *date = *localtime(&date_seconds) ; ; 
} 

사용 예제 :

#include <iostream> 

int main() 
{ 
    struct tm date = { 0, 0, 12 } ; // nominal time midday (arbitrary). 
    int year = 2010 ; 
    int month = 2 ; // February 
    int day = 26 ; // 26th 

    // Set up the date structure 
    date.tm_year = year - 1900 ; 
    date.tm_mon = month - 1 ; // note: zero indexed 
    date.tm_mday = day ;  // note: not zero indexed 

    // Date, less 100 days 
    DatePlusDays(&date, -100) ; 

    // Show time/date using default formatting 
    std::cout << asctime(&date) << std::endl ; 
} 
+0

게시 해 주셔서 감사합니다. 굉장히 유용하다. – ForeverLearning

+0

초 계산이 엉망이 되겠습니까? – vargonian

+0

@vargonian : 좋은 질문입니다. UNIX 시간대는 1970 년 1 월 1 일부터이며 윤년을 계산하지 않습니다. 그러나 공칭 시간을 정오로 설정하면 수만년 동안 잠재적 인 문제를 피할 수 있습니다. – Clifford

1

이 기능을 사용해보십시오 당신이 후, 1900 년보다 이전 날짜가 필요하지 않는 한 너무 오래. 더하기 또는 빼기를 올바르게 계산합니다. dateTime 인수는 UTC 형식이어야합니다.

tm* dateTimeAdd(const tm* const dateTime, const int& days, const int& hours, const int& mins, const int& secs) { 
    tm* newTime = new tm; 
    memcpy(newTime, dateTime, sizeof(tm)); 

    newTime->tm_mday += days; 
    newTime->tm_hour += hours; 
    newTime->tm_min += mins; 
    newTime->tm_sec += secs;   

    time_t nt_seconds = mktime(newTime) - timezone; 
    delete newTime; 

    return gmtime(&nt_seconds); 
} 

그리고 사용의 예가 :

time_t t = time(NULL); 
tm* utc = gmtime(&t); 
tm* newUtc = dateTimeAdd(utc, -5, 0, 0, 0); //subtract 5 days 
0

나는 이것이 아주 오래된 질문 알고 있지만 날짜 및 시간을 사용한 작업에 관해서는 재미 있고 몇 가지 일반적인 하나입니다. 그래서 C++에서 inbuilt time 기능을 사용하지 않고 새로운 날짜를 계산하는 코드를 공유 할 것을 생각했습니다.

#include <iostream> 
#include <string> 

using namespace std; 

class Date { 
public: 
    Date(size_t year, size_t month, size_t day):m_year(year), m_month(month), m_day(day) {} 
    ~Date() {} 

    // Add specified number of days to date 
    Date operator + (size_t days) const; 

    // Subtract specified number of days from date 
    Date operator - (size_t days) const; 

    size_t Year() { return m_year; } 
    size_t Month() { return m_month; } 
    size_t Day() { return m_day; } 

    string DateStr(); 
private: 
    // Leap year check 
    inline bool LeapYear(int year) const 
     { return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); } 

    // Holds all max days in a general year 
    static const int MaxDayInMonth[13]; 

    // Private members 
    size_t m_year; 
    size_t m_month; 
    size_t m_day; 
}; 

// Define MaxDayInMonth 
const int Date::MaxDayInMonth[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 

//=========================================================================================== 
/// Add specified number of days to date 
Date Date::operator + (size_t days) const { 
    // Maximum days in the month 
    int nMaxDays(MaxDayInMonth[m_month] + (m_month == 2 && LeapYear(m_year) ? 1 : 0)); 

    // Initialize the Year, Month, Days 
    int nYear(m_year); 
    int nMonth(m_month); 
    int nDays(m_day + days); 

    // Iterate till it becomes a valid day of a month 
    while (nDays > nMaxDays) { 
     // Subtract the max number of days of current month 
     nDays -= nMaxDays; 

     // Advance to next month 
     ++nMonth; 

     // Falls on to next year? 
     if (nMonth > 12) { 
      nMonth = 1; // January 
      ++nYear; // Next year 
     } 

     // Update the max days of the new month 
     nMaxDays = MaxDayInMonth[nMonth] + (nMonth == 2 && LeapYear(nYear) ? 1 : 0); 
    } 

    // Construct date 
    return Date(nYear, nMonth, nDays); 
} 

//=========================================================================================== 
/// Subtract specified number of days from date 
Date Date::operator - (size_t days) const { 
    // Falls within the same month? 
    if (0 < (m_day - days)) { 
     return Date(m_year, m_month, m_day - days); 
    } 

    // Start from this year 
    int nYear(m_year); 

    // Start from specified days and go back to first day of this month 
    int nDays(days); 
    nDays -= m_day; 

    // Start from previous month and check if it falls on to previous year 
    int nMonth(m_month - 1); 
    if (nMonth < 1) { 
     nMonth = 12; // December 
     --nYear;  // Previous year 
    } 

    // Maximum days in the current month 
    int nDaysInMonth = MaxDayInMonth[nMonth] + (nMonth == 2 && LeapYear(nYear) ? 1 : 0); 

    // Iterate till it becomes a valid day of a month 
    while (nDays >= 0) { 
     // Subtract the max number of days of current month 
     nDays -= nDaysInMonth; 

     // Falls on to previous month? 
     if (nDays > 0) { 
      // Go to previous month 
      --nMonth; 

      // Falls on to previous year? 
      if (nMonth < 1) { 
       nMonth = 12; // December 
       --nYear;  // Previous year 
      } 
     } 

     // Update the max days of the new month 
     nDaysInMonth = MaxDayInMonth[nMonth] + (nMonth == 2 && LeapYear(nYear) ? 1 : 0); 
    } 

    // Construct date 
    return Date(nYear, nMonth, (0 < nDays ? nDays : -nDays)); 
} 

//=========================================================================================== 
/// Get the date string in yyyy/mm/dd format 
string Date::DateStr() { 
    return to_string(m_year) 
     + string("/") 
     + string(m_month < 10 ? string("0") + to_string(m_month) : to_string(m_month)) 
     + string("/") 
     + string(m_day < 10 ? string("0") + to_string(m_day) : to_string(m_day)); 
} 


int main() { 
    // Add n days to a date 
    cout << Date(2017, 6, 25).DateStr() << " + 10 days = " 
     << (Date(2017, 6, 25) /* Given Date */ + 10 /* Days to add */).DateStr() << endl; 

    // Subtract n days from a date 
    cout << Date(2017, 6, 25).DateStr() << " - 10 days = " 
     << (Date(2017, 6, 25) /* Given Date */ - 10 /* Days to subract */).DateStr() << endl; 

    return 0; 
} 

Output 
2017/06/25 + 10 days = 2017/07/05 
2017/06/25 - 10 days = 2017/06/15