使用C或C ++在日历日期上的算术(在给定日期添加N天)

我得到了一个约会,我作为一个输入,如(日,月,年): 12, 03, 87

现在我需要找出n天后的日期。

我已为此编写代码,但效率不高。 能不能告诉我任何好的逻辑,它运行得更快,复杂性更低。

 #include  static int days_in_month[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; int day, month, year; unsigned short day_counter; int is_leap(int y) { return ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0); } next_day() { day += 1; day_counter++; if (day > days_in_month[month]) { day = 1; month += 1; if (month > 12) { month = 1; year += 1; if (is_leap(year)) { days_in_month[2] = 29; } else { days_in_month[2] = 28; } } } } set_date(int d, int m, int y) { m  12 ? m = 12 : 0; d  days_in_month[m] ? d = days_in_month[m] : 0; if (is_leap(y)){ days_in_month[2] = 29; } else { days_in_month[2] = 28; } day = d; month = m; year = y; } skip_days(int x) { int i; for (i=0;i<x;i++) next_day(); } print_date() { printf ("day: %d month: %d year: %d\n", day, month, year); } int main(int argc, char **argv) { int i; set_date(5, 2, 1980); skip_days(40); day_counter = 0; /* after this call next_day each day */ print_date(); return 0; } 

能不能告诉我任何好的逻辑,它运行得更快,复杂性更低。

如果这个确切的事情确实是您的应用程序的性能关键部分,那么您可能做错了什么。 为了清晰和正确,您应该坚持现有的解决方案。 选择最适合您的开发环境的那个。


C方法:

 #include  #include  int main() { /* initialize */ int y=1980, m=2, d=5; struct tm t = { .tm_year=y-1900, .tm_mon=m-1, .tm_mday=d }; /* modify */ t.tm_mday += 40; mktime(&t); /* show result */ printf("%s", asctime(&t)); /* prints: Sun Mar 16 00:00:00 1980 */ return 0; } 

不使用Boost方法的C ++:

 #include  #include  int main() { // initialize int y=1980, m=2, d=5; std::tm t = {}; t.tm_year = y-1900; t.tm_mon = m-1; t.tm_mday = d; // modify t.tm_mday += 40; std::mktime(&t); // show result std::cout << std::asctime(&t); // prints: Sun Mar 16 00:00:00 1980 } 

Boost.Date_Time方法:

 #include  #include  int main() { using namespace boost::gregorian; // initialize date d(1980,2,5); // modify d += days(40); // show result std::cout << d << '\n'; // prints: 1980-Mar-16 } 

标准库mktimefunction包括一个技巧,可以很容易地在给定日期添加几个月或几天:你可以给它一个日期,如“二月45日”或“第40个月的第二天”和mktime将将其标准化为正确的日期。 例:

 #include  #include  int main() { int y = 1980; int m = 2; int d = 5; int skip = 40; // Represent the date as struct tm. // The subtractions are necessary for historical reasons. struct tm t = { 0 }; t.tm_mday = d; t.tm_mon = m-1; t.tm_year = y-1900; // Add 'skip' days to the date. t.tm_mday += skip; mktime(&t); // Print the date in ISO-8601 format. char buffer[30]; strftime(buffer, 30, "%Y-%m-%d", &t); puts(buffer); } 

与使用time_t在几秒钟内完成算术相比,这种方法的优点是夏令时转换不会导致任何问题。

以下是使用Howard Hinnant发布的算法的解决方案。

 int main() { int day_count = days_from_civil(1980, 5, 2); auto [year, month, day] = civil_from_days(day_count + 40); printf("%04i-%02i-%02-i\n", (int)year, (int)month, (int)day); } 

新的日期function已被批准包含在C ++ 20中,但具有不同的API。 C ++ 20解决方案可能看起来像:

 #include  int main() { using namespace std::chrono; sys_days in_days = year_month_day{1980y, may, 2d}; std::cout << year_month_day(in_days + days(40)) << '\n'; } 

最简单的技巧是使用time_t类型和相应的函数。

mktime会将tm结构转换为time_t 。 这是一个整数值,计算从1970年1月1日开始的秒数。

在你有time_t值后,只需添加你需要的秒数(每天86400)。

要转换回来,请使用gmtimelocaltime

只需添加一个time_t对象即可获得多少天。

 #define SECOND 1 #define MINUTE 60 * SECOND #define HOUR 60 * MINUTE #define DAY 24 * HOUR time_t curTime; time_t futureTime; time( & curTime ); futureTime = curTime + (5 * DAY); struct tm * futureDate = gmtime(&futureTime); std::cout<<"5 days from now will be: "<tm_mday<<"/"<tm_mon+1<<"/"<tm_year+1900< 

可以使用C ++运算符实现,并通过将日期表示为类来以非常OOP的方式实现。

 #include  #include  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; 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); } /// 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; return 0; } Output 2017/06/25 + 10 days = 2017/07/05 

从纪元开始使用秒数而不是直接操作日期字段可能更容易。

例如,此程序将在7天后打印日期:

 #include  #include  main() { time_t t; struct tm *tmp; time(&t); /* add a week to today */ t += 7 * 24 * 60 * 60; tmp = localtime(&t); printf("%02d/%02d/%02d\n", tmp->tm_mon+1, tmp->tm_mday, tmp->tm_year % 100); } 

此代码将打印10天后的日期。 将值更改为N以获取用户定义的数字。

 #include< iostream.h> #include< conio.h> struct date{int d,m,y;}; void main() { date d1; void later (date); cout<<"ENTER A VALID DATE (dd/mm/yy)"; cin>>d1.d>>d1.m>>d1.y; later(d1); getch(); } void later(date d1) { int mdays[12]={31,28,31,30,31,30,31,31,30,31,30,31}; if(((d1.y%4==0) && (d1.y%100!=0))||(d1.y%400==0)) mdays[1]=29; d1.d=d1.d+10; if(d1.d>mdays[d1.m-1]) { d1.d=d1.d-mdays[d1.m-1]; d1.m++; if(d1.m>12) {d1.m=1; d1.y++; } } cout<<"DATE AFTER TEN DAYS IS "<