C ++:获取任何一个月的最后一周

C++: Get the last week day of any month

我正在编写代码来解析 cron format

在经历了不同的语法之后,我卡在了 'L' 运算符上,特别是在“3L”上,它会给我这个月的最后一个星期三(例如,2021 年 9 月的最后一个星期三将是第 29 位) 数字 3 是天数 :

0 = Sunday
1 = Monday
.
.
6 = Saturday

我浏览了互联网,找不到任何可以帮助我的东西(我不想使用任何图书馆)

我找到了这个计算每个月最后一个星期五的代码,我想更改它以便我可以得到我想要的任何月份的最后一周。

已编辑

#include <iostream>
using namespace std;

class lastFriday
{
    int lastDay[12];  //to store last day of all month//хранить последний день всего месяца
    int year; //for given year//за данный год
    string m[12];  // to store names of all 12 months//хранить имя всех 12 месяцев
    bool isleap;  // to check given year is leap year or not//проверить, является ли год високосным или нет
 private:
    //function to find leap year//функция поиска високосного года
    void isleapyear()
    {
        if ((year % 4))
        {
            if (year % 100)
                isleap = true;
            else if ((year % 400))
                isleap = true;
        }
    }

    // to display last  friday of each month
    void display()
    {
        for (int x = 0; x < 12; x++)
            cout << m[x] << lastDay[x] << endl;
    }

    //function to find last friday for a given month 
    int getWeekDay(int m, int d)
    {
        int y = year;

        int f = y + d + 3 * m - 1;
        m++;
        if (m < 3)
            y--;
        else
            f -= int(.4 * m + 2.3);

        f += int(y / 4) - int((y / 100 + 7) * 0.75);
        f %= 7;

        return f;
    }
 public:
    //set name of 12 months
    lastFriday()
    {
        m[0] = "JANUARY:   "; m[1] = "FEBRUARY:  "; m[2] = "MARCH:     "; m[3] = "APRIL:     ";
        m[4] = "MAY:       "; m[5] = "JUNE:      "; m[6] = "JULY:      "; m[7] = "AUGUST:    ";
        m[8] = "SEPTEMBER: "; m[9] = "OCTOBER:   "; m[10] = "NOVEMBER:  "; m[11] = "DECEMBER:  ";
    }

    //function to find last fridays
    void findLastFriday(int y)
    {
        year = y;

        //to check given year is leap year or not
        isleapyear();

        //if given year is leap year then feb has 28 else 29 
        int days[] = { 31, isleap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };  // to set number of days for each month
        int d;

        //for all 12 months we have to find last friday
        for (int i = 0; i < 12; i++)
        {
            d = days[i];
            while (true)
            {
                if (!getWeekDay(i, d))
                    break;
                d--;
            }
            lastDay[i] = d;
        }

        //function call to print display dates of last friday for each month
        display();
    }
};

int main()
{
    int year;  //to store year given by user
    lastFriday LF;

    cout << "Enter the year in the range 1970 to 2037 : ";
    cin >> year;

    //validation for year between 1970 to 2037 
    if (year>2037|year<1970)
    {
        cout << "Not available for this year";
    }
    else
    {
        LF.findLastFriday(year);
    }

    return 0;
}

任何人都可以帮助我理解解释这段代码。 谢谢!

我找到了解决我的问题的方法,我想与您分享,也许有人会觉得它有用。

我在问题中提到我想获取任何月份最后一个工作日的日期。 首先,在 cron 格式中,如果要指定可以这样写:"0 14 10 ? SEP 3L ?" 这意味着,在每个 9 月的最后一个星期三 10:14:00 上执行。 为了在我的代码中工作,我需要得到星期三是一个月中的哪一天,

此代码是我项目的一部分,但我会尝试解释所有内容,

else if (contains(str[5],'L'))
{
    if (str[5] == "L") bdaysOfWeekDesc[6]=6;
    else
    {
        int diff;
        auto parts = split(str[5],'L');
        auto LDoM = LastDay(stoi(monthReplaced),currentYear);
        tm time_in = { 0, 0, 0, LDoM, stoi(monthReplaced)-1, currentYear - 1900};
              time_t time_temp = mktime(&time_in);
              const tm * time_out = localtime(&time_temp);
              if (stoi(parts[0].data()) == time_out->tm_wday)
              {
                  bdaysOfMonthsDesc[time_out->tm_mday] = time_out->tm_mday;
              }
              else if ((stoi(parts[0].data()) > time_out->tm_wday) || time_out->tm_wday ==0 )
              {
                  diff = time_out->tm_wday - stoi(parts[0].data());
                  for(size_t j=0;j<=sizeof(bdaysOfMonthsDesc) / sizeof(bdaysOfMonthsDesc[0]);j++)
                    {
                      bdaysOfMonthsDesc[j]=0;
                      bdaysOfMonthsDesc[time_out->tm_mday + abs(diff) - 7] = time_out->tm_mday + abs(diff) - 7;
                    }
              }
              else if (stoi(parts[0].data()) < time_out->tm_wday)
              {
                  diff = time_out->tm_wday - stoi(parts[0].data());
                  for(size_t j=0; j <= sizeof(bdaysOfMonthsDesc) / sizeof(bdaysOfMonthsDesc[0]); j++)
                    {
                      bdaysOfMonthsDesc[j] = 0;
                      bdaysOfMonthsDesc[time_out->tm_mday - abs(diff)] = time_out->tm_mday - abs(diff);
                    }
              }
    }
}
  • split函数是根据给定的分隔符拆分字段 例如:auto parts = split("3L", 'L'); 零件 [0] 等于“3”

  • contains函数检查一个字符是否存在于字符串中 例如:contains("3L", 'L');

拆分和包含函数来自 croncpp

  • LastDay function returns the last day (30 or 31 or 28 or 29) of the month given. This function is from @saqlain response on an other thread

首先,我需要获取该月最后一天的日期 所以:

tm time_in = {seconds, minutes, hours, dayOfMonth, Month, year-1900}

秒:从0开始,
分钟:从0开始,
小时数:从 0 开始,
DOM: 1 天,
Month:从0开始的月份(代码中的-1是因为我的月份字段是从1开始的)
年:自 1900 年以来的年份

使用 mktime()localtime() 函数我可以得到哪个工作日是在每月的 30 号或 31 号

之后我测试了我在cron格式中请求的工作日是否与每月最后一天的工作日相同,
或者是优劣。

有了这段代码,我的问题就解决了,也许对其他人也有帮助。

顺便说一句,这是 C++20 的解决方案:

#include <chrono>
#include <iostream>

void
lastFriday(int y)
{
    using namespace std;
    using namespace std::chrono;
    month m = January;
    do
    {
        cout << m << " : " << sys_days{Friday[last]/m/y} << '\n';
    } while (++m != January);
}

int
main()
{
    lastFriday(2021);
}

输出:

Jan : 2021-01-29
Feb : 2021-02-26
Mar : 2021-03-26
Apr : 2021-04-30
May : 2021-05-28
Jun : 2021-06-25
Jul : 2021-07-30
Aug : 2021-08-27
Sep : 2021-09-24
Oct : 2021-10-29
Nov : 2021-11-26
Dec : 2021-12-31

如果你没有 C++20,但你有 C++11 或更高版本,你仍然可以使用这个 free, open-source, header-only C++20 chrono preview library。只需添加 #include "date/date.h"using namespace date;.

y 在 [-32767, 32767] 范围内时,这将为民用日历输出正确的值。

如果您需要提取月、日和年的整数值,这很容易从这个表达式产生的对象中做到:sys_days{Friday[last]/m/y}