I have a Time column in a database table. The date is not important, we just want a time in the day. What type would be best to represent it in C#? I was going to use a DateTime, but I don't like the idea of having a date.
8 Answers
Updated Answer:
Starting with .NET 6, you can use the built-in TimeOnly
data type. The rationale is the same as below:
Original Answer:
While the other answers are mostly correct that a TimeSpan
is the only built-in type that will work, it's important to realize that there are distinct differences between an "elapsed measurement of time" and a "time of day".
The most obvious difference is that a time of day must be less than 24 hours. A
TimeSpan
object can cover much more than that.Another difference is that a
TimeSpan
type can be negative. This represents moving backwards in time. A negative value would be meaningless as a time-of-day.And finally, a time-of-day includes any concept of daylight saving time that might apply to the time zone in which it was taken. So you can't think of it as "elapsed time since midnight".
If it's the day of the spring-forward DST transition (in the USA), then a value of
4:00
has only elapsed 3 hours since midnight.If it's the day of the fall-back DST transition (in the USA), then a value of
4:00
has actually elapsed 5 hours since midnight.And since DST is different all over the world, it's entirely possible that midnight doesn't even exist, or exists twice. This happens in places like Brazil, and others.
So if you use TimeSpan
as a time-of-day, you need to be aware of these issues. .NET doesn't have a built-in type for a time-of-day, so this is an acceptable compromise, even though it's in violation of it's own design.
Even the .NET Framework itself makes this compromise. For example:
- The
DateTime
class has aTimeOfDay
property that returns aTimeSpan
. - If you have
time
type in SQL Server, it will be aTimeSpan
when returned through the .NET SQL Client.
The MSDN Reference Documentation has this to say about the TimeSpan
type:
The TimeSpan structure can also be used to represent the time of day, but only if the time is unrelated to a particular date. Otherwise, the DateTime or DateTimeOffset structure should be used instead.
That is basically another way of saying what I covered in my third point above about DST.
However, if you are not interested in making compromises in your design and would like a real time-of-day type, then take a look at the Noda Time library.
- There is the
LocalTime
type, which represents a time of day. This is the direct answer to the question that was asked. - There is a
Duration
type, which represents an elapsed measure of time. - There is also a
Period
type, which represents a positional movement on a calendar - which is something else thatTimeSpan
can't do. For example, "3 years and 5 months" would be aPeriod
value. - There is also an
Offset
type, which is similar to aDuration
, but is used as an offset from UTC for time zones. It has a range limited to that purpose.
While some could say that TimeSpan
is more versatile since it can handle all of these, the truth is that it allows you to get into trouble. By separating the types, you get safety and consistency.
Alternatively, you may consider the Update: this is now built-in, as the System.Time
package available from Microsoft as part of CoreFX Lab. This package contains implementations of a time-only type called Time
, and a date-only type called Date
. You will need to use the dotnet-corefxlab
MyGet feed to import this package.TimeOnly
data type in .NET 6+

- 230,703
- 74
- 448
- 575
-
You are just trying to make it more complicated than it is. Most of this is just not relevant to the question at all. – Guffa Sep 06 '13 at 19:58
-
6@Guffa - The question was "What type would be best to represent it (a time of day) in C#?" - The answer is a `LocalTime` type from the Noda Time library. The rest is justification. – Matt Johnson-Pint Sep 06 '13 at 20:51
-
You have given your own interpretation of "it" in that sentence, but that's not what the question is. The OP has a value from a database column with a specific type, and want the corresponding type in C#. It's not more complicated than that. – Guffa Sep 06 '13 at 20:59
-
4@Guffa - Clearly we agree to disagree. I stand by my position, and I respect yours. Good day. – Matt Johnson-Pint Sep 06 '13 at 21:02
-
6But isn't a TimeSpan a range of time? Apparently, the end time is unknown, the event could just start at 2pm and last indefinitely. Would it still be a good idea to use a TimeSpan? – Carlo Sep 10 '10 at 23:22
-
1But a time of day is really just the time elapsed since midnight. So, the same concept, really. – dommer Sep 10 '10 at 23:32
-
-
3
-
TimeSpan stands for representing time interval. Best approach should be using the DateTime's time component. – Sercan Mar 29 '17 at 07:37
Jon Skeet's been working on something called Noda Time, maybe this will help.
Skeet's post on why it may be right for you: What's Wrong with DateTime Anyway?

- 230,703
- 74
- 448
- 575

- 15,655
- 7
- 50
- 82
You could try something like this
TimeSpan ts = DateTime.Now.TimeOfDay
Where you are applying the time property of the DateTime object and just use that.

- 2,185
- 3
- 21
- 35
Use a Timespan to represent the time span from midnight to the time.

- 687,336
- 108
- 737
- 1,005
-
That's a common misconception, or really a compromise. See my answer for more detail. – Matt Johnson-Pint Sep 06 '13 at 02:16
-
@MattJohnson: No, it's neither a misconception nor a compromise. Even if you are correct about daylight savings time, that is not really relevant to the question, as the data type in the database has the exact same issue. Using a Timespan to hold a Time value doesn't introduce the issues that you mention. – Guffa Sep 06 '13 at 14:17
-
Hi. Actually, no, that's not true. Assuming he is talking about the [SQL Server `time` type](http://technet.microsoft.com/en-us/library/bb677243.aspx), it represents a time-of-day, and not an elapsed duration of time. I also touched on this point [in this answer](http://stackoverflow.com/a/18345493/634824). Where this might bite you in real life is in user input validation. A string might be parseable as a valid `TimeSpan`, but won't fit into a `time` column in the database. If a user enters `24:00` as a time of day, this will fail unless you take the extra step of doing range validation – Matt Johnson-Pint Sep 06 '13 at 17:28
-
@MattJohnson: No, sorry, you are mistaken. It's true. You can try to make it complicated if you like, but it's not. How a value can be parsed into a Timespan value is not relevant to the question either. – Guffa Sep 06 '13 at 19:55
I would use a TimeSpan to represent this, with the TimeSpan being the span of time since midnight. This correlates to DateTime's TimeOfDay property in the framework.

- 554,122
- 78
- 1,158
- 1,373
-
-
@MattJohnson I don't see how anything in your answer negates what I wrote. Yes, a TimeSpan *can* represent other times, but it is perfectly acceptable to use to represent time from (0,24] hours as well. – Reed Copsey Sep 06 '13 at 16:20
-
Hi Reed. Time of day is actually `[0,24)`, but anyway the main point is in the third bullet in my answer. You can't just say that it's the "time elapsed since midnight" because there are values where that is just not true. The MSDN reference says it slightly differently, and I will update my answer to reflect that. – Matt Johnson-Pint Sep 06 '13 at 17:20
-
@MattJohnson I'm not arguing with you on that, but `TimeSpan` does allow you to represent the values where that **is** true, which is what I was saying. – Reed Copsey Sep 06 '13 at 17:27
-
Sure. And that's why I call it a "compromise". Not trying to start an argument, just this is a common source of bugs so I try to be as accurate as possible. – Matt Johnson-Pint Sep 06 '13 at 17:43
Given that this question was the top result in a Google search I just did, it might be worth saying that following the imminent release of .NET 6 (currently slated for November 9th 2021) the correct answer to the question will probably be the new TimeOnly
struct.

- 4,513
- 4
- 45
- 71
We actually rolled our own Time class. The issue we ran into is TimeSpan has no knowledge of timezone offsets which we still needed. So We created a TimeSpanOffset class. Kind of analogous to the DateTimeOffset class. If timezone is not important than I would definitely stick with the TimeSpan.

- 111
- 1
- 12