C++ 如何计算给定日期的周数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/274861/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I calculate the week number given a date?
提问by Big GH
If I have a date, how do I calculate the week number for that date within that year?
如果我有一个日期,我如何计算该日期在那一年中的周数?
For example, in 2008, January 1st to January 6th are in week 1 and January 7th to the 13th are in week 2, so if my date was January 10th 2008, my week number would be 2.
例如,在 2008 年,1 月 1 日至 1 月 6 日在第 1 周,1 月 7 日至 13 日在第 2 周,因此如果我的日期是 2008 年 1 月 10 日,那么我的周数将为 2。
An algorithm would be great to get me started and sample code would also help - I'm developing in C++ on Windows.
算法对我入门很有帮助,示例代码也会有所帮助 - 我正在 Windows 上使用 C++ 进行开发。
Related:
有关的:
采纳答案by Olie
Pseudocode:
伪代码:
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)
To clarify, this algorithm assumes you number your weeks like this:
为了澄清起见,该算法假设您像这样计算周数:
S M T W R F S
1 2 3 <-- week #1
4 5 6 7 8 9 10 <-- week #2
[etc.]
getDayOfWeek() and getDayOfYear() are standard date-object operations in most languages. If yours doesn't have them, you can count-forward from some known date (Jan 1, 1970 is a common one), after looking up to see what day of the week it was.
getDayOfWeek() 和 getDayOfYear() 是大多数语言中的标准日期对象操作。如果你的没有它们,你可以从某个已知日期(1970 年 1 月 1 日是一个常见的日期)开始倒数,然后查看一周中的哪一天。
If you're going to implement your own date counting routines, remember that years that are divisible by 100 are NOTleap years, unless they are also divisible by 400. So 1900 was not a leap year, but 2000 was. If you're going to work far back in time, you have to mess with Gregorian vs Julian calendars, etc., see Wikipediafor loads of info on that.
如果您要实现自己的日期计数例程,请记住可被 100 整除的年份不是闰年,除非它们也可被 400 整除。因此 1900 不是闰年,但 2000 是。如果您要回到过去工作很长时间,则必须弄乱公历与儒略历等,请参阅维基百科以获取有关此内容的大量信息。
This linktalks about date/time functions in Windows/C++ in greater detail.
此链接更详细地讨论了 Windows/C++ 中的日期/时间函数。
回答by Jonathan Leffler
Be aware that while your definition of nthweek of the year is tenable, it is also not 'the' standard one.
请注意,虽然您对一年中第 n周的定义是站得住脚的,但它也不是“标准”。
ISO 8601 defines a standard for the representation of dates, times and time zones. It defines weeks that start on a Monday. It also says Week 1 of a year is the one which contains at least 4 days from the given year. Consequently, the 29th, 30th and 31st of December 20xx could be in week 1 of 20xy (where xy = xx + 1), and the 1st, 2nd and 3rd of January 20xy could all be in the last week of 20xx. Further, there can be a week 53.
ISO 8601 定义了表示日期、时间和时区的标准。它定义了从星期一开始的周。它还说一年中的第 1 周是包含从给定年份起至少 4 天的那一周。因此,20xx 年 12 月 29 日、30 日和 31 日可能在 20xy 的第 1 周(其中 xy = xx + 1),而 20xy 1 月 1 日、2 日和 3 日可能都在 20xx 的最后一周。此外,可能有一个星期 53。
[Added: note that the C standard and the `strftime() function provides for weeks that start on Sunday as well as weeks that start on Monday. It is not clear that the C standard provides for the year number of week 0 for Sunday-based weeks. See also the answer from Emerick Rogul.]
[补充:请注意,C 标准和`strftime() 函数提供从星期日开始的周以及从星期一开始的周。目前尚不清楚 C 标准为基于星期日的周提供了第 0 周的年数。另请参阅 Emerick Rogul 的回答。]
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.
然后是有趣的测试阶段——你什么时候到第 53 周?一个答案是 2010 年 1 月 1 日星期五,也就是 2009-W53(实际上是 2010 年 1 月 3 日星期日)。同样,2005 年 1 月 1 日星期六在 2004-W53 中,但 2006 年 1 月 1 日星期日在 2005-W52 中。
That is an extract from a comment in the following code, which is actually in Informix SPL (Stored Procedure Language), but is readable - though probably not writable - without much further explanation. The '||' operator is the SQL string concatenation operation, and Sunday is day 0, Monday is day 1, ... Saturday is day 6 of the week. There are extensive notes in the comments, including relevant text from the standard. One line comments start '--
'; possibly multiline comments start with '{
' and end at the next '}
'.
这是从以下代码中的注释中摘录的,它实际上是 Informix SPL(存储过程语言),但可读 - 尽管可能不可写 - 无需进一步解释。'||' 运算符是 SQL 字符串连接操作,星期日是第 0 天,星期一是第 1 天,……星期六是一周的第 6 天。评论中有大量注释,包括标准中的相关文本。一行注释以“ --
”开头;多行注释可能以 ' {
'开头并在下一个 ' }
'结束。
-- @(#)$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;
For completeness, the inverse function is also easy to write with the day_one_week_one()
function above:
为了完整起见,反函数也很容易用day_one_week_one()
上面的函数编写:
-- @(#)$Id: ywd_date.spl,v 1.1 2012/12/29 05:13:27 jleffler Exp $
-- @(#)Create ywd_date() and ywdstr_date() stored procedures
-- Convert a date in format year, week, day (ISO 8601) to DATE.
-- Two variants:
-- ywd_date(yyyy SMALLINT, ww SMALLINT, dd SMALLINT) RETURNING DATE;
-- ywdstr_date(ywd CHAR(10)) RETURNING DATE;
-- NB: If week 53 is supplied, there is no check that the year had week
-- 53 (GIGO).
-- NB: If year yyyy is a leap year and yyyy-01-01 falls on Wed (3) or
-- Thu (4), there are 53 weeks in the year.
-- NB: If year yyyy is not a leap year and yyyy-01-01 falls on Thu (4),
-- there are 53 weeks in the year.
CREATE PROCEDURE ywd_date(yyyy SMALLINT, ww SMALLINT, dd SMALLINT) RETURNING DATE AS date;
DEFINE d DATE;
-- Check ranges
IF yyyy < 1 OR yyyy > 9999 OR ww < 1 OR ww > 53 OR dd < 1 OR dd > 7 THEN
RETURN NULL;
END IF;
LET d = day_one_week_one(yyyy);
LET d = d + (ww - 1) * 7 + (dd - 1);
RETURN d;
END PROCEDURE;
-- Input: 2012-W52-5
CREATE PROCEDURE ywdstr_date(ywd CHAR(10)) RETURNING DATE AS date;
DEFINE yyyy SMALLINT;
DEFINE ww SMALLINT;
DEFINE dd SMALLINT;
LET yyyy = SUBSTR(ywd, 1, 4);
LET ww = SUBSTR(ywd, 7, 2);
LET dd = SUBSTR(ywd, 10, 1);
RETURN ywd_date(yyyy, ww, dd);
END PROCEDURE;
CREATE TEMP TABLE test_dates(d DATE);
INSERT INTO test_dates VALUES('2011-12-28');
INSERT INTO test_dates VALUES('2011-12-29');
INSERT INTO test_dates VALUES('2011-12-30');
INSERT INTO test_dates VALUES('2011-12-31');
INSERT INTO test_dates VALUES('2012-01-01');
INSERT INTO test_dates VALUES('2012-01-02');
INSERT INTO test_dates VALUES('2012-01-03');
INSERT INTO test_dates VALUES('2012-01-04');
INSERT INTO test_dates VALUES('2012-01-05');
INSERT INTO test_dates VALUES('2012-01-06');
INSERT INTO test_dates VALUES('2012-01-07');
SELECT d, iso8601_weeknum(d), iso8601_weekday(d), ywdstr_date(iso8601_weekday(d))
FROM test_dates
ORDER BY d;
As noted in the comments, the code will accept a week 53 date even if the year should only accept 52 weeks.
如评论中所述,即使一年只接受 52 周,代码也将接受第 53 周的日期。
回答by Emerick Rogul
I strongly recommend using the C Standard Library's time functions to calculate the week number. Specifically, the strftime
function has specifiers to print the week number (among many other values) given a date in broken-down (struct tm
) format. Here's a small sample program that illustrates this:
我强烈建议使用 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;
}
The output from this program (compiled with GCC on Linux and Microsoft Visual Studio 2005 SP1 on Windows) is:
这个程序的输出(在 Linux 上用 GCC 编译,在 Windows 上用 Microsoft Visual Studio 2005 SP1 编译)是:
Week number is: 44
Week number is: 44
You can learn more about strftime here.
您可以在此处了解有关 strftime 的更多信息。
回答by dicroce
struct tm is used to represent "broken down time" and has at least the following fields:
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.
You can create a struct tm from a time_t with the localtime() function.
您可以使用 localtime() 函数从 time_t 创建一个 struct tm。
You can create a time_t from a struct tm with the mktime() function.
您可以使用 mktime() 函数从 struct tm 创建 time_t。
The best part about struct tm is that you can do things like add 24 to the month of year member and when you call mktime() you'll get a time_t thats 2 years in the future (this works with any of its members, so you can, for example, increment the hour by 1000 and then get a time_t 41 days in the future)...
关于 struct tm 最好的部分是你可以做一些事情,比如将 24 添加到月份成员,当你调用 mktime() 时,你会得到一个 time_t 那是未来 2 年(这适用于它的任何成员,所以例如,您可以将小时增加 1000,然后在未来 41 天获得 time_t)...
回答by Pascalo
Sorry, i'm new here and cant comment on the answer itself but the pseudo code from the answer with the checkmark isnt compeltey correct.
抱歉,我是新来的,无法对答案本身发表评论,但带有复选标记的答案中的伪代码并不完全正确。
Pseudocode:
伪代码:
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)
you should not look for the "first of year's day", but for the last day of last year.
你不应该寻找“元旦”,而应该寻找去年的最后一天。
getDayOfWeek("12/31/" + thisYear-1)
would be correct instead of
将是正确的,而不是
getDayOfWeek("1/1/" + thisYear)
If you don't do this, the last weekday of last year (like Monday) would always be one week ahead.
如果您不这样做,则去年的最后一个工作日(如星期一)将始终提前一周。
回答by Marius
My definition which is non-ISO 8601 (good enough for my purposes and fast):
我的定义是非 ISO 8601(对于我的目的来说足够好并且很快):
// 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;
}
回答by Remis
Using iso_week.h
from howardhinnant.github.io/iso_week.htmlthis is easily achievable:
iso_week.h
从howardhinnant.github.io/iso_week.html使用这很容易实现:
#include <iostream>
#include "iso_week.h"
int main() {
using namespace iso_week;
using namespace std::chrono;
// Get the current time_point and floor to convert to the sys_days:
auto today = floor<days>(system_clock::now());
// Convert from sys_days to iso_week::year_weeknum_weekday format
auto yww = year_weeknum_weekday{today};
// Print current week number of the year
std::cout << "The current week of " << yww.year() << " is: "
<< yww.weeknum() << std::endl;
// Set any day
auto any_day = 2014_y/9/28;
// Get week of `any_day`
std::cout << "The week of " << any_day.year() << " on `any day` was: "
<< any_day.weeknum() << std::endl;
}
and the output is:
输出是:
The current week of 2019 is: W18
The week in 2014 on `any day` was: W09
回答by afull
/**********************************************************************************
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
***********************************************************************************/
回答by Steve Jessop
Use gmtime or localtime to calculate days since Sunday (that is, day of the week) and days since January 1 (note that Jan 1 is "0" in the latter).
使用 gmtime 或 localtime 计算自星期日(即一周中的某天)以来的天数和自 1 月 1 日以来的天数(注意后者中的 Jan 1 为“0”)。
The arbitrary bit is deciding what day of the year Week 1 starts on: usually it only depends what day of the week Jan 1 was, which of course you can calculate from the two pieces of information from gmtime. Then use a table lookup for the 7 possibilities, it's probably easier than coding the rules.
任意位决定了第 1 周在一年中的哪一天开始:通常它只取决于 1 月 1 日是一周中的哪一天,当然你可以从 gmtime 的两条信息中计算出来。然后使用表查找 7 种可能性,这可能比编写规则更容易。
For example, I think Outlook uses the standard that Week 1 is the first week containing a Thursday. So if Jan 1 is a Sunday, then the first day of Week 1 is Jan 1, or day 0. The remaining possibilities are Monday, -1; Tuesday, -2; Wednesday, -3; Thursday, -4; Friday, 2; Saturday, 1.
例如,我认为 Outlook 使用的标准是第 1 周是包含星期四的第一周。因此,如果 1 月 1 日是星期日,则第 1 周的第一天是 1 月 1 日或第 0 天。其余的可能性是星期一,-1;星期二,-2;星期三,-3;星期四,-4;星期五,2;星期六,1。
Note the negative numbers: "Sunday of week 1" doesn't actually exist in 4 out of 7 cases, but if we pretend it was a day back in the previous year, we'll get the right answer out.
注意负数:7 种情况中有 4 种情况实际上并不存在“第 1 周的星期日”,但如果我们假装它是前一年的某一天,我们就会得到正确的答案。
Once you have that, the number of days between it and your date tells you the week number: divide by 7 and add 1.
一旦你有了它,它和你的日期之间的天数就会告诉你周数:除以 7 再加 1。
That said, I imagine there's a Windows API somewhere that will give you the same week number that Outlook uses. I just don't know what it is, and of course if your Week 1 rules are different from Outlook's then it's probably not much use.
也就是说,我想有一个 Windows API 可以为您提供与 Outlook 使用相同的周数。我只是不知道它是什么,当然,如果您的第 1 周规则与 Outlook 的不同,那么它可能没有多大用处。
Untested code:
未经测试的代码:
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;
Something like that, anyway.
反正就是这样。
回答by Arun Rao
This is my solution but it's not in C++
这是我的解决方案,但它不在 C++ 中
NoOfDays = (CurrentDate - YearStartDate)+1
IF NoOfDays MOD 7 = 0 Then
WeekNo = INT(NoOfDays/7)
ELSE
WeekNo = INT(NoOfDays/7)+1
END