【问题标题】:Representing Time (not date and time) in C#在 C# 中表示时间(不是日期和时间)
【发布时间】:2010-08-25 15:28:59
【问题描述】:

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

如何最好地代表这些? 稍后它们将被持久化到数据库中...

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

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; }
}

DateTime 是否仍然适用于表示以下内容:

星期一 - 9:00 - 17:30

【问题讨论】:

  • 我建议您将“OpeningTime”类重命名为“OperationHours”之类的名称
  • 您在 .Net 中比在 SQL 中具有更大的灵活性。首先考虑如何将它持久化到表中,然后在 .Net 中进行模拟(假设您只满足一个 RDBMS,并且会保持这种状态一段时间)。你希望这个时间有多精确?

标签: c# datetime time


【解决方案1】:

坚持使用日期时间

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

为什么不使用 TimeSpan?

因为它的名字和它的含义。 TimeSpan 表示一段时间,而不是时间点。虽然它在框架中用于表示准确的时间(在 TimeOfDay 中),但该属性定义为 in the docs 为:

一个时间跨度,表示自午夜以来经过的一天中的分数。

但是……其实并不重要

最后差别不大,您可以使用 TimeSpan、DateTime 或您自己的结构。两者都几乎没有开销,它只是归结为您发现更具可读性和更易于维护的内容。

【讨论】:

    【解决方案2】:

    我个人会使用 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; }
    }
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

        现在打开更多的 DDD 帽子...您“可以”使用 TimeSpan 对象来表示一天中的某个时间,但如果我按照 DDD 术语考虑,我会想考虑商店打开的时间. TimeSpan 可以表示更多信息,您必须在每次与它们打交道时专门验证它们不超过一天。

        因此,一种方法是创建一个简单的类来表示您要表示的内容(您可以只包装一个 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;
            }
        }
        

        【讨论】:

        • 重新发明日期时间,亲爱的!
        • 您应该在您的域中公开嵌入类型吗? DateTime 和 TimeSpan 实际上都不代表一天中的通用时间,它们可以用来这样做,但这并不能使它正确。您可以将所有内容存储为字符串,为什么不这样做呢?它没有概念意义
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-12-16
        • 2011-03-04
        • 1970-01-01
        • 2012-08-03
        • 1970-01-01
        • 2012-09-02
        • 1970-01-01
        相关资源
        最近更新 更多