用C++从给定日期中减去天数(从头开始)



下面有一个函数,用于将天数添加到给定日期(格式:yyyy/mm/dd addDays(。它不适用于闰年(有一次尝试让闰年生效,但很快就失败了。(我该如何编辑它,以便从给定的日期中减去天数?我想我需要一个for循环,它也从addDays_中减去days,但带有递减和重置。我也想让它成功地计算闰年日期。

int year;
int month;
int day;
int changeDays;
void DaysToDate::add(int addDays_) {
//Calculate the date add the changeDays.
// Do NOT input values greater than 730 days.
int monthdays[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
int daysInYear = 365;

if (isLeapYear(year) || isLeapYear(year+1) == true) {
monthdays[2] = 29;
daysInYear = 366;

}
if (addDays_ >= daysInYear) {
int addyears = addDays_ / daysInYear;
year += addyears;
if (isLeapYear(year) == true) {

monthdays[2] = 29;
daysInYear = 366;
}
}

int currentDays = day;
int i = month;
if (addDays_ >= monthdays[month]) {
while (addDays_ >= monthdays[i]) {
if (i + 1 >= 12) {
month = 1;
i = 1;
}
else 
month++;
addDays_ -= monthdays[i];
//cout << "monthdays[i] "<< monthdays[i] << "n";
if (addDays_ + day < monthdays[month]) {
day += addDays_;
}
i++;
}
}
if (addDays_ + day < monthdays[month]) {
day += addDays_;
}
if ((day == monthdays[month - 1]) && (month < 12))
{
day = 1;
month++;
}
if ((day == monthdays[month - 1]) && (month == 12))
{
day = 1;
month = 1;
year++;
}
else {

}
cout << year << " " << month << " " << day << " " << "n";
}
bool DaysToDate::isLeapYear(int year_) {
if (year % 400 == 0) {
return true;
}
if (year % 100 == 0) {
return false;
}
if (year % 4 == 0) {
return true;
}
else {
return false;
}

}

输入2009/04/05 7-输出2009 4 12

用于修复闰年的代码:

#include <iostream>
int year = 2009;
int month = 02;
int day = 1;
int changeDays;
enum Months
{
None,
January,
February,
March,
April,
May,
June,
July,
August,
September,
October,
November,
December
};
bool isLeapYear(int year_)
{
if (year % 400 == 0)
{
return true;
}
if (year % 100 == 0)
{
return false;
}
if (year % 4 == 0)
{
return true;
}
else
{
return false;
}
}
void add(int addDays_)
{
// Calculate the date add the changeDays.
//  Do NOT input values greater than 730 days.
int monthdays[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int daysInYear = 365;
if (isLeapYear(year))
{
monthdays[Months::February] = 29;
daysInYear = 366;
}
int currentDays = day;
int i = month;
while (addDays_ >= monthdays[i])
{
addDays_ -= monthdays[i];

if (i + 1 > Months::December)
{
i = Months::January;
year++;
if (isLeapYear(year))
{
monthdays[Months::February] = 29;
daysInYear = 366;
} else {
monthdays[Months::February] = 28;
daysInYear = 365;
}
}
else
{
i++;
}
}
month = i;
if (addDays_ + day <= monthdays[month])
{
day += addDays_;
}
else if (month < Months::December) {
addDays_ -= monthdays[month] - day;
day = addDays_;
month++;
} else {
addDays_ -= monthdays[month] - day;
day = addDays_;
month = Months::January;
year ++;
if (isLeapYear(year))
{
monthdays[Months::February] = 29;
daysInYear = 366;
} else {
monthdays[Months::February] = 28;
daysInYear = 365;
}
}
std::cout << year << " " << month << " " << day << " "
<< "n";
}

int main(int argc, char const *argv[])
{
add(7);
add(365);
add(365);
add(365);
add(365);
return 0;
}

当然,我的建议可以做一些改进,但我认为它很容易遵循,因为它的结构与你的非常相似。

作为一般提示,您有很多多余的if语句,其中一些语句会导致错误,例如

if (isLeapYear(year) || isLeapYear(year+1) == true) {
monthdays[2] = 29;
daysInYear = 366;  
}

如果你在三月之前开始,检查isLeapYear(year+1(会给你错误的天数

您可以为此使用范围。将天数n与给定日期ymd相加(或相减(的操作可以被认为是:

  • 生成当前日期ymd加上以下日期(最多730(的视图
  • 从该视图中,删除第一个n元素
  • 然后取剩余元素中的第一个元素

ranges::views::generate_n代码将包含在给定日期上加(或减(一天的逻辑:

  • 此逻辑将使用days_per_month函数
  • days_per_month函数将使用is_leap_year函数

下面的代码:

  • 定义一个结构ymd来保存给定日期的值
  • 作为结构体ymd的非成员运算符,实现给定日期的天数相加和相减
  • 使用Eric Niebler的Range-v3库进行测距操作

【演示】

#include <cassert>  // assert
#include <iomanip>  // setw
#include <iostream>  // cout
#include <fmt/core.h>
#include <range/v3/all.hpp>
#include <utility>
#include <vector>
struct ymd {
int year{};
int month{};
int day{};
};
auto is_leap_year(int y) {
return (y % 4 == 0) and ((y % 100 != 0) or (y % 400 == 0));
}
auto days_per_month(int y, int m) {
static int dpm[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (m == 2 and is_leap_year(y)) { return 29; }
else { return dpm[m]; }
}
auto operator+(const ymd& d, int days_to_add) {
static const int max_days_to_add{730};
assert(days_to_add <= max_days_to_add);
auto ret_v =
ranges::views::generate_n([dd=d]() mutable -> ymd {
auto tmp{dd};
dd.day += 1;
if (dd.day > days_per_month(dd.year, dd.month)) { dd.day = 1; dd.month += 1; }
if (dd.month > 12) { dd.month = 1; dd.year += 1; }
return tmp;
}, max_days_to_add + 1)
| ranges::views::drop(days_to_add)
| ranges::views::take(1)
| ranges::to<std::vector>();
return ret_v[0];
}
auto operator+(int days_to_add, const ymd& d) {
return d + days_to_add;
}
auto operator-(const ymd& d, int days_to_subtract) {
static const int max_days_to_subtract{730};
assert(days_to_subtract <= max_days_to_subtract);
auto ret_v =
ranges::views::generate_n([dd=d]() mutable -> ymd {
auto tmp{dd};
dd.day -= 1;
if (dd.day < 1) {
dd.month -= 1;
if (dd.month < 1) { dd.month = 12; dd.year -= 1; }
dd.day = days_per_month(dd.year, dd.month);
}
return tmp;
}, max_days_to_subtract + 1)
| ranges::views::drop(days_to_subtract)
| ranges::views::take(1)
| ranges::to<std::vector>();
return ret_v[0];
}
std::ostream& operator<<(std::ostream& os, const ymd& d) {
return os << fmt::format("{:04d}/{:02d}/{:02d}", d.year, d.month, d.day);
}
int main() {
std::vector<std::pair<ymd,int>> input{
{{2009,4,5}, 7},
{{2009,4,5}, 730},
{{2020,2,20}, 30}
};
for (const auto& [d, number_of_days] : input){
auto dd{ d + number_of_days };
std::cout << d << " + " << std::setw(3) << number_of_days << " = " << dd << ",t";
std::cout << dd << " - " << std::setw(3) << number_of_days << " = " << dd - number_of_days << "n";
}
}
// Outputs:
//   2009/04/05 +   7 = 2009/04/12, 2009/04/12 -   7 = 2009/04/05
//   2009/04/05 + 730 = 2011/04/05, 2011/04/05 - 730 = 2009/04/05
//   2020/02/20 +  30 = 2020/03/21, 2020/03/21 -  30 = 2020/02/20

另一个可能更简单的解决方案是循环,直到消耗了要添加的天数,增加当前日期,直到下个月初,或者直到您没有天数添加(或者如果要减去,则减少到上个月底(。再次,我将使用daysPerMonthisLeapYear辅助函数:

【演示】

void add(int addDays) {
static int maxAddDays = 730;
assert(addDays <= maxAddDays);
while (addDays) {
auto current_month_days(daysPerMonth(year_, month_));
auto tmpAddDays = std::min(addDays, current_month_days - day_ + 1);
day_ += tmpAddDays;
addDays -= tmpAddDays;
if (day_ == current_month_days + 1) { day_ = 1; month_++; }
if (month_ == 13) { month_ = 1; year_++; }
}
}
void subtract(int subtractDays) {
static int maxSubtractDays = 730;
assert(subtractDays <= maxSubtractDays);
while (subtractDays) {
auto tmpSubtractDays = std::min(subtractDays, day_);
day_ -= tmpSubtractDays;
subtractDays -= tmpSubtractDays;
if (day_ == 0) {
month_--;
if (month_ == 0) { month_ = 12; year_--; }
day_ = daysPerMonth(year_, month_);
}
}
}

相关内容

  • 没有找到相关文章

最新更新