Windows' Wrong Week information

By Egbert Zijlema, journalist and programmer

Some time ago there was a discussion on week numbers in Power Basic's peer-to-peer forums. It prompted me to do some digging in Windows and its Application Programming Interface (API). The conclusion of my survey is rather discouraging. I found that the Windows API returns a wrong first-week-of-the-year value for quite a number of member states in the European Union, such as the United Kingdom, Belgium, France, Spain and Portugal. The wrong Locale settings, found in Windows XP (both Home and Pro Edition) – service packs 1, 2 and 3 – may seriously mislead programmers, for instance if they have planned to implement week numbers in their applications.

During my survey on this subject, it became obvious that Windows returns a wrong "first week" under several Regional Settings, especially for countries in the European Union. In this article Belgium - more specifically Flanders - and Spain have a special position, since two fellow-programmers from those countries were so kind to check some relevant calendar information. So I can be 100 percent sure (see: Further reading, below). The conclusions drawn for the other three countries mentioned here are my own. They are based upon the results of a tiny, self-written application that ran on my own computer with the Dutch language version of Windows XP Professional installed.

GetLocaleInfo

What I found forced me to rewrite the week number routine in my Gregorian Calendar Library. The API-function to retrieve regional information from the system is GetLocaleInfo. Parameters passed through this function are: a country/language specific Locale and a specifier, referred to as LCType. In order to retrieve information on the first week of the year, a programmer should pass %LOCALE_IFIRSTWEEKOFYEAR (= &H0000100D) as LCType. Here is the (pseudo) code:

GetLocaleInfo CountrySpecificLocale, %LOCALE_IFIRSTWEEKOFYEAR, szRetVal, SIZEOF(szRetVal)

According to Microsoft's Platform SDK Collection, this call will return one of the following values:

0 Week containing January 1 is the first week of the year
1 First full week following January 1 is the first week of the year
2 First week containing at least four days is the first week of the year

It will return one of the above mentioned values; no question about that. But what should it return? In countries that follow the rules set by the International Organisation for Standardization (ISO) the answer to this question is not difficult. ISO rule 8601:2004 says: week number 1 is the week that contains the first Thursday of the year. Given that in these countries Monday is considered to be the first day of the week, this rule implies that the first January-week containing at least four days in the new year (Thursday to Sunday inclusive) is the first week of the year. In other words: a call to GetLocaleInfo, passing %LOCALE_IFIRSTWEEKOFYEAR as the specifier, should return 2 when the country/language specific Locale represents a country that follows ISO rule 8601:2004. I've tested this for several countries in the European Union and in many cases my call to GetLocaleInfo returned 0(!), not 2.

Having found these wrong data, and just to be 100 percent sure, I've asked the Power Basic community to check a few local calendar issues, such as: How are week numbers implemented on printed calendars? Two fellow-programmers, José Roca from Spain and Eddy Van Esch from Flanders, were so kind as to respond. Both Spanish and Flemish calendars are correctly printed in line with ISO-8601:2004, which means week number 1 is the week that contains the first Thursday of the year. This remote finding implicitly proves that the value returned by GetLocaleInfo for the first week of a given year is not correct for these countries. Thanks José and Eddy. Your help has been much appreciated.

Month calendar control

So far, so bad: the Windows API sometimes returns wrong calendar information on the first-week-of-the-year issue. What next? Well, another big surprise comes from the "Redmond-gang". Microsoft appears to speak with two tongues sometimes. The coders who created the GetLocaleInfo API obviously got it wrong at this point. Their colleagues who wrote the month calendar control (SysMonthCal32) for the common controls library (Comctl32.dll, version 4.70 and later) introduced the MCS_WEEKNUMBERS style. Microsoft's Platform SDK Collection states about this attribute: "The month calendar control will display week numbers (1-52) to the left of each row of days. Week 1 is defined as the first week that contains at least four days". This is very, very close to ISO-8601:2004. In fact, it will create month calendar sheets with correct ISO-8601:2004 week numbers in all those countries that follow the ISO rule and thus consider Monday to be the first day of the week (provided Regional Settings have been correctly set at this point).

The really strange thing - in my opinion - is that the first-week-of-the-year setting from the system and the one used by the common calendar control do not match, although both have been created by the same think tank.

Despite intensive searches across the World Wide Web, I did not find any Microsoft paper or article dealing with this discrepancy, so maybe this is not a known, or at least a neglected, issue in Redmond?

Gregorian Library

Finally a few words about my Gregorian Library routines. There was a week number routine in the previous version. It used the first-week-of-the-year setting as returned by GetLocaleInfo to calculate weeknumber 1, causing wrong results in several countries, e.g. Belgium and Spain. I therefore created the possibility to let the programmer replace the valid Locale by a negative value (-1), in order to force an ISO-proof week enumeration. This feature is still on board (it does no harm, after all), but normally the function now follows Windows' month calendar control (MCS_WEEKNUMBERS style) and connects week number 1 to the first week in January that counts four days or more.

Further reading: Week of Day? and Allow me to repeat my question?
Download: Gregorian.zip.

Valid HTML 4.01!