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.
An algorithm would be great to get me started and sample code would also help - I'm developing in C++ on Windows.
This is my solution but it's not in C++
Be aware that while your definition of nth week of the year is tenable, it is also not 'the' standard one.
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.
[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.]
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.
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 '}
'.For completeness, the inverse function is also easy to write with the
day_one_week_one()
function above:As noted in the comments, the code will accept a week 53 date even if the year should only accept 52 weeks.
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).
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.
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.
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.
Once you have that, the number of days between it and your date tells you the week number: divide by 7 and add 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.
Untested code:
Something like that, anyway.
struct tm is used to represent "broken down time" and has at least the following fields:
You can create a struct tm from a time_t with the localtime() function.
You can create a time_t from a struct tm with the mktime() function.
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)...
Pseudocode:
To clarify, this algorithm assumes you number your weeks like this:
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.
If you're going to implement your own date counting routines, remember that years that are divisible by 100 are NOT leap 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 Wikipedia for loads of info on that.
This link talks about date/time functions in Windows/C++ in greater detail.