Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
It's obvious, use TimeSpans to measure time

I know, this is probably not news to anyone. TimeSpan is the native .NET type to represent time intervals. But answer quickly, SqlCommand.CommandTimeout represents the interval in milliseconds, seconds, or minutes? What about System.Timers.Timer.Interval ?

To circumvent this situation we see all sorts of API design contortions, like trying to standardize all time units to the same unit, which sometimes is not viable, or using unnatural affixes when naming the class members, for example.

class CalendarEvent
{
	public string Name { get; set; }
	public int DurationMinutes { get; set; }
}
//or..
class EquipmentError
{
	public int ErrorCode { get; set; }
	public double MillisecondsTotal { get; set; }
}
//or...
class ProjectPhase
{
	public int ProjectID { get; set; }
	public string PhaseName { get; set; }
	public int PhaseWeeksDuration { get; set; }
}

I think this stinks. Why do we constantly ignore the TimeSpan structure? I know it's kind of the bastard child of the System namespace. It lacks for example string formats. It's larger than a simple Int32. But the complete annihilation of any doubt as to what time unit we are using is worth all that.

The previous examples could be made clearer with TimeSpans.

class CalendarEvent
{
	public string Name { get; set; }
	public TimeSpan Duration { get; set; }
}
//or..
class EquipmentError
{
	public int ErrorCode { get; set; }
	public TimeSpan TotalTime { get; set; }
}
//or...
class ProjectPhase
{
	public int ProjectID { get; set; }
	public string PhaseName { get; set; }
	public TimeSpan PhaseDuration { get; set; }
}

But let's not stop there. We can simplify our lives by, for example, creating some extension methods to deal with time interval tasks. I don't show below, but we could very well write an extension method to fix the lack of a TimeSpan.ToString(string format) method.

using System;
namespace Utils.Extensions.Time
{
	public static class TimespanExt
	{
		public static TimeSpan Minutes(this int interval)
		{
			return Minutes((double)interval);
		}
		
		public static TimeSpan Minutes(this double interval)
		{
			return TimeSpan.FromMinutes(interval);
		}

		public static TimeSpan Seconds(this int interval)
		{
			return Seconds((double)interval);
		}

		public static TimeSpan Seconds(this double interval)
		{
			return TimeSpan.FromSeconds(interval);
		}

		//.. a metric ton more utility methods like these...
	}
}

With these extension methods, we get some handy syntax to ease the creation of TimeSpans.

TimeSpan interval = 5.Seconds();
TimeSpan elapsedTime = 0.7.Minutes();

And don't forget to use the Nulalble<TimeSpan>, a.k.a. TimeSpan? when the interval is optional. I think the nullable is clearer than using TimeSpan.Zero (or TimeSpan.MinValue — argh!!!) to represent unknown or missing values.


Posted 07-24-2008 2:39 AM by sergiopereira
Filed under: ,

[Advertisement]

Comments

El Guapo wrote re: It's obvious, use TimeSpans to measure time
on 07-24-2008 8:39 AM

1. Timespan is not serializible

2. Timespan cannot be passed in SqlCommand argument

It's very limited because of these. You end up having to store "DurationInSeconds" anyway so you just use only that for simplicity.

Joshua Flanagan wrote re: It's obvious, use TimeSpans to measure time
on 07-24-2008 8:41 AM

This is a great point when it comes to the infrastructure timeout value examples.

However, when you start talking about your domain objects, I think using the TimeSpan may create an even more awkward API. Your domain should likely be intentionally constrained to the situations that make sense for it. If your domain always calls for ProjectPhases to be measured in weeks, it would help if the API would guide the user (developer) in that direction. if you use the TimeSpan. It tells the user that any time duration is possible and suggests a possible phase duration could be: 1 week, 3 days: 4 hours, 2 and seconds. I think it provides better documentation to use the slightly awkward PhasesWeeksDuration property, as opposed to a PhaseDuration property which has a bunch of ArgumentOutOfRange checks to to ensure the value is always a number of days divisible by 7.

sergiopereira wrote re: It's obvious, use TimeSpans to measure time
on 07-24-2008 9:12 AM

@El Guapo

1 - good point. That's another problem that comes with being the bastard child data type.

2 - Not a big problem, at least for me. I can always use TotalSeconds if that is what the underlying database needs. I prefer to not let the DB dictate my domain objects, if possible.

sergiopereira wrote re: It's obvious, use TimeSpans to measure time
on 07-24-2008 9:15 AM

@Joshua, in this case you don't really have a time interval, you have time boxes or a pre-defined time unit that everyone knows about. Probably a bad example on my part.

TimeSpans can't replace all forms of time measurement.

Dmitri wrote re: It's obvious, use TimeSpans to measure time
on 08-02-2008 10:40 AM

Definitely not the class for performance measurements, though :)

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)