在C#中表示时间(不是日期和时间)

我正在开发一款需要开放时间概念的应用程序(有点像商店)

如何最好地代表这些? 它们将在以后持久存储在数据库中……

到目前为止,我有以下课程:

public class OpeningTime { public DayOfWeek DayOfWeek { get; set; } public DateTime OpeningTime { get; set; } public DateTime ClosingTime { get; set; } } 

所以我虚构的“商店”课程会是这样的:

 public class Shop { public string Name { get; set; } public string Address { get; set; } public List OpeningTimes { get; set; } } 

DateTime仍然适用于表示类似的内容:

周一 – 9:00 – 17:30

就个人而言,我会使用TimeSpan而不是DateTime,但我听到其他人表达相反的观点。

 [Serializable()] public class OpeningTime { protected OpeningTime() { } public OpeningTime(DayOfWeek dayOfWeek, TimeSpan fromTime, TimeSpan toTime) : this(dayOfWeek, fromTime.Hours, fromTime.Minutes, toTime.Hours, toTime.Minutes) { } public OpeningTime(DayOfWeek dayOfWeek, int fromHours, int fromMinutes, int toHours, int toMinutes) { if (fromHours < 0 || fromHours > 23) { throw new ArgumentOutOfRangeException("fromHours", "fromHours must be in the range 0 to 23 inclusive"); } if (toHours < 0 || toHours > 23) { throw new ArgumentOutOfRangeException("toHours", "toHours must be in the range 0 to 23 inclusive"); } if (fromMinutes < 0 || fromMinutes > 59) { throw new ArgumentOutOfRangeException("fromMinutes", "fromMinutes must be in the range 0 to 59 inclusive"); } if (toMinutes < 0 || toMinutes > 59) { throw new ArgumentOutOfRangeException("toMinutes", "toMinutes must be in the range 0 to 59 inclusive"); } this.FromTime = new TimeSpan(fromHours, fromMinutes, 0); this.ToTime = new TimeSpan(toHours, toMinutes, 0); if (this.FromTime >= this.ToTime) { throw new ArgumentException("From Time must be before To Time"); } this.DayOfWeek = dayOfWeek; } public virtual DayOfWeek DayOfWeek { get; private set; } public virtual TimeSpan FromTime { get; private set; } public virtual TimeSpan ToTime { get; private set; } } 

坚持使用DateTime

我会使用DateTime,因为它很好地映射到SQL(SQL也使用DateTime),我发现它比使用TimeSpan更具可读性。 您也可以使用相同的对象并为其添加日期以获取今天的开放时间。

为什么不是TimeSpan?

因为它的名字真的和它意味着什么。 TimeSpan代表一段时间而不是某个时间点。 虽然它在框架中用于表示确切的时间(在TimeOfDay中),但该属性在文档中定义为:

TimeSpan,表示自午夜以来经过的一天中的一小部分。

但是……并不重要

最后它没什么区别,你可以使用TimeSpan,DateTime或你自己的结构。 两者都有很少的开销,它只是归结为你发现更易读和更容易维护的东西。

您可以使用TimeSpan来表示一天中的某个时间。

我认为你可以在内部将其表示为开始的DateTime(它为您提供DayOfWeek),然后为结束时表示TimeSpan,但将它们显示为三个属性,即DateTimes或TimeSpans

现在打开一个更多的DDD帽子……你“可以”使用TimeSpan对象来表示一天中的时间,但如果我正在考虑DDD术语,我会想要考虑商店打开的时间。 TimeSpans可以表示更多信息,您必须在每次处理它们时专门validation它们不超过一天。

因此,一种方法是创建一个表示您尝试表示的简单类(您可以只包装TimeSpan对象而不是使用多个整数)。

 public struct Time { private readonly int _hour; private readonly int _minute; private readonly int _second; public Time(int hour, int minute, int second) { if (hour < 0 || hour >= 24) throw new ArgumentOutOfRangeException("hour", "Hours must be between 0 and 23 inclusive"); if (minute < 0 || minute > 59) throw new ArgumentOutOfRangeException("minute", "Minutes must be between 0 and 23 inclusive"); if (second < 0 || second > 59) throw new ArgumentOutOfRangeException("second", "Seconds must be between 0 and 23 inclusive"); _hour = hour; _minute = minute; _second = second; } public Time(Time time) : this(time.Hour, time.Minute, time.Second) { } public int Hour { get { return _hour; } } public int Minute { get { return _minute; } } public int Second { get { return _second; } } public override string ToString() { return ToString(true); } public string ToString(bool showSeconds) { if (showSeconds) return string.Format("{0:00}:{1:00}:{2:00}", Hour, Minute, Second); return string.Format("{0:00}:{1:00}:{2:00}", Hour, Minute); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (obj.GetType() != typeof (Time)) return false; return Equals((Time) obj); } public bool Equals(Time other) { return other._hour == _hour && other._minute == _minute && other._second == _second; } public override int GetHashCode() { unchecked { int result = _hour; result = (result*397) ^ _minute; result = (result*397) ^ _second; return result; } } } public class OpeningHours { public DayOfWeek DayOfWeek { get; set; } public Time OpeningTime { get; set; } public Time ClosingTime { get; set; } public OpeningHours(DayOfWeek dayOfWeek, Time openingTime, Time closingTime) { DayOfWeek = dayOfWeek; OpeningTime = openingTime; ClosingTime = closingTime; } }