我需要查看给定日期范围的小时数,与其他范围重叠,如下所示:
[]表示范围
[<<-07:00->> <<-(next day)01:00->>]
[<<-00:00->> <<-08:00->>] [<<-20:00->><<-23:59->>][<<-00:00->> <<-08:00->>]
顶行是用户提供的日期范围。在此示例中,答案应该是重叠 6小时,剩余的 12小时不重叠。
这是我目前的代码:
// The float that represents the hours overlapping
float overlappingHours = 0.0;
// Calculate overlapping interval
NSDate *overlapFrom = [spanStart laterDate:userRangeStart];
NSDate *overlapTo = [spanStop earlierDate:userRangeStop];
// Calculate new salary
if ([overlapFrom compare:overlapTo] > 0) {
// Date ranges do not overlap
} else {
// Date ranges do not overlap
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *dateComponents = [calendar components:NSCalendarUnitHour fromDate:overlapFrom toDate:overlapTo options:0];
overlappingHours = [dateComponents hour];
}
通过为所提供的四个日期提供不同的组合,我得到不同的结果。例如,如果我省略了日期,只包括小时等等。
问题:
通过测试不同的组合,我设法得到的最好的是一小时之外。问题是如果userRangeStart和userRangeStop延伸了几天,我就无法获得第一天以外的重叠时间。 如何才能使这种重叠检测连续进行?
我真的坚持这一点,非常感谢你的帮助! 埃里克
更新
看起来像这样:
a---------------------------------------b
c-----------------d
或者这个:
a-------------------------b
c--------------------d e-------------f
或者这个:
a----------------------b
c------------------d e-------f
或其他任何事情。没有规则,所以我需要一个无论设置如何工作的功能
答案 0 :(得分:1)
对我来说,你是在想这个。
NSDates实际上只是一段时间以来的几秒钟。 (2001年1月1日午夜,UTC)。
您可以使用timeIntervalSinceReferenceDate方法将任何NSDate转换为秒。
当您这样做时,您的日期是浮点数,以秒为单位。然后,您可以自由地进行任何数学运算。
这样处理,2个日期范围是时间线上的线段。计算日期范围之间的重叠变为简单逻辑和浮点运算。
您的结果将以秒为单位,因此只需3600即可得到重叠的小时数。
假设我的日期范围是从a到b,另一个日期范围是从c到d。
他们是NSDates或NSTimeInterval值。这两个是可以使用timeIntervalSinceReferenceDate互换的。
假设范围c:d晚于范围a:b,并且c:d的开头与a的结尾重叠:b
在时间轴上可视化,左侧较旧,右侧较近:
a b
c d
因此,如果a,b,c和d都是NSTimeInterval值,则日期的重叠将只是b-c
。这将是几秒钟内的重叠。 (b-c)/3600
会在几小时和几小时内给你重叠。
根本不需要使用NSCalendar和NSTimeInterval。
我正在思考一个结构&#34; span&#34;包含开始日期和结束日期为NSTimeInterval值(双精度)
有一些简单的方法可以将日期转换为时间间隔
-[NSDate timeIntervalSinceReferenceDate]
和日期的时间间隔
+[NSDate dateWithTimeIntervalSinceReferenceDate]
typedef struct
{
NSTimeInterval start;
NSTimeInterval end;
} span;
跨越a,b,c,d;
查看2个跨距是否重叠的方法:
+ (BOOL) span: (span) spanA
overlapsSpan: (span) spanB;
{
return
//The spans overlap if spanB's start is inside spanA
(spanB.start > spanA.start && spanB.start < spanA.en)
||
//or if spanB's END is inside spanA
(spanB.end > spanA.start && spanB.end < spanA.end)
||
//or if spanA's start is inside spanB
(spanA.start > spanB.start && spanA.start < spanB.end);
}
计算重叠的方法(以秒为单位)
+ (NSTimeInterval) ovelapFromSpan: (span) spanA
overlapsSpan: (span) spanB
{
BOOL bStartInsideA =
spanB.start >= spanA.start && spanB.start <= spanA.end;
BOOL bEndInsideA =
spanB.end >= spanA.start && spanB.end <= spanA.end;
BOOL aStartInsideB =
spanA.start >= spanB.start && spanA.start <= spanB.end;
BOOL aEndInsideB =
spanA.end >= spanB.start && spanA.end <= spanB.end;
// ----A----
// ----B----
if (bStartInsideA && !bEndInsideA)
return spanA.end - spanB.end;
// ----A----
// ----B----
else if (bEndInsideA && !bStartInsideA)
return spanB.end - spanA.start;
// ----A----
// --B--
else if (bStartInsideA && bEndInsideA )
return spanB.end - spanB.start;
// --A--
// ----B----
else if (aStartInsideB && aEndInsideB )
return spanA.end - spanA.start;
else return 0; //No overlap
}
如果您的span结构包含NSDates,您也可以使它工作。您只需要将所有对span开头和结尾的引用更改为[spanA.start timeIntervalSinceReferenceDate]
还有另一组案例,其中一个或两个端点匹配。我只是改变了上面的逻辑,使所有的比较包括平等。我认为这样可以处理所有情况,但请亲自检查一下。