Skip to Content
Course content

113: Working with TimeSpan

Click on the "Edit" button in the top corner of the screen to edit your slide content.

A few years ago, I was reviewing a PR from a junior dev who was building a session timeout feature. They had stored the "timeout limit" as a simple integer in the configuration file—30—and then scattered DateTime.Now.AddMinutes(timeoutLimit) all over the codebase. The problem started when the product manager asked for the timeout to be 90 seconds instead of 30 minutes. Suddenly, that integer 30 didn't make sense anymore, and the developer had to hunt down every instance of AddMinutes and change it to AddSeconds, while also updating the config value to 90. It was a mess of "magic numbers" and guesswork.

This is exactly why TimeSpan exists. In C#, DateTime represents a specific point in time (a date and a clock reading), but TimeSpan represents a duration—the amount of time that passes between two points. When you start thinking in terms of durations rather than just adding numbers to dates, your code becomes much more intentional and far less prone to these kinds of bugs.

Defining Durations without the Math Headaches

You can create a TimeSpan in a few ways, but I always recommend the From... static methods. They are explicit and readable. If you see TimeSpan.FromMinutes(30), you know exactly what's happening. If you see new TimeSpan(0, 30, 0), you have to remember the order of the constructor arguments (hours, minutes, seconds), which is a waste of your mental energy.

// The clear way to do it
TimeSpan sessionTimeout = TimeSpan.FromMinutes(30);
TimeSpan gracePeriod = TimeSpan.FromSeconds(45);
TimeSpan longTermStorage = TimeSpan.FromDays(7);

// You can also use the static constants for common durations
TimeSpan zero = TimeSpan.Zero;
TimeSpan infinity = TimeSpan.MaxValue;

I've found that using these methods makes the code self-documenting. You aren't just passing an integer; you're passing a type that explicitly says "I am a length of time."

The Trap of TotalSeconds vs Seconds

This is the part that trips up almost everyone at first. TimeSpan has two types of properties: the component properties and the "Total" properties. This distinction is critical.

  • Component Properties (e.g., .Seconds): These return the remaining part of the time slice. If your TimeSpan is 1 minute and 10 seconds, .Seconds will return 10.
  • Total Properties (e.g., .TotalSeconds): These return the entire duration expressed in that unit. For that same 1 minute and 10 seconds, .TotalSeconds will return 70.
TimeSpan interval = TimeSpan.FromSeconds(70);

Console.WriteLine(interval.Seconds);      // Output: 10
Console.WriteLine(interval.TotalSeconds); // Output: 70

If you're calculating a timeout or a countdown for a UI, you almost always want TotalSeconds or TotalMilliseconds. Using .Seconds in a calculation is a classic bug that usually results in a timer that resets every 60 seconds.

Calculating the Gap Between Events

The most common way you'll encounter TimeSpan is as the result of subtracting one DateTime from another. In C#, the subtraction operator for DateTime is overloaded to return a TimeSpan automatically.

DateTime startTime = DateTime.Now;
// ... some heavy processing happens here ...
DateTime endTime = DateTime.Now;

TimeSpan elapsed = endTime - startTime;

if (elapsed.TotalMilliseconds > 500)
{
    Console.WriteLine($"Warning: Operation took too long! {elapsed.TotalMilliseconds}ms");
}

You can also go the other way: adding a TimeSpan to a DateTime gives you a new DateTime. This is much cleaner than calling AddDays() or AddHours() repeatedly when you already have a duration object defined in your settings.




📋 Practical Task

Exercise: Building a Server Response Latency Tracker

Create a small program that simulates tracking the response time of several API calls. Your goal is to determine if the "average latency" of these calls exceeds a specific threshold.

Requirements:

  • Define a TimeSpan variable called latencyThreshold set to 200 milliseconds.
  • Create a list of DateTime objects representing the "start time" and "end time" of three simulated API calls (you can just hardcode these as DateTime.Now.AddMilliseconds(...) to simulate different durations).
  • Calculate the TimeSpan for each call by subtracting the start from the end.
  • Calculate the average total milliseconds across all three calls.
  • Print whether the average latency was "Acceptable" or "Too Slow" based on your latencyThreshold.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.