DateTime. Think of a certain point in time. In C# programs, a DateTime struct instance can be used to represent this time value (and handle its complexities).
We use DateTime and its many formatting codes to parse and format time. As a struct, a DateTime is more like an int than a class instance.
Constructor. Here we call the instance DateTime constructor. The arguments must match a real date that occurred. This is a validating constructor—the month and day follow the year argument.
Finally The code writes the value of the fully constructed DateTime struct to the console.
using System;
// Create a DateTime with 3 arguments.
DateTime value = new DateTime(2022, 6, 22);
Console.WriteLine("TIME: {0}", value);TIME: 6/22/2022 12:00:00 AM
Un-representable error. The DateTime constructor validates possible arguments. If we try to create a DateTime that cannot exist, we get an argument exception.
using System;
// This will cause an error.
DateTime x = new DateTime(-1, 1, 1);An unhandled exception of type 'System.ArgumentOutOfRangeException'
occurred in mscorlib.dll
Additional information: Year, Month, and Day parameters describe an
un-representable DateTime.
AddDays, Add. We can add values to a DateTime with methods like AddDays, AddMonths and Add() which receives a TimeSpan. The most versatile method is Add(), and we can add any TimesSpan.
Info The Add method (and Subtract) requires a TimeSpan argument. We must first use the TimeSpan constructor.
Next AddDays receives a double—it can add or subtract days. We can use AddHours, AddMinutes, AddSeconds and more.
using System;
var year2K = new DateTime(2000, 1, 1);
// Update the time with AddDays, AddMonths and Add.
var updated = year2K.AddDays(1);
Console.WriteLine("ADD 1 DAY: {0}", updated);
updated = updated.AddMonths(1);
Console.WriteLine("ADD 1 MONTH: {0}", updated);
// Add 1 day with Add and TimeSpan.
updated = updated.Add(TimeSpan.FromDays(1));
Console.WriteLine("ADD 1 DAY: {0}", updated);ADD 1 DAY: 1/2/2000 12:00:00 AM
ADD 1 MONTH: 2/2/2000 12:00:00 AM
ADD 1 DAY: 2/3/2000 12:00:00 AM
Yesterday. Here we subtract one day from the current day. We do this by adding -1 to the current day. This is necessary because no "SubtractDays" method is provided.
Note The example was run a few years ago. The output will naturally vary depending on the day you run it.
And DateTime.Today is always set to the machine's local time, which depends on the current system.
using System;
class Program
{
static void Main()
{
Console.WriteLine("Today: {0}", DateTime.Today);
DateTime y = GetYesterday();
Console.WriteLine("Yesterday: {0}", y);
}
/// <summary>/// Gets the previous day to the current day./// </summary>
static DateTime GetYesterday()
{
// Add -1 to now.
return DateTime.Today.AddDays(-1);
}
}Today: 11/30/2008 12:00:00 AM
Yesterday: 11/29/2008 12:00:00 AM
Tomorrow. To figure out tomorrow, we add one using the Add() method. This is useful with date queries in databases. We use the AddDays method.
Detail GetTomorrow is a static method—it does not require state to be saved. DateTime.Today is also static.
Tip DateTime.Add uses offsets. It accepts both negative and positive numbers. Here we go back in time.
using System;
class Program
{
static void Main()
{
Console.WriteLine("Today: {0}", DateTime.Today);
DateTime d = GetTomorrow();
Console.WriteLine("Tomorrow: {0}", d);
}
/// <summary>/// Gets the next day, tomorrow./// </summary>
static DateTime GetTomorrow()
{
return DateTime.Today.AddDays(1);
}
}Today: 11/30/2008 12:00:00 AM
Tomorrow: 12/1/2008 12:00:00 AM
First day. We use a helper method to find the first day in a year. We use an overloaded method. With overloading, we often can use methods in an easier, clearer way.
Detail If we want the current year, we can call FirstDayOfYear with no parameter. The year from Today will be used.
using System;
class Program
{
static void Main()
{
Console.WriteLine("First day: {0}", FirstDayOfYear());
DateTime d = new DateTime(1999, 6, 1);
Console.WriteLine("First day of 1999: {0}", FirstDayOfYear(d));
}
/// <summary>/// Gets the first day of the current year./// </summary>
static DateTime FirstDayOfYear()
{
return FirstDayOfYear(DateTime.Today);
}
/// <summary>/// Finds the first day of year of the specified day./// </summary>
static DateTime FirstDayOfYear(DateTime y)
{
return new DateTime(y.Year, 1, 1);
}
}First day: 1/1/2008 12:00:00 AM
First day of 1999: 1/1/1999 12:00:00 AM
Last day. Here we find the last day in any year. Leap years make this more complicated, as February may have 28 or 29 days. We must programmatically find the year's length.
Tip This method is ideal for when you want to count days, as for a database range query for a certain year.
Tip 2 It is better to use the DateTime constructor, rather than DateTime.Parse. This is faster and has clearer syntax.
using System;
class Program
{
static void Main()
{
Console.WriteLine("Last day: {0}", LastDayOfYear());
DateTime d = new DateTime(1999, 6, 1);
Console.WriteLine("Last day of 1999: {0}", LastDayOfYear(d));
}
/// <summary>/// Finds the last day of the year for today./// </summary>
static DateTime LastDayOfYear()
{
return LastDayOfYear(DateTime.Today);
}
/// <summary>/// Finds the last day of the year for the selected day's year./// </summary>
static DateTime LastDayOfYear(DateTime d)
{
// Get first of next year.
DateTime n = new DateTime(d.Year + 1, 1, 1);
// Subtract one from it.
return n.AddDays(-1);
}
}Last day: 12/31/2008 12:00:00 AM
Last day of 1999: 12/31/1999 12:00:00 AM
Now, UtcNow. The Now property returns the current DateTime, with all of the fields correctly filled. UtcNow is Universal Coordinated Time, or Greenwich MeanTime.
Tip The Now property returns the time as a local time, which means it depends on the time zone of the current computer configuration.
using System;
var now = DateTime.Now;
var utc = DateTime.UtcNow;
// UTC is Greenwich MeanTime.
Console.WriteLine("LOCAL: {0}", now);
Console.WriteLine("UTC: {0}", utc);LOCAL: 3/14/2020 3:17:55 AM
UTC: 3/14/2020 10:17:55 AM
Parse. It is possible to parse DateTime instances. This converts a string value into a DateTime. The "Try" methods avoid expensive exceptions on invalid strings.
Here The program uses TryParse in an if-statement. If the parsing is successful, we print the RESULT line.
using System;
string value = "3/13/2020";
// Use TryParse to convert from string to DateTime.
if (DateTime.TryParse(value, out DateTime result))
{
Console.WriteLine("RESULT: {0}", result);
}RESULT: 3/13/2020 12:00:00 AM
Subtract DateTime. We find the "age" of a certain date, and how long ago it was in time. We can do this with DateTime.Subtract, which will return a TimeSpan.
Tip To get the number of days ago a date occurred, we can use the DateTime.Now property.
using System;
string value1 = "3/13/2020";
string value2 = "3/14/2020";
// Parse the dates.
var date1 = DateTime.Parse(value1);
var date2 = DateTime.Parse(value2);
// Compute the difference between the 2 dates.
var difference = date2.Subtract(date1);
Console.WriteLine("DAYS DIFFERENCE: {0}", difference.TotalDays);DAYS DIFFERENCE: 1
Month property. We access the Month property—this returns an integer from 1 to 12 that indicates the month. The value 3 here indicates the month of March.
using System;
// Print the month for this date string.
var date = DateTime.Parse("3/13/2020");
Console.WriteLine("MONTH: {0}", date.Month);MONTH: 3
DaysInMonth. Many static methods are also available on the DateTime class. With DaysInMonth we look up the number of days in a month based on the year.
using System;
int days = DateTime.DaysInMonth(2014, 9); // September.
Console.WriteLine(days);
days = DateTime.DaysInMonth(2014, 2); // February.
Console.WriteLine(days);30
28
Error, null. A DateTime cannot be assigned to null. It is a struct, and like an int cannot be null. To fix this program, try using the special value DateTime.MinValue instead of null.
using System;
DateTime current = null;error CS0037: Cannot convert null to 'DateTime'
because it is a non-nullable value type
MinValue example. We can use a special value like DateTime.MinValue to initialize an empty DateTime. This is the same idea as a null or uninitialized DateTime.
using System;
// This program can be compiled.// ... Use MinValue instead of null.
DateTime current = DateTime.MinValue;
Console.WriteLine("MIN VALUE: {0}", current);MIN VALUE: 1/1/0001 12:00:00 AM
Nullable. We can never have a null DateTime instance. DateTime is a value type. But we can use a nullable DateTime. We use a question mark "DateTime?" for this type.
using System;
using System.Collections.Generic;
var values = new List<DateTime>();
values.Add(new DateTime(2023, 1, 1));
values.Add(new DateTime(2021, 1, 1));
values.Add(new DateTime(2022, 1, 1));
// Sort the dates.
values.Sort();
// The dates have been sorted from first to last chronologically.
foreach (var value in values)
{
Console.WriteLine(value);
}1/1/2021 12:00:00AM
1/1/2022 12:00:00AM
1/1/2023 12:00:00AM
Benchmark, DateTime cache. Here is a way to optimize DateTime usage. When a method calls DateTime.Now, we can sometimes cache this value. This prevents excessive time queries.
Info Using DateTime.Now is slower than most property accesses as it must fetch the time from the OS.
Version 1 We get a new time only every 20 accesses. This cache makes sense if the current time is queried millions of times rapidly.
Version 2 While version 2 gets DateTime.Now each time—no caching layer is introduced.
Result Using a cached value is faster, although .NET 7 in 2023 has made creating a DateTime much faster than before.
using System;
using System.Diagnostics;
static class DateTimeNowCache
{
const int _count = 20;
static DateTime _recentTime = DateTime.Now;
static int _skipped;
public static DateTime GetDateTime()
{
// Get a new DateTime.Now every several requests.// ... This reduces the number of OS time accesses.
_skipped++;
if (_skipped > _count)
{
_recentTime = DateTime.Now;
_skipped = 0;
}
return _recentTime;
}
}
class Program
{
const int _max = 1000000;
static void Main()
{
// Version 1: use cached DateTime.Now.
var s1 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
var result = DateTimeNowCache.GetDateTime();
if (result == DateTime.MaxValue)
{
return;
}
}
s1.Stop();
// Version 2: use DateTime.Now each time.
var s2 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
var result = DateTime.Now;
if (result == DateTime.MaxValue)
{
return;
}
}
s2.Stop();
Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns"));
Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns"));
}
}29.76 ns DateTimeNowCache
141.39 ns DateTime.Now
Summary. Time is a complex subject. But with DateTime and TimeSpan we represent it with relative ease in our programs. These types are value types—like an int.
Dot Net Perls is a collection of tested code examples. Pages are continually updated to stay current, with code correctness a top priority.
Sam Allen is passionate about computer languages. In the past, his work has been recommended by Apple and Microsoft and he has studied computers at a selective university in the United States.
This page was last updated on Nov 10, 2023 (simplify).