Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 计算重叠日期中的夜数_C#_Date_Logic - Fatal编程技术网

C# 计算重叠日期中的夜数

C# 计算重叠日期中的夜数,c#,date,logic,C#,Date,Logic,我在想一个合乎逻辑的方法来解决这个问题时遇到了一个问题。 我有一个日期范围列表,例如: 01/01/15 - 11/01/15 02/01/15 - 04/01/15 09/01/15 - 13/01/15 18/01/15 - 20/01/15 var vRanges = new List<Range> { new Range("01/01/15", "11/01/15"), new Range

我在想一个合乎逻辑的方法来解决这个问题时遇到了一个问题。 我有一个日期范围列表,例如:

01/01/15 - 11/01/15 
02/01/15 - 04/01/15 
09/01/15 - 13/01/15 
18/01/15 - 20/01/15
        var vRanges = new List<Range>
        {
            new Range("01/01/15", "11/01/15"),
            new Range("02/01/15", "04/01/15"),
            new Range("09/01/15", "13/01/15"),
            new Range("18/01/15", "20/01/15"),
        };
        var v = ComputeNights(vRanges);
我需要做的是计算出所有这些日期范围内的总夜数

因此,对于本例,总计应为14晚:

01/01/15 - 11/01/15 // 10 nights
02/01/15 - 04/01/15 // Ignored as nights are covered in 1-11
09/01/15 - 13/01/15 // 2 nights as 11th and 12th nights haven't been covered
18/01/15 - 20/01/15 // 2 nights
我可以使用min-max dates轻松计算出总的夜晚数,但这忽略了丢失的日期(示例中为14-17),这是我无法计算的


有没有办法找到总天数来帮助解决这个问题?

类似的方法应该可以:

internal class Range
{
    internal DateTime From, To;

    public Range(string aFrom, string aTo)
    {
        From = DateTime.ParseExact(aFrom, "dd/mm/yy", CultureInfo.InvariantCulture);
        To = DateTime.ParseExact(aTo, "dd/mm/yy", CultureInfo.InvariantCulture);
    }
}

    public static int ComputeNights(IEnumerable<Range> ranges)
    {
        var vSet = new HashSet<DateTime>();
        foreach (var range in ranges)
            for (var i = range.From; i < range.To; i = i.AddDays(1)) vSet.Add(i)
        return vSet.Count;
    }
内部类范围
{
内部日期时间从,到;
公共范围(字符串aFrom、字符串aTo)
{
From=DateTime.ParseExact(aFrom,“dd/mm/yy”,CultureInfo.InvariantCulture);
To=DateTime.ParseExact(aTo,“dd/mm/yy”,CultureInfo.InvariantCulture);
}
}
公共静态整数计算权限(IEnumerable ranges)
{
var vSet=new HashSet();
foreach(范围中的var范围)
对于(var i=范围从;i<范围到;i=i.AddDays(1))vSet.Add(i)
返回vSet.Count;
}
运行示例的代码如下:

01/01/15 - 11/01/15 
02/01/15 - 04/01/15 
09/01/15 - 13/01/15 
18/01/15 - 20/01/15
        var vRanges = new List<Range>
        {
            new Range("01/01/15", "11/01/15"),
            new Range("02/01/15", "04/01/15"),
            new Range("09/01/15", "13/01/15"),
            new Range("18/01/15", "20/01/15"),
        };
        var v = ComputeNights(vRanges);
var vRanges=新列表
{
新范围(“2015年1月1日”、“2015年11月1日”),
新系列(“2015年1月2日”、“2015年1月4日”),
新系列(“09/01/15”、“13/01/15”),
新系列(“2015年1月18日”、“2015年1月20日”),
};
var v=计算亮度(vRanges);

v的计算结果为14

类似的结果应该可以:

internal class Range
{
    internal DateTime From, To;

    public Range(string aFrom, string aTo)
    {
        From = DateTime.ParseExact(aFrom, "dd/mm/yy", CultureInfo.InvariantCulture);
        To = DateTime.ParseExact(aTo, "dd/mm/yy", CultureInfo.InvariantCulture);
    }
}

    public static int ComputeNights(IEnumerable<Range> ranges)
    {
        var vSet = new HashSet<DateTime>();
        foreach (var range in ranges)
            for (var i = range.From; i < range.To; i = i.AddDays(1)) vSet.Add(i)
        return vSet.Count;
    }
内部类范围
{
内部日期时间从,到;
公共范围(字符串aFrom、字符串aTo)
{
From=DateTime.ParseExact(aFrom,“dd/mm/yy”,CultureInfo.InvariantCulture);
To=DateTime.ParseExact(aTo,“dd/mm/yy”,CultureInfo.InvariantCulture);
}
}
公共静态整数计算权限(IEnumerable ranges)
{
var vSet=new HashSet();
foreach(范围中的var范围)
对于(var i=范围从;i<范围到;i=i.AddDays(1))vSet.Add(i)
返回vSet.Count;
}
运行示例的代码如下:

01/01/15 - 11/01/15 
02/01/15 - 04/01/15 
09/01/15 - 13/01/15 
18/01/15 - 20/01/15
        var vRanges = new List<Range>
        {
            new Range("01/01/15", "11/01/15"),
            new Range("02/01/15", "04/01/15"),
            new Range("09/01/15", "13/01/15"),
            new Range("18/01/15", "20/01/15"),
        };
        var v = ComputeNights(vRanges);
var vRanges=新列表
{
新范围(“2015年1月1日”、“2015年11月1日”),
新系列(“2015年1月2日”、“2015年1月4日”),
新系列(“09/01/15”、“13/01/15”),
新系列(“2015年1月18日”、“2015年1月20日”),
};
var v=计算亮度(vRanges);

v计算为14,你可以这样计算:

var laterDateTime = Convert.ToDateTime("11/01/15 ");
var earlierDateTime = Convert.ToDateTime("01/01/15");

TimeSpan dates = laterDateTime - earlierDateTime;

int nights = dates.Days - 1;
你可以把你所有的转换成DateTime。 然后可以使用-运算符减去这两个日期时间。 您的结果将是一种类型的struct TimeSpan

TimeSpan是一个天属性。从中减去1,你就得到了夜晚

两天之间等于一晚
三天之间是两晚
4天之间是3夜


我相信你可以做剩下的。

你可以这样计算:

var laterDateTime = Convert.ToDateTime("11/01/15 ");
var earlierDateTime = Convert.ToDateTime("01/01/15");

TimeSpan dates = laterDateTime - earlierDateTime;

int nights = dates.Days - 1;
你可以把你所有的转换成DateTime。 然后可以使用-运算符减去这两个日期时间。 您的结果将是一种类型的struct TimeSpan

TimeSpan是一个天属性。从中减去1,你就得到了夜晚

两天之间等于一晚
三天之间是两晚
4天之间是3夜


我相信您可以完成剩下的工作。

这里有一种使用哈希集的方法:

public static int CountDays(IEnumerable<TimeRange> periods)
{
    var usedDays = new HashSet<DateTime>();

    foreach (var period in periods)
        for (var day = period.Start; day < period.End; day += TimeSpan.FromDays(1))
            usedDays.Add(day);

    return usedDays.Count;
}
注意:对于较大的日期范围,这不是很有效!如果要考虑大的日期范围,将重叠范围合并为单个范围的方法会更好。


[编辑]修复了使用半开区间而不是闭合区间的代码。

这里有一种使用哈希集的方法:

public static int CountDays(IEnumerable<TimeRange> periods)
{
    var usedDays = new HashSet<DateTime>();

    foreach (var period in periods)
        for (var day = period.Start; day < period.End; day += TimeSpan.FromDays(1))
            usedDays.Add(day);

    return usedDays.Count;
}
注意:对于较大的日期范围,这不是很有效!如果要考虑大的日期范围,将重叠范围合并为单个范围的方法会更好。


[编辑]修复了使用半开放时间间隔而不是封闭时间间隔的代码。

假设在1月1日和1月3日之间有两个晚上,这应该有效。如果您已经有了
DateTime
值而不是字符串,则可以去掉解析位。基本上,我使用
DateTime.Subtract()
来计算两个日期之间的天数(即夜数)

namespace DateTest1
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;

    class Program
    {
        static void Main(string[] args)
        {
            var intervals = new List<Tuple<string, string>>
                                {
                                    new Tuple<string, string>("01/01/15", "11/01/15"),
                                    new Tuple<string, string>("02/01/15", "04/01/15"),
                                    new Tuple<string, string>("09/01/15", "13/01/15"),
                                    new Tuple<string, string>("18/01/15", "20/01/15")
                                };

            var totalNights = 0;

            foreach (var interval in intervals)
            {
                var dateFrom = DateTime.ParseExact(interval.Item1, "dd/MM/yy", CultureInfo.InvariantCulture);
                var dateTo = DateTime.ParseExact(interval.Item2, "dd/MM/yy", CultureInfo.InvariantCulture);

                var nights = dateTo.Subtract(dateFrom).Days;

                Console.WriteLine("{0} - {1}: {2} nights", interval.Item1, interval.Item2, nights);

                totalNights += nights;
            }

            Console.WriteLine("Total nights: {0}", totalNights);
        }
    }
}

假设在1月1日和1月3日之间有两个晚上,这应该有效。如果您已经有了
DateTime
值而不是字符串,则可以去掉解析位。基本上,我使用
DateTime.Subtract()
来计算两个日期之间的天数(即夜数)

namespace DateTest1
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;

    class Program
    {
        static void Main(string[] args)
        {
            var intervals = new List<Tuple<string, string>>
                                {
                                    new Tuple<string, string>("01/01/15", "11/01/15"),
                                    new Tuple<string, string>("02/01/15", "04/01/15"),
                                    new Tuple<string, string>("09/01/15", "13/01/15"),
                                    new Tuple<string, string>("18/01/15", "20/01/15")
                                };

            var totalNights = 0;

            foreach (var interval in intervals)
            {
                var dateFrom = DateTime.ParseExact(interval.Item1, "dd/MM/yy", CultureInfo.InvariantCulture);
                var dateTo = DateTime.ParseExact(interval.Item2, "dd/MM/yy", CultureInfo.InvariantCulture);

                var nights = dateTo.Subtract(dateFrom).Days;

                Console.WriteLine("{0} - {1}: {2} nights", interval.Item1, interval.Item2, nights);

                totalNights += nights;
            }

            Console.WriteLine("Total nights: {0}", totalNights);
        }
    }
}

为了防止您没有足够的答案,这里还有一个使用Linq和
Aggregate
。返回14晚

List<Tuple<DateTime, DateTime>> dates = new List<Tuple<DateTime, DateTime>>
    {
        Tuple.Create(new DateTime(2015, 1,1), new DateTime(2015, 1,11)),
        Tuple.Create(new DateTime(2015, 1,2), new DateTime(2015, 1,4)),
        Tuple.Create(new DateTime(2015, 1,9), new DateTime(2015, 1,13)),
        Tuple.Create(new DateTime(2015, 1,18), new DateTime(2015, 1,20))
    };

    var availableDates = 
          dates.Aggregate<Tuple<DateTime, DateTime>, 
                          IEnumerable<DateTime>, 
                          IEnumerable<DateTime>>
                (new List<DateTime>(),
                (allDates, nextRange) => allDates.Concat(Enumerable.Range(0, (nextRange.Item2 - nextRange.Item1).Days)
                                                 .Select(e => nextRange.Item1.AddDays(e))),
                 allDates => allDates);


    var numDays = 
          availableDates.Aggregate<DateTime, 
                                  Tuple<DateTime, int>, 
                                  int> 
                         (Tuple.Create(DateTime.MinValue, 0),                                                                                               
                         (acc, nextDate) =>
                         {
                             int daysSoFar = acc.Item2;                                                                                    
                             if ((nextDate - acc.Item1).Days == 1)                                                                                                
                             {                                                                                      
                                daysSoFar++;                                                                                                                                                                
                             }                                                                                                                                                                                                                                                                                                                        

                             return Tuple.Create(nextDate, daysSoFar);                                                                          
                          },
                          acc => acc.Item2);
列表日期=新列表
{
创建(新日期时间(2015,1,1),新日期时间(2015,1,11)),
创建(新日期时间(2015,1,2),新日期时间(2015,1,4)),
创建(新日期时间(2015,1,9),新日期时间(2015,1,13)),
创建(新日期时间(2015,1,18),新日期时间(2015,1,20))
};
var availableDates=
日期.合计
(新列表(),
(allDates,nextRange)=>allDates.Concat(Enumerable.Range(0,(nextRange.Item2-nextRange.Item1).Days)
.Select(e=>nextRange.Item1.AddDays(e)),
allDates=>allDates);
变量numDays=
可用数据。聚合
(Tuple.Create(DateTime.MinValue,0),
(附件,下一日期)=>
{
int daysSoFar=附件项目2;
如果((下一个日期-附件项1).Days==1)
{