1

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

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

4

3 回答 3

0

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

  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;
于 2012-06-17T06:33:30.883 回答
0

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

  1. 从一年的周数,获取该年的day numbers(即开始和结束日期)。(在这里照顾第一周和最后一周)
  2. 现在很容易找到day numbers谎言中的月份和日期。(在这里照顾二月)
于 2012-06-17T05:36:16.550 回答
0

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

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;
}
于 2012-06-17T10:55:22.473 回答