CodeGym /Courses /C# SELF /Main Types for Working with Time

Main Types for Working with Time

C# SELF
Level 15 , Lesson 0
Available

1. Getting to Know DateTime

Date and time are such a fundamental building block of any business logic that you just can't ignore them, even in the simplest projects. You often need to know when a user registered, when to send an email, how to handle flight schedules, time zones—dates are everywhere! But, as practice shows, working with date and time is one of the trickiest topics in programming. 😅

C# gives you two especially important types for working with time: DateTime and DateTimeOffset. In a nutshell—one is for simple scenarios, the other is for stuff involving time zones and precise time storage.

What is DateTime?

The DateTime type is a struct defined in the System namespace. It's meant for storing date and time with a precision of up to 100 nanoseconds (that's 1/10th of a billionth of a second).

  • It's a value type (struct), so it's copied by value.
  • Holds both date and time.
  • Lets you store just a date (2025-05-24) or a date with time (2025-05-24 15:17:42).
  • Doesn't "know" about time zones unless you explicitly tell it.

2. Creating a DateTime

There are a few ways—let's check out the main ones.

1. Current Date and Time

DateTime now = DateTime.Now;           // Local computer time
DateTime utcNow = DateTime.UtcNow;     // Greenwich Mean Time (UTC)
  • Now is "as on your computer," taking into account your local Windows time zone.
  • UtcNow is "universal," meaning Coordinated Universal Time. Super handy for storing time, like in databases or systems that work worldwide.

2. Constructors

// Year, month, day
var date1 = new DateTime(2025, 5, 24);

// Year, month, day, hour, minute, second
var date2 = new DateTime(2025, 5, 24, 12, 0, 0);

// Year, month, day, hour, minute, second, millisecond
var date3 = new DateTime(2025, 5, 24, 12, 0, 0, 500);

Months are NOT zero-based! So January is 1, December is 12.

3. Parsing from a String

Very often, a date comes as a string! For example, a user types in a date manually.

string userInput = "2025-05-24 18:30";
DateTime parsed = DateTime.Parse(userInput); // Might throw an exception!

For safe parsing—use TryParse:

string input = "2025-05-24 18:30";
if (DateTime.TryParse(input, out DateTime result))
{
    Console.WriteLine($"Converted successfully: {result}");
}
else
{
    Console.WriteLine("Couldn't convert string to date.");
}

4. Getting a Date "Without Time"

DateTime today = DateTime.Today; // Current day, but time = 00:00:00

Extracting Date and Time Components

You can grab all the properties super quick:

var dt = new DateTime(2025, 5, 24, 15, 17, 42);

int year = dt.Year;         // 2025
int month = dt.Month;       // 5 (May)
int day = dt.Day;           // 24
int hour = dt.Hour;         // 15
int minute = dt.Minute;     // 17
int second = dt.Second;     // 42
DayOfWeek dow = dt.DayOfWeek; // Friday

3. Working with DateTime

Adding and Subtracting Dates

Time in programming moves fast, and instead of counting "how many hours till the deadline," just use the class methods:

DateTime now = DateTime.Now;
DateTime tomorrow = now.AddDays(1); // Tomorrow
DateTime afterFiveHours = now.AddHours(5); // In 5 hours
DateTime inTenMinutes = now.AddMinutes(10); // In 10 minutes

Difference Between Two Dates: TimeSpan

The difference between two dates is a separate value, the TimeSpan type:

DateTime deadline = new DateTime(2026, 6, 1);
DateTime now = DateTime.Now;

TimeSpan untilDeadline = deadline - now;

Console.WriteLine($"Days left until deadline: {untilDeadline.Days}");
Console.WriteLine($"Hours left until deadline: {untilDeadline.TotalHours:N2}");

TimeSpan is a "difference," not a "specific date/time"!

Checking if a Date is in the Future/Past

if (deadline > now)
    Console.WriteLine("Deadline is still ahead!");
else
    Console.WriteLine("Deadline has already passed! Submit your work ASAP!");

4. How Dates are Stored Under the Hood

To make adding and subtracting dates easier, programmers decided to store all dates as the number of seconds since the beginning of our era. Value ranges:

Property Value
Minimum date
DateTime.MinValue
= 0001-01-01 00:00:00
Maximum date
DateTime.MaxValue
= 9999-12-31 23:59:59.9999999
Unit of measurement 1 tick = 100 nanoseconds

DateTime doesn't just store the number of seconds, but the number of "ticks" (ticks) since a special date—January 1, 0001 (yep, programmers don't care about dinosaurs, their calendar is stricter). One tick = 100 nanoseconds.

5. The DateTimeOffset Type

Sometimes DateTime just isn't enough. Classic case: a company works in two countries, they have different time zones, and all meetings are scheduled "in my time." What do you do?

Time written as DateTime is often "abstract": it's just a bunch of digits and ticks until you explicitly say what zone it's in. For example, if you get "2025-05-24 15:00", you can't be sure—is that Nairobi time? Baghdad? Berlin? (And if it's daylight saving time—hold on tight!).

That's why, for stuff where you need the exact moment in time, not just a "calendar date," there's a second type—DateTimeOffset. Creating a DateTimeOffset with an offset (like Nairobi +3 to UTC):


var localTime = new DateTimeOffset(2025, 5, 24, 15, 0, 0, TimeSpan.FromHours(3));

Use DateTimeOffset if:

  • You need to know the exact moment in time (like for log events tied to server time).
  • Your app works with users in different time zones.
  • You need to store/pass time with the zone (like for transactions, events, schedules).

6. How to Create a DateTimeOffset?

  1. Current moment in time
    DateTimeOffset now = DateTimeOffset.Now; // Local time + offset
    DateTimeOffset utc = DateTimeOffset.UtcNow; // UTC (offset 0)
    
  2. Explicit creation
    // Year, month, day, hour, minute, second, offset (like, +2 hours)
    DateTimeOffset custom = new DateTimeOffset(2025, 5, 24, 20, 0, 0, TimeSpan.FromHours(2));
    
  3. Convert from DateTime
    DateTime dt = DateTime.Now;
    DateTimeOffset dto = new DateTimeOffset(dt); // Local offset will be picked up automatically
    

Extracting Components

DateTimeOffset dto = DateTimeOffset.Now;
var datePart = dto.Date;      // Just the date
var timePart = dto.TimeOfDay; // Just the time
var offset = dto.Offset;      // Offset from UTC, like 03:00:00

Converting Between Time Zones

Offset magic:

// Get date in UTC
var now = DateTimeOffset.Now;
var utc = now.ToUniversalTime();
Console.WriteLine(utc); // Greenwich Mean Time

// Convert to another zone
var berlinTime = utc.ToOffset(TimeSpan.FromHours(2));
Console.WriteLine(berlinTime); // For Berlin (CET +2)

7. When to Use DateTime and When to Use DateTimeOffset?

The Philosophy of Choosing

When it's something simple and local—like a birthday, article publish date, or a survey deadline at 3:00 PM—usually DateTime is enough. In these cases, absolute time isn't critical, and it's only important that the event happened on a certain day and hour, without worrying about the time zone.

But if you need to lock in the exact moment in time with the time zone, like in logs, transactions, or distributed systems—it's better to use DateTimeOffset. It won't let you get confused when passing time between systems, especially if they're in different time zones.

Scenario Type Why
Birthday
DateTime
Only the date matters, zone doesn't (usually)
Login time
DateTimeOffset
Need to know the exact moment and offset
Product expiration date
DateTime
End date, zone doesn't matter
Log event time
DateTimeOffset
It's best to always store with offset
2
Task
C# SELF, level 15, lesson 0
Locked
Displaying the current date and time in different formats
Displaying the current date and time in different formats
2
Task
C# SELF, level 15, lesson 0
Locked
Adding and Subtracting Time
Adding and Subtracting Time
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION