TOC
Data types:

Working with Dates & Time

C# comes with a really great struct for working with dates and time - it's called DateTime. It's not actually a data type, but I have included it in this chapter, because you will often find your self working with dates and/or time using the DateTime struct - sometimes just as much as you work with strings and numbers.

Let's start by instantiating a new DateTime object:

DateTime dt = new DateTime();
Console.WriteLine(dt.ToString());

The result is pretty boring though: 01-01-0001 00:00:00. This corresponds with the DatetTime.MinValue field, but DateTime has more helping properties - the most interesting one is the DateTime.Now:

DateTime dt = DateTime.Now;
Console.WriteLine(dt.ToString());

This leaves us with the current date and time, which is often very relevant - we will see that in some of the upcoming examples. However, in a lot of situations, you are probably looking to represent a specific date and time - fortunately for us, the DateTime has several constructors to help us with just that. Here's an example:

DateTime dt = new DateTime(2042, 12, 24);
Console.WriteLine(dt.ToString());

The order of the parameters in this constructor is Year, Month, Day, so this will give us a DateTime object with a date representing Christmas Eve in the year 2042.

DateTime - with or without time?

But what about time? Well, if you don't specify one, it will default to 00:00:00, as you can see from our previous example. You can easily specify time as well though:

DateTime dt = new DateTime(2042, 12, 24, 18, 42, 0);
Console.WriteLine(dt.ToString());

Now the DateTime has time as well, in this case at 18:42. Notice that the hours should be specified as a number between 0 and 23, since we use the 24 hour clock for the input, but don't worry if you want it as a 12 hour clock with AM/PM - that's easily done in the output, as we'll discuss later.

The remaining question is: What to do if you're only interested in the date part? The obvious answer would be to use the Date class instead of the DateTime class, but actually, no such thing exists . Instead, the DateTime class has a Date property:

DateTime dt = new DateTime(2042, 12, 24, 18, 42, 0);
DateTime date = dt.Date;
Console.WriteLine(date.ToString());

As you will see however, the Date property is also a DateTime object, where the time part has been set to 00:00:00. This might be a bit confusing, but it also makes pretty good sense, because the DateTime should always just serve as a container, holding the data that you can output to the user in many ways and forms. We have already used the basic ToString() method, but there are many more ways to get the output of a DateTime object.

DateTime output

Getting the output of a DateTime is one of the most important aspects, but it can also be a complicated task - it really depends on your needs. So far, we have seen the very basic version of the output: The simple call to the ToString() method. This will output date and time based on the current culture of the application, which is, by default, based on the system settings. This means that if you just call the ToString() method, the date and time will be presented to the user in a way that makes sense to them no matter where in the world they are, because as you are probably aware, the format of time and especially the date varies a LOT from region to region.

If you are looking to get more control of the output, there are several ways to do that. The quickest way is to use one of the To* methods, e.g. the ToShortDateString() method:

Console.WriteLine(DateTime.Now.ToShortDateString());

This will output a short version of the date, omitting the time part completely. You can also use the ToLongDateString() method:

Console.WriteLine(DateTime.Now.ToLongDateString());

The output will vary, based on the region settings, but usually a long date includes a text representation of the month instead of a numeric representation.

If you're looking to get more control, perhaps because you want to adapt your date/time info to a specific region, you can use one of the overloads of the ToString() method, e.g. by specifying exactly which culture/region you are targeting:

var usCulture = new System.Globalization.CultureInfo("en-US");
Console.WriteLine(DateTime.Now.ToString(usCulture.DateTimeFormat));

The CultureInfo class allows you to get an entire box of info about a language, e.g. how they write dates and time (the CultureInfo class will be covered later on in this tutorial). We can then pass this information on to the DateTime class, to let it know that we want a visual representation of the date and time to match this language. But what if we want to be even more specific about the output?

Standard Date & Time Format Strings

To gain even more control of the output, you can use the standard date & time format strings provided by the .NET framework. It's one letter, used to represent a way to display the date and/or time. For the full list, I suggest that you have a look at the documentation, but for now, here's a couple of examples:

DateTime dt = new DateTime(2042, 12, 24, 18, 42, 0);  

Console.WriteLine("Short date pattern (d): " + dt.ToString("d"));  
Console.WriteLine("Long date pattern (D): " + dt.ToString("D"));  
Console.WriteLine("Full date/time pattern (F): " + dt.ToString("F"));  
Console.WriteLine("Year/month pattern (y): " + dt.ToString("y"));

The output will look like this:

Short date pattern (d):                 24-12-2042
Long date pattern (D):          24. december 2042
Full date/time pattern (F):     24. december 2042 18:42:00
Year/month pattern (y):                 december 2042

This gives you a bit more control of the output, but sometimes that's not enough - in those cases, you need custom format strings.

Custom Date & Time Format Strings

For full control, we have custom format strings. They are a combination of letters and special characters which you pass on to the ToString() method, to show the exact format you want for your date and/or time - this includes where you want the date/time parts, how you want them and what kind of separators you would like to use. Obviously this leaves you with a lot of options, so for the full list of available format specifiers, please check out the documentation, but let's see how it works straight away:

DateTime dt = new DateTime(2042, 12, 24, 18, 42, 0);

Console.WriteLine(dt.ToString("MM'/'dd yyyy"));
Console.WriteLine(dt.ToString("dd.MM.yyyy"));
Console.WriteLine(dt.ToString("MM.dd.yyyy HH:mm"));
Console.WriteLine(dt.ToString("dddd, MMMM (yyyy): HH:mm:ss"));
Console.WriteLine(dt.ToString("dddd @ hh:mm tt", System.Globalization.CultureInfo.InvariantCulture));

The output will look something like this:

12/24 2042
24.12.2042
12.24.2042 18:42
onsdag, december (2042): 18:42:00
Wednesday @ 06:42 PM

In general, one or several d's will get you some version of the day, one or several M's will give you the month (lowercase m is for minutes) and a number of y's will give you the year. To fully understand what these format specifiers do, I still suggest that you have a look at the documentation, but hopefully the above example has given you a good idea of just how powerful the custom format strings are.

Parsing dates

So far, we have worked with dates defined directly in code, but you will probably quickly run into a situation where you need to work with a date specified by the user. This is a surprisingly complicated subject because there are so many ways of writing a date. The .NET framework can help you with this, because it supports all the cultures, as illustrated in previous examples, but you still need to help the user specify the date in the format you expect. After that, you can use the Parse() method to turn a user-specified string into a DateTime object, like this:

var usCulture = new System.Globalization.CultureInfo("en-US");
Console.WriteLine("Please specify a date. Format: " + usCulture.DateTimeFormat.ShortDatePattern);
string dateString = Console.ReadLine();
DateTime userDate = DateTime.Parse(dateString, usCulture.DateTimeFormat);
Console.WriteLine("Date entered (long date format):" + userDate.ToLongDateString());

This example is actually pretty cool because it shows just how much the .NET framework can help us, as long as we have an instance of the CultureInfo class that we want to use (US English in this case - and don't worry, we will discuss the CultureInfo class in much greater detail later on). As soon as we have this, we use it for letting the user know which format we expect. Then we use it again in the 4th line, to actually parse the input. In the last line, we output the user-specified date, this time just using the format specified by the system.

However, be aware that the Parse() method is very strict - if the user doesn't enter the date in the expected format, it will throw an exception. For that reason, it's usually a good idea to use the TryParse() method instead - it does the exact same thing, but it allows you to check if the date could be parsed or not, and it doesn't throw an exception. Here's a revised version of the previous example:

var usCulture = new System.Globalization.CultureInfo("en-US");
Console.WriteLine("Please specify a date. Format: " + usCulture.DateTimeFormat.ShortDatePattern);
string dateString = Console.ReadLine();
DateTime userDate;
if (DateTime.TryParse(dateString, usCulture.DateTimeFormat, System.Globalization.DateTimeStyles.None, out userDate))
    Console.WriteLine("Valid date entered (long date format):" + userDate.ToLongDateString());
else
    Console.WriteLine("Invalid date specified!");

Summary

Working with dates and time is very important but also very complex. Lucky for us, the .NET framework is there to help us in almost all situations with the brilliant DateTime class.