c++ - 日历程序的偏移

标签 c++ calendar offset

该程序采用1753年以来的任何用户输入年份和月份,并为其创建日历。但是我在偏移量方面有问题,偏移量是本月开始的那一天。据我所知,只是偏移量关闭了,其他所有东西似乎都很好。
这是我的代码。

#include <iostream>
#include <iomanip>
using namespace std;


int getMonth(int month);
int getYear(int year);
int computeOffset(int year, int month);
int numDaysYear(int year);
int numDaysMonth(int year, int month);
bool isLeapYear(int year);
void display(int year, int month, int offset);


/**********************************************************************
 * This function will call all the functions necessary to make a calendar
 * for any given month and year.
 ***********************************************************************/
int main()
{
   int numDays;
   int offset;
   int month;
   int year;

   month = getMonth(month);

   year = getYear(year);

   offset = computeOffset(year, month);

   display(year, month, offset);

   return 0;
}

/***********************************************************************
 * Gets the month number.
 **********************************************************************/
int getMonth(int month)
{
   cout << "Enter a month number: ";
   cin >> month;

   while ( month < 1 || month > 12)
   {
      cout << "Month must be between 1 and 12.\n"
           << "Enter a month number: ";
      cin >> month;
   }

   return month;
}

/***********************************************************************
 * Gets the year.
 **********************************************************************/
int getYear(int year)
{
   cout << "Enter year: ";
   cin >> year;

   while ( year < 1753)
   {
      cout << "Year must be 1753 or later.\n"
           << "Enter year: ";
      cin >> year;
   }
   return year;
}

/***********************************************************************
 * Computes the offset.
 **********************************************************************/

int computeOffset(int year, int month)
{
   int offset = 0;
   int count = year - 1753;
   for ( int iYear = 0; iYear < count; iYear++)
   {
      offset = ( offset + 365 + isLeapYear(year)) % 7;
   }

   for ( int iMonth = 1; iMonth < month; iMonth++)
   {
      offset = ( offset + numDaysMonth(year, iMonth)) % 7;
   }

   return offset;
}



/***********************************************************************
 * Computes the number of days in the given year.
 **********************************************************************/
int numDaysYear(int year)
{
   int daysYear = 365 + isLeapYear(year);
   return daysYear;
}

/***********************************************************************
 * Calculates the number of days in the given month.
 **********************************************************************/
int numDaysMonth(int year, int month)
{
   int daysMonth;

   if ( month == 1)
      daysMonth = 31;
   else if ( month == 2)
   {
      if (isLeapYear(year) == true)
         daysMonth = 29;
      else
         daysMonth = 28;
   }
   else if ( month == 3)
      daysMonth = 31;
   else if ( month == 4)
      daysMonth = 30;
   else if ( month == 5)
      daysMonth = 31;
   else if ( month == 6)
      daysMonth = 30;
   else if ( month == 7)
      daysMonth = 31;
   else if ( month == 8)
      daysMonth = 31;
   else if ( month == 9)
      daysMonth = 30;
   else if ( month == 10)
      daysMonth = 31;
   else if ( month == 11)
      daysMonth = 30;
   else if ( month == 12)
      daysMonth = 31;

   return daysMonth;
}

/***********************************************************************
 * Determines if given year is a leap year.
 **********************************************************************/
bool isLeapYear(int year)
{
   if ( year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
      return true;
   else
      return false;
}
 /**********************************************************************
 * Displays the calender table.
 **********************************************************************/
void display(int year, int month, int offset)
 {
    int dayOfWeek;
    int day;

    cout << endl;
    if ( month == 1)
       cout << "January";
    else if ( month == 2)
       cout << "February";
    else if ( month == 3)
       cout << "March";
    else if ( month == 4)
       cout << "April";
    else if ( month == 5)
       cout << "May";
    else if ( month == 6)
       cout << "June";
    else if ( month == 7)
       cout << "July";
    else if ( month == 8)
       cout << "August";
    else if ( month == 9)
       cout << "September";
    else if ( month == 10)
       cout << "October";
    else if ( month == 11)
       cout << "November";
    else if ( month == 12)
       cout << "December";


    cout << ", " << year << "\n";
    // Display month header
    cout << "  Su  Mo  Tu  We  Th  Fr  Sa\n";

    // Gets the correct offset width and end the line on the right
    //day of the week
    if (offset == 0)
    {
       day = 2;
       cout << setw(6);
    }
    else if (offset == 1)
    {
       day = 3;
       cout << setw(10);
    }
    else if (offset == 2)
    {
       day = 4;
       cout << setw(14);
    }
    else if (offset == 3)
    {
       day = 5;
       cout << setw(18);
    }
    else if (offset == 4)
    {
       day = 6;
       cout << setw(22);
    }
    else if (offset == 5)
    {
       day = 7;
       cout << setw(26);
    }
    else if (offset == 6)
    {
       day = 1;
       cout << setw(2);
    }
    else
       cout << "Error offset must be >= 0 and <=6\n";

    // The loop for displaying the days and ending the line in the right place
    for ( dayOfWeek = 1; dayOfWeek <= numDaysMonth(year, month); dayOfWeek++ )
    {
       cout << "  " <<  setw(2) << dayOfWeek;
       ++day;
       if (day == 8)
       {
          cout << "\n";
          day = 1;
       }
    }
    if ( day >= 2 && day <= 7)
       cout << "\n";

    return;
 }`

最佳答案

旧问题的新答案。新答案的依据:在此 Realm 中使用更好的工具和技术。

这个答案大量使用了free, open-source header-only library。我将从最高级别开始给出此答案,然后深入到较低级别的细节。但是,无论何时何地,我们都无需深入进行详细的日历计算。 "date.h" 为我们处理。

这是main:

#include "date.h"
#include <iomanip>
#include <ostream>
#include <string>
#include <iostream>

int
main()
{
    print_calendar_year(std::cout);
}

这只是为我输出:
January 2016
  S  M  T  W  T  F  S
                 1  2
  3  4  5  6  7  8  9
 10 11 12 13 14 15 16
 17 18 19 20 21 22 23
 24 25 26 27 28 29 30
 31

February 2016
  S  M  T  W  T  F  S
     1  2  3  4  5  6
  7  8  9 10 11 12 13
 14 15 16 17 18 19 20
 21 22 23 24 25 26 27
 28 29

March 2016
  S  M  T  W  T  F  S
        1  2  3  4  5
  6  7  8  9 10 11 12
 13 14 15 16 17 18 19
 20 21 22 23 24 25 26
 27 28 29 30 31

April 2016
  S  M  T  W  T  F  S
                 1  2
  3  4  5  6  7  8  9
 10 11 12 13 14 15 16
 17 18 19 20 21 22 23
 24 25 26 27 28 29 30

May 2016
  S  M  T  W  T  F  S
  1  2  3  4  5  6  7
  8  9 10 11 12 13 14
 15 16 17 18 19 20 21
 22 23 24 25 26 27 28
 29 30 31

June 2016
  S  M  T  W  T  F  S
           1  2  3  4
  5  6  7  8  9 10 11
 12 13 14 15 16 17 18
 19 20 21 22 23 24 25
 26 27 28 29 30

July 2016
  S  M  T  W  T  F  S
                 1  2
  3  4  5  6  7  8  9
 10 11 12 13 14 15 16
 17 18 19 20 21 22 23
 24 25 26 27 28 29 30
 31

August 2016
  S  M  T  W  T  F  S
     1  2  3  4  5  6
  7  8  9 10 11 12 13
 14 15 16 17 18 19 20
 21 22 23 24 25 26 27
 28 29 30 31

September 2016
  S  M  T  W  T  F  S
              1  2  3
  4  5  6  7  8  9 10
 11 12 13 14 15 16 17
 18 19 20 21 22 23 24
 25 26 27 28 29 30

October 2016
  S  M  T  W  T  F  S
                    1
  2  3  4  5  6  7  8
  9 10 11 12 13 14 15
 16 17 18 19 20 21 22
 23 24 25 26 27 28 29
 30 31

November 2016
  S  M  T  W  T  F  S
        1  2  3  4  5
  6  7  8  9 10 11 12
 13 14 15 16 17 18 19
 20 21 22 23 24 25 26
 27 28 29 30

December 2016
  S  M  T  W  T  F  S
              1  2  3
  4  5  6  7  8  9 10
 11 12 13 14 15 16 17
 18 19 20 21 22 23 24
 25 26 27 28 29 30 31

可以使用以下命令打印出明年的日历:
using namespace date::literals;
print_calendar_year(std::cout, 2017_y);

我将从以下语句开始:

This is a type-safe system.



文字2017_ydate::year类型的对象,而不是简单的整数。具有意味着yearmonth的类型意味着将这些概念混淆的可能性很小。错误往往会在编译时被发现。
print_calendar_year非常简单:
void
print_calendar_year(std::ostream& os, date::year y = current_year())
{
    using namespace date;
    for (auto ym = y/jan; ym < y/jan + years{1}; ym += months{1})
    {
        print_calendar_month(os, ym);
        os << '\n';
    }
}

表达式year/month创建了一个称为date::year_month的类型,它只不过是一个简单的结构{year, month}。因此,此函数只是简单地设置了一个循环,以从y年的1月到下一个1月(不包括下一个1月)进行迭代。所有这些都非常易读。请注意,不允许使用“裸int s”。一切都有非整数类型。
print_calendar_month是橡胶与路的交汇处:
void
print_calendar_month(std::ostream& os, date::year_month ym = current_year_month())
{
    using namespace std;
    using namespace date;
    os << format("%B %Y\n", sys_days{ym/1});
    os << "  S  M  T  W  T  F  S\n";
    auto wd = unsigned{weekday{ym/1}};
    os << string(wd*3, ' ');
    auto const e = (ym/last).day();
    for (day d = 1_d; d <= e; wd = 0)
    {
        for (; wd < 7 && d <= e; ++wd, ++d)
            os << setw(3) << unsigned{d};
        os << '\n';
    }
}
os << format("%B %Y\n", sys_days{ym/1});是每个月打印出标题的内容(例如January 2016)。这些是类似于strftime的格式设置标志,将遵守当前全局std::locale的本地化设置(与操作系统支持的一样多)。

子表达式ym/1创建一个date::year_month_day类型,代表所指示的月份和年份的第一天。 date::year_month_day是持有{year, month, day}的简单类。
sys_days是基于chrono::time_pointsystem_clock,精度为daysdate::format可以采用任何精度的system_clock time_point并使用类似于strftime的格式标记对其进行格式化。如图所示,可以将year_month_day转换为sys_days。这是从{year, month, day}字段类型到串行{count of days}类型的转换。
os << " S M T W T F S\n";显然会打印出日历的星期几标题。
auto wd = unsigned{weekday{ym/1}};查找每月第一天的星期几,并使用weekday编码将该unsigned转换为[Sun == 0, Sat == 6]。 [注意:gcc需要语法unsigned(weekday{ym/1})。它不喜欢{}unsigned。 —尾注]
os << string(wd*3, ' ');仅在每月的第一天之前每天打印出3个空格以填充第一行。
auto const e = (ym/last).day();date::day类型的常量,它等于今年和月份组合的月份的最后一天。
for (day d = 1_d; d <= e; wd = 0)
从第1天开始循环,直到该月的最后一天(包括该天),然后将unsigned wd设置回每次迭代的星期日编码。
for (; wd < 7 && d <= e; ++wd, ++d):直到达到星期末或月末,才增加星期几和月几。
os << setw(3) << unsigned{d};:将月份中的日期转换为unsigned并以3个空格的宽度a右对齐打印出来。
os << '\n';在打印星期后返回。

这就是程序的大部分!几乎所有棘手的日历逻辑都封装在以下两行代码中:
auto wd = unsigned{weekday{ym/1}};
auto const e = (ym/last).day();

为了完整起见,以下是获取当前date::year和当前date::year_month的函数:
date::year_month
current_year_month()
{
    using namespace std::chrono;
    using namespace date;
    year_month_day ymd = floor<days>(system_clock::now());
    return ymd.year()/ymd.month();
}

date::year
current_year()
{
    using namespace std::chrono;
    using namespace date;
    year_month_day ymd = floor<days>(system_clock::now());
    return ymd.year();
}

这两种方法都只是使用system_clock::time_pointsystem_clock::now()返回的days截断为floor的精度,然后将该天精度的time_point转换为date::year_month_day类型。然后,此类型具有yearmonth的 setter/getter ,以选择所需的部分日历类型。

更新

好吧,TemplateRex在下面问了一个我最初不想回答的问题,然后我无济于事,因为答案突出了"date.h"的强大功能。 ;-)

问题是:

Can you print out the calendars in a 3x4 format like this?


 January 2016            February 2016           March 2016          
 Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa
                 1  2        1  2  3  4  5  6           1  2  3  4  5
  3  4  5  6  7  8  9     7  8  9 10 11 12 13     6  7  8  9 10 11 12
 10 11 12 13 14 15 16    14 15 16 17 18 19 20    13 14 15 16 17 18 19
 17 18 19 20 21 22 23    21 22 23 24 25 26 27    20 21 22 23 24 25 26
 24 25 26 27 28 29 30    28 29                   27 28 29 30 31      
 31                                                                  

 April 2016              May 2016                June 2016           
 Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa
                 1  2     1  2  3  4  5  6  7              1  2  3  4
  3  4  5  6  7  8  9     8  9 10 11 12 13 14     5  6  7  8  9 10 11
 10 11 12 13 14 15 16    15 16 17 18 19 20 21    12 13 14 15 16 17 18
 17 18 19 20 21 22 23    22 23 24 25 26 27 28    19 20 21 22 23 24 25
 24 25 26 27 28 29 30    29 30 31                26 27 28 29 30      

 July 2016               August 2016             September 2016      
 Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa
                 1  2        1  2  3  4  5  6                 1  2  3
  3  4  5  6  7  8  9     7  8  9 10 11 12 13     4  5  6  7  8  9 10
 10 11 12 13 14 15 16    14 15 16 17 18 19 20    11 12 13 14 15 16 17
 17 18 19 20 21 22 23    21 22 23 24 25 26 27    18 19 20 21 22 23 24
 24 25 26 27 28 29 30    28 29 30 31             25 26 27 28 29 30   
 31                                                                  

 October 2016            November 2016           December 2016       
 Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa
                    1           1  2  3  4  5                 1  2  3
  2  3  4  5  6  7  8     6  7  8  9 10 11 12     4  5  6  7  8  9 10
  9 10 11 12 13 14 15    13 14 15 16 17 18 19    11 12 13 14 15 16 17
 16 17 18 19 20 21 22    20 21 22 23 24 25 26    18 19 20 21 22 23 24
 23 24 25 26 27 28 29    27 28 29 30             25 26 27 28 29 30 31
 30 31                                                               

显然是这样,因为我不想手动输入以上所有内容! ;-)

它需要重写print_calendar_year并引入几个新函数,最值得注意的是:
void
print_line_of_calendar_month(std::ostream& os, date::year_month ym, unsigned line,
                             date::weekday firstdow);

此函数仅打印与year_month ym关联的日历的一行,并且是此3x4格式的核心。

我还认为使该程序本地化会很有趣,以便可以打印出所需的第一周的第一天,以及月份和一周中某天的本地化名称(与您的std::locale一样多)平台允许)。

这些行编号为[0,infinity]。第0行会打印出月份年份,例如January 2016。第1行打印出星期几的标题:Su Mo Tu We Th Fr Sa。然后,第[2,infinity]行将打印出该月的某几天。

为什么无限?

因为不同的月份使用不同的行数,所以我希望能够告诉year/month打印下一行,即使它不需要(因为该季度的另一个月份需要它)。因此,当您要求日历打印出不需要的行时,它仅会输出适当数量的' '进行填充。

足够的介绍,这里是功能:
void
print_line_of_calendar_month(std::ostream& os, date::year_month ym, unsigned line,
                             date::weekday firstdow)
{
    using namespace std;
    using namespace date;
    switch (line)
    {
    case 0:
        os << left << setw(21) << format(os.getloc(), " %B %Y", sys_days{ym/1}) << right;
        break;
    case 1:
        {
        auto sd = sys_days{ym/firstdow[1]};
        for (auto const esd = sd + weeks{1}; sd < esd; sd += days{1})
        {
            auto d = format(os.getloc(), "%a", sd);
            d.resize(2);
            os << ' ' << d;
        }
        break;
        }
    case 2:
        {
        auto wd = weekday{ym/1};         // This line and the next are the "offset"
        os << string((wd-firstdow).count()*3, ' '); // referred to in the question.
        auto d = 1_d;
        do
        {
            os << setw(3) << unsigned(d);
            ++d;
        } while (++wd != firstdow);
        break;
        }
    default:
        {
        unsigned index = line - 2;
        auto sd = sys_days{ym/1};
        if (weekday{sd} == firstdow)
            ++index;
        auto ymdw = ym/firstdow[index];
        if (ymdw.ok())
        {
            auto d = year_month_day{ymdw}.day();
            auto const e = (ym/last).day();
            auto wd = firstdow;
            do
            {
                os << setw(3) << unsigned(d);
            } while (++wd != firstdow && ++d <= e);
            os << string((firstdow-wd).count()*3, ' ');
        }
        else
            os << string(21, ' ');
        break;
        }
    }
}

因此,打开行号[0,infinity],然后为每个行号做正确的事情:
0.打印月份年份标题。

这传递给formatlocaleos以获得本地化的月份名称。
1.打印星期几的标题。

这传递给formatlocaleos以获得本地化的工作日名称,并打印前2个字符。 (不幸的是)只有当这些字符是多字节字符时,这才是大致正确的,但是本文主要是关于日历,而不是Unicode。
2.打印出第一周,可能以空格为前缀。要加前缀的空格数为3 *(月初的天数超出一周的第一天)。然后附加几天,直到到达一周的最后一天。请注意,工作日减法始终是7模,因此您不必担心星期几的基础编码。工作日形成一个循环范围。在一周的所有天中循环时,这确实需要这种do-while的内容,而不是传统的for
3 - infinity。啊,这是有趣的部分。
"date.h"中有一个类型称为year_month_weekday,它是一种存储{year, month, weekday, unsigned}的类型。您可以通过以下方式指定母亲节:五月的第二个星期日:sun[2]/may/2016。该表达式创建一个结构{2016, 5, 0, 2}(大致而言)。因此,如果switch落在此处,那么我们正在寻找本月和年的[第一个,最后一个]周日,确切的索引取决于line,以及是否在第2行中打印出一个周日。

同样重要的是,该库允许使用任何索引:
auto ymdw = ym/firstdow[index];
index可以为1,也可以为57。上面的行可以编译,而不是运行时错误。

但是几个月不能有57个星期日(或星期一或其他日期)!

没问题。您可以询问ym/firstdow[index]是否为有效日期。这是下一行的内容:
if (ymdw.ok())

如果日期有效,那么您需要做的工作。否则,您只需打印出空白行。

如果我们有工作要做,请将year_month_weekday转换为year_month_day,以便您可以从中获取当月的日期(d)。并找到该月的最后一天:
auto const e = (ym/last).day();

然后从一周的第一天开始迭代,以先到者为准:月末或一周的最后一天。打印每个地点的每月日期。然后,如果您没有在一周的最后一天结束,请打印空格以填充到一周的最后一天。

至此,我们完成了print_line_of_calendar_month!请注意,从未在该级别上输出换行符。在此级别上甚至没有输出月间填充。每个日历的宽度正好为21 char,并且可以打印到任意行。

现在,我们需要另一个辅助工具:日历月开始填充空白行之前需要多少行?
unsigned
number_of_lines_calendar(date::year_month ym, date::weekday firstdow)
{
    using namespace date;
    return ceil<weeks>((weekday{ym/1} - firstdow) +
                       ((ym/last).day() - day{0})).count() + 2;
}

这是一个月中的天数,再加上从一周的第一天到该月的第一天的天数,再加上两行,分别是星期几和年月标题。最后的小数周四舍五入!

笔记:
  • 从一周的第一天到一个月的第一天的天数很简单:(weekday{ym/1} - firstdow)
  • 一个月中的天数在此处编码为((ym/last).day() - day{0})。请注意,day{0}不是有效的day,但在减法中仍然有用:day - day给出chrono::duration的结果days。另一种说法是((ym/last).day() - day{1} + days{1})
  • 请注意,此处使用ceil<weeks>days的数量转换为weeks的数量,如果转换不精确,则四舍五入到下一个weeks。 1周== 1行。此汇总说明了在一周的最后一天之前结束的最后一周。

  • 现在可以按照以下原语重写print_calendar_year:
    void
    print_calendar_year(std::ostream& os, unsigned const cols = 3,
                        date::year const y = current_year(),
                        date::weekday const firstdow = date::sun)
    {
        using namespace date;
        if (cols == 0 || 12 % cols != 0)
            throw std::runtime_error("The number of columns " + std::to_string(cols)
                                     + " must be one of [1, 2, 3, 4, 6, 12]");
        // Compute number of lines needed for each calendar month
        unsigned ml[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
        for (auto& m : ml)
            m = number_of_lines_calendar(y/month{m}, firstdow);
        for (auto r = 0u; r < 12/cols; ++r) // for each row
        {
            const auto lines = *std::max_element(std::begin(ml) + (r*cols),
                                                 std::begin(ml) + ((r+1)*cols));
            for (auto l = 0u; l < lines; ++l) // for each line
            {
                for (auto c = 0u; c < cols; ++c) // for each column
                {
                    if (c != 0)
                        os << "   ";
                    print_line_of_calendar_month(os, y/month{r*cols + c+1}, l, firstdow);
                }
                os << '\n';
            }
            os << '\n';
        }
    }
    

    首先计算每个月需要多少行:
    // Compute number of lines needed for each calendar month
    unsigned ml[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    for (auto& m : ml)
        m = number_of_lines_calendar(y/month{m}, firstdow);
    

    然后,对于每个“日历行”,通过搜索ml的适当子集来找到该行所需的行数。

    然后,对于每一行和每个“日历列”,为该列打印出相应日历月的行。

    在每行之后打印'\n'

    在每个日历行之后,打印'\n'

    请注意,我们仍然不需要沉迷于日历计算中。在这个级别上,我们需要知道“每周7天”,“每天3个空格”和“每个日历行12 / cols月”。

    在macOS上,此驱动程序:
    using namespace date::literals;
    std::cout.imbue(std::locale("de_DE"));
    print_calendar_year(std::cout, 3, 2016_y, mon);
    

    输出:
     Januar 2016             Februar 2016            März 2016          
     Mo Di Mi Do Fr Sa So    Mo Di Mi Do Fr Sa So    Mo Di Mi Do Fr Sa So
                  1  2  3     1  2  3  4  5  6  7        1  2  3  4  5  6
      4  5  6  7  8  9 10     8  9 10 11 12 13 14     7  8  9 10 11 12 13
     11 12 13 14 15 16 17    15 16 17 18 19 20 21    14 15 16 17 18 19 20
     18 19 20 21 22 23 24    22 23 24 25 26 27 28    21 22 23 24 25 26 27
     25 26 27 28 29 30 31    29                      28 29 30 31         
    
     April 2016              Mai 2016                Juni 2016           
     Mo Di Mi Do Fr Sa So    Mo Di Mi Do Fr Sa So    Mo Di Mi Do Fr Sa So
                  1  2  3                       1           1  2  3  4  5
      4  5  6  7  8  9 10     2  3  4  5  6  7  8     6  7  8  9 10 11 12
     11 12 13 14 15 16 17     9 10 11 12 13 14 15    13 14 15 16 17 18 19
     18 19 20 21 22 23 24    16 17 18 19 20 21 22    20 21 22 23 24 25 26
     25 26 27 28 29 30       23 24 25 26 27 28 29    27 28 29 30         
                             30 31                                       
    
     Juli 2016               August 2016             September 2016      
     Mo Di Mi Do Fr Sa So    Mo Di Mi Do Fr Sa So    Mo Di Mi Do Fr Sa So
                  1  2  3     1  2  3  4  5  6  7              1  2  3  4
      4  5  6  7  8  9 10     8  9 10 11 12 13 14     5  6  7  8  9 10 11
     11 12 13 14 15 16 17    15 16 17 18 19 20 21    12 13 14 15 16 17 18
     18 19 20 21 22 23 24    22 23 24 25 26 27 28    19 20 21 22 23 24 25
     25 26 27 28 29 30 31    29 30 31                26 27 28 29 30      
    
     Oktober 2016            November 2016           Dezember 2016       
     Mo Di Mi Do Fr Sa So    Mo Di Mi Do Fr Sa So    Mo Di Mi Do Fr Sa So
                     1  2        1  2  3  4  5  6              1  2  3  4
      3  4  5  6  7  8  9     7  8  9 10 11 12 13     5  6  7  8  9 10 11
     10 11 12 13 14 15 16    14 15 16 17 18 19 20    12 13 14 15 16 17 18
     17 18 19 20 21 22 23    21 22 23 24 25 26 27    19 20 21 22 23 24 25
     24 25 26 27 28 29 30    28 29 30                26 27 28 29 30 31   
     31                                                                  
    

    您的里程可能因std::lib / OS支持本地化的程度而异。但是,现在您可以将日历打印成以月份为单位的任意月份(每个年份的除数为12([1、2、3、4、6、12])之间的月份数,以任何一年为单位,以星期几为第一天周,并使用任何语言环境(语言环境的模块化OS支持)。

    这是print_calendar_year(std::cout, 4, 2017_y);的输出
     January 2017            February 2017           March 2017              April 2017          
     Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa
      1  2  3  4  5  6  7              1  2  3  4              1  2  3  4                       1
      8  9 10 11 12 13 14     5  6  7  8  9 10 11     5  6  7  8  9 10 11     2  3  4  5  6  7  8
     15 16 17 18 19 20 21    12 13 14 15 16 17 18    12 13 14 15 16 17 18     9 10 11 12 13 14 15
     22 23 24 25 26 27 28    19 20 21 22 23 24 25    19 20 21 22 23 24 25    16 17 18 19 20 21 22
     29 30 31                26 27 28                26 27 28 29 30 31       23 24 25 26 27 28 29
                                                                             30                  
    
     May 2017                June 2017               July 2017               August 2017         
     Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa
         1  2  3  4  5  6                 1  2  3                       1           1  2  3  4  5
      7  8  9 10 11 12 13     4  5  6  7  8  9 10     2  3  4  5  6  7  8     6  7  8  9 10 11 12
     14 15 16 17 18 19 20    11 12 13 14 15 16 17     9 10 11 12 13 14 15    13 14 15 16 17 18 19
     21 22 23 24 25 26 27    18 19 20 21 22 23 24    16 17 18 19 20 21 22    20 21 22 23 24 25 26
     28 29 30 31             25 26 27 28 29 30       23 24 25 26 27 28 29    27 28 29 30 31      
                                                     30 31                                       
    
     September 2017          October 2017            November 2017           December 2017       
     Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa
                     1  2     1  2  3  4  5  6  7              1  2  3  4                    1  2
      3  4  5  6  7  8  9     8  9 10 11 12 13 14     5  6  7  8  9 10 11     3  4  5  6  7  8  9
     10 11 12 13 14 15 16    15 16 17 18 19 20 21    12 13 14 15 16 17 18    10 11 12 13 14 15 16
     17 18 19 20 21 22 23    22 23 24 25 26 27 28    19 20 21 22 23 24 25    17 18 19 20 21 22 23
     24 25 26 27 28 29 30    29 30 31                26 27 28 29 30          24 25 26 27 28 29 30
                                                                             31                  
    

    关于c++ - 日历程序的偏移,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19780335/

    相关文章:

    mysql - 为什么 1582 中的两个 MySQL 日期看起来相同,但比较结果是错误的?

    c++ - 使用CMake创建可以在其他计算机上独立运行的可执行文件

    c++ - 如果一个引用一旦被初始化为一个对象,它就不能被改变,为什么会这样呢?

    android - Calendar.MONTH 返回错误值

    python - 给定周内的天数/日期

    html - 与行内 block 错位(其他元素被压低)

    apache-kafka - Apache 卡夫卡 : commitSync after pause

    c - 如何使用c中的偏移量读取文件

    c++ - 一个类的方法覆盖另一个类的所有方法

    c++ - 在 C++/CLI 中计算时间