![]() |
Languages »
VB.NET »
Applications
Intermediate
License: The Code Project Open License (CPOL)
VB.NET Class Library: Date WizardBy George B GilbertA toolkit that simplifies working with dates. |
VB, Windows, .NET, Visual Studio, Dev
|
|
Advanced Search Add to IE Search |
|
|
||||||||||||||||||
* There are two DLLs in the demo project's BIN folder: 2gs_datetextbox.dll and 2gs_extendedtextbox.dll. Click here to read about these user controls.

Demo project
Dates are strange beasts that do not lend themselves well to being handled in code. I'm probably preaching to the choir with that bold statement; however, if your experience is anything like mine, you've had to include dates in your applications often and doing any but the simplest tasks with dates has been challenging. The Date Wizard class library is intended to be a toolkit that simplifies many date-related tasks. The Date Wizard class library (2gs_datewizard.dll) houses three classes.
C_DateWizard: used to instantiate a date object. This class has nine constructors and exposes thirteen methods and forty three properties. C_DateFunctions: exposes eighteen standalone methods. C_DateInterval: used to return the calculation results from the C_DateFunctions CalcDateInterval method. The demo project is designed to illustrate the constructor options, methods and properties in both the date wizard and function classes. In the demo main window (shown above), you instantiate a date object using any of the nine constructor options. With a date object instantiated, you can click on the Properties button to see the values for all of the properties as well as change the first month in the object's fiscal year. The Methods button opens a window in which you can modify the date object's base date using any one of twelve methods. The only method that is not illustrated is ResetTimestamp.
The Date Functions button, which is available with or without a date object instantiated, opens another window that demonstrates the three date function methods that are not used either in the C_DateWizard class or the demo project. In this window, you can calculate the interval between two dates (years, months, weeks, and days), check if two date ranges overlap, and test whether or not a date lies within a date range. If you click on the Overlap and In Range buttons with none or only some of the dates filled in, you can see that these two methods do not require dates for any of their parameters.
I developed my first date wizard class in VB 6, with the intention of simplifying dates. That early date wizard, still available for download from my website, has proven to be popular. The date wizard offered with this article is the .NET successor of my original VB 6 class. This new date wizard has proven to be even more useful because it is locale aware. Dates are formatted as per the region settings in the operating system.
An important term you will find in this article is "base date." When a C_DateWizard object is instantiated, the primary property of that object is, of course, the object's date. This is referred to as the base date. Eight of the C_DateWizard property names start with "Base" to differentiate these properties from similar date properties in Visual Studio.
Follow these steps to make the 2gs_datewizard class library available in a project:
At the top of each class and module in which either the C_DateWizard or C_DateFunctions classes are consumed, add this statement:
Imports _2gs_datewizard
There are a plethora of examples in the demo project for consuming both the C_DateWizard and C_DateFunctions classes. Here is a sample from the Methods form. This is what happens when the Calc button is clicked. In this process, the DateStringOK and CalcDateInterval methods in the C_DateFunctions class are invoked. This code also demonstrates the use of the C_DateInterval class:
Private Sub btnCalc_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles btnCalc.Click
'--------------------------------------------------------------
' Date Developer Code Change
' ---------- -------------------- ----------------------------
' 03/21/2006 G Gilbert Original code
'--------------------------------------------------------------
'--------------------------------------------------------------
' The From date is required and must be a valid date
'--------------------------------------------------------------
Dim df As New C_DateFunctions
If Not df.DateStringOK(uctlFromDate.TextBox_Text, "From") Then
uctlFromDate.Focus()
df = Nothing
Exit Sub
End If
'--------------------------------------------------------------
' The Through date is required and must be a valid date
'--------------------------------------------------------------
If Not df.DateStringOK(uctlThroughDate.TextBox_Text, "Through") Then
uctlThroughDate.Focus()
df = Nothing
Exit Sub
End If
'---------------------------------------------------------------
' Calculate the interval
'---------------------------------------------------------------
Dim di As New C_DateInterval
di = df.CalcDateInterval(CType(uctlFromDate.TextBox_Text, Date), _
CType(uctlThroughDate.TextBox_Text, Date))
df = Nothing
'---------------------------------------------------------------
' Display the results and place the focus
'---------------------------------------------------------------
With di
lblYears.Text = .Years.ToString
lblMonths.Text = .Months.ToString
lblWeeks.Text = .Weeks.ToString
lblDays.Text = .Days.ToString
End With
di = Nothing
uctlFromDate.Focus()
End Sub
The C_DateWizard class affords nine constructor options. With the exception of the basic constructor which has no parameters, instantiating a date object with invalid parameters results in the base date defaulting to the current system date. You can find out whether or not the base date for a date object defaulted to the current date by querying the UsedDefaultDate property.
| Constructor option | Signature | Description |
| No parameters | Empty | Set the base date to the current date. |
| Date | Date |
Set the base date to the passed date. If the passed date is not valid, the base date defaults to the current date. |
| Month | Integer |
Set the base date to the first date in the month passed, defaulting the year to the current year. If baseMonth is invalid, the base date is set to the current date. |
| Month and year | Integer, Integer |
Set the base date to the first date in the month and year passed. If baseMonth or baseYear are invalid, the base date defaults to the current date. |
| Month, day, and year | Integer, Integer, Integer |
Set the base date to the month, day and year passed. If any of the passed parameters are invalid, the base date defaults to the current date. |
| Month, ordinal week, weekday, and year | Integer, Integer, Integer, Integer |
Set the base date to the weekday (0-6) in an ordinal week (1-4) in a month (1-12) and year. For example, the third Tuesday in January, 2005 would be passed as: Dim dw As New C_DateWizard(1, 3, 2, 2005)
' . . . .
'January ........ . . .
'3rd ........... . .
'Tuesday .............. .
'Year ..................
If any of the passed parameters are not valid, the base date defaults to the current date. |
| Sort date | String |
Set the base date from a sort date (YYYYMMDD). If the sort date is not valid, the base date is set to the current date. |
| Julian date | Long |
Set the base date from a Julian date (YYYYJJJ). If the passed Julian date is not valid, the base date defaults to the current date. |
| Julian day | Short |
Set the base date from a Julian day (JJJ) and the current year. If the Julian day is not valid, the base date defaults to the current date. |
The C_DateWizard class exposes thirteen methods. They are listed here in alphabetical order:
| Method | Parameters | Description |
AddDays |
Integer |
Adjust the base date by the number of passed days, which may be positive or negative. If the adjustment is into a different month, the fiscal year is updated. |
AddWorkdays |
Integer, Date Array (optional) |
Adjust the base date by the number of passed workdays, which may be positive or negative. Valid dates in the optional date array are not treated as workdays (e.g. holidays). If the adjustment is into a different month, the fiscal year is updated. |
AddMonths |
Integer, Boolean (optional; defaults to False |
Adjust the base date by the number of passed months, which may be positive or negative. When the optional Boolean parameter is True, set the new date to the last day in the new month. The fiscal year is updated. |
AddYears |
Integer |
Adjust the base date by the number of passed years, which may be positive or negative. The fiscal year is updated. |
ResetTimeStamp |
Empty | Change the base date's hour, minute and second properties to the current time. |
SetFirstWorkdayInMonth |
Empty | Change the base date to the first workday (Mon-Fri) in the base date's month. |
SetLastWeekdayInMonth |
Integer |
Change the base date to the last occurrence of the passed weekday (0-6) in the base date's month. |
SetLastWorkdayInMonth |
Empty | Change the base date to the last workday (Mon-Fri) in the base date's month. |
SetNextWorkday |
Empty | Change the base date to the workday (Mon-Fri) immediately after the current base date day. If the next workday is in the next month, the base date is changed to the new month and the fiscal year is updated. |
SetNthDayInMonth |
Integer |
Change the base date to the Nth day within the base date's month. If the passed dayNumber is not within the month, the base date is not changed. |
SetNthWorkdayInMonth |
Integer |
Change the base date to the Nth workday within the base date's month. If the passed workdayNumber is not within the month, the base date is not changed. |
SetOrdinalWeekAndDay |
Integer, Integer |
Change the base date to a weekday (0-6) within an ordinal week (1-5) within the base date's month (e.g. the third Wednesday). Ordinal week number 5 is interpreted as the last occurrence of the weekday in the base month, regardless of how many times the weekday occurs in the month. If either of the parameters are not valid, the base date is not changed. |
SetPreviousWorkday |
Empty | Change the base date to the workday (Mon-Fri) immediately before the current base date day. If the new workday is in a previous month, the base date is changed to the previous month and the fiscal year is updated. |
The C_DateWizard class exposes forty-three properties. They are listed here in alphabetical order:
| Property | Variable type | Set value (=) or (Parameters) | Description |
BaseDate |
Date |
= Date |
Get/set the base date. If the set Date value is not a valid date, the base date is not changed. If needed, the fiscal year is updated. |
BaseDayInMonth |
Integer |
N/A | Get the day in month number of the base date. |
BaseWorkdayInMonth |
Integer |
N/A | Get the workday in month number of the base date. If the base date is not a workday (Mon-Fri), -1 is returned. |
BaseDayInWeek |
Integer |
N/A | Get the day in week number of the base date. |
BaseDayInYear |
Integer |
N/A | Get the day in year number of the base date. |
BaseMonthNumber |
Integer |
N/A | Get the month number of the base date. |
BaseQuarterNumber |
Integer |
N/A | Get the fiscal quarter number of the base date. |
BaseWeekInMonth |
Integer |
N/A | Get the ordinal week number of the base date. |
BaseYear |
Integer |
N/A | Get the year of the base date. |
FirstDateInMonth |
Date |
N/A | Get the first date in the month containing the base date. |
FirstDateInQuarterMonth |
Date |
Integer optional; defaults to 1 |
Get the first date in the specified month (1-3) of the fiscal quarter containing the base date. If the specified month is not valid, Nothing is returned. |
FirstDateInWeek |
Date |
N/A | Get the first date (Sunday) in the week containing the base date. |
FirstFiscalMonth |
Integer |
= Integer |
Get/set the number of the first month in the base date's fiscal year. If not in the range 1 to 12, the values for the fiscal months and years are not changed. |
FirstFiscalMonthAndYear |
String |
N/A | Get the month and year (m/yyyy) of the first month of the base date's fiscal year |
FirstWorkdateInMonth |
Date |
N/A | Get the date of the first workday (Mon-Fri) in the month containing the base date. |
FirstWorkdateInQuarterMonth |
Date |
Integer optional; defaults to 1 |
Get the first work date (Mon-Fri) in the specified month (1-3) of the fiscal quarter containing the base date. If the specified month is not valid, Nothing is returned. |
FirstWorkdateInWeek |
Date |
N/A | Get the first work date (Monday) in the week containing the base date. |
IsLeapYear |
Boolean |
N/A | Determines if the year of the base date is a leap year. Takes into account those even centuries that are not leap years. |
IsWorkday |
Boolean |
N/A | Determines whether the base date day is in the range Monday through Friday. |
JulianDate |
Long |
N/A | Get the base date expressed as a Julian date (YYYYJJJ) where JJJ is the Julian day. |
JulianDay |
String |
N/A | Get the Julian day of the base date expressed as a three-character string, with leading zeros as needed. |
LastDateInMonth |
Date |
N/A | Get the last date in the month containing the base date. |
LastDateInQuarterMonth |
Date |
Integer optional; defaults to 3 |
Get the last date in the specified month (1-3) of the fiscal quarter containing the base date. If the specified month is not valid, Nothing is returned. |
LastDateInWeek |
Date |
N/A | Get the last date (Saturday) in the week containing the base date. |
LastWorkdateInMonth |
Date |
N/A | Get the date of the last workday (Mon-Fri) in the month containing the base date. |
LastWorkdateInQuarterMonth |
Date |
Integer optional; defaults to 3 |
Get the last work date (Mon-Fri) in the specified month (1-3) of the fiscal quarter containing the base date. If the specified month is not valid, Nothing is returned. |
LastWorkdateInWeek |
Date |
N/A | Get the last work date (Friday) in the week containing the base date. |
MonthName |
String |
N/A | Get the full name of the month containing the base date. |
MonthNameAbbrev |
String |
N/A | Get the abbreviated name of the month containing the base date. |
Next1stOr15th |
Date |
N/A | Get the 1st or 15th of the month that is on or immediately after the base date. |
NumberOfDaysInMonth |
Integer |
N/A | Get the number of days in the month containing the base date. |
NumberOfWorkdaysInMonth |
Integer |
N/A | Get the number of workdays (Mon-Fri) in the month containing the base date. |
OrdinalDayInMonth |
String |
N/A | Get the day number from the base month, expressed as an ordinal. |
OrdinalMonthNumber |
String |
N/A | Get the base month number, expressed as an ordinal. |
OrdinalQuarterNumber |
String |
N/A | Get the fiscal quarter containing the base month, expressed as an ordinal. |
OrdinalWeekNumber |
String |
N/A | Get the number of the week in the base month, expressed as an ordinal. |
Previous1stOr15th |
Date |
N/A | Get the 1st or 15th of the month that is on or immediately before the base date. |
SortDateString |
String |
N/A | Get the base date as a string in YYYYMMDD format. |
SortDateTimeString |
String |
N/A | Get the base date and time as a string in YYYYMMDDHHMMSS format. |
TimeStampString |
String |
N/A | Get the base date's hour, minute and second properties as a string in HHMMSS format. |
UsedDefaultDate |
Boolean |
N/A | Get the flag indicating whether or not the base date was set using the default of the current system date. |
WeekdayDate |
Date |
(integer) |
Get the date of a specified day (0-6) in the week containing the base date. If an invalid weekdayNumber is passed, Nothing is returned. |
WeekdayName |
String |
N/A | Get the full name of the base date's weekday. |
WeekdayNameAbbrev |
String |
N/A | Get the abbreviated name of the base date's weekday. |
The C_DateFunctions class exposes eighteen stand-alone methods that are not appropriate for including in the C_DateWizard class. Most of these methods are consumed in the C_DateWizard class. All of the methods are listed here alphabetically:
| Method | Parameters | Returns | Description | ||||||||||
BuildDate |
String, String, String |
Date |
Construct a date from the passed date elements (month, day, year). | ||||||||||
CalcDateInterval |
Date, Date |
N/A | Calculate the number of years, months, weeks and days between two dates. Calculation results are returned with a C_DateInterval object. |
||||||||||
DateRangesOverlap |
Date, Date, Date, Date |
Boolean |
Determine whether one date range overlaps another date range. Dates can be either valid dates or Nothing. When Nothing, a start date is set to #1/1/1700# and an end date is set to #12/31/9998#. |
||||||||||
DateStringOK |
String, String, Boolean (optional; defaults to True) |
Boolean |
Determine whether a date string is a valid date. Display error messages when either the string is empty and required or the string is not a valid date. The passed date name is used in error messages. Return True when the string is empty and a date is not required. |
||||||||||
DateToInternal |
Date |
String |
Convert a date to the Visual Studio internal format (#m/d/yyyy#). | ||||||||||
GoodDateElements |
Integer, Integer, Integer, ByRef Boolean, ByRef Boolean, ByRef Boolean |
Boolean |
Determine if the passed month, day and year are valid. | ||||||||||
GoodJulianDate |
Long, ByRef Date |
Boolean |
Determine whether a Julian date is valid. When valid, pass back the date in Gregorian format. | ||||||||||
InDateRange |
String, String, String |
Boolean |
Determine whether a date is within a date range (inclusive). | ||||||||||
InternalToDate |
String |
Date |
Convert a date in Visual Studio internal format (#m/d/yyyy#) to a date in the current region format. | ||||||||||
IsWorkday |
Integer |
Boolean |
Determine whether the passed day number is a workday (Mon - Fri). | ||||||||||
MonthName |
Integer |
String |
Return the full name for the passed month number. | ||||||||||
MonthNameAbbrev |
Integer |
String |
Return the abbreviated name for the passed month number. | ||||||||||
NextWorkdate |
Date, Boolean (optional; defaults to False) |
Date |
Advance the passed date to the next work date (Mon-Fri). The passed date can optionally be returned if it is a work date. | ||||||||||
NthDayInMonth |
Integer, Integer, Integer, Integer (optional; defaults to the current year) |
Date |
Calculate the Nth weekday in a month (e.g., the second Friday). If any of the parameters are not valid, Nothing is returned. |
||||||||||
OrdinalNumber |
Integer |
String |
Return the ordinal equivalent for the passed number. Returns valid results for numbers 1 through 31 only. Works for ordinal:
|
||||||||||
PreviousWorkdate |
Date, Boolean (optional; defaults to False) |
Date |
Back up the passed date to the previous work date (Mon-Fri). The passed date can optionally be returned if it is a work date. | ||||||||||
WeekdayName |
Integer |
String |
Return the full name for the passed weekday number. | ||||||||||
WeekdayNameAbbrev |
Integer |
String |
Return the abbreviated name for the passed weekday number. |
Two of the properties maintained in the C_DateWizard class are the month and year for the twelve months that comprise the fiscal year that contains the base date. When a date object is instantiated, the fiscal year defaults to January through December, with each month being in the same year as the base date. The fiscal year can be changed with the FirstFiscalMonth property. When the first fiscal month is changed to something other than January, the fiscal year is adjusted so that it always contains the base date.
For example, let's say you instantiate a date object with a base date in July, 2006. Then you set FirstFiscalMonth to September. The new fiscal year will be from September, 2005 through August, 2006. If, in this example, the first fiscal month were set to April, the new fiscal year would be from April, 2006 to March, 2007.
You can permanently change the default fiscal year in your copy of the date wizard. In the Members/Variables region of the C_DateWizard class, change the initial value of intDefaultFiscalFirstMonth to the number of whichever month you want to be the first month in the default fiscal year:
#Region " ... Variables "
Private intDefaultFirstFiscalMonth As Integer = 1
#End Region
When testing an application that stores dates in text files, I changed the operating system region settings to ensure that all dates would be displayed correctly in the user interface. An exception occurred because the format of the dates being read from the text files no longer agreed with the region date format. This test brought home to me the importance of insuring that dates stored and transmitted between applications in text files (e.g. XML) must be in a format that is independent of the region settings in any recipient's machine. The DateToInternal and InternalToDate methods in the C_DateFunctions class are used to create a storable date string that is independent of the operating system region settings. As per the standard set by Microsoft, this independent, internal date format is #mm/dd/yyyy#.
The intent of the DateToInternal and InternalToDate methods is only the storage and retrieval of date strings in text files. Their use is, therefore, very limited. I use these methods only when building a string to be written to a text file, and when interpreting that string when read from the file. This technique isolates the internally formatted dates from the rest of the program code while ensuring that the dates read from text files will be handled correctly, regardless of the region settings.
My current project depends heavily on dates; ergo, my motivation for putting together this .NET version of my date wizard. I do not yet have a need for all of the methods and properties exposed by the C_DateWizard and C_DateFunctions classes. However, I wanted this date toolkit to be as complete as possible before writing this article. Since much of the functionality in these classes was written without a current need for that functionality, there is a possibility I forgot something. If you see any functionality that I missed, please let me know.
You may use all code offered in this article in any way you choose without restriction.
Under no circumstances, and under no legal theory, tort, contract, or otherwise, will George Gilbert (hereafter referred to as "software author") or his licensors, be liable to the user of the Double Text library and all code offered in this article (hereafter referred to collectively as "article code") for any damages, including any lost profits, lost data, or other indirect, special, incidental, or consequential damages, arising out of the use or inability to use the article code, and data or information supplied, even if the software author, his licensors, or authorized dealer have been advised of the possibility of such damages, or for any claim by any other party.
C_DateFunctions CalcDateInterval method has been converted from by-reference parameters to the C_DateInterval class. SetLastWeekdayInMonth method has been added to the C_DateWizard class. This new method changes the date wizard object's base date to the last occurrence in the base month of the weekday number passed to the method. SetOrdinalWeekAndDay method in the C_DateWizard class, in addition to week numbers 1-4, now accepts week number 5. The 5th occurrence of a weekday is interpreted as the last occurrence of the weekday number in the month, regardless of how many times the weekday occurs within the month. BaseWorkdayInMonth property to the C_DateWizard class. This new property returns the number of workdays in the month (excluding Saturday and Sunday) between the 1st and the base date. If the base date is not a workday, -1 is returned. NthDayInMonth method in the C_DateFunctions class. The method now accepts an ordinal week number in the range 1-5, with 5 interpreted as the last weekday in the month.
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 24 Aug 2007 Editor: Sean Ewington |
Copyright 2006 by George B Gilbert Everything else Copyright © CodeProject, 1999-2009 Web16 | Advertise on the Code Project |