ISO Week Numbering

The ISO week date system is a leap week calendar system that is part of the ISO 8601 date and time standard. The system is used (mainly) in government and business for fiscal years, as well as in timekeeping.

This script is an example of how to calculate the week number for any given date.

//  ISO Week Numbering

/*
Tony Goodman
*/

int dayNumber(string day)
{
	// return the number of the day (starting from 1, not zero)
	string days[] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }

	int i = 0

	for (i = 0; i < sizeof(days); i++)
	{
		if (day == days[i]) break
	}

	return(i + 1)
}

bool isLeapYear(int yyyy)
{
	// return true if the given year is a leap year
	if (yyyy % 4 != 0)
	{
		return(false)
	}

	if (yyyy %100 != 0)
	{
		return(true)
	}

	if (yyyy % 400 != 0)
	{
		return(false)
	}

	return(true)
}

bool yearHas53Weeks(int yyyy)
{
	// normal years starting on a thursday and leap years starting on a Wednesday have 53 weeks

	Date firstJan = null
	string firstJanDay = ""

	firstJan = "01 January " (yyyy) ""
	firstJanDay = stringOf(firstJan, "dddd")

	// normal years starting on a thursday and leap years starting on a Wednesday have 53 weeks
	if ((isLeapYear(yyyy) && firstJanDay == "Wednesday") ||
		(firstJanDay == "Thursday"))
	{
		return(true)
	}

	return(false)
}

void getISOWeekNumber(Date dt, int &week, int &year)
{
	// number of days in preceeding months jan - dec
	int months[13] = {0,31,59,90,120,151,181,212,243,273,304,334};

	// extract day month and year as integers
	string dateString = stringOf(dt, "ddMMyyyy")
	string weekDay = stringOf(dt, "dddd")
	int dd = intOf(dateString[0:1])
	int mm = intOf(dateString[2:3])
	int yyyy = intOf(dateString[4:7])

	// ordinal position of day in the year
	int ordinal = dd + months[mm - 1]

	// correction for leap years
	if (isLeapYear(yyyy) && ordinal >= 59)
	{
		ordinal += 1
	}

	// calculate ISO week number
	week = (ordinal - dayNumber(weekDay) + 10) / 7

	// set return value. this may change later
	year = yyyy

	if (week == 0)
	{
		// this week is in the previous year, maybe 52 or 53
		year = yyyy - 1

		if (yearHas53Weeks(yyyy - 1))
		{
			week = 53
		}
		else
		{
			// all other years have 52 weeks
			week = 52
		}
	}
	else if (week == 53)
	{
		// this is either week 53 of the current year, or week 1 of the following year
		if (yearHas53Weeks(yyyy))
		{
			week = 53
		}
		else
		{
			// the year has 52 weeks, so the day is in the first week of the following year
			week = 1
			year = yyyy + 1
		}
	}
}

int week = 0
int year = 0
Date d = "01 January 2005"

getISOWeekNumber(d, week, year)

print(year " " week "\n")