代码之家  ›  专栏  ›  技术社区  ›  Alex

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

  •  4
  • Alex  · 技术社区  · 14 年前

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

    如何最好地表现这些? 它们稍后将被保存在数据库中…

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

    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

    4 回复  |  直到 14 年前
        1
  •  3
  •   Ian Nelson    14 年前

    我个人会使用时间跨度而不是日期时间,但我听说其他人表达了相反的观点。

    [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; }
    }
    
        2
  •  3
  •   badbod99    14 年前

    坚持使用日期时间

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

    为什么不是时间跨度?

    因为它的名字是真的,这意味着什么。TimeSpan表示一段时间,而不是一个时间点。虽然它在框架中被用来表示精确的时间(在time-ofday中),但该属性是被定义的 in the docs AS:

    表示从午夜开始一天中所经过的时间段。

    但是…其实没什么关系

    最后,它没有什么区别,您可以使用TimeSpan、DateTime或您自己的结构。这两者的开销都很小,归根结底就是您发现更易于阅读和维护的内容。

        3
  •  2
  •   Peter    14 年前

    你可以使用 TimeSpan 代表一天中的某个时间。

        4
  •  2
  •   Ian Johnson    14 年前

    我认为您可以在内部将其表示为开始的日期时间(它为dayOfWeek),然后表示结束的时间跨度,但将它们公开为日期时间或时间跨度三个属性。

    现在打开更多的DDD帽子…您可以使用TimeSpan对象来表示一天中的某个时间,但是如果我按照DDD术语进行思考,我会想知道商店什么时候开门。时间跨度可以代表更多信息的方式,每次与它们打交道时,您必须具体验证它们的长度不超过一天。

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

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