For many developers, their first experience handling time in C# is by using DateTime.Now.
When needing to retrieve the current date and time, they’d search for it, reaching a StackOverflow question or some documentation page by Microsoft. They’d quickly find that the way you get the current instant is by using the “DateTime.Now.” They’d go back to their code, use the property, and be done with it.
Also, for many developers, the scenario described above is the extent of their education about DateTime.Now. This isn’t good. Why?
Well, time is one of the trickiest topics in programming. Not knowing about its intricacies can get you into trouble. We’re here to help avoid that, by taking a look at the dos and don’ts of DateTime.Now.
We’re going to cover what DateTime.Now is the basics of its use. Then we’ll go a bit deeper, showing some more advanced usage scenarios (i.e. output formatting), covering the best practices you should employ and also the pitfalls you must be aware of when working with this property.
Let’s get started.
DateTime.Now: What It Is and How to Use It
DateTime.Now is a static property on the DateTime struct. By calling it, you get back a DateTime object, representing the current time in your computer, expressed as local time.
Don’t worry about what “expressed as local time” means. We’ll get to that soon.
For now, let’s see some examples of DateTime.Now in use:
static void Main(string[] args) { DateTime now = DateTime.Now; if (now.DayOfWeek == DayOfWeek.Saturday || now.DayOfWeek == DayOfWeek.Sunday) { Console.WriteLine("Enjoy the weekend!"); } else { Console.WriteLine("Get back to work!"); } }
The DateTime object you get back by calling the property is, for the most part, identical to any other you could create by using one of the available constructors or even by parsing some text.
In the example, we use the “DayOfWeek” property of the resulting object to test whether we’re in the weekend and print a message accordingly.
Let’s see a new example:
var now = DateTime.Now; Console.WriteLine(now.ToString("d", System.Globalization.CultureInfo.GetCultureInfo("pt-BR"))); Console.WriteLine(now.ToString("d", System.Globalization.CultureInfo.GetCultureInfo("en-US"))); Console.WriteLine(now.ToString("d", System.Globalization.CultureInfo.GetCultureInfo("tr")));
In this last version of the example, I’ve replaced the name of the type with the var keyword, making use of type inference.
I’ve also included three new lines, which print the value of the “now” variable, formatted in the short date format (“d”), according to the Brazilian Portuguese, American English, and Turkish locales, respectively.
If you run the code above on your machine, you’ll see either the “Enjoy the weekend!” or “Get back to work!” sentences, immediately followed by the current date repeated three times, according to the following formats:
- dd/MM/yyyy (pt-br)
- M/dd/YYYY (en-US)
- dd.MM.YYYY (tr)
This is just to showcase how the DateTime object you get by calling DateTime.Now doesn’t differ from others you get by other methods?except in one important way, which we’ll see soon.
Formatting the Output from DateTime.Now
When dealing with DateTime values, you’ll eventually want to display them, which means you must learn about formatting. Otherwise you might run into globalization issues, among other problems.
So, what are the use cases for formatting?
One of the reasons you might want to format the current date and time is to only show either the date or the time.
As you already now, by using the DateTime.Now property you get an instance of the DateTime type. As its name makes clear, this type can hold not only a date but also the time of the day.
That doesn’t mean that when displaying the value you’re forced to always show both components. There’ll be plenty of occasions when you’ll want to show either just the date or just the time.
The other, more important reason you might want to format the current date and time has to do with globalization.
We humans are awfully inconsistent on how to represent time. This inconsistency manifests itself in the large number of different formats for dates used around the world. An American might want to see a date like “January 25, 2019” represented as “01/25/2019”, while a Brazilian will prefer to see it expressed as “25/01/2019.”
With all of the above in mind, let’s cover some of the available options to format the output of DateTime.Now.
Short Date String
The first format we’re going to cover is the “short date string” format. Consider the code below:
Console.WriteLine(DateTime.Now.ToShortDateString());
Here we’re using the “ToShortDateString()” method, that returns a string containing the date (but not the time) formatted to a short format. The line above is equivalent to the following one:
Console.WriteLine(DateTime.Now.ToString("d"));
So, what is the output we get?
That depends on the culture your app is running on. If you’re in the US, then you’d likely see the date in the “MM/dd/yyyy” format. On the other hand, if you live in the UK?for instance?you’ll probably see the date in the “dd/MM/yyyy” format.
If, for whatever reason, you can’t or won’t use the culture of the system, it’s possible to override that, by explicitly setting the culture you want to use. You use that by using the overload of the “ToString()” method that takes an instance of some implementation of IFormatProvider as a parameter.
The following example shows it clearly:
var date = DateTime.Now; // let's say this is March 15th, 2019 var culture = new System.Globalization.CultureInfo("pt-BR"); // setting the culture to Brazilian Portuguese Console.WriteLine(DateTime.Now.ToString("d", culture)); // prints '15/03/2019' culture = new System.Globalization.CultureInfo("en-US"); // setting the culture to American English Console.WriteLine(DateTime.Now.ToString("d", culture)); // prints '3/15/2019' culture = new System.Globalization.CultureInfo("tr"); // setting the culture to Turkish Console.WriteLine(DateTime.Now.ToString("d", culture)); // prints '15.03.2019'
Long Date String
If we have a way of outputting the current date/time in a short format, it just makes sense to be able to do the same in a longer format. By using the “ToLongDateString()” format, we can display the date spelling out the names of the day and month.
See the following example:
// assume the date is March 15th, 2019 // assume the culture is en-US Console.WriteLine(DateTime.Now.ToLongDateString()); // displays 'Friday, March 15, 2019'
Using the “ToLongDateString()” method is equivalent to using the “ToString()” method passing the “D” formatting code. So, the line above does exactly the same as the one below:
// assume the date is March 15th, 2019 // assume the culture is en-US Console.WriteLine(DateTime.Now.ToString("D")); // displays 'Friday, March 15, 2019'
As in the previous example, you can explicitly set the culture by passing it as the second argument to the “ToString()” method.
Take a look at the following excerpt of code:
var date = DateTime.Now; // let's say this is March 15th, 2019 var culture = new System.Globalization.CultureInfo("pt-BR"); // setting the culture to Brazilian Portuguese Console.WriteLine(DateTime.Now.ToString("D", culture)); // prints 'sexta-feira, 15 de mar?o de 2019' culture = new System.Globalization.CultureInfo("en-US"); // setting the culture to American English Console.WriteLine(DateTime.Now.ToString("D", culture)); // prints 'Friday, March 15th, 2019' culture = new System.Globalization.CultureInfo("tr"); // setting the culture to Turkish Console.WriteLine(DateTime.Now.ToString("D", culture)); // prints '15 Mart 2019 Cuma'
Short Time String
You already know the drill by now. We’ll cut the chatter and go straight to the examples:
using System; using System.Globalization; using System.Threading; class MainClass { public static void Main (string[] args) { var date = DateTime.Now; // let's say this is March 15th, 2019, 9:15 AM // Change culture to en-US Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); // the following two lines are equivalent // both of them print 9:15 AM Console.WriteLine(date.ToShortTimeString()); Console.WriteLine(date.ToString("t")); // Change culture to pt-BR Thread.CurrentThread.CurrentCulture = new CultureInfo("pt-BR"); // the following two lines are equivalent // both of them print 09:15 Console.WriteLine(date.ToShortTimeString()); Console.WriteLine(date.ToString("t")); } }
Unsurprisingly, there’s also a “ToLongTimeString()” method. Its usage will be left as an exercise to the reader.
Custom Formats
Finally, you also have at your disposal a huge number of custom format specifiers.
For the sake of brevity, we’ll only show some of the them; feel free to see the complete list on the Microsoft’s documentation site for the .NET framework.
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); var now = DateTime.Now; // assume 'now' is March, 15th, 2019, at 9:15 AM Console.WriteLine(now.ToString("MM/dd/yyyy")); // prints 03/15/2019 Console.WriteLine(now.ToString("dddd, dd MMMM yyyy")); // prints Friday, 15 March 2019 Console.WriteLine(now.ToString("dd/MM/yyyy")); // prints 15/03/2019 Console.WriteLine(now.ToString("dddd, dd MMMM yyyy HH:mm:ss")); // prints Friday, 15 March 2019 09:15:00 Console.WriteLine(now.ToString("MM/dd/yyyy HH:mm")); // prints 03/15/2019 09:15 Console.WriteLine(now.ToString("MMMM dd")); // prints March 15 Console.WriteLine(now.ToString("yyyy?-?MM?-?dd?T?HH?:?mm?:?ss")); // prints 2019'-'03'-'15'T'09':'15':'00 Console.WriteLine(now.ToString("HH:mm")); // prints 09:15 Console.WriteLine(now.ToString("hh:mm tt")); // prints 09:15 AM Console.WriteLine(now.ToString("H:mm")); // prints 9:15 Console.WriteLine(now.ToString("h:mm tt")); // prints 9:15 AM Console.WriteLine(now.ToString("HH:mm:ss")); // prints 09:15:00
The Important Pitfall of DateTime.Now
As promised, now it’s time to start delving more deeply into the DateTime.Now property.
We’ll start out by answering what on earth is wrong with it in the first place.
As it turns out, there’s nothing wrong with the DateTime.Now property per se. The problem is with the DateTime object itself.
“OK then,” you might be thinking, “what’s the problem with DateTime?”
It all comes down to some unfortunate design decisions about the DateTime type. The main one relates to the “Kind” property.
Here’s the thing: a DateTime object can fall into one of three different categories. Each one of these represents a fairly different concept, so a more sensible approach would be to create different types for each one. That’s the approach that the NodaTime open-source library uses, for instance.
Instead, the DateTime object has a property called “Kind” that represents each one of the possible categories a DateTime object can fall into. Let’s quickly review each one of them.
UTC
The first kind we’re covering is “UTC,” whose name is very self-explanatory.
This kind is used to represent date?and time in the UTC (Coordinated Universal Time). It’s really useful and, in fact, should be the most-used kind.
One of the most common mistakes developers make while dealing with date and time issues is not using UTC when they should.
And when is that? In short, every time you need to record, in a precise and unambiguous way, when a given event happened.
And how would you go about getting a DateTime object with the UTC kind?
There are several ways to do that, be it by parsing or using one of the DateTime constructors. But since we’re covering how to retrieve the current date and time, you’d do that by using the “DateTime.UtcNow” property.
Let’s see an example:
class Program { static void Main(string[] args) { DateTime now = DateTime.UtcNow; Console.WriteLine(now.Kind); } }
You’ll see that now we’re using the “UtcNow” property, instead of just “Now.” There’s also a line that prints the value of the Kind property of the now variable. If you run the code above, you should see “Utc.”
Unspecified
Now we go to the “Unspecified” kind.
Unlike the previous one, the name of this kind isn’t that self-explanatory. Here’s what unspecified means in this context: it refers to a date, plus time, totally devoid of context.
In other words, it’s just a date and a time, and that’s it.
At first, the Unspecified kind might sound weird. Why would you want such a value?
As it turns out, this kind is surprisingly useful in a number of situations. For instance, you could use it to represent the opening hours of a company or other institution. There’s no way to get the “current” date and time as an unspecified value.
Keep reading to find out why that is.
Local
The “Local” kind is weird. Anyone reading about it for the first time would probably think that this is more useful than the Unspecified kind, but it’s actually the opposite.
There are basically two main problems with it. First, local DateTime values don’t carry any information about time zones at all. You’d think that’s the case, based on the name, but you’d be wrong.
A local DateTime value only knows that it’s local in relation to the machine where it was generated, but that’s it. It has no concept of “hey, I’m a date in the America/Los_Angeles time zone.” It’s pretty much just a label with “Local” on it.
The second issue is that Local values don’t roundtrip. If you have a local DateTime value, as soon as it leaves your machine, it becomes unspecified.
You’re Allowed to Mix Between Kinds (And You Shouldn’t Be!)
So, we have one super useful kind with a clear descriptive name, another super useful kind with a somewhat confusing name, and finally, a kind that’s pretty much useless, with a name that makes it sound like it’s useful.
This situation is already bad enough, but it gets worse.
How so? Well, you can mix up values of different kinds, in ways that create inconsistent results, and nothing stops you from doing that.
Consider the code below:
var d1 = new DateTime(2019, 1, 1, 12, 15, 40, DateTimeKind.Local); var d2 = new DateTime(2019, 1, 1, 15, 15, 40, DateTimeKind.Utc); Console.WriteLine("Duration: {0}", d2 - d1);
At this point, I think it’s clear what’s wrong with the example above.
We’re subtracting two DateTime values, one with the Local kind and the other with the UTC kind. That doesn’t make sense and shouldn’t be allowed since the two values represent different concepts of time.
Just like adding a Celsius temperature to a Fahrenheit one requires conversion to a single unit, the same applies here. Remember to always convert dates to UTC before performing arithmetic with them.
DateTime.Now Alternatives
Now we know that DateTime.Now is problematic because it returns the current date and time, expressed as local time (i.e., with the Local kind, which is the least useful one).
It carries no information that allows someone geographically removed to reconstruct what the time would be in their time zone. And even if it did, it wouldn’t make a difference, since Local values stop being Local as soon as they cross a machine’s boundary.
What are the alternatives then?
You’ve already seen one. Let’s learn some more.
DateTime.UtcNow
The first alternative is the one you’ve already seen. Use “UtcNow” to retrieve the current date and time, expressed as Utc.
The disadvantage of this approach is that the result is still a normal DateTime object that can be abused by combining with values of different kinds, and there’s no way to prevent that from happening.
DateTimeOffset.Now
Without resorting to third-party solutions, DateTimeOffset.Now is the preferred alternative to avoid many of the potential problems of the DateTime object. It also returns the current date and time, plus the offset from UTC.
The main advantage of this approach is that its result is a DateTimeOffset object, which is a different type and thus can’t be abused in the ways that DateTime values can.
DateTimeOffset values are easily converted back to UTC, since they carry the offset. They’re also expressed in the local time, which allows for easy visualization when you need to understand when something happened in the local time zone.
In other words, DateTimeOffset the best of both worlds, combined.
Third-Party Solutions
Finally, you can always go the open-source route and use the NodaTime library, which has different types to describe each different facet of date and time, allowing you to easily express your intent with your code in a safe manner.
DateTime.Now Best Practices
Time for some best practices related to the DateTime.Now property.
First of all, let’s address when it’s OK to actually use it.
The answer is?only when the downsides of the Local kind don’t cause any harm. That is, when it doesn’t matter that Local values don’t have time zone information and when the values aren’t supposed to leave the machine.
In other words, DateTime.Now is OK to use when you just want to display the current time on your application’s screen.
When printing out the current date and time, refrain from hardcoding the format.
If you’re from a country that uses the “dd/MM/yyyy” format for short dates, it might be tempting to hardcode that format when displaying the date. Don’t do so! If you do, your app won’t display the date in a meaningful format when used by people in other countries that adopt different formats.
Instead, show preference to alternatives that will automatically adapt to whatever language/culture your app happens to be running in. In the case of the short date, that would be the “d” format string.
Finally, a very important practice: don’t use DateTime.Now to benchmark code!
Besides precision issues, you might run into trouble due to DST. Remember that DateTime.Now provides you with Local values that are subject to Daylight Savings Time, if this is a thing where you live. So if you have the bad luck of a DST transition happening during your benchmark session, you’ll get a result that is off by one hour?or whatever the transition amount is?in either direction.
Instead, use the?Stopwatch class.
Now It’s Up to You
Date and time issues are a fascinating, weird, and tricky subject. It’s very hard to do it justice in a humble blog post, but I hope I did a good job of teaching you a little bit about the DateTime.Now property and the problems its misuse can cause, as well as equipping you with some best practices and alternatives to help when you’re working with date and time problems.
Never stop learning. See you next time!
Learn more how CodeIt.Right can help you automate code reviews and improve the quality of your code.
3 Comments. Leave new
[…] DateTime.Now: Usage, Examples, Best Practices, and Pitfalls – Carlos Schults […]
Dealing with DateTimes is a very delicate matter and should be treated as such. This blog provides very useful information going about that. It should be mandatory to any developer that takes their job seriously.
Fabulous choice of topic… learnt a lot, which I didn’t in many years..