我正在写一个简单的日历类。我正在尝试重载operator++
以使用它将日历移动到下个月。但是,我找到下个月开始日的算法并不完全正确。
calendar calendar::operator ++(int)
{
int hold;
calendar cal = *this;
month++;
if (month > December)
{
month = January;
year++;
if (year == 0)
year++;
}
previousStartDay = startDay;
startDay = nextStartDay;
nextStartDay = findNextStartDay();
return cal;
}
int calendar::findNextStartDay() const
{
int monthLength,
day = startDay;
monthLength = findMonthLength(false);
monthLength -= 28;
day += monthLength;
if (day > Saturday)
day -= Saturday;
return day;
}
1月被定义为0,12月是11,星期日是0,星期六是6. startDay,previousStartDay,nextStartDay,month和year都是私有类变量
当我在2013年测试时,日期是正确的,直到3月。在这一点上,它将下一个开始日定为星期二而不是星期一。
我也试过这个:
int calendar::findNextStartDay() const
{
int monthLength,
day = startDay;
monthLength = findMonthLength(false);
monthLength -= 28;
day -= monthLength;
if (day < Sunday)
day += Saturday;
return day;
}
然而,它也给出了相同的结果。
修改
我正在考虑闰年。以下是我findMonthLength()
的代码,以确定它是否存在。
if ((!(year % 4) && (year % 100)) || !(year % 400))
monthLength = 29;
else
monthLength = 28;
答案 0 :(得分:3)
假设我们在三月,你有正确的开始日(星期五,5)。
您的findNextStartDay
算法会发现monthlength
等于3(31-28),然后一天将是2(8 - 6),即星期二(2)而不是星期一(1)。 ..
让我们通过运行算法(第一版findNextStartDay
)来了解这是错误的原因:
1月:31-28 = 3,日= 2(星期二)+ 3 = 5(星期五),这是2月的正确开始日期。
2月:28 - 28 = 0,日= 5(星期五)+ 0 = 5(星期五),这是3月的正确开始日期。
3月:31-28 = 3,日= 5(星期五)+ 3 - 6(星期六)= 2(星期二),这是错误的4月开始日期。
问题在于,当你将星期六减去溢出的结果(超过星期六)时,你将离开计数一天(即:你减去一天比你想要的少一天)。
想想你最终得到day == 7
的情况。你想要星期天(比周六多一点 - 循环增加),然后你必须删除7而不是6,否则你将获得星期一!
错误是循环增量:在正确的算法1中,超过6(即7)必须返回0,2超过6(即8)必须返回1,依此类推。
在你的算法1中,超过6(即7)会回到1,遗漏穷人0(星期日),并且每次你在这种情况下结束时,每周的一天都会消失。
如果你减去Saturday + 1
,那么在#34;星期几天溢出&#34;的情况下,你会得到下个月的正确日期。
简而言之,请更改此行:
day -= Saturday;
到
day -= (Saturday + 1);
但是请考虑将代码复习到更简洁的算法版本中!
一个小技巧是使用模运算符进行循环加法:
day = ((day + monthlength) % (Saturday + 1))
答案 1 :(得分:1)
boost为您提供了几个不错的examples。在这里,我根据示例中的一个实现了boost::gregorian
。此代码需要年,月和打印日期和下个月第一天的星期几:
#include <cstdlib>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <iostream>
#include <stdio.h>
int main(int argc, char** argv) {
using namespace boost::gregorian;
greg_year year(1400);
greg_month month(1);
// get a month and a year from the user
try {
int y, m;
std::cout << " Enter Year(ex: 2002): ";
std::cin >> y;
year = greg_year(y);
std::cout << " Enter Month(1..12): ";
std::cin >> m;
month = greg_month(m);
}
catch(bad_year by) {
std::cout << "Invalid Year Entered: " << by.what() << '\n'
<< "Using minimum values for month and year." << std::endl;
}
catch(bad_month bm) {
std::cout << "Invalid Month Entered" << bm.what() << '\n'
<< "Using minimum value for month. " << std::endl;
}
// create date and add one day to the end of month
date d(year, month, 1);
d=(year,month,d.end_of_month());
date_duration dd(1);
d += dd;
// print date
std::cout << d << " " << d.day_of_week() << std::endl;
return 0;
}
示例输出:
输入年份(例如:2002年):2013
输入月份(1..12):3
2013年4月1日星期一
RUN SUCCESSFUL(总时间:6s)
使用std::vector
:
boost::gregorian::date d1(2013,boost::gregorian::Jan,31);
boost::gregorian::date d2(2013,boost::gregorian::Feb,28);
boost::gregorian::date d3(2013,boost::gregorian::Mar,31);
std::vector<boost::gregorian::date > v;
v.push_back(d1);
v.push_back(d2);
v.push_back(d3);
boost::gregorian::date_duration duration(1);
for(std::vector<boost::gregorian::date >::iterator it=v.begin();it!=v.end();it++){
*it+=duration;
std::cout << *it <<" "<< (*it).day_of_week() << std::endl;
}
答案 2 :(得分:0)
我认为问题出在2月份,因为这个月可能有29天或28天(取决于年份是否为二年级)。您可以在本月创建一个if语句。 你可以通过使用mod运算符来判断年份是否是bissextile:if%4 =! 0比2月有28天,你有29天。 希望这会对你有所帮助!
答案 3 :(得分:0)
此代码为您提供上个月的第一天和最后一天。我用它在我的应用程序中设置TDateTimePicker组件。
Word Year, Month, Day;
TDateTime datum_tdatetime = Date();
// first day of actual month
datum_tdatetime.DecodeDate(&year, &month, &day);
day = 1;
datum_tdatetime = EncodeDate(year, month, day);
// last day of previous month
datum_tdatetime -= 1;
// first day of previous month
datum_tdatetime.DecodeDate(&year, &month, &day);
day = 1;
datum_tdatetime = EncodeDate(year, month, day);