C# 是否有处理时间块的结构?

C# 是否有处理时间块的结构?,c#,datetime,collections,timespan,C#,Datetime,Collections,Timespan,我想处理时间块,这意味着一组两个日期时间,代表例如员工的存在。在特定时间之前或之后,是否已有任何结构可用于搜索块? 我可以想象有很多方式来表达这种情况,就像我说的,用两个Datetime表示开始和结束,或者用一个Datetime表示开始和时间跨度。但我想把它们收集起来。那么,有没有类似的东西我可以使用,或者我必须完全靠自己来实现 谢谢这不是内置的。如果您想自己实现它,您可能需要创建一个结构。这将为您提供值类型复制语义。这种值的行为与内置类型类似,如int或DateTime。使用起来非常直观。此库

我想处理时间块,这意味着一组两个日期时间,代表例如员工的存在。在特定时间之前或之后,是否已有任何结构可用于搜索块? 我可以想象有很多方式来表达这种情况,就像我说的,用两个Datetime表示开始和结束,或者用一个Datetime表示开始和时间跨度。但我想把它们收集起来。那么,有没有类似的东西我可以使用,或者我必须完全靠自己来实现


谢谢这不是内置的。如果您想自己实现它,您可能需要创建一个结构。这将为您提供值类型复制语义。这种值的行为与内置类型类似,如
int
DateTime
。使用起来非常直观。

此库是一件很棒的事情-祝您受到启发


您可以查看TimeSpan。这是一个处理“时间块”的结构

我以前使用过一个
DateSpan
结构。你可以随意扩展,但这会给你一个起点

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace StackOverFlowDateSpan
{
[StructLayout(LayoutKind.Auto)]
[Serializable]
public struct DateSpan : IComparable, IComparable<DateSpan>, IEquatable<DateSpan>
{
    public DateSpan(DateTime start, DateTime end)
        : this()
    {
        Start = start;
        End = end;
    }

    #region Properties

    public TimeSpan Duration
    {
        get { return TimeSpan.FromTicks((End - Start).Ticks); }
    }

    public DateTime End { get; private set; }
    public DateTime Start { get; private set; }

    #endregion

    public int CompareTo(DateSpan other)
    {
        long otherTicks = other.Duration.Ticks;
        long internalTicks = Duration.Ticks;

        return internalTicks > otherTicks ? 1 : (internalTicks < otherTicks ? -1 : 0);
    }

    public bool Equals(DateSpan other)
    {
        return End.Equals(other.End) && Start.Equals(other.Start);
    }

    public int CompareTo(object other)
    {
        if (other == null)
        {
            return 1;
        }

        if (!(other is DateSpan))
        {
            throw new ArgumentNullException("other");
        }

        return CompareTo((DateSpan)other);
    }

    public override bool Equals(object other)
    {
        if (ReferenceEquals(null, other))
        {
            return false;
        }
        return other is DateSpan && Equals((DateSpan)other);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            return (End.GetHashCode() * 397) ^ Start.GetHashCode();
        }
    }

    public static bool operator ==(DateSpan left, DateSpan right)
    {
        return left.Equals(right);
    }

    public static bool operator !=(DateSpan left, DateSpan right)
    {
        return !left.Equals(right);
    }

    private sealed class EndStartEqualityComparer : IEqualityComparer<DateSpan>
    {
        #region IEqualityComparer<DateSpan> Members

        public bool Equals(DateSpan x, DateSpan y)
        {
            return x.End.Equals(y.End) && x.Start.Equals(y.Start);
        }

        public int GetHashCode(DateSpan obj)
        {
            unchecked
            {
                return (obj.End.GetHashCode() * 397) ^ obj.Start.GetHashCode();
            }
        }

        #endregion
    }

    private static readonly IEqualityComparer<DateSpan> _endStartComparerInstance = new EndStartEqualityComparer();

    public static IEqualityComparer<DateSpan> EndStartComparer
    {
        get { return _endStartComparerInstance; }
    }
}
}
使用系统;
使用System.Collections.Generic;
使用System.Runtime.InteropServices;
命名空间StackOverFlowDateSpan
{
[StructLayout(LayoutKind.Auto)]
[可序列化]
公共结构日期跨度:IComparable、IComparable、IEquatable
{
公共日期跨度(日期时间开始,日期时间结束)
:此()
{
开始=开始;
结束=结束;
}
#区域属性
公共时间跨度持续时间
{
获取{return TimeSpan.FromTicks((End-Start.Ticks);}
}
公共日期时间结束{get;private set;}
公共日期时间开始{get;private set;}
#端区
公共整数比较(日期跨度其他)
{
long otherTicks=other.Duration.Ticks;
长内部滴答声=持续时间。滴答声;
返回internalTicks>otherTicks?1:(internalTicks
课程:

public class TimePeriod
{
    public DateTime Oldest { get; set; }
    public DateTime Newest { get; set; }

    public TimePeriod(DateTime oldest, DateTime newest)
    {
        Oldest = oldest;
        Newest = newest;
    }

    public bool Contains (DateTime time)
    {
        return Oldest.CompareTo(time) <= 0 && Newest.CompareTo(time) >= 0;
    }

    public bool IsAfter(DateTime time)
    {
        return Newest.CompareTo(time) <= 0;
    }

    public bool IsBefore(DateTime time)
    {
        return Oldest.CompareTo(time) >= 0; 
    }
}

现在,您可以使用集合和linq以及扩展方法和lambda表达式来查找时间块。

谢谢您的帮助!我将仔细查看时间周期库,并用Linq做一些实验。我已经有了一种实现二进制搜索的方法,所以如果有人感兴趣,你可以写信给我;)

下面是一个开始:
struct TimeBlock{private readonly DateTime start;private readonly TimeSpan duration;public TimeBlock(DateTime start,TimeSpan duration){this.start=start;this.duration=duration;}public DateTime start{get{return start;}}public TimeSpan duration get{return duration
@lucero:将其作为anwser发布。您遵循了结构不变性的黄金法则。我想你可以在你的答案中指出这一点(可能建议覆盖gethashcode、equals等),这与我所寻找的差不多,我将尝试在集合中使用它,但在我的例子中它看起来非常有用。也许通过一些扩展,它们适合于SortedDictionary或类似的东西……我有一个可能的自制实现的想法,但我不想自己做,因为已经有处理交叉点和类似东西的功能,但无论如何,谢谢你,但没有开始或结束。只是一个持续时间。TimeSpan只能处理一个持续时间,但我想管理具有特定开始和结束的块。您好,看起来不错,我会将CompareTo方法更改为
public int CompareTo(DateSpan other){return duration.CompareTo(other.duration);}
这是一个好的观点。下一次我在使用我的实用程序库时,我会修改它。简单的方法,但我从未想过使用linq,感谢hintI同意Lucero的评论(关于这个问题)。我认为使用结构更直观(TimeSpan、DateTime也是结构)。
class Program
{
    static void Main(string[] args)
    {
        var period = new TimePeriod(
                    DateTime.Now.AddDays(-2),
                    DateTime.Now.AddDays(1));

        var date = DateTime.Now;
        var contains = period.Contains(date); // true
        var isBefore = period.IsBefore(date); // false
        var isAfter = period.IsAfter(date);   // false

        date = DateTime.Now.AddDays(-10);
        contains = period.Contains(date); // false
        isBefore = period.IsBefore(date); // true
        isAfter = period.IsAfter(date);   // false

        date = DateTime.Now.AddDays(10);
        contains = period.Contains(date); // false
        isBefore = period.IsBefore(date); // false
        isAfter = period.IsAfter(date);   // true
    }
}