Algorithm for Converting Gregorian Dates to ISO 8601 Week Date
(Y2K Compliant)
Rick McCarty, 1999
From: Gregorian Year-Month-Day
To: ISO YearNumber-WeekNumber-Weekday
ISO 8601 specifies that Week 01 of the year is the week containing
the first Thursday; Monday is Weekday 1, Sunday is Weekday 7;
WeekNumber requires two digits (W01, W02, etc.; "W" is optional)
Algorithm Conventions:
"/" = integer division, discard remainder (5/2 = 2)
"%" = modulus, keep only remainder (5%2 = 1)
"&" = concatenation ("W" & 12 = "W12")
"!=" = unequal (7 != 8 is true)
"+=" = add right value to left variable,
if F = 3, then (F += 4) yields F = 7
"-=" = subtract right value from left variable
1. Convert input to Y M D
Y = Year (full specification; input 98 = year 0098)
M = Month (1 through 12)
D = Day (1 through 31)
2. Find if Y is LeapYear
if (Y % 4 = 0 and Y % 100 != 0) or Y % 400 = 0
then
Y is LeapYear
else
Y is not LeapYear
3. Find if Y-1 is LeapYear
4. Find the DayOfYearNumber for Y M D
Mnth[1] = 0 Mnth[4] = 90 Mnth[7] = 181 Mnth[10] = 273
Mnth[2] = 31 Mnth[5] = 120 Mnth[8] = 212 Mnth[11] = 304
Mnth[3] = 59 Mnth[6] = 151 Mnth[9] = 243 Mnth[12] = 334
DayOfYearNumber = D + Mnth[M]
if Y is LeapYear and M > 2
then
DayOfYearNumber += 1
5. Find the Jan1Weekday for Y (Monday=1, Sunday=7)
YY = (Y-1) % 100
C = (Y-1) - YY
G = YY + YY/4
Jan1Weekday = 1 + (((((C / 100) % 4) x 5) + G) % 7)
6. Find the Weekday for Y M D
H = DayOfYearNumber + (Jan1Weekday - 1)
Weekday = 1 + ((H -1) % 7)
7. Find if Y M D falls in YearNumber Y-1, WeekNumber 52 or 53
if DayOfYearNumber <= (8-Jan1Weekday) and Jan1Weekday > 4
then
YearNumber = Y - 1
if Jan1Weekday = 5 or (Jan1Weekday = 6 and Y-1 is LeapYear)
then
WeekNumber = 53
else
WeekNumber = 52
else
YearNumber = Y
8. Find if Y M D falls in YearNumber Y+1, WeekNumber 1
if YearNumber = Y
then
if Y is LeapYear
then
I = 366
else
I = 365
if (I - DayOfYearNumber) < (4 - Weekday)
then
YearNumber = Y + 1
WeekNumber = 1
9. Find if Y M D falls in YearNumber Y, WeekNumber 1 through 53
if YearNumber = Y
then
J = DayOfYearNumber + (7 - Weekday) + (Jan1Weekday -1)
WeekNumber = J / 7
if Jan1Weekday > 4
WeekNumber -= 1
10. Output ISO Week Date:
if WeekNumber < 10
then
WeekNumber = "0" & WeekNumber (WeekNumber requires 2 digits)
YearNumber - WeekNumber - Weekday (Optional: "W" & WeekNumber)