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

如何在.NET中表示仅限时间的值?

  •  198
  • sduplooy  · 技术社区  · 15 年前

    有没有一种方法可以在.NET中表示仅限时间的值而不包含日期?例如,指示商店的营业时间?

    TimeSpan 指示一个范围,而我只想存储一个时间值。使用 DateTime 表明这将导致新的 DateTime(1,1,1,8,30,0) 这并不是真正需要的。

    7 回复  |  直到 8 年前
        1
  •  157
  •   Jon Skeet    9 年前

    正如其他人所说,你 可以 DateTime 忽略日期,或使用 TimeSpan . 就我个人而言,我对这两种解决方案都不感兴趣,因为这两种类型都没有真正反映您试图表达的概念-我认为.NET中的日期/时间类型有点稀疏,这是我开始使用的原因之一 Noda Time . 在野田佳彦时代,你可以使用 LocalTime

    需要考虑的一点是:一天中的时间不一定是从同一天午夜开始的时间长度。。。

    (另一方面,如果你也想代表 结束 商店的时间,您可能会发现您希望表示24:00,即一天结束时的时间。大多数日期/时间API(包括Noda time)不允许将其表示为一天中的时间值。)

        2
  •  179
  •   John G    15 年前

    timespan

    TimeSpan timeSpan = new TimeSpan(2, 14, 18);
    Console.WriteLine(timeSpan.ToString());     // Displays "02:14:18".
    

    [编辑]
    考虑到其他答案和问题的编辑,我仍然会使用TimeSpan。如果框架中已有的结构已经足够,那么创建新结构是毫无意义的。

        3
  •  37
  •   Rubens Farias    9 年前

    如果那是空的 Date Time 结构:

    // more work is required to make this even close to production ready
    class Time
    {
        // TODO: don't forget to add validation
        public int Hours   { get; set; }
        public int Minutes { get; set; }
        public int Seconds { get; set; }
    
        public override string ToString()
        {  
            return String.Format(
                "{0:00}:{1:00}:{2:00}",
                this.Hours, this.Minutes, this.Seconds);
        }
    }
    

    或者,为什么要麻烦呢:如果您不需要对这些信息进行任何计算,只需将其存储为 String .

        4
  •  21
  •   bugfixr    12 年前

    我说用约会时间。如果您不需要日期部分,请忽略它。如果您只需要向用户显示时间,请将其格式化后输出给用户,如下所示:

    DateTime.Now.ToString("t");  // outputs 10:00 PM
    

    似乎制作一个新类,甚至使用时间跨度的所有额外工作都是不必要的。

        5
  •  12
  •   Chibueze Opata    9 年前

    我认为鲁本斯的课程是一个好主意,因此我认为他可以制作一个带有基本验证的时间课程不变的样本。

    class Time
    {
        public int Hours   { get; private set; }
        public int Minutes { get; private set; }
        public int Seconds { get; private set; }
    
        public Time(uint h, uint m, uint s)
        {
            if(h > 23 || m > 59 || s > 59)
            {
                throw new ArgumentException("Invalid time specified");
            }
            Hours = (int)h; Minutes = (int)m; Seconds = (int)s;
        }
    
        public Time(DateTime dt)
        {
            Hours = dt.Hour;
            Minutes = dt.Minute;
            Seconds = dt.Second;
        }
    
        public override string ToString()
        {  
            return String.Format(
                "{0:00}:{1:00}:{2:00}",
                this.Hours, this.Minutes, this.Seconds);
        }
    }
    
        6
  •  6
  •   Jules    8 年前

    除了 :

    class Time
    {
        public int Hours   { get; private set; }
        public int Minutes { get; private set; }
        public int Seconds { get; private set; }
    
        public Time(uint h, uint m, uint s)
        {
            if(h > 23 || m > 59 || s > 59)
            {
                throw new ArgumentException("Invalid time specified");
            }
            Hours = (int)h; Minutes = (int)m; Seconds = (int)s;
        }
    
        public Time(DateTime dt)
        {
            Hours = dt.Hour;
            Minutes = dt.Minute;
            Seconds = dt.Second;
        }
    
        public override string ToString()
        {  
            return String.Format(
                "{0:00}:{1:00}:{2:00}",
                this.Hours, this.Minutes, this.Seconds);
        }
    
        public void AddHours(uint h)
        {
            this.Hours += (int)h;
        }
    
        public void AddMinutes(uint m)
        {
            this.Minutes += (int)m;
            while(this.Minutes > 59)
                this.Minutes -= 60;
                this.AddHours(1);
        }
    
        public void AddSeconds(uint s)
        {
            this.Seconds += (int)s;
            while(this.Seconds > 59)
                this.Seconds -= 60;
                this.AddMinutes(1);
        }
    }
    
        7
  •  6
  •   Steve Lautenschlager    5 年前

    对于简单的情况来说,这是过分的,但是如果您需要像我一样的更高级的功能,这可能会有所帮助。

    它可以处理各种情况,一些基本的数学、比较、与DateTime的交互、解析等。

    下面是TimeOfDay类的源代码。您可以查看使用示例并了解更多信息 here

    该类使用DateTime进行大多数内部计算和比较,因此我们可以利用DateTime中已经嵌入的所有知识。

    // Author: Steve Lautenschlager, CambiaResearch.com
    // License: MIT
    
    using System;
    using System.Text.RegularExpressions;
    
    namespace Cambia
    {
        public class TimeOfDay
        {
            private const int MINUTES_PER_DAY = 60 * 24;
            private const int SECONDS_PER_DAY = SECONDS_PER_HOUR * 24;
            private const int SECONDS_PER_HOUR = 3600;
            private static Regex _TodRegex = new Regex(@"\d?\d:\d\d:\d\d|\d?\d:\d\d");
    
            public TimeOfDay()
            {
                Init(0, 0, 0);
            }
            public TimeOfDay(int hour, int minute, int second = 0)
            {
                Init(hour, minute, second);
            }
            public TimeOfDay(int hhmmss)
            {
                Init(hhmmss);
            }
            public TimeOfDay(DateTime dt)
            {
                Init(dt);
            }
            public TimeOfDay(TimeOfDay td)
            {
                Init(td.Hour, td.Minute, td.Second);
            }
    
            public int HHMMSS
            {
                get
                {
                    return Hour * 10000 + Minute * 100 + Second;
                }
            }
            public int Hour { get; private set; }
            public int Minute { get; private set; }
            public int Second { get; private set; }
            public double TotalDays
            {
                get
                {
                    return TotalSeconds / (24d * SECONDS_PER_HOUR);
                }
            }
            public double TotalHours
            {
                get
                {
                    return TotalSeconds / (1d * SECONDS_PER_HOUR);
                }
            }
            public double TotalMinutes
            {
                get
                {
                    return TotalSeconds / 60d;
                }
            }
            public int TotalSeconds
            {
                get
                {
                    return Hour * 3600 + Minute * 60 + Second;
                }
            }
            public bool Equals(TimeOfDay other)
            {
                if (other == null) { return false; }
                return TotalSeconds == other.TotalSeconds;
            }
            public override bool Equals(object obj)
            {
                if (obj == null) { return false; }
                TimeOfDay td = obj as TimeOfDay;
                if (td == null) { return false; }
                else { return Equals(td); }
            }
            public override int GetHashCode()
            {
                return TotalSeconds;
            }
            public DateTime ToDateTime(DateTime dt)
            {
                return new DateTime(dt.Year, dt.Month, dt.Day, Hour, Minute, Second);
            }
            public override string ToString()
            {
                return ToString("HH:mm:ss");
            }
            public string ToString(string format)
            {
                DateTime now = DateTime.Now;
                DateTime dt = new DateTime(now.Year, now.Month, now.Day, Hour, Minute, Second);
                return dt.ToString(format);
            }
            public TimeSpan ToTimeSpan()
            {
                return new TimeSpan(Hour, Minute, Second);
            }
            public DateTime ToToday()
            {
                var now = DateTime.Now;
                return new DateTime(now.Year, now.Month, now.Day, Hour, Minute, Second);
            }
    
            #region -- Static --
            public static TimeOfDay Midnight { get { return new TimeOfDay(0, 0, 0); } }
            public static TimeOfDay Noon { get { return new TimeOfDay(12, 0, 0); } }
            public static TimeOfDay operator -(TimeOfDay t1, TimeOfDay t2)
            {
                DateTime now = DateTime.Now;
                DateTime dt1 = new DateTime(now.Year, now.Month, now.Day, t1.Hour, t1.Minute, t1.Second);
                TimeSpan ts = new TimeSpan(t2.Hour, t2.Minute, t2.Second);
                DateTime dt2 = dt1 - ts;
                return new TimeOfDay(dt2);
            }
            public static bool operator !=(TimeOfDay t1, TimeOfDay t2)
            {
                if (ReferenceEquals(t1, t2)) { return true; }
                else if (ReferenceEquals(t1, null)) { return true; }
                else
                {
                    return t1.TotalSeconds != t2.TotalSeconds;
                }
            }
            public static bool operator !=(TimeOfDay t1, DateTime dt2)
            {
                if (ReferenceEquals(t1, null)) { return false; }
                DateTime dt1 = new DateTime(dt2.Year, dt2.Month, dt2.Day, t1.Hour, t1.Minute, t1.Second);
                return dt1 != dt2;
            }
            public static bool operator !=(DateTime dt1, TimeOfDay t2)
            {
                if (ReferenceEquals(t2, null)) { return false; }
                DateTime dt2 = new DateTime(dt1.Year, dt1.Month, dt1.Day, t2.Hour, t2.Minute, t2.Second);
                return dt1 != dt2;
            }
            public static TimeOfDay operator +(TimeOfDay t1, TimeOfDay t2)
            {
                DateTime now = DateTime.Now;
                DateTime dt1 = new DateTime(now.Year, now.Month, now.Day, t1.Hour, t1.Minute, t1.Second);
                TimeSpan ts = new TimeSpan(t2.Hour, t2.Minute, t2.Second);
                DateTime dt2 = dt1 + ts;
                return new TimeOfDay(dt2);
            }
            public static bool operator <(TimeOfDay t1, TimeOfDay t2)
            {
                if (ReferenceEquals(t1, t2)) { return true; }
                else if (ReferenceEquals(t1, null)) { return true; }
                else
                {
                    return t1.TotalSeconds < t2.TotalSeconds;
                }
            }
            public static bool operator <(TimeOfDay t1, DateTime dt2)
            {
                if (ReferenceEquals(t1, null)) { return false; }
                DateTime dt1 = new DateTime(dt2.Year, dt2.Month, dt2.Day, t1.Hour, t1.Minute, t1.Second);
                return dt1 < dt2;
            }
            public static bool operator <(DateTime dt1, TimeOfDay t2)
            {
                if (ReferenceEquals(t2, null)) { return false; }
                DateTime dt2 = new DateTime(dt1.Year, dt1.Month, dt1.Day, t2.Hour, t2.Minute, t2.Second);
                return dt1 < dt2;
            }
            public static bool operator <=(TimeOfDay t1, TimeOfDay t2)
            {
                if (ReferenceEquals(t1, t2)) { return true; }
                else if (ReferenceEquals(t1, null)) { return true; }
                else
                {
                    if (t1 == t2) { return true; }
                    return t1.TotalSeconds <= t2.TotalSeconds;
                }
            }
            public static bool operator <=(TimeOfDay t1, DateTime dt2)
            {
                if (ReferenceEquals(t1, null)) { return false; }
                DateTime dt1 = new DateTime(dt2.Year, dt2.Month, dt2.Day, t1.Hour, t1.Minute, t1.Second);
                return dt1 <= dt2;
            }
            public static bool operator <=(DateTime dt1, TimeOfDay t2)
            {
                if (ReferenceEquals(t2, null)) { return false; }
                DateTime dt2 = new DateTime(dt1.Year, dt1.Month, dt1.Day, t2.Hour, t2.Minute, t2.Second);
                return dt1 <= dt2;
            }
            public static bool operator ==(TimeOfDay t1, TimeOfDay t2)
            {
                if (ReferenceEquals(t1, t2)) { return true; }
                else if (ReferenceEquals(t1, null)) { return true; }
                else { return t1.Equals(t2); }
            }
            public static bool operator ==(TimeOfDay t1, DateTime dt2)
            {
                if (ReferenceEquals(t1, null)) { return false; }
                DateTime dt1 = new DateTime(dt2.Year, dt2.Month, dt2.Day, t1.Hour, t1.Minute, t1.Second);
                return dt1 == dt2;
            }
            public static bool operator ==(DateTime dt1, TimeOfDay t2)
            {
                if (ReferenceEquals(t2, null)) { return false; }
                DateTime dt2 = new DateTime(dt1.Year, dt1.Month, dt1.Day, t2.Hour, t2.Minute, t2.Second);
                return dt1 == dt2;
            }
            public static bool operator >(TimeOfDay t1, TimeOfDay t2)
            {
                if (ReferenceEquals(t1, t2)) { return true; }
                else if (ReferenceEquals(t1, null)) { return true; }
                else
                {
                    return t1.TotalSeconds > t2.TotalSeconds;
                }
            }
            public static bool operator >(TimeOfDay t1, DateTime dt2)
            {
                if (ReferenceEquals(t1, null)) { return false; }
                DateTime dt1 = new DateTime(dt2.Year, dt2.Month, dt2.Day, t1.Hour, t1.Minute, t1.Second);
                return dt1 > dt2;
            }
            public static bool operator >(DateTime dt1, TimeOfDay t2)
            {
                if (ReferenceEquals(t2, null)) { return false; }
                DateTime dt2 = new DateTime(dt1.Year, dt1.Month, dt1.Day, t2.Hour, t2.Minute, t2.Second);
                return dt1 > dt2;
            }
            public static bool operator >=(TimeOfDay t1, TimeOfDay t2)
            {
                if (ReferenceEquals(t1, t2)) { return true; }
                else if (ReferenceEquals(t1, null)) { return true; }
                else
                {
                    return t1.TotalSeconds >= t2.TotalSeconds;
                }
            }
            public static bool operator >=(TimeOfDay t1, DateTime dt2)
            {
                if (ReferenceEquals(t1, null)) { return false; }
                DateTime dt1 = new DateTime(dt2.Year, dt2.Month, dt2.Day, t1.Hour, t1.Minute, t1.Second);
                return dt1 >= dt2;
            }
            public static bool operator >=(DateTime dt1, TimeOfDay t2)
            {
                if (ReferenceEquals(t2, null)) { return false; }
                DateTime dt2 = new DateTime(dt1.Year, dt1.Month, dt1.Day, t2.Hour, t2.Minute, t2.Second);
                return dt1 >= dt2;
            }
            /// <summary>
            /// Input examples:
            /// 14:21:17            (2pm 21min 17sec)
            /// 02:15               (2am 15min 0sec)
            /// 2:15                (2am 15min 0sec)
            /// 2/1/2017 14:21      (2pm 21min 0sec)
            /// TimeOfDay=15:13:12  (3pm 13min 12sec)
            /// </summary>
            public static TimeOfDay Parse(string s)
            {
                // We will parse any section of the text that matches this
                // pattern: dd:dd or dd:dd:dd where the first doublet can
                // be one or two digits for the hour.  But minute and second
                // must be two digits.
    
                Match m = _TodRegex.Match(s);
                string text = m.Value;
                string[] fields = text.Split(':');
                if (fields.Length < 2) { throw new ArgumentException("No valid time of day pattern found in input text"); }
                int hour = Convert.ToInt32(fields[0]);
                int min = Convert.ToInt32(fields[1]);
                int sec = fields.Length > 2 ? Convert.ToInt32(fields[2]) : 0;
    
                return new TimeOfDay(hour, min, sec);
            }
            #endregion
    
            private void Init(int hour, int minute, int second)
            {
                if (hour < 0 || hour > 23) { throw new ArgumentException("Invalid hour, must be from 0 to 23."); }
                if (minute < 0 || minute > 59) { throw new ArgumentException("Invalid minute, must be from 0 to 59."); }
                if (second < 0 || second > 59) { throw new ArgumentException("Invalid second, must be from 0 to 59."); }
                Hour = hour;
                Minute = minute;
                Second = second;
            }
            private void Init(int hhmmss)
            {
                int hour = hhmmss / 10000;
                int min = (hhmmss - hour * 10000) / 100;
                int sec = (hhmmss - hour * 10000 - min * 100);
                Init(hour, min, sec);
            }
            private void Init(DateTime dt)
            {
                Init(dt.Hour, dt.Minute, dt.Second);
            }
        }
    }
    
        8
  •  3
  •   Matt Johnson-Pint    4 年前

    A. System.TimeOfDay 该类型最近被批准用于即将发布的.NET 6。

    看见 https://github.com/dotnet/runtime/issues/49036

    一天中的时间 与任何特定日期或时区不关联的值。

    System.TimeSpan 仍将是推荐的代表方式

        9
  •  2
  •   Jason Williams    15 年前

    如果您不想使用DateTime或TimeSpan,只想存储一天中的时间,您可以将午夜后的秒数存储在Int32中,或者(如果您甚至不想要秒数)将午夜后的分钟数存储在Int16中。编写从这样的值访问小时、分钟和秒所需的几个方法是很简单的。

    我能想到的避免DateTime/TimeSpan的唯一原因是如果结构的大小很关键。

    (当然,如果您使用一个简单的方案,比如上面包装在一个类中的方案,那么如果您突然意识到这会给您带来优势,那么在将来用时间跨度替换存储也是很简单的)