Hello, does anyone have a function to calculate ISO week numbers, the xHarbour WEEK() is not returning the correct ISO week number.
Thank you,
Hello, does anyone have a function to calculate ISO week numbers, the xHarbour WEEK() is not returning the correct ISO week number.
Thank you,

Uwe,
the program date_e is not working correctly.
I detected several mistakes.
Today, 12/30/2008 is already part of the ISO week no. 1 of 2009.
Your program claims it's week no. 53 of 2008, which is wrong.
Regards,
Detlef
FUNCTION FT_WOY(dInDate)
LOCAL nFirstDays, nDayOffset, nWkNumber, cCentury
IF VALTYPE( dInDate) <> "D"
nWkNumber := NIL
ELSE
// resolve century issue
IF LEN(DTOC(dInDate)) > 8 // CENTURY is on
cCentury := SUBSTR( DTOC( dInDate) ,7 ,4)
ELSE
cCentury := SUBSTR( DTOC( dInDate) ,7 ,2)
ENDIF
// find number of days in first week of year
nFirstDays := 8 - (DOW(CTOD("01/01/" + cCentury)))
nWkNumber := 1
// find how many days after first week till dInDate
nDayOffset := (dInDate - CTOD ("01/01/" + cCentury)) - nFirstDays + 1
// count weeks in offset period
DO WHILE nDayOffset > 0
++nWkNumber
nDayOffset -= 7
ENDDO
ENDIF
RETURN(nWkNumber)Regards,
Michel D.
Genk (Belgium)
I use : FiveWin for (x)Harbour v. 25.12 - Harbour 3.2.0 (May 2025) - xHarbour Builder (January 2020) - Bcc773
Thank You for your reply, however this function returns an invalid week of 53 for date 12/29/2008 which is week 1 for 2009
Hello Darrell,
I noticed, that nearly all date-calculations don't take care of a LEAP-YEAR. I will check this, maybe that is the reason for wrong calculations.
February 29, 2008
The year 2008 is a leap year. If you look at a 2008 calendar, you will see that February has five Fridays–the month begins and ends on a Friday. Between the years 1904 and 2096, leap years that share the same day of week for each date repeat only every 28 years. The most recent year in which February comprised five Fridays was in 1980, and the next occurrence will be in 2036. February 29, the leap day, has been associated with age-old traditions, superstitions and folklore.
What is a leap year?
A leap year is a year in which one extra day has been inserted, or intercalated, at the end of February. A leap year consists of 366 days, whereas other years, called common years, have 365 days.
Regards
Uwe ![]()
Hi Uwe,
Here is VBA code I found, does this help? Can you translate this to FWH?
//------------------------------------------------------------------------------------------
Public Function ISOWeekNum(AnyDate As Date, _
Optional WhichFormat As Variant) As Integer
'
' WhichFormat: missing or <> 2 then returns week number,
' = 2 then YYWW
'
Dim ThisYear As Integer
Dim PreviousYearStart As Date
Dim ThisYearStart As Date
Dim NextYearStart As Date
Dim YearNum As Integer
ThisYear = Year(AnyDate)
ThisYearStart = YearStart(ThisYear)
PreviousYearStart = YearStart(ThisYear - 1)
NextYearStart = YearStart(ThisYear + 1)
Select Case AnyDate
Case Is >= NextYearStart
ISOWeekNum = (AnyDate - NextYearStart) \ 7 + 1
YearNum = Year(AnyDate) + 1
Case Is < ThisYearStart
ISOWeekNum = (AnyDate - PreviousYearStart) \ 7 + 1
YearNum = Year(AnyDate) - 1
Case Else
ISOWeekNum = (AnyDate - ThisYearStart) \ 7 + 1
YearNum = Year(AnyDate)
End Select
If IsMissing(WhichFormat) Then
Exit Function
End If
If WhichFormat = 2 Then
ISOWeekNum = CInt(Format(Right(YearNum, 2), "00") & _
Format(ISOWeekNum, "00"))
End If
End Function
//------------------------------------------------------------------------------------------
Function YearStart(WhichYear As Integer) As Date
Dim WeekDay As Integer
Dim NewYear As Date
NewYear = DateSerial(WhichYear, 1, 1)
WeekDay = (NewYear - 2) Mod 7
If WeekDay < 4 Then
YearStart = NewYear - WeekDay
Else
YearStart = NewYear - WeekDay + 7
End If
End Function
nIsoWeek := Week (Date(), .f.)function IsoWeek (dDate)
LOCAL nWeek := 0, dDate2
dDate2 := dDate + 3 - ( DoW( dDate ) + 5 ) % 7
nWeek := Int (( DoY( dDate2 ) - 1 ) / 7 + 1)
return (nWeek)Stefan,
Thank you, the function IsoWeek function worked, the week( DATE(), .F.) did not work. Thank you for your help!!!
Sorry, I tested more dates and I found that the week number was not calculating correctly. Here are some examples
12/28/2008 - calculates to week 52, should be week 1
01/11/2009 - calculates to week 2, should be week 3
01/18/2009 - calculates to week 3, should be week 4
It is my understanding that the ISO week starts on a Sunday. Please correct me if I am wrong.
Hello Darrell,
It is not easy, to calculate this with just a simple function.
There are many things to do for a correct calculation.
You have to take care of the year-end before the calculated year and the start of the next year.
That is the problem, You figured out :
Get week number 1 to 53 of the year this date falls in, according to
the rules of ISO standard IS−8601 section 5.5. A week that lies partly
in one year and partly in another is assigned a number in the year in
which most of its days lie. This means that week 1 of any year is the
week that contains 4 January, or equivalently week 1 of any year is
the week that contains the first Thursday in January. Most years have
52 weeks, but years that start on a Thursday and leap years that start
on a Wednesday have 53 weeks. Jan 1 may well be in week 53 of the
previous year! Only defined for dates on or after 1600 Jan 01.
I'm on the way, to find a solution for FWH.
Regards
Uwe ![]()
Hi Uwe, I really appreciate your assistance!!!


ISO_WN( y, m, d )
{
dow = DOW( y, m, d );
dow0101 = DOW( y, 1, 1 );
if ( m == 1 && 3 < dow0101 < 7 - (d-1) )
{
// days before week 1 of the current year have the same week number as
// the last day of the last week of the previous year
dow = dow0101 - 1;
dow0101 = DOW( y-1, 1, 1 );
m = 12;
d = 31;
}
else if ( m == 12 && 30 - (d-1) < DOW( y+1, 1, 1 ) < 4 )
{
// days after the last week of the current year have the same week number as
// the first day of the next year, (i.e. 1)
return 1;
}
return ( DOW( y, 1, 1 ) < 4 ) + 4 * (m-1) + ( 2 * (m-1) + (d-1) + dow0101 - dow + 6 ) * 36 / 256;
}FUNCTION ISO_WEEKNR( y, m, d )
// Year/month/day
// Sample : ISO_WEEKNR(08,12,29)
y1 := PADL( STR(y), 2, "0")
y2 := PADL( STR(y - 1), 2, "0")
Y3 := PADL( STR(y + 1), 2, "0")
m1 := PADL( STR(m), 2, "0")
d1 := PADL( STR(d), 2, "0")
date1 := CTOD ( '"'+ y1 + "." + m1 + "." + d1 + '"' ) // Test : 08.12.29
date2 := CTOD ( '"'+ y1 + ".01.01" ) // 08.01.01
date3 := CTOD ( '"'+ y2 + ".01.01" ) // 07.01.01 Year before
date4 := CTOD ( '"'+ y3 + ".01.01" ) // 09.01.01 Year after
dow1 := DOW( date1 )
dow0101 := DOW( date2 )
if ( m == 1 && 3 < dow0101 < 7 - (d-1) ) // To be translated !!!
// days before week 1 of the current year have the same week number as
// the last day of the last week of the previous year
dow1:= dow0101 - 1
dow0101 := DOW( date3 )
m := 12
d := 31
ELSE
IF ( m == 12 && 30 - (d-1) < DOW( date4 ) < 4 ) // To be translated !!!!
// days after the last week of the current year have the same week number as
// the first day of the next year, (i.e. 1)
return 1
ENDIF
ENDIF
RETURN ( DOW( date2 ) < 4 ) + 4 * (m-1) + ( 2 * (m-1) + (d-1) + dow0101 - dow1 + 6 ) * 36 / 256cdmmaui wrote:Sorry, I tested more dates and I found that the week number was not calculating correctly. Here are some examples
12/28/2008 - calculates to week 52, should be week 1
01/11/2009 - calculates to week 2, should be week 3
01/18/2009 - calculates to week 3, should be week 4
It is my understanding that the ISO week starts on a Sunday. Please correct me if I am wrong.
First day of the week
In most of Europe, and some other countries, Monday is considered to be the first day of the week. Monday is literally named as such in Baltic languages, for example Lithuanian (pirmadienis - means First Day); in Estonian (esmaspäev - means First Day); Hungarian (hétfő - means literally Head of The Seven/Week); Basque (astelehen - means Week-First) and Mandarin (pinyin Xīngqà Yī, literally means Weekday One). In Slavic languages, Tuesday, Thursday and Friday were named literally for their number after Monday[5], a meaning still conserved in Russian (for example Tuesday: вторник - vtórnik - means second).
The ISO prescribes Monday as the first day of the week with ISO 8601 for software date formats.
In Jewish, Arab, Western Christian and Greek Orthodox tradition, the first day of the week is Sunday. The Hebrew, Ecclesiastical Latin and Medieval and Modern Greek languages number most of the days of the week. In Hebrew, Sunday through Friday are numbered one through six; in Arabic, Sunday through Thursday are numbered one through five; in Ecclesiastical Latin and modern Portuguese, Monday through Friday are numbered the second through the sixth days of the week (feria in Latin or feira in Portuguese); in Medieval and Modern Greek, Monday through Thursday are numbered the second through fifth. For many Western Christians and Jews, Sunday remains the first day of the week. Most, though not all, business and social calendars in North America mark Sunday as the first day of the week.
Thank you for the clarification