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

C# 用C表示时间(不是日期和时间)#,c#,datetime,time,C#,Datetime,Time,我正在开发一个需要开放时间概念的应用程序 (有点像商店) 如何最好地表示这些? 它们将在以后的数据库中持久化 到目前为止,我有以下课程: public class OpeningTime { public DayOfWeek DayOfWeek { get; set; } public DateTime OpeningTime { get; set; } public DateTime ClosingTime { get; set; } } 所以我虚构的“商店”类是这样

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

如何最好地表示这些? 它们将在以后的数据库中持久化

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

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<OpeningTime> OpeningTimes { get; set; }
}
公共类商店
{
公共字符串名称{get;set;}
公共字符串地址{get;set;}
公共列表打开时间{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; }
}
[Serializable()]
公共类开放时间
{
受保护的OpeningTime()
{
}
公共开放时间(星期五星期五星期五、TimeSpan fromTime、TimeSpan toTime)
:this(dayOfWeek,fromTime.Hours,fromTime.Minutes,toTime.Hours,toTime.Minutes){}
公共开放时间(星期一星期一星期五,整数从小时,整数从分钟,整数到小时,整数到分钟)
{
如果(从小时数<0 | |从小时数>23)
{
抛出新ArgumentOutOfRangeException(“fromHours”,“fromHours必须在0到23之间,包括0到23之间”);
}
如果(toHours<0 | | toHours>23)
{
抛出新ArgumentOutOfRangeException(“toHours”,“toHours必须在0到23之间,包括0到23之间”);
}
如果(从分钟数<0 | |从分钟数>59)
{
抛出新ArgumentOutOfRangeException(“fromMinutes”,“fromMinutes必须在0到59之间,包括0到59之间”);
}
如果(toMinutes<0 | | toMinutes>59)
{
抛出新ArgumentOutOfRangeException(“toMinutes”,“toMinutes必须在0到59之间(含0到59));
}
this.FromTime=新的时间跨度(fromHours,fromMinutes,0);
this.ToTime=新的时间跨度(toHours,toMinutes,0);
如果(this.FromTime>=this.ToTime)
{
抛出新ArgumentException(“From Time必须在To Time之前”);
}
this.DayOfWeek=DayOfWeek;
}
公共虚拟DayOfWeek DayOfWeek{get;private set;}
公共虚拟时间跨度FromTime{get;private set;}
公共虚拟时间跨度到时间{get;private set;}
}

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

我认为您可以在内部将其表示为开始的日期时间(它为您提供了DayOfWeek),然后表示结束的时间跨度,但将其公开为三个属性,即DateTimes或TimeSpans

现在打开一个更DDD的帽子。。。您“可以”使用TimeSpan对象来表示一天中的某个时间,但是如果我按照DDD术语来考虑,那么我希望考虑商店什么时候开门。时间跨度可以代表更多的信息,每次处理时间跨度时,您都必须特别确认时间跨度不超过一天

因此,一种方法是创建一个简单的类来表示您试图表示的内容(您可以只包装一个TimeSpan对象,而不是使用几个int)

公共结构时间
{
私人只读整数小时;
私人只读整数分钟;
私有只读整数秒;
公共时间(整数小时、整数分钟、整数秒)
{
如果(小时<0 | |小时>=24)
抛出新ArgumentOutOfRangeException(“小时”,“小时数必须介于0和23之间(含0和23));
如果(分钟<0 | |分钟>59)
抛出新ArgumentOutOfRangeException(“分钟”,“分钟必须介于0和23之间,包括0和23”);
如果(秒<0 | |秒>59)
抛出新ArgumentOutOfRangeException(“秒”,“秒数必须介于0和23之间,包括0和23”);
_小时=小时;
_分钟=分钟;
_秒=秒;
}
公共时间(时间)
:此(time.Hour,time.min,time.Second)
{
}
公共整数小时{get{return{u Hour;}}
公共整数分钟{get{return{u Minute;}}
public int Second{get{return_Second;}}
公共重写字符串ToString()
{
返回到字符串(true);
}
公共字符串到字符串(bool showSeconds)
{
如果(显示秒)
返回string.Format(“{0:00}:{1:00}:{2:00}”,小时、分钟、秒);
返回string.Format(“{0:00}:{1:00}:{2:00}”,小时,分钟);
}
公共覆盖布尔等于(对象对象对象)
{
if(ReferenceEquals(null,obj))返回false;
if(obj.GetType()!=typeof(Time))返回false;
返回等于((时间)obj);
}
公共布尔等于(其他时间)
{
返回other.\u hour===\u hour&other.\u minute==\u minute&other.\u second==\u second;
}
公共覆盖int GetHashCode()
{
未经检查
{
int结果=_小时;
结果=(结果*397)^分钟;
结果=(结果*397)^秒;
返回结果;
}
}
}
公共课开放时间
{
公共DayOfWeek DayOfWeek{get;set;}
公共时间打开时间{get;set;}
公共时间结束时间{get;set;}
公开开放时间(星期一星期五、时间开放时间、时间关闭时间)
{
DayOfWeek=DayOfWeek;
OpeningTime=OpeningTime;
ClosingTime=ClosingTime;
}
}

坚持使用日期时间

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

为什么不选择TimeSpan?

因为它的名字和它的含义。TimeSpan表示与时间点相对的一段时间。虽然它在框架中用于表示精确的时间(以TimeOfDay为单位),但该属性定义为:

表示从午夜起一天中经过的部分的时间跨度

但是。。。其实没什么大不了的

最后,这没什么不同
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;
    }
}