Visual Basic .NET provides a DateTime structure for working with, you guessed it, dates and times. Along with this structure there are many static and instance functions it provides. These functions allow us to do simple things from changing the time value to more complex things like displaying the Date or Time based on specific cultural settings. This tutorial dives into how these functions can be used in VB.NET application development.
Although the DateTime structure is useful by itself, the real power comes in all the functions that Microsoft provides for us to interact with these DateTime structures.
Note: if you haven’t read the Introduction to VB.NET's DateTime Tutorial I would suggest you jump over there first to get a good solid foundation before diving into this article.
Note: This tutorial has a corresponding source sample file: Date Time Source Examples
Since, as described in the Introduction Article, a DateTime variable is immutable how are we able to change its value. The answer is pretty intuitive once you think about it. Let me start by giving you an example of another variable type that is immutable – the integer. That’s right most of us understand how to change an integer’s value without even thinking about it. So if we play this out how do we change the value of an integer? Simple we do something to it and then assign it back to the same variable. For example say I have an integer with the value of 5 and I want to add 5 more to it in order to get 10. This is how my code would look:
Dim myInt As Integer = 5 myInt = myInt + 5
For a DateTime variable I can do the same thing:
Dim dateTime As DateTime = New DateTime(2011, 2, 20) dateTime = dateTime + 1 ' WAIT THIS LINE BREAKS!!!
Ok so not quite the same thing because when I try to add one to a DateTime it doesn’t know what that means – 1 day? 1 Year? 1 Millisecond? So instead I can use a helper method to explain what unit of the DateTime I want to add to:
Dim dateTime As DateTime = New DateTime(2011, 2, 20) dateTime = dateTime.AddYears(5)
This code will give me a dateTime variable with the value 2/20/2016 stored in it. You will find helper functions like this for all the parts of a DateTime variable. Note, you won’t find corresponding Subtract… functions instead you can simply call the Add… function with the a negative value. For example if I wanted to subtract 10 years from my DateTime variable it would look like this:
Dim dateTime As DateTime = New DateTime(2011, 2, 20) dateTime = dateTime.AddYears(-10)
Besides years you can add or subtract every part of the DateTime structure. Below is an example of a couple of the functions that are at our disposal. Play around with them and the others:
Dim dateTime As DateTime = New DateTime(2011, 2, 20, 3, 45, 33) dateTime = dateTime.AddYears(5) MessageBox.Show(dateTime) ' Will be 2/20/2016 3:45:33 am dateTime = dateTime.AddMinutes(-15) MessageBox.Show(dateTime) ' Will be 2/20/2016 3:30:33 am
Above we saw how we can use the functions that live off of the instances of DateTime variables, but the DateTime structure itself also has quite a few static functions that can be very useful. Some of these methods are functionally equivalent to their instance counterparts such as DateTime.Equals and DateTime.Compare. However, there are also some functions that are unique such as these:
This method will tell you how many days are in a given month. A handy function to have if you ever forget that rhyme you learned in grade school that tells you how many days are in each month. The DaysInMonth function takes to paramters. One of them is the month number as you would expect the other is the year number. The year number is required because DaysInMonth will take into account leap years when it calculates the number of days for February.
MessageBox.Show(DateTime.DaysInMonth(2011, 2)) ' Will be 28 MessageBox.Show(DateTime.DaysInMonth(2012, 2)) ' Will be 29 - leap year
Speaking of leap year, DateTime has a static method to let us know if the specified year is in fact a leap year. It only takes one parameter which of course is the year number.
MessageBox.Show(DateTime.IsLeapYear(2011)) ' Will be false MessageBox.Show(DateTime.IsLeapYear(2012)) ' Will be true
This is a static property that returns a DateTime instance that with the date set to the current date and the time set to the current time.
MessageBox.Show(DateTime.Now) ' Will be current Date & Time
Similar to DateTime.Now this property returns a DateTime instance but it will only have the Date portion set. The time will not be set.
MessageBox.Show(DateTime.Today) ' Will be just current Date
DateTime.Parse & DateTime.TryParse
DateTime.Parse and DateTime.TryParse provide similar functionality in that they both allow you to convert a string to its corresponding DateTime variable. However, they do have a slight difference as discussed below:
DateTime.Parse takes one parameter a string that will be parsed. If the string can be parsed into a valid DateTime this value will be returned from the function, where as if the string can’t be converted it will throw an exception. To be specific it will through a FormatException with an error message of: “The string was not recognized as a valid DateTime…” You can see examples of both a valid parse and invalid one with the following code:
Dim value As DateTime value = DateTime.Parse("01/29/1990") MessageBox.Show(value) ' Will be 1/29/1990 value = DateTime.Parse("blah") ' Exception is thrown here MessageBox.Show(value) ' Won't get here
What’s the moral of the story? DateTime.Parse is a great function to use if you are pretty sure the string you are parsing is in fact a date, but what do you do if you have no idea (for instance when you are handling user input)?
DateTime.TryParse is similar to DateTime.Parse, but instead of throwing an exception if the string can’t be parsed it will simply return false. The first question that you might have is if DateTime.TryParse returns a Boolean indicating its success then how do we get the DateTime value. It would be very inefficient if we had to first call DateTime.TryParse and then immediately call DateTime.Parse. Fortunately DateTime.TryParse works better than this. Unlike Parse, TryParse takes two parameters. The first is the string to be parsed (just like DateTime.Parse) but the second is an out parameter of DateTime. So, if the string can be parsed it will return true and will pass the converted DateTime out through the second parameter. If the value can’t be parsed it will return false and the out DateTime will be set to DateTime.MinValue. See below for examples of both a successful and unsuccessful TryParse:
Dim value As DateTime Dim result As Boolean result = DateTime.TryParse("01/29/1990", value) MessageBox.Show(result & ", " & value) ' Will be True, 1/29/1990 result = DateTime.TryParse("blah", value) MessageBox.Show(result & ", " & value) ' Will be False, DateTime.MinValue
Notice that in the first case TryParse returned true because it was able to parse the input, in the second case ‘Blah’ could not be parsed so it returns false. Also pay attention to a common gotcha: If we look at the second TryParse call the DateTime value starts out being 1/29/1990 as we pass it into our method. Often what people think is that if TryParse fails it leaves the value alone, but in fact it returns false and still updates the DateTime value passed into it. So when our second MessageBox is shown we will see false as our result and our value will be set to DateTime.MinValue
When to use Parse vs. TryParse
Since Parse and TryParse have similar functionality how do you decide which one to use. This is one of those questions that probably doesn’t have an exact answer but my rule of thumb is this. If I expect the string value I am dealing with to always be a valid Date or DateTime then I simply use Parse, because if it is not correct this is an exceptional situation (where there is a bug in my code or something) and I in fact want to throw an Exception (which Parse does). If instead I am not sure if the string I am dealing with is a valid Date or DateTime then I will always use TryParse. It is usually better in these situations to handle to invalid case without an exception because it is not Exceptional.
A perfect example of this is if you have a generic TextBox that you ask a user to put their birthdate in. I know from experience that there is a good chance that a user will do something like enter in the value 3/2/q1975 because the accidently hit the q when they were trying to hit the 1. I don’t want to throw an exception and have to deal with it, instead I want to use TryParse and if the it can’t be parsed I display a message saying you entered an invalid birthdate please fix it. No on the other hand let’s say I am reading a value from an XML file that I am in charge of exporting in the first place. Now I know that every birthdate tag’s value should in fact be a valid Date so I will simply call DateTime.Parse. If an exception occurs I want it to because somehow my data got really screwed up (or I have some weird bug in my code). Again there are some grey areas with this whole thing and at times its probably just the preference of the programmer, but this might these two examples help show one way to think through it.
All and all Microsoft with their DotNet language and VB.NET with its implementation of it has given us some pretty great DateTime functionality. As you begin writing more and more advance Visual Basic applications you will probably find yourself making use of these features quite often.
Note: This tutorial has a corresponding source sample file: Date Time Source Examples