Click here to Skip to main content
6,595,444 members and growing! (21,010 online)
Email Password   helpLost your password?
Languages » VB.NET » Applications     Intermediate License: The Code Project Open License (CPOL)

VB.NET Class Library: Date Wizard

By George B Gilbert

A toolkit that simplifies working with dates.
VB, Windows, .NET, Visual Studio, Dev
Posted:28 Mar 2006
Updated:24 Aug 2007
Views:109,134
Bookmarked:96 times
Announcements
Loading...
 
Search    
Advanced Search
Add to IE Search
Prize winner in Competition "VB.NET Feb 2006"
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
17 votes for this article.
Popularity: 5.09 Rating: 4.14 out of 5
3 votes, 18.8%
1

2
1 vote, 6.3%
3
2 votes, 12.5%
4
10 votes, 62.5%
5

* 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

Contents

Introduction

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.

Background

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.

Terminology

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.

Using the Class Library

Follow these steps to make the 2gs_datewizard class library available in a project:

  1. Copy the DLL (2gs_datewizard.dll) to the project's BIN folder.
  2. In the VS Solution Explorer, add the DLL to the project's References.

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

Date Wizard Class

Constructors

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.

Methods

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.

Properties

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.

Methods in the DateFunctions Class

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:

Day in a month 1st - 31st
Day in a week 1st - 7th (weekday numbers (0-6) must be incremented by 1 before being passed to this function)
Week in a month 1st - 5th
Month in a year 1st - 12th
Quarter in a month 1st - 4th
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.

Points of Interest

Fiscal Year

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

Internal Dates

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.

Conclusion

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.

Licensing and Limitation of Liability

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.

History

  • 3/28/2006
    • The return of calculation results from the C_DateFunctions CalcDateInterval method has been converted from by-reference parameters to the C_DateInterval class.
  • 4/5/2006
    • The 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.
    • The 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.
  • 8/20/2007
    • Added the 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.
    • Modified the 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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

George B Gilbert


Member
Click here to see a complete list of my articles.
Occupation: Software Developer
Company: 2 Good Software
Location: United States United States

Other popular VB.NET articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 25 of 33 (Total in Forum: 33) (Refresh)FirstPrevNext
GeneralExcellent Work PinmemberRandy Parsons6:33 24 Jul '08  
GeneralRe: Excellent Work PinmemberGeorge B Gilbert7:19 24 Jul '08  
GeneralIs today part of this work week PinmemberUltraWhack11:13 21 Apr '08  
GeneralRe: Is today part of this work week PinmemberGeorge B Gilbert11:32 21 Apr '08  
GeneralThanks Pinmemberkwhite19:52 3 Sep '07  
GeneralRe: Thanks PinmemberGeorge B Gilbert7:28 4 Sep '07  
GeneralNthDayInMonth (8,5,5) Pinmemberjyjohnson6:55 17 Aug '07  
GeneralRe: NthDayInMonth (8,5,5) PinmemberGeorge B Gilbert11:09 17 Aug '07  
GeneralRe: NthDayInMonth (8,5,5) Pinmemberjyjohnson12:17 17 Aug '07  
GeneralRe: NthDayInMonth (8,5,5) PinmemberGeorge B Gilbert15:06 17 Aug '07  
GeneralRe: NthDayInMonth (8,5,5) PinmemberUltraWhack11:18 21 Apr '08  
GeneralRe: NthDayInMonth (8,5,5) PinmemberGeorge B Gilbert11:35 21 Apr '08  
GeneralCalculating the DateInterval PinmemberPaolo Benjamin T. Briones10:09 30 Jun '07  
GeneralRe: Calculating the DateInterval PinmemberGeorge B Gilbert11:16 1 Jul '07  
GeneralProblem with InternalToDate Pinmembervbelani16:47 24 Mar '07  
GeneralRe: Problem with InternalToDate PinmemberGeorge B Gilbert6:01 25 Mar '07  
GeneralRe: Problem with InternalToDate Pinmemberkeith.b1:22 29 Aug '07  
GeneralRe: Problem with InternalToDate PinmemberGeorge B Gilbert7:51 4 Sep '07  
GeneralRe: Problem with InternalToDate Pinmemberkeith.b22:48 8 Sep '07  
GeneralPayroll Year Pinmemberbeatriz6713:22 11 Jul '06  
GeneralRe: Payroll Year PinmemberGeorge B Gilbert20:00 11 Jul '06  
GeneralRe: Payroll Year Pinmemberbeatriz6710:51 12 Jul '06  
GeneralRe: Payroll Year PinmemberGeorge B Gilbert13:15 12 Jul '06  
GeneralAllowing for a Fiscal Offset Pinmemberdgauerke11:31 10 Apr '06  
GeneralRe: Allowing for a Fiscal Offset PinmemberGeorge B Gilbert14:31 10 Apr '06  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin 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