Lesson 11 - Date and time in VB.NET
In the previous lesson, Properties in VB.NET, we learned all about properties in Visual Basic .NET. Today's project will require the use of properties, specifically, we're going to learn how .NET works with date and time.
DateTime
We use the DateTime class from the .NET framework to work with date and time. We use it as a data type for storing date or time. When we think about the date and the time, we know that they're both times elapsed from a starting point. With that in mind, Microsoft set them both as a common type. The class is pretty ingenious and has many useful properties and methods. We'll be going over them today.
Creating an instance
Let's start by creating a DateTime instance. We'll create a project named DateAndTime and create an instance of the DateTime class using the parameterless constructor:
{VBNET_CONSOLE}
Dim dateTime As DateTime = New DateTime()
Console.WriteLine(dateTime)
Console.ReadKey()
{/VBNET_CONSOLE}
The output will look something like this (depending on your OS regional settings):
Console application
1/1/0001 12:00:00 AM
Let's take a look at the two constructors we can use to create a DateTime instance.
First, let's create an instance and only add the date (the time won't be set and will remain at 0:00:00). Let's specify the year, month, and day (in that order):
{VBNET_CONSOLE}
Dim dateTime as DateTime = New DateTime(2016, 7, 15)
Console.WriteLine(dateTime)
{/VBNET_CONSOLE}
Console output:
Console application
7/15/2016 12:00:00 AM
If you want to set both the date and the time, all you have to do is add it like:
Dim dateTime As DateTime = New DateTime(2016, 7, 15, 3, 15, 0)
Now, the time has been set to 3:15 AM.
It's very important for you to know how to get the current date and time. The DateTime class has a static property called Now that returns a DateTime instance with the current date and time. We call it, of course, directly on the class. The time in this instance does not increment. If we were to use the Now property and needed the current date and time for once again we would have to call the Now property a second time:
{VBNET_CONSOLE}
Dim dateTime As DateTime = DateTime.Now
Console.WriteLine("Today is: {0}", dateTime)
Console.ReadKey()
{/VBNET_CONSOLE}
Console output:
Console application
Today is: 5/12/2016 10:49:08
DateTime also has a property called Today that returns the current date with time set to 0:00:00.
Other properties
As a matter of fact, DateTime has many properties made for accessing individual date and time components:
- Day
- Month
- Year
- Hour
- Minute
- Second
- Millisecond
We can also call for the number of Ticks in which the date and time are internally stored. The number returned would be huge, seeing as how one tick represents one hundred nanoseconds, which is one ten-millionth of a second. Still, they may come in handy for very accurate calculations.
Other than the aforementioned DateTime components, .NET allows us to access:
- DayOfWeek - Returns the day of the week as an enumerated type which we will cover in the next couple of lessons. Let's just say that the output value would be, e.g. DayOfWeek.Monday. When printed, it is implicitly converted to a String depending on the system regional settings.
- DayOfYear - The numerical representation of the current day of the year. Meaning that it returns a value from 1 to 366.
We isolate the date from a DateTime instance by setting the time component to 0:00:00 and using the Date property which returns the DateTime instance formatted to only include the date. This can be useful when working with whole days because adding a time factor would cause inaccuracies.
Let's try some of these properties out:
{VBNET_CONSOLE}
Dim dateTime As DateTime = DateTime.Now
Console.WriteLine("Today is {0} {1}.", dateTime.DayOfWeek, dateTime.Day)
Console.WriteLine("It is month number {0} of the year {1}.", dateTime.Month, dateTime.Year)
Console.WriteLine("{0} hours, {1} minutes and {2} seconds.", dateTime.Hour, dateTime.Minute, dateTime.Second)
Console.ReadKey()
{/VBNET_CONSOLE}
The output:
Console application
Today is Thursday 12.
It is month number 5 of the year 2016.
10 hours, 51 minutes and 31 seconds
My OS settings are set to English standards so VB.NET returns the current date in English. Results may vary depending on your OS' regional settings. This is nice feature because it relieves us from having to worry about whether the output will be displayed correctly in all regional settings.
Methods
Now let's take a look at the methods the DateTime class provides for us. Please remember that methods don't change the DateTime instance, they return a new one in which the changes have been applied!
Changing the inner value
The inner date and time value can easily be manipulated using methods that add various time periods. They take periods of time as parameters, e.g. days. Then, if we want to remove them from the instance, just use a negative value. Methods for changing the inner value are the following:
- AddDays()
- AddMonths()
- AddYears()
- AddHours()
- AddMinutes()
- AddSecond()
- AddMilliseconds()
- AddTicks()
We can also ask whether the given DateTime instance is in daylight saving time format:
- IsDaylightSavingTime()
Static methods
The DateTime class also provides two static methods:
- DaysInMonth() - Static method returning the number of days in a given month. The parameters are the month and the year (we specify the year because we could be referring to a February on a leap year).
- IsLeapYear() - Returns whether the year is a leap year, the parameter is a year.
Parsing and converting to string
Let's say we want the user to enter a date, which would eventually include time. DateTime has both Parse() and TryParse() methods for these purposes.
The simplest way to retrieve the date and time via user input is the following:
Dim dateTime As DateTime = DateTime.Parse(Console.ReadLine())
Date and time format depends on the regional settings. Generally, it is dd/mm/yyyy hh:mm. If we omit time, it would automatically set it to 0:00:00.
When we want to specify the input format we use patterns:
Dim pattern As String = "M/dd/yyyy"
The table of possible values is rather extensive. You can read the official documentation at http://msdn.microsoft.com/…kb3ddd4.aspx where you'll find explanations for different pattern components.
We'll use the ParseExact() method to parse and pass our pattern like so:
Dim dateTime As DateTime = DateTime.ParseExact(Console.ReadLine(), pattern, Nothing)
Now, we'll go over date to text conversion. We could very well use the ToString() method, it has no parameters and VB.NET calls it implicitly. We can even add a pattern as a parameter to make it return a date in whatever format we want it to:
dateTime.ToString("dd MMMM, yyyy")
There are 4 preset formats, 2 for printing dates and 2 for printing time. We can print in the long or the short format:
- ToShortDateString()
- ToShorTimeString()
- ToLongDateString()
- ToLongTimeString()
Dates, eventually including time, can be compared using the > < = operators (internally, all it is is a huge number of ticks that we compare to other values).
Be sure to look at the date and time exercises for this lesson to put your knowledge to the test and get a taste of what a real-world program using DateTime would include.
Note: As you probably know, time can be expressed as local, your time
zone, or international (UTC format). For simplicity's sake, we will always work
with local time in our courses. If you would like to determine the current time
in UTC, use the UtcNow static property. You can determine whether a DateTime
instance is local or international by using the Kind property. To create a
DateTime instance in UTC format, you would use the same constructor that we did
in this lesson, and fill in one extra parameter with the DateTime instance's
Kind
. The DateTime can also be changed using the SpecifyKind()
static method. Yo could also convert time using the ToLocalTime() and
ToUniversalTime() methods.
TimeSpan
TimeSpans store the difference between two dates. The main difference between DateTime and TimeSpan is that DateTime represents the entire date and TimeSpan represents a time interval (which can be years or seconds).
On DateTime, the TimeOfDay property returns a TimeSpan with the time and discards the date.
TimeSpan is also created when you subtract two DateTime instances. We can add a TimeSpan to a DateTime using the Add() method on the DateTime instance.
Properties
We can access individual TimeSpan components using properties (sort of like we did with DateTime, but their names are in plural form):
- Days
- Hours
- Minutes
- Seconds
- Milliseconds
- Ticks
If we want to express the interval as a single unit, we use the properties with the "Total" prefix which return Doubles instead of Integers:
- TotalDays
- TotalHours
- TotalMinutes
- TotalSeconds
- TotalMilliseconds
Methods
TimeSpan has several constructors, let's look at two basic ones:
Dim ts As TimeSpan = New TimeSpan(hours, minutes, seconds) Dim ts As TimeSpan = New TimeSpan(days, hours, minutes, seconds)
The methods that come with it are similar to the ones in DateTime. The Add() method here adds a TimeSpan to another TimeSpan (don't try to add DateTime instances to it, there are better ways of doing that). We can create a TimeSpan using static methods from the interval expressed in different units:
- FromDays()
- FromHours()
- FromMinutes()
- FromSeconds()
- FromMilliseconds()
TimeSpans Parse() and ToString() methods are identical to the ones in DateTime.
We'll make one last example program to try and get a complete understanding of what was shown to you in this lesson. We'll ask the user for his/her birthday and calculate his/her age based on the input. We will also tell him/her how old he/she is in days and hours. Unfortunately, we can't determine years using TimeSpans because years don't have a constant number of days. Meaning that we're only able to get the total number of days in the interval. We'll divide days by 365,255 and then round them down. This approach might not work for a few birth dates, but you will still get to apply all that you've learned today (we'll do a complete version in the exercises for this lesson). Now, let's get right into it! (don't forget to enter the birth date in your regional format when running):
{VBNET_CONSOLE}
Console.WriteLine("Enter your date of birth: ")
Dim born As DateTime = DateTime.Parse(Console.ReadLine())
Dim age As TimeSpan = DateTime.Today - born
Console.WriteLine("You are {0} years old", Math.Floor(age.Days/365.255))
Console.WriteLine("You are {0} days or {1} hours old", age.TotalDays, age.TotalHours)
Console.ReadKey()
{/VBNET_CONSOLE}
Console application
Enter your date of birth
1/15/1989
You are 27 years old
You are 9979 days or 239496 hours old
As you can see, subtracting two DateTime instances results in the creation of a TimeSpan. It is a very common practice to store dates of birth instead of ages in User objects. We can easily calculate the age then and the value would be updatable.
In then next lesson, Solved tasks for OOP in VB .NET lesson 11, we'll introduce a collection into which we can add and remove items as we please. What sort of collection, you say? We'll create a simple database using List.
In the following exercise, Solved tasks for OOP in VB .NET lesson 11, we're gonna practice our knowledge from previous lessons.