Introduction
In .NET the DateTime
class is implemented using Gregorian calendar.
Sometimes, we need to extend the capabilities of this DateClass
class.
For example, if we wanted to know the ISO 8601 week number of the year, we need to
create a new class for this implementation, as we can't extend the DateTime
class. The following class DateEx
written in C# is used to convert
a date from Gregorian Calendar to ISO formatted date.
ISO-8601 defines the week as starting with Monday and ending with Sunday,
i.e., Monday is weekday 1 and Sunday is weekday 7. The first week of a year
is the week, which contains the first Thursday of the Gregorian year;
and the week containing January 4th. Week numbers in ISO 8601 are integers
from 1 to 52 or 53; parts of week 1 may be in the previous calendar year;
parts of week 52 may be in the following calendar year; and if a year has
a week 53, parts of it must be in the following calendar year.
The correct way to represent a week in ISO 8601 format is YYYY-WW.
For example, in the year 2002, the ISO week 1 began on Monday December 31st,
2001; and the last ISO week (week 53) ended on Sunday January 2nd, 2003.
Therefore, December 31st, 2001, is in the ISO week 2002-01; and January 2nd,
2003, is in the ISO week 2002-53.
Following is the code for DateEx
. It contains four static
functions; ISOWeekNumber, WeekDay, IsLeapYear, DisplayISODate.
using System;
public class DateEx {
public static bool IsLeapYear(int yyyy) {
if ((yyyy % 4 == 0 && yyyy % 100 != 0) || (yyyy % 400 == 0))
return true;
else
return false;
}
public static int ISOWeekNumber(DateTime dt) {
int yyyy=dt.Year;
int mm=dt.Month;
int dd=dt.Day;
int DayOfYearNumber;
int Jan1WeekDay;
int WeekNumber=0, WeekDay;
int i,j,k,l,m,n;
int[] Mnth = new int[12] {0,31,59,90,120,151,181,212,243,273,304,334};
int YearNumber;
DayOfYearNumber = dd + Mnth[mm-1];
if ((IsLeapYear(yyyy) == true) && (mm == 2))
DayOfYearNumber += 1;
i = (yyyy - 1) % 100;
j = (yyyy - 1) - i;
k = i + i/4;
Jan1WeekDay = 1 + (((((j / 100) % 4) * 5) + k) % 7);
l= DayOfYearNumber + (Jan1WeekDay - 1);
WeekDay = 1 + ((l - 1) % 7);
if ((DayOfYearNumber <= (8 - Jan1WeekDay)) && (Jan1WeekDay > 4))
{
YearNumber = yyyy - 1;
if ((Jan1WeekDay == 5) || ((Jan1WeekDay == 6) && (Jan1WeekDay > 4)))
WeekNumber = 53;
else
WeekNumber = 52;
}
else
YearNumber = yyyy;
if (YearNumber == yyyy)
{
if (IsLeapYear(yyyy)==true)
m = 366;
else
m = 365;
if ((m - DayOfYearNumber) < (4-WeekDay))
{
YearNumber = yyyy + 1;
WeekNumber = 1;
}
}
if (YearNumber==yyyy) {
n=DayOfYearNumber + (7 - WeekDay) + (Jan1WeekDay -1);
WeekNumber = n / 7;
if (Jan1WeekDay > 4)
WeekNumber -= 1;
}
return (WeekNumber);
}
public static int WeekDay(DateTime dt) {
int yyyy=dt.Year;
int mm=dt.Month;
int dd=dt.Day;
int DayOfYearNumber;
int Jan1WeekDay;
int WeekDay;
int i,j,k,l;
int[] Mnth = new int[12] {0,31,59,90,120,151,181,212,243,273,304,334};
DayOfYearNumber = dd + Mnth[mm-1];
if ((IsLeapYear(yyyy) == true) && (mm == 2))
DayOfYearNumber += 1;
i = (yyyy - 1) % 100;
j = (yyyy - 1) - i;
k = i + i/4;
Jan1WeekDay = 1 + (((((j / 100) % 4) * 5) + k) % 7);
l= DayOfYearNumber + (Jan1WeekDay - 1);
WeekDay = 1 + ((l - 1) % 7);
return WeekDay;
}
public static string DisplayISODate(DateTime dt) {
string str;
int year,weekday,weeknumber;
year=dt.Year;
weeknumber = ISOWeek(dt);
weekday = WeekDay(dt);
str = year.ToString("d0") + "-" + weeknumber.ToString("d0")
+ "-" + weekday.ToString("d0");
return str;
}
}
Now converting Gregorian Date to ISO Date is very easy.
using System;
using System.Globalization;
public class DateImpl {
public static void Main() {
try {
DateTime dt=new DateTime(2002,12,1);
Console.WriteLine("Gregorian Date : {0}",
dt.ToString("d", DateTimeFormatInfo.InvariantInfo));
Console.WriteLine("ISO Date : {0}",DateEx.DisplayISODate(dt));
}
catch(Exception e) {
Console.WriteLine("Error \n\n {0}", e.ToString());
}
}
}
This class can be easily extended to handle needs for other calendars such as
Julian, Indian Civil Calendar etc.