Introduction
In many cases developers have a demand of calculation and manipulations with business dates. Standard tasks are usually the following:
- Calculate next business date from current date.
- Calculate previous business date from current date.
- Calculate a date in future or in past that is distant from current date by several business days.
- Check if current date is a working day or holiday and so on.
Formally, business dates set is a subset of calendar dates that doesn�t include such dates as weekend days and holidays. Business dates and business periods are often used for defining dates concerning to business agreements, so the term of Business Date is very famous and widely utilized.
Therefore it seems to be very useful having a standard way to manipulate business dates.
XDateTime C# class described in this article is an applied class that provides a basic functionality for business date manipulations and calculations.
Purpose
Commonly speaking, Microsoft .NET Framework Library already contains the DateTime class that provides quite a lot functionality for manipulating dates. But, as already mentioned, there is no functionality for calculation of business dates. Thus, the basic idea of XDateTime class was not to repeat what we already have in the standard DateTime but to expand its features to cover business date operations.
Here comes the purpose of the XDateTime. Use the XDateTime class in cases where you require additional functionality with business dates manipulation than that provided by the standard System.DateTime type from the Microsoft .NET Framework. XDateTime class doesn�t repeat any functionality that already exists in the System.DateTime type. So, there is no reason to use the XDateTime instead of the System.DateTime. Use them together to extend existing features of the System.DateTime type.
Basic Approach
Basically, the XDateTime is a wrapper for the standard DateTime. XDateTime contains an instance of the DateTime type as a private class member variable and performs almost all the operations using this private variable. All the functionality of working with business dates is exposed as several public methods. Also some properties are provided for utility purpose.
Primary Calculations
As a matter of fact, we only need to perform two basic calculations: calculate the next business date from the given date, and the previous business date. In order to calculate an arbitrary business date from the given date, we can just repeat one of the mentioned basic calculations as many times as needed.
In that way calculating business dates actually means moving consequently along the time axis forth or back with a step of a single day, skipping weekends and holidays.
Hence, the corner stone in the business date calculation is of knowing exactly the holidays that should be excluded from the calendar dates set. Thus XDateTime contains a special method that initiates a list of holidays used for calculations.
Meet XDateTime
At last it's time to take a closer look at the XDateTime class itself. You can get the entire XDateTime code from the zipped Visual Studio .NET solution provided above. Here, let's consider only the key parts of the XDateTime implementation that prove the basic assumptions.
Member Variables
XDateTime contains several private member variables used for calculations:
public enum XDateTimeType { Calendar=0, Business=1 };
public class XDateTime
{
private DateTime _date;
private XDateTimeType _type;
private Hashtable _holidays;
...
}
Here I define an enumeration XDateTimeType and use a private _date member of the standard DateTime type. The standard Hashtable is used for storing a holiday list.
Constructors
For convenience, I include three constructors for class instantiation:
public XDateTime();
public XDateTime(string dateTime);
public XDateTime(string dateTime, XDateTimeType dateType);
Main Logic
First of all, we have to determine whether the current date is a business day. As we already mentioned business dates don�t include weekends and holidays. So, the result of the following logic expression is an answer to the question Is a Business Day?:
!(_date.DayOfWeek == DayOfWeek.Saturday ||
_date.DayOfWeek == DayOfWeek.Sunday || this.IsHoliday)
where AddDays and DayOfWeek are standard features of the DateTime class, and IsHoliday is defined using a standard method of the Hashtable.
_holidays.ContainsValue(_date.ToString())
Now we can find the next and previous business dates.
Next business date:
do
{
date = date.AddDays(1.0);
}
while (date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday ||
_holidays.ContainsValue(date.ToString(_format)));
And previous business date:
do
{
date = date.AddDays(-1.0);
}
while (date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday ||
_holidays.ContainsValue(date.ToString(_format)));
As you can see, I repeat adding or subtracting a day until it's not a business date according to my definition. Actually that's it. The only detail else I want to mention is it's very useful to define a helper private method of checking the current date against the business date definition and use this method every time I change a date. We can do it like the following:
private void check()
{
if (_type == XDateTimeType.Business && !this.IsWorkDay)
{
_date = this.NextBusinessDay();
}
}
It is very important to notice that I slide the date over only forward, not backward. That's pretty obvious; if you change a date, say add five days, and after changing, the resulting date is not a business date, the date should be implicitly changed to the next business date.
Conclusion
In this article, I have shortly described a simple approach of business date calculation. I have to mention that this approach has been used in a real development project and showed the total accuracy of it. In real life you may want to adapt the XDateTime class for your requirements, like reading a holiday list from a database or something else. You can do it easily using the source code provided. And please feel free to discuss any questions and suggestions you might have made with me.
| You must Sign In to use this message board. |
|
|
 |
|
 |
hi all..... I want to make an application that will run in server and will keep track the net usage of clients with out installing any client side application. like hotspot programs when any user opens IE a default login page will come and the user with right user name and password can only do the browsing......... can any body help me how to create this type of application.. check antamedia hotspot application for details
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I just started to learn C#, can anyone give me details on how to start, books to read that can really guide through my learning. Hope to Hear from you as soon as possible.
Trying to get my self in the world of programming
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
 |
Well, you're right. So this is why the source code is provided. Just get it, customize it, use it. It's that simple.
Alexander Turlov Software development consultant, MCSD.NET
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
 |
I tried out your source code sample. If you choose a day which is a saturday, a sunday or an holiday in XDateTimeTest.cs as sDate, the next business day is calculated incorrectly (+ 1 day). This is because if you initiate your date:
XDateTime sDate = new XDateTime(date.ToString(), XDateTimeType.Business);
you get in check(). There you check, if the date you initiated, is a saturday, a sunday or an holiday. In this case the date is set to the next business day, because it is one of these days:
private void check() { if (_type == XDateTimeType.Business && !this.IsWorkDay) { _date = this.NextBusinessDay(); } }
To correct this problem you should not call check() while initiating the date:
public XDateTime(string dateTime, XDateTimeType dateType) { init(Convert.ToDateTime(dateTime), dateType); check(); <-- This is the problem!!! }
If you don't call check() the next Business Day is calculated correctly!
Stefan
|
| Sign In·View Thread·PermaLink | 1.00/5 |
|
|
|
 |
|
 |
Hello Stefan,
thanks for your posting. You're right with the code analisys. Particularly that the private method check() is responsible for changing a date if it should be changed. But you are wrong in your evaluation that this is an error. It's a logic of the XDateTime class how it is meant by me to work. Also it's been described in the article that when you instanciate an XDateTime object using XDateTimeType.Business mode and the date you start from is not a business date then the XDateTime changes itself to the next business day. It's pretty obvious why. 'Cause XDateTime works in a Business mode it simply can not contain a date that is not a business date. That is why when you use Saturday for instance, for initiating XDateTime in Business mode then it changes to Monday. After that if you call NextBusinessDay() it will obviously return Tuesday to you.
But you can change the code provided as you want accordingly to your needs.
So, in conclusion I'd like to mention once again that there is no wrong code. There are different requirements.
Alexander Turlov Software development consultant, MCP
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
 |
Thanks for your reply! You are right there are different requirements. I needed to get the next business day. If the date I have entered was a saturday, I would get Tuesday, but for my needs it would be Monday. So I changed the code and it works perfectly for me. I thought it would be an error, but for your point of view you're right! But anyway the main thing is, that it is working! Thanks a lot!
Stefan
|
| Sign In·View Thread·PermaLink | 1.00/5 |
|
|
|
 |
|
 |
Great Stefan! Way to go! But I just want to give you a little point. May be you can use original XDateTime in Calendar mode. In that case it will work exactly as you want: you initiate it with Saturday and the next business day will be Monday. Simply take it in the consideration. Anyway, I'm glad it works for you. Good luck!
Alexander Turlov Software development consultant, MCP
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
 |
I see people rate my article, but I don't see your comments. So if you rate my articel I'll apreciate very much if you put a comment: what you like and what you don't like. You are welcome! And thanks in advance for your feedback.
Alexander Turlov Software development consultant, MCP
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hello Alexander,
Thanks for that useful class. It will help me a lot in my current development. I would like to have your input on how I can easily add a function in your class, to be able to calculate the number of business day between two date.
Thanks,
Sebastien
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi Sebastien,
Thank you for your good feedback. I'm glad that my hamble work could help you in your job. I would solve your task in easy way like the following. Add the following public method to the class:
public int NumberOfBusinessDaysFrom(DateTime date) { double dayToAdd = -1; int numberOfBusinessDays = 0;
if (date < _date) { dayToAdd = 1; } while ( _date != date ) { date = date.AddDays(dayToAdd); if (!(date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday || _holidays.ContainsValue(date.ToString(_format)))) { numberOfBusinessDays++; } } return numberOfBusinessDays; } and then call it in your code like the following:
XDateTime sDate = new XDateTime(DateTime.Today.ToString(), XDateTimeType.Business); DateTime date = new DateTime(2005, 5, 1); Console.WriteLine("Between Today and {0} there are {1} business days.", date, sDate.NumberOfBusinessDaysFrom(date)); You can adjust the code above for your needs. Hope it'll help.
Alexander Turlov Software development consultant, MCP
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I've also updated the demo project. Now it includes the new method NumberOfBusinessDaysFrom and corresponding sample of calling this method. Thank you Sebastien once again for a good idea.
Alexander Turlov Software development consultant, MCP
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi Alexander - good article
do you think there are any mathematical ways of doing the same versus this iterative method ?? it occurs to me that if the # days was larger than (maybe 7, ie a week), a pure mathematical method could be formulated (although everything Ive seen does iterate) ..
my thinking goes alone the lines of :-
lets assume we start on Wednesday 6th April, and Im asked to calulate 14 business days from then (Im going to cheat and only go 'forward' for this example)
a rough calulation would go
6th April (as Julian or 'linear' date) - note, there's a number of assumptions here ! plus 14 days requested plus 2 days for every weekend plus any holidays
ok,
so we have 96 (day # since the start of the year, just for a quick test) plus 14 days requested plus ((14 div 7 (integer arithmetic)) = # Weekends) * 2 (=4 calendar days) plus 1 holiday (April 25th is a public holiday here)
which would end up on 115 (April 25th, which is the holiday) - but since we started with 96 being April 6th, in reality I think you'd start from 'the next day', ie the 7th or '97' and then you'd end up on 116 - April 26th, which is more what I had thought if I simply traced it on a calendar
It points out that one would have to be careful about the start and end of a business day (hence once of the assumptions mentioned in the rough method) and what you mean when you says '14 business days from today' for example - do you mean to start counting from the end of the current business day or what ? what happens if you start on a Saturday for example ??
I have seen long discussions about when you start the 14 day period from, there doesnt appear to be a standard ...
maybe one could do something like :-
Julian date (Today) (plus 2 if Today = Saturday, 1 if Today = Sunday, or n public holidays) plus 14 days requested plus 2 days for every weekend plus any holidays
it seems the iterative method solves some of the issues with the caluclatiuon method, at the expense of looping for potentially a large number of iterations !!
anyway, thanks for your article ...
Garth
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
 |
Hello Garth,
thank you for your feedback. I completely agree with you on that it's possible to formulate some mathematical way to achieve the same result. But when I was thinking that algorithm out the main requirements for me were: quick development of the code, and simple and reliable testing of the code. So that's pretty obvious why I choose iterative methods instead of exact mathematical calculations. I even can say more. I did try to develop some math for that but I met the problem of huge numbers of different scenarios of calculations with lots of exclusions and it has been practically impossible to reliably test all that mess. But I think there is a condition for researching a good math way. When you are doing lots of heavy cyclic calculations it's definitely better not to use iterative approach. Luckily it's been not my case. So wish you good luck and I would like to participate in your research if it could be helpful.
Alexander Turlov Software development consultant, MCP
|
| Sign In·View Thread·PermaLink | 1.00/5 |
|
|
|
 |
|
 |
Alexander Turlov wrote: met the problem of huge numbers of different scenarios of calculations with lots of exclusions
agreed .. I think I'll take the approach of
1) looking at how everyone else defines 'business day' 2) how commercial software defines/handles terms & exclusions
then see if I can apply a simple way of modelling that...
Thanks, Garth
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hmmmm,
I would also be interested in how commercial software calculates business days. However, in my case a simple looping will do the trick. It is simple, and it works.
There are a few examples of more complex business day calculation algorithms around - but I have found many bugs!!!!!
Thanks
|
| Sign In·View Thread·PermaLink | 3.71/5 |
|
|
|
 |
|
|