C++ 如何计算给定日期的周数?

C++ 如何计算给定日期的周数?,c++,windows,algorithm,time,C++,Windows,Algorithm,Time,如果我有一个日期,如何计算该年内该日期的周数 例如,在2008年,1月1日至1月6日在第1周,1月7日至13日在第2周,因此,如果我的日期是2008年1月10日,我的周数将是2 一个算法可以帮助我入门,而且示例代码也有帮助——我在Windows上开发C++。 相关的: 伪代码: int julian = getDayOfYear(myDate) // Jan 1 = 1, Jan 2 = 2, etc... int dow = getDayOfWeek(myDate) // Sun

如果我有一个日期,如何计算该年内该日期的周数

例如,在2008年,1月1日至1月6日在第1周,1月7日至13日在第2周,因此,如果我的日期是2008年1月10日,我的周数将是2

一个算法可以帮助我入门,而且示例代码也有帮助——我在Windows上开发C++。 相关的:

伪代码:

int julian = getDayOfYear(myDate)  // Jan 1 = 1, Jan 2 = 2, etc...
int dow = getDayOfWeek(myDate)     // Sun = 0, Mon = 1, etc...
int dowJan1 = getDayOfWeek("1/1/" + thisYear)   // find out first of year's day
// int badWeekNum = (julian / 7) + 1  // Get our week# (wrong!  Don't use this)
int weekNum = ((julian + 6) / 7)   // probably better.  CHECK THIS LINE. (See comments.)
if (dow < dowJan1)                 // adjust for being after Saturday of week #1
    ++weekNum;
return (weekNum)
int julian=getDayOfYear(myDate)//Jan 1=1,Jan 2=2,等等。。。
int-dow=getDayOfWeek(myDate)//Sun=0,Mon=1,等等。。。
int dowJan1=getDayOfWeek(“1/1/”+今年)//找出一年中的第一天
//int badWeekNum=(julian/7)+1//Get Wear week#(错误!不要使用此选项)
int weekNum=((朱利安+6)/7)//可能更好。检查这条线。(见评论。)
如果(道指
为了澄清这一点,该算法假设您的周数如下:

S  M  T  W  R  F  S
            1  2  3    <-- week #1
4  5  6  7  8  9 10    <-- week #2
[etc.]
S M T W R F S

1.2.3使用gmtime或localtime计算自周日(即一周中的某一天)起的天数和自1月1日起的天数(注意,后者中的1月1日为“0”)

任意的一点是决定一年中的哪一天第1周开始:通常它只取决于一周中的哪一天是1月1日,当然你可以从gmtime的两条信息中计算出来。然后使用表查找7种可能性,这可能比编码规则更容易

例如,我认为Outlook使用的标准是第1周是包含星期四的第一周。因此,如果1月1日是星期日,那么第1周的第一天是1月1日,或第0天。剩下的可能性是星期一,-1;星期二-2;星期三-3;星期四-4;2006年12月2日星期五;2006年1月1日星期六

注意负数:“第一周的星期日”实际上在7个案例中没有4个存在,但是如果我们假设它是前一年的一天,我们会得到正确的答案

一旦你有了它,它和你的日期之间的天数告诉你周数:除以7加1

这就是说,我想在某个地方有一个Windows API,它将为您提供与Outlook相同的周数。我只是不知道它是什么,当然,如果你的第一周规则与Outlook不同,那么它可能没有多大用处

未测试代码:

int firstdays[7] = { 0, -1, -2, -3, -4, 2, 1 }; // or some other Week 1 rule
struct tm breakdown;
time_t target = time_you_care_about();
_gmtime_s(&breakdown,&target);
int dayofweek = breakdown.tm_wday;
int dayofyear = breakdown.tm_yday;

int jan1wday = (dayofweek - dayofyear) % 7;
if (jan1wday < 0) jan1wday += 7;

int week1first = firstdays[jan1wday];
if (dayofyear < week1first) return 0;
return ((dayofyear - week1first)/7) + 1;
int firstdays[7]={0,-1,-2,-3,-4,2,1};//或者其他的第一周规则
struct-tm分解;
时间目标=你关心的时间();
_gmtime(分解和目标);
int dayofweek=细分.tm_wday;
int dayofyear=细分.tm_yday;
int jan1wday=(星期日-一年中的某一天)%7;
如果(1月1日<0)1月1日+=7;
int week1first=第一天[一月一日];
如果(dayofyear

无论如何,类似的东西。

请注意,虽然你对一年中第n周的定义是成立的,但它也不是“标准的”

ISO 8601定义了日期、时间和时区的表示标准。它定义了从周一开始的几周。它还说,一年中的第一周是指从给定的一年开始至少有4天的时间。因此,20xx年12月29日、30日和31日可能在20xy的第1周(其中xy=xx+1),20xy年1月1日、2日和3日可能都在20xx的最后一周。此外,可能还有一周的时间

[新增:请注意,C标准和'strftime()函数提供了从周日开始的周数以及从周一开始的周数。不清楚C标准是否提供了从周日开始的周数0。另请参见Emerick Rogul的答案。]

接下来是有趣的测试阶段——第53周什么时候开始? 一个答案是在2010年1月1日星期五,也就是2009-W53(as, 事实上,星期日是2010年1月3日)。同样,1月1日星期六 2005年是2004-W53,但2006年1月1日星期日是2005-W52

这是以下代码中注释的摘录,实际上是Informix SPL(存储过程语言)中的注释,但是可读性很强,尽管可能不可写,无需进一步解释。“| |”运算符是SQL字符串连接操作,星期日是第0天,星期一是第1天。。。星期六是一周中的第六天。注释中有大量注释,包括标准中的相关文本。单行注释以“
--
”开头;多行注释可能以“
{
”开头,并以下一个“
}
”结尾

-- @(#)$Id: iso8601_weekday.spl,v 1.1 2001/04/03 19:34:43 jleffler Exp $
--
-- Calculate ISO 8601 Week Number for given date
-- Defines procedure: iso8601_weekday().
-- Uses procedure: iso8601_weeknum().

{
According to a summary of the ISO 8601:1988 standard "Data Elements and
Interchange Formats -- Information Interchange -- Representation of
dates and times":

    The week notation can also be extended by a number indicating the
    day of the week.  For example the day 1996-12-31 which is the
    Tuesday (day 2) of the first week of 1997 can also be written as

        1997-W01-2 or 1997W012

    for applications like industrial planning where many things like
    shift rotations are organized per week and knowing the week number
    and the day of the week is more handy than knowing the day of the
    month.

This procedure uses iso8601_weeknum() to format the YYYY-Www part of the
date, and appends '-d' to the result, allowing for Informix's coding of
Sunday as day 0 rather than day 7 as required by ISO 8601.
}

CREATE PROCEDURE iso8601_weekday(dateval DATE DEFAULT TODAY) RETURNING CHAR(10);
    DEFINE rv CHAR(10);
    DEFINE dw CHAR(4);
    LET dw = WEEKDAY(dateval);
    IF dw = 0 THEN
            LET dw = 7;
    END IF;
    RETURN iso8601_weeknum(dateval) || '-' || dw;
END PROCEDURE;
-- @(#)$Id: iso8601_weeknum.spl,v 1.1 2001/02/27 20:36:25 jleffler Exp $
--
-- Calculate ISO 8601 Week Number for given date
-- Defines procedures: day_one_week_one() and iso8601_weeknum().

{
According to a summary of the ISO 8601:1988 standard "Data Elements and
Interchange Formats -- Information Interchange -- Representation of
dates and times":

    In commercial and industrial applications (delivery times,
    production plans, etc.), especially in Europe, it is often required
    to refer to a week of a year.  Week 01 of a year is per definition
    the first week which has the Thursday in this year, which is
    equivalent to the week which contains the fourth day of January.  In
    other words, the first week of a new year is the week which has the
    majority of its days in the new year.  Week 01 might also contain
    days from the previous year and the week before week 01 of a year is
    the last week (52 or 53) of the previous year even if it contains
    days from the new year.  A week starts with Monday (day 1) and ends
    with Sunday (day 7).  For example, the first week of the year 1997
    lasts from 1996-12-30 to 1997-01-05 and can be written in standard
    notation as

        1997-W01 or 1997W01

    The week notation can also be extended by a number indicating the
    day of the week.  For example the day 1996-12-31 which is the
    Tuesday (day 2) of the first week of 1997 can also be written as

        1997-W01-2 or 1997W012

    for applications like industrial planning where many things like
    shift rotations are organized per week and knowing the week number
    and the day of the week is more handy than knowing the day of the
    month.

Referring to the standard itself, section 3.17 defines a calendar week:

    week, calendar: A seven day period within a calendar year, starting
    on a Monday and identified by its ordinal number within the year;
    the first calendar week of the year is the one that includes the
    first Thursday of that year.  In the Gregorian calendar, this is
    equivalent to the week which includes 4 January.

Section 5.2.3 "Date identified by Calendar week and day numbers" states:

    Calendar week is represented by two numeric digits.  The first
    calendar week of a year shall be identified as 01 [...]

    Day of the week is represented by one decimal digit.  Monday
    shall be identified as day 1 of any calendar week [...]

Section 5.2.3.1 "Complete representation" states:

    When the application clearly identifies the need for a complete
    representation of a date identified by calendar week and day
    numbers, it shall be one of the alphanumeric representations as
    follows, where CCYY represents a calendar year, W is the week
    designator, ww represents the ordinal number of a calendar week
    within the year, and D represents the ordinal number within the
    calendar week.

    Basic format: CCYYWwwD
        Example: 1985W155
    Extended format: CCYY-Www-D
        Example: 1985-W15-5

Both the summary and the formal definition are intuitively clear, but it
is not obvious how to translate it into an algorithm.  However, we can
deal with the problem by exhaustively enumerating the seven options for
the day of the week on which 1st January falls (with actual year values
for concreteness):

    1st January 2001 is Monday    => Week 1 starts on 2001-01-01
    1st January 2002 is Tuesday   => Week 1 starts on 2001-12-31
    1st January 2003 is Wednesday => Week 1 starts on 2002-12-30
    1st January 2004 is Thursday  => Week 1 starts on 2003-12-29
    1st January 2010 is Friday    => Week 1 starts on 2010-01-04
    1st January 2005 is Saturday  => Week 1 starts on 2005-01-03
    1st January 2006 is Sunday    => Week 1 starts on 2006-01-02

(Cross-check: 1st January 1997 was a Wednesday; the summary notes state
that week 1 of 1997 started on 1996-12-30, which is consistent with the
table derived for dates in the first decade of the third millennium
above).

When working with the Informix DATE types, bear in mind that Informix
uses WEEKDAY values 0 = Sunday, 1 = Monday, 6 = Saturday.  When the
weekday of the first of January has the value in the LH column, you need
to add the value in the RH column to the 1st of January to obtain the
date of the first day of the first week of the year.

    Weekday         Offset to
    1st January     1st day of week 1

    0               +1
    1                0
    2               -1
    3               -2
    4               -3
    5               +3
    6               +2

This can be written as MOD(11-w,7)-3 where w is the (Informix encoding
of the) weekday of 1st January and the value 11 is used to ensure that
no negative values are presented to the MOD operator.  Hence, the
expression for the date corresponding to the 1st day (Monday) of the 1st
week of a given year, yyyy, is:

    d1w1 = MDY(1, 1, yyyy) + MOD(11 - WEEKDAY(MDY(1,1,yyyy)), 7) - 3

This expression is encapsulated in stored procedure day_one_week_one:
}

CREATE PROCEDURE day_one_week_one(yyyy INTEGER) RETURNING DATE;
    DEFINE jan1 DATE;
    LET jan1 = MDY(1, 1, yyyy);
    RETURN jan1 + MOD(11 - WEEKDAY(jan1), 7) - 3;
END PROCEDURE;

{
Given this date d1w1, we can calculate the week number of any other date
in the same year as:

    TRUNC((dateval - d1w1) / 7) + 1

The residual issues are ensuring that the wraparounds are correct.  If
the given date is earlier than the start of the first week of the year
that contains it, then the date belongs to the last week of the previous
year.  If the given date is on or after the start of the first week of
the next year, then the date belongs to the first week of the next year.

Given these observations, we can write iso8601_weeknum as shown below.
(Beware: iso8601_week_number() is too long for servers with the
18-character limit; so is day_one_of_week_one()).

Then comes the interesting testing phase -- when do you get week 53?
One answer is on Friday 1st January 2010, which is in 2009-W53 (as,
indeed, is Sunday 3rd January 2010).  Similarly, Saturday 1st January
2005 is in 2004-W53, but Sunday 1st January 2006 is in 2005-W52.
}

CREATE PROCEDURE iso8601_weeknum(dateval DATE DEFAULT TODAY) RETURNING CHAR(8);
    DEFINE rv CHAR(8);
    DEFINE yyyy CHAR(4);
    DEFINE ww CHAR(2);
    DEFINE d1w1 DATE;
    DEFINE tv DATE;
    DEFINE wn INTEGER;
    DEFINE yn INTEGER;
    -- Calculate year and week number.
    LET yn = YEAR(dateval);
    LET d1w1 = day_one_week_one(yn);
    IF dateval < d1w1 THEN
        -- Date is in early January and is in last week of prior year
        LET yn = yn - 1;
        LET d1w1 = day_one_week_one(yn);
    ELSE
        LET tv = day_one_week_one(yn + 1);
        IF dateval >= tv THEN
            -- Date is in late December and is in the first week of next year
            LET yn = yn + 1;
            LET d1w1 = tv;
        END IF;
    END IF;
    LET wn = TRUNC((dateval - d1w1) / 7) + 1;
    -- Calculation complete: yn is year number and wn is week number.
    -- Format result.
    LET yyyy = yn;
    IF wn < 10 THEN
        LET ww = '0' || wn;
    ELSE
        LET ww = wn;
    END IF
    LET rv = yyyy || '-W' || ww;
    RETURN rv;
END PROCEDURE;

如注释中所述,代码将接受第53周的日期,即使一年只接受52周。

我强烈建议使用C标准库的时间函数来计算周数。具体地说,
strftime
函数具有说明符,用于以细分(
struct tm
)格式打印给定日期的周数(以及许多其他值)。下面是一个小示例程序,说明了这一点:

#include <stdio.h>
#include <string.h>
#include <time.h>

int
main(void)
{
  struct tm tm;
  char timebuf[64];

  // Zero out struct tm
  memset(&tm, 0, sizeof tm);

  // November 4, 2008 11:00 pm
  tm.tm_sec = 0;
  tm.tm_min = 0;
  tm.tm_hour = 23;
  tm.tm_mday = 4;
  tm.tm_mon = 10;
  tm.tm_year = 108;
  tm.tm_isdst = -1;

  // Call mktime to recompute tm.tm_wday and tm.tm_yday
  mktime(&tm);

  if (strftime(timebuf, sizeof timebuf, "%W", &tm) != 0) {
    printf("Week number is: %s\n", timebuf);
  }

  return 0;
}

您可以了解有关strftime的更多信息。

struct tm用于表示“故障时间”,至少包含以下字段:

int tm_sec Seconds [0,60]. int tm_min Minutes [0,59]. int tm_hour Hour [0,23]. int tm_mday Day of month [1,31]. int tm_mon Month of year [0,11]. int tm_year Years since 1900. int tm_wday Day of week [0,6] (Sunday =0). int tm_yday Day of year [0,365]. int tm_isdst Daylight Savings flag. int tm_秒[0,60]。 分钟[0,59]。 int tm_小时[0,23]。 int TMmd;mday of month[1,31]。 每年一个月[0,11]。 自1900年以来的一年。 int tm_wday of week[0,6](星期日=0)。 int tm_yday Day of year[0365]。 int tm_isdst夏令时标志。 可以使用localtime()函数从时间创建struct tm

可以使用mktime()函数从struct tm创建时间

struct tm最棒的地方在于,你可以做一些事情,比如在每月成员中添加24个,当你调用mktime()时,你将得到一个2年的时间(这适用于它的任何成员,因此你可以,例如,将小时数增加1000,然后在将来得到一个41天的时间)。

Week number is: 44
int tm_sec Seconds [0,60]. int tm_min Minutes [0,59]. int tm_hour Hour [0,23]. int tm_mday Day of month [1,31]. int tm_mon Month of year [0,11]. int tm_year Years since 1900. int tm_wday Day of week [0,6] (Sunday =0). int tm_yday Day of year [0,365]. int tm_isdst Daylight Savings flag.
int julian = getDayOfYear(myDate)  // Jan 1 = 1, Jan 2 = 2, etc...
int dow = getDayOfWeek(myDate)     // Sun = 0, Mon = 1, etc...
int dowJan1 = getDayOfWeek("1/1/" + thisYear)   // find out first of year's day
int weekNum = (julian / 7) + 1     // Get our week#
if (dow < dowJan1)                 // adjust for being after Saturday of week #1
    ++weekNum;
return (weekNum)
getDayOfWeek("12/31/" + thisYear-1)
getDayOfWeek("1/1/" + thisYear) 
// week number of the year
// (Monday as the first day of the week) as a decimal number [00,53].
// All days in a new year preceding the first Monday are considered to be in week 0.
int GetWeek(const struct tm& ts)
{
    return (ts.tm_yday + 7 - (ts.tm_wday ? (ts.tm_wday - 1) : 6)) / 7;
}
tm t = ... //the date on which to find week of year

int wy = -1;

struct tm t1;
t1.tm_year = t.tm_year;
t1.tm_mday = t1.tm_mon = 1; //set to 1st of January
time_t tt = mktime(&t1); //compute tm

//remove days for 1st week
int yd = t.tm_yday - (7 - t1.tm_wday);
if(yd <= 0 ) //first week is now negative
  wy = 0;
else
  wy = (int)std::ceil( (double) ( yd/7) ); //second week will be 1 
public int GetWeekOfYear(DateTime todayDate)
{
    int days = todayDate.DayOfYear;
    float result = days / 7;
    result=result+1;
    Response.Write(result.ToString());
    return Convert.ToInt32(result);
}
time_t t = time(NULL);
tm* timePtr = localtime(&t);
double day_of_year=timePtr->tm_yday +1 ; // 1-365
int week_of_year =(int) ceill(day_of_year/7.0);
/**
 * @brief WeekNo
 * @param yr
 * @param mon
 * @param day
 * @param iso
 * @return
 *
 *  Given a date, return the week number
 *  Note. The first week of the year begins on the Monday
 *  following the previous Thursday
 *  Follows ISO 8601
 *
 *  Mutually equivalent definitions for week 01 are:
 *
 *  the week with the year's first Thursday in it (the ISO 8601 definition)
 *  the week with the Thursday in the period 1 – 7 January
 *  the week starting with the Monday in the period 29 December – 4 January
 *  the week starting with the Monday which is nearest in time to 1 January
 *  the week ending with the Sunday in the period 4 – 10 January
 *  the week with 4 January in it
 *  the first week with the majority (four or more) of its days in the starting year
 *    If 1 January is on a Monday, Tuesday, Wednesday or Thursday, it is in week 01.
 *    If 1 January is on a Friday, Saturday or Sunday, it is part of week 52 or 53 of the previous year.
 *    the week with the year's first working day in it (if Saturdays, Sundays, and 1 January are not working days).
 ***    strftime has a conversion of struct tm to weeknumber.  strptime fills in tm struct**
 *   Code uses strptime, strftime functions.
 */

int WeekNo( int yr,int mon, int day, int iso)
{
    struct tm tm;
    char format[32];
    //memset(tm,0,sizeof(tm));
    sprintf(format,"%d-%02d-%02d",yr,mon,day);
    strptime(format, "%Y-%m-%d", &tm);
    // structure tm is now filled in for strftime

   strftime(format, sizeof(format), iso? "%V":"%U", &tm);

    //puts(format);
    return atoi(format);
}
NoOfDays = (CurrentDate - YearStartDate)+1
IF NoOfDays MOD 7 = 0 Then
    WeekNo = INT(NoOfDays/7)
ELSE
    WeekNo = INT(NoOfDays/7)+1
END 
The current week of 2019 is: W18
The week in 2014 on `any day` was: W09
/**********************************************************************************
Function Name: rtcCalcYearWeek
Description  : Function to calculate the working week of the year (changing on a Monday)
Arguments    : IN  iYear - The year 2000...
               IN  iMonth - The month 1..12
               IN  iDay - The day 1..31
               IN  iWeekDay - The week day 0 = Monday ... 6 = Sunday
Return Value : The year week 1..52
***********************************************************************************/
int rtcCalcYearWeek(int iYear, int iMonth, int iDay, int iWeekDay)
{
    int iLeap = 0;
    static const int ppiYearDays[2][13] =
    {
         /* Normal year */
         {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
         /* Leap year */
         {0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
    };
    /* Check for leap year */
    if (((iYear % 4) == 0) && (((iYear % 100) != 0) || ((iYear % 400) == 0)))
    {
        iLeap = 1;
    }
    /* Calculate the year week */
    return (((ppiYearDays[iLeap][iMonth] + iDay) - (iWeekDay + 7) % 7 + 7) / 7) + 1;
}
/***********************************************************************************
End of function  rtcCalcYearWeek
***********************************************************************************/

/**********************************************************************************
* Function Name: rtcCalcWeekDay
* Description  : Function to calculate the week day for a given date from 2000
*                to 2099.
* Arguments    : IN  iDay - The day 1..31
*                IN  iMonth - The month 1..12
*                IN  iYear - The year 2000..2099
* Return Value : The weekday 0 = Monday ... 6 = Sunday
***********************************************************************************/
int rtcCalcWeekDay(int iDay, int iMonth, int iYear)
{
    if (iMonth < 3)
    {
        iMonth += 12;
        iYear -= 1;
    }
    return (iDay + (2 * iMonth) + (6 * (iMonth + 1) / 10) + iYear 
            + (iYear / 4)- (iYear / 100) + (iYear / 400)) % 7;
}
/***********************************************************************************
End of function  rtcCalcWeekDay
***********************************************************************************/