C# DateTime: What "date" to use when I'm using just the "time"?
Solution 1
what about DateTime.MinValue?
Solution 2
Let's help out the guys who want a Time structure:
/// <summary>
/// Time structure
/// </summary>
public struct Time : IComparable
{
private int minuteOfDay;
public static Time Midnight = "0:00";
private static int MIN_OF_DAY = 60 * 24;
public Time(int minuteOfDay)
{
if (minuteOfDay >= (60 * 24) || minuteOfDay < 0)
throw new ArgumentException("Must be in the range 0-1439", "minuteOfDay");
this.minuteOfDay = minuteOfDay;
}
public Time(int hour, int minutes)
{
if (hour < 0 || hour > 23)
throw new ArgumentException("Must be in the range 0-23", "hour");
if (minutes < 0 || minutes > 59)
throw new ArgumentException("Must be in the range 0-59", "minutes");
minuteOfDay = (hour * 60) + minutes;
}
#region Operators
public static implicit operator Time(string s)
{
var parts = s.Split(':');
if (parts.Length != 2)
throw new ArgumentException("Time must be specified on the form tt:mm");
return new Time(int.Parse(parts[0]), int.Parse(parts[1]));
}
public static bool operator >(Time t1, Time t2)
{
return t1.MinuteOfDay > t2.MinuteOfDay;
}
public static bool operator <(Time t1, Time t2)
{
return t1.MinuteOfDay < t2.MinuteOfDay;
}
public static bool operator >=(Time t1, Time t2)
{
return t1.MinuteOfDay >= t2.MinuteOfDay;
}
public static bool operator <=(Time t1, Time t2)
{
return t1.MinuteOfDay <= t2.MinuteOfDay;
}
public static bool operator ==(Time t1, Time t2)
{
return t1.GetHashCode() == t2.GetHashCode();
}
public static bool operator !=(Time t1, Time t2)
{
return t1.GetHashCode() != t2.GetHashCode();
}
/// Time
/// Minutes that remain to
/// Time conferred minutes
public static Time operator +(Time t, int min)
{
if (t.minuteOfDay + min < (24 * 60))
{
t.minuteOfDay += min;
return t;
}
else
{
t.minuteOfDay = (t.minuteOfDay + min) % MIN_OF_DAY;
return t;
}
}
public static Time operator -(Time t, int min)
{
if (t.minuteOfDay - min > -1)
{
t.minuteOfDay -= min;
return t;
}
else
{
t.minuteOfDay = MIN_OF_DAY + (t.minuteOfDay - min);
return t;
}
}
public static TimeSpan operator -(Time t1, Time t2)
{
return TimeSpan.FromMinutes(Time.Span(t2, t1));
}
#endregion
public int Hour
{
get
{
return (int)(minuteOfDay / 60);
}
}
public int Minutes
{
get
{
return minuteOfDay % 60;
}
}
public int MinuteOfDay
{
get { return minuteOfDay; }
}
public Time AddHours(int hours)
{
return this + (hours * 60);
}
public int CompareTo(Time other)
{
return this.minuteOfDay.CompareTo(other.minuteOfDay);
}
#region Overrides
public override int GetHashCode()
{
return minuteOfDay.GetHashCode();
}
public override string ToString()
{
return string.Format("{0}:{1:00}", Hour, Minutes);
}
#endregion
///
/// Safe enumerering - whatever interval applied max days
///
/// Start time
/// Spring in minutes
///
public static IEnumerable Range(Time start, int step)
{
return Range(start, start, step);
}
///
/// Safe enumeration - whatever interval applied max days
///
public static IEnumerable Range(Time start, Time stop, int step)
{
int offset = start.MinuteOfDay;
for (var i = 0; i < Time.Span(start, stop); i += step)
{
yield return Time.Midnight + (i + offset);
}
}
///
/// Calculates the number of minutes between t1 and t2
///
public static int Span(Time t1, Time t2)
{
if (t1 < t2) // same day
return t2.MinuteOfDay - t1.MinuteOfDay;
else // over midnight
return MIN_OF_DAY - t1.MinuteOfDay + t2.MinuteOfDay;
}
}
Solution 3
A TimeSpan most certainly can store the time of the day - you just have to treat the value as the amount of time elapsed since midnight, basically the same way we read a clock.
Solution 4
Personally I'd create a custom Time
struct
that contains a DateTime
instance, and which has similar properties, constructors etc. but doesn't expose days/months/etc. Just make all your public accessors pass through to the contained instance. Then you can simply have the epoch as a private static readonly DateTime
field and it doesn't matter what value you choose as it's all neatly contained within your custom struct. In the rest of your code can simply write:
var time = new Time(16, 47, 58);
Solution 5
Given that DateTime.TimeOfDay returns a TimeSpan, I'd use that.
Why can't you use a TimeSpan? I don't understand your comment that it doesn't store times of day.
mistertodd
Any code is public domain. No attribution required. జ్ఞా <sup>🕗</sup>🕗 Yes, i do write i with a lowercase i. The Meta Stackexchange answer that I am most proud of
Updated on November 13, 2020Comments
-
mistertodd over 3 years
I'm using a
DateTime
in C# to display times. What date portion does everyone use when constructing a time?E.g. the following is not valid because there is no zero-th month or zero-th day:
// 4:37:58 PM DateTime time = new DateTime(0, 0, 0, 16, 47, 58);
Do I use COM's zero date?
// 4:37:58 PM DateTime time = new DateTime(1899, 12, 30, 16, 47, 58);
Or perhaps SQL Server's?
//4:37:58 PM DateTime time = new DateTime(1900, 1, 1, 16, 47, 58);
I realize it's arbitrary, since I'll be ignoring the date portions in code, but it would still be nice to be able to use:
DateTime duration = time2 - time1;
Answer
I think I like MinValue
DateTime time = DateTime.MinValue.Date.Add(new TimeSpan(16, 47, 58));
Note: I can't use a
TimeSpan
, because that doesn't store times of the day. And the reason I know that is because there's no way to display its contents as a time.Which is to say that
TimeSpan
records a span of time, not a time of day, e.g.:TimeSpan t = new TimeSpan(16, 47, 58); t.ToString();
returns a span of time in the format hours:minutes:seconds, e.g.:
16:47:58
rather than a time:
4:47:58 PM (United States) 04:47:58 nm (South Africa) 4:47:58.MD (Albania) 16:47:58 (Algeria) 04:47:58 م (Bahrain) PM 4:47:58 (Singapore) 下午 04:47:58 (Taiwan) 04:47:58 PM (Belize) 4:47:58 p.m. (New Zealand) 4:47:58 μμ (Greece) 16.47.58 (Italy) 오후 4:47:58 (Korea) 04:47:58 ب.ظ (Iran) ਸ਼ਾਮ 04:47:58 (India) 04:47:58 p.m. (Argentina) etc
In other words, there is a difference between a timespan, and a time. And also realize that
TimeSpan
doesn't provide a mechanism to convert a span of time into a time of day - and there is a reason for that.