【问题标题】:Calculate the starting and ending date/time from a given year and week number根据给定的年份和周数计算开始和结束日期/时间
【发布时间】:2012-06-17 04:38:44
【问题描述】:

我如何计算给定年份的开始和结束日期/时间 (YYYY-mm-DD HH:MM::SS) 和一年中的 ISO 周数?

在再次询问此类问题之前,我搜索了 SO。当然,有一些关于 SO 上从 (year, weeknumber) 到 (datetime) 的转换的线索。但他们的回答是说 Perl、PHP、JAVA、SQL、C#、.NET、Excel 和除 C/C++ 之外的其他编程语言。

【问题讨论】:

  • SO 不是获取编程任务的逐字解决方案的地方。

标签: c++ datetime


【解决方案1】:

恐怕使用简单的 C++ 无法快速解决这个问题。但是,编写解决方案应该不是一项艰巨的工作。您只需要处理特殊情况(例如第一周和最后一周、二月、闰年)。一种方法可以是

  1. 从一年的周数,获取该年的day numbers(即开始和结束日期)。 (注意这里的第一周和最后一周)
  2. 现在使用day numbers 谎言很容易找到月份和日期。 (注意这里的二月)

【讨论】:

  • 感谢您的友好建议!我会努力弄清楚的。
【解决方案2】:

您可以从下面的代码开始并稍微调整一下(您对第一周的定义是:第一周或第一周)。你还必须处理第一周和上周的特殊情况。

  int const year = 2012;
  int const week = 24;
  boost::gregorian::greg_weekday const firstDayOfWeek = boost::gregorian::Monday;

  boost::gregorian::date const jan1st(year, boost::gregorian::Jan, 1);
  boost::gregorian::first_day_of_the_week_after const firstDay2ndWeek(firstDayOfWeek);
  boost::gregorian::date const begin2ndWeek = firstDay2ndWeek.get_date(jan1st);
  boost::gregorian::date const end2ndWeek = begin2ndWeek + boost::gregorian::days(6);

  boost::gregorian::date const beginNthWeek = begin2ndWeek + boost::gregorian::weeks(week - 2);
  boost::gregorian::date const endNthWeek = end2ndWeek + boost::gregorian::weeks(week - 2);

  std::cout << boost::gregorian::to_iso_extended_string(jan1st) << std::endl;
  std::cout << boost::gregorian::to_iso_extended_string(begin2ndWeek) << std::endl;
  std::cout << boost::gregorian::to_iso_extended_string(end2ndWeek) << std::endl;
  std::cout << boost::gregorian::to_iso_extended_string(beginNthWeek) << std::endl;
  std::cout << boost::gregorian::to_iso_extended_string(endNthWeek) << std::endl;

【讨论】:

    【解决方案3】:

    为了帮助其他人,我想回答我自己的问题如下:

    COleDateTime YearWeekDayToCalendarDate(int nYear, int nWeekNumber, int nWeekDay)
    {   
    // This method requires that one know the weekday of 4 January of the year in question
    int nFirstWeekDay = WeekDay(nYear, 1, 4);
    
    // Add 3 to the number of this weekday, giving a correction to be used for dates within this year
    int nDaysOffset = nFirstWeekDay + 3;
    
    // Multiply the week number by 7, then add the weekday. 
    int nOrdinalDayNumber = (nWeekNumber * 7) + nWeekDay;
    
    // From this sum subtract the correction for the year.
    nOrdinalDayNumber = nOrdinalDayNumber - nDaysOffset;
    
    // If the ordinal date thus obtained is zero or negative, the date belongs to the previous calendar year; 
    if (nOrdinalDayNumber <= 0)
       nYear--;
    
    int nTotalDaysInTheYear = 365;
    
    if ( LeapYear(nYear) )
       nTotalDaysInTheYear++;
    
    // If greater than the number of days in the year, to the following year.
    if (nOrdinalDayNumber > nTotalDaysInTheYear)
       nYear++;
    
    // The result is the ordinal date, which can be converted into a calendar date using the following function
    unsigned int nMonth, nDay;
    YearDayToMonthDay(nOrdinalDayNumber, nYear, nDay, nMonth);
    
    COleDateTime dtCalendar(nYear, nMonth, nDay, 0, 0, 0);
    
    return dtCalendar;
    }
    
    int WeekDay(int nYear, int nMonth, int nDay)
    {   
    // Find the DayOfYearNumber for the specified nYear, nMonth, and nDay
    const int AccumulateDaysToMonth [] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
    
    // Set DayofYear Number for nYear, nMonth, and nDay
    int nDayOfYearNumber = nDay + AccumulateDaysToMonth[nMonth - 1];
    
    // Increase of Dayof Year Number by 1, if year is leapyear and month greater than February
    //if ( LeapYear(nYear) && (nMonth == 2) )
    if ( LeapYear(nYear) && (nMonth > 2) )
       nDayOfYearNumber += 1;
    
    // Find the Jan1Weekday for nYear (Monday = 1, Sunday = 7)
    int i, j, k, l, nJan1Weekday, nWeekday;
    
    i = (nYear - 1) % 100;
    j = (nYear - 1) - i;
    k = i + i / 4;
    
    nJan1Weekday = 1 + (((((j / 100) % 4) * 5) + k) % 7);
    
    // Calcuate the WeekDay for the given date
    l = nDayOfYearNumber + (nJan1Weekday - 1);
    nWeekday = 1 + ((l - 1) % 7);
    
    return nWeekday;
    }
    
    void YearDayToMonthDay(unsigned int nYearDay, unsigned int nYear, 
                           unsigned int& nMonthDay, unsigned int& nMonth)
    {   
    // Day is the day between 1 and 366
    // Year is the year you wish
    unsigned int nMonthTable[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    unsigned int nMonthDays = 0;
    
    if ((nYear % 4 == 0) && ((!(nYear % 100 == 0)) || (nYear % 400 == 0))) 
       nMonthTable[1] = 29;
    else 
       nMonthTable[1] = 28;
    
    nMonth = 0;
    
    while (nYearDay > nMonthDays) 
       nMonthDays += nMonthTable[nMonth++];
    
    nMonthDay = nYearDay - nMonthDays + nMonthTable[nMonth - 1];
    }
    
    inline bool LeapYear( int nYear )  
    {  
    // Find if nYear is LeapYear        
    if ( (nYear % 4 == 0 && nYear % 100 != 0) || nYear % 400 == 0)
      return true;
    else
      return false;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-30
      • 1970-01-01
      • 2020-10-08
      • 1970-01-01
      • 2020-08-06
      • 1970-01-01
      相关资源
      最近更新 更多