Coder Perfect

In.NET, how can I represent a time-only value?

Problem

Is there a method to describe a time value in.NET without include the date? For instance, indicating a store’s operating hours?

I just want to save a time value, hence TimeSpan specifies a range. If you use DateTime to indicate this, you’ll get new DateTime(1,1,1,8,30,0), which isn’t ideal.

Asked by sduplooy

Solution #1

You can make use of the time span feature.

TimeSpan timeSpan = new TimeSpan(2, 14, 18);
Console.WriteLine(timeSpan.ToString());     // Displays "02:14:18".

[Edit] In light of the previous responses and the question’s revision, I would continue to use TimeSpan. There’s no purpose in establishing a new structure when the framework already has one. You’d end up replicating a lot of native data types along these lines.

Answered by John G

Solution #2

You can use a DateTime and ignore the date, or you can use a TimeSpan, as others have suggested. Personally, I don’t like either of these solutions because neither type accurately represents the concept you’re trying to portray – I think the date/time types in.NET are a bit sparse, which is one of the reasons I created Noda Time in the first place. The LocalTime type in Noda Time can be used to express a time of day.

There are TimeOnly and DateOnly types in.NET 6 that are basically analogous to Noda Time’s LocalTime and LocalDate types.

One thing to keep in mind is that the time of day is not always the same as the time since midnight on the same day…

(As an aside, if you’re also trying to indicate a shop’s closing hour, you might want to use 24:00, which is the time at the end of the day.) Most date/time APIs, including Noda Time, don’t support representing that as a time-of-day value.)

Answered by Jon Skeet

Solution #3

If that empty Date is truly bothering you, you can make a simpler Time structure like this:

// more work is required to make this even close to production ready
class Time
{
    // TODO: don't forget to add validation
    public int Hours   { get; set; }
    public int Minutes { get; set; }
    public int Seconds { get; set; }

    public override string ToString()
    {  
        return String.Format(
            "{0:00}:{1:00}:{2:00}",
            this.Hours, this.Minutes, this.Seconds);
    }
}

Or, why bother: if you don’t need to calculate anything with that data, just save it as a String.

Answered by Rubens Farias

Solution #4

Use a DateTime, in my opinion. Ignore the date section if you don’t require it. If you only need to show the user the time, format the output to look like this:

DateTime.Now.ToString("t");  // outputs 10:00 PM

All of the extra labor of creating a new class or even using a TimeSpan appears to be redundant.

Answered by bugfixr

Solution #5

Because I think Rubens’ class is a nice idea, I decided to create an immutable sample of it with minimal validation.

class Time
{
    public int Hours   { get; private set; }
    public int Minutes { get; private set; }
    public int Seconds { get; private set; }

    public Time(uint h, uint m, uint s)
    {
        if(h > 23 || m > 59 || s > 59)
        {
            throw new ArgumentException("Invalid time specified");
        }
        Hours = (int)h; Minutes = (int)m; Seconds = (int)s;
    }

    public Time(DateTime dt)
    {
        Hours = dt.Hour;
        Minutes = dt.Minute;
        Seconds = dt.Second;
    }

    public override string ToString()
    {  
        return String.Format(
            "{0:00}:{1:00}:{2:00}",
            this.Hours, this.Minutes, this.Seconds);
    }
}

Answered by Chibueze Opata

Post is based on https://stackoverflow.com/questions/2037283/how-do-i-represent-a-time-only-value-in-net