我假设所有给定的时间间隔都在同一月份,然后您可以使用以下代码段标记属于该时间间隔的每一天,并将结果存储到数组中。最后,您可以遍历此数组来了解非重叠间隔。
代码段
String pattern = "yyyy-MM-dd HH:mm";
String[] a = {"2015-01-01 00:00","2015-01-20 00:00"};
String[] b = {"2015-01-05 00:00","2015-01-10 00:00"};
String[] c = {"2015-01-11 00:00","2015-01-14 00:00"};
String[] d = {"2015-01-19 00:00","2015-01-25 00:00"};
String days[] = new String[31];
Arrays.fill(days,"X");
Arrays.fill(days,LocalDateTime.parse(a[0],DateTimeFormatter.ofPattern(pattern)).getDayOfMonth()-1,LocalDateTime.parse(a[1],DateTimeFormatter.ofPattern(pattern)).getDayOfMonth(),"A");
Arrays.fill(days,LocalDateTime.parse(b[0],LocalDateTime.parse(b[1],"B");
Arrays.fill(days,LocalDateTime.parse(c[0],LocalDateTime.parse(c[1],"C");
Arrays.fill(days,LocalDateTime.parse(d[0],LocalDateTime.parse(d[1],"D");
System.out.println(Arrays.toString(days));
控制台输出
[A,A,A,A,B,B,B,B,B,B,C,C,C,C,A,A,A,A,A,D,D,D,D,D, D,D,X,X,X,X,X,X]
,
ThreeTen-Extra
ThreeTen-Extra 库添加了Java 8和更高版本中内置的 java.time 框架的功能。
此库提供了两个类来表示时间轴上的时间跨度:
-
Interval
代表一对瞬间,两个Instant
物体。
-
LocalDateRange
代表一对日期,两个LocalDate
对象。
两个类都包含方便进行比较的方法,例如abuts
,contains
,equals
,intersection
,overlaps
,span
和{ {1}}。
定义范围
定义目标范围。
union
定义其他范围。
LocalDateRange target = LocalDateRange.of(
LocalDate.parse( "2015-01-01" ),LocalDate.parse( "2015-01-20" ),) ;
流日期
可能有一种更聪明的方法可以更有效率。但是通过这种方法,我们只需流式传输目标范围的所有日期。对于每个日期,我们询问是否有任何范围包含该日期。
流式处理范围的日期看起来像这样一行。
List < LocalDateRange > ranges = List.of(
LocalDateRange.of( LocalDate.parse( "2015-01-05" ),LocalDate.parse( "2015-01-10" ) ),LocalDateRange.of( LocalDate.parse( "2015-01-11" ),LocalDate.parse( "2015-01-14" ) ),LocalDateRange.of( LocalDate.parse( "2015-01-19" ),LocalDate.parse( "2015-01-25" ) )
);
该行调用了我们编写的自定义方法。
List < LocalDate > dates = target.stream().filter( localDate -> this.rangesDoNotContain( ranges,localDate ) ).collect( Collectors.toList() );
结果:
dates.toString():[2015-01-01、2015-01-02、2015-01-03、2015-01-04、2015-01-10、2015-01-14、2015-01- 2015年1月15日,2015年1月17日,2015年1月18日]
流范围
我们可以进一步使用流来缩减此代码。通过用private boolean rangesDoNotContain ( List < LocalDateRange > ranges,LocalDate localDate )
{
for ( LocalDateRange range : ranges )
{
if ( range.contains( localDate ) )
{
return false;
}
}
return true;
}
调用Stream::nonMatch
,我们可以消除我们编写的ranges.stream()
方法。
rangesDoNotContain
让我们包装该代码以使其更具可读性。然后,使参数的类型明确。
List < LocalDate > list = target.stream().filter( localDate -> ranges.stream().noneMatch( range -> range.contains( localDate ) ) ).collect( Collectors.toList() );
相同的结果。
[2015-01-01、2015-01-02、2015-01-03、2015-01-04、2015-01-10、2015-01-14、2015-01-15、2015-01- 2015年1月16日,2015年1月18日]
如果您对lambda和流还不满意,当然可以使用常规循环编写所有这些内容。
半开放
请注意,我的结果与您的结果不太匹配。我的代码使用常用的Half-Open方法来定义时间跨度。在这种方法中,开始为包含,而结束为排他。这允许时间跨度整齐地彼此邻接,而不会重叠且没有间隙。我建议您也采用这种方法。
如果您拒绝我的建议,请注意List < LocalDate > list =
target
.stream()
.filter(
( LocalDate localDate ) -> ranges
.stream()
.noneMatch(
( LocalDateRange range ) -> range.contains( localDate )
)
)
.collect( Collectors.toList() )
;
可以使用其他工厂方法来使用全封闭方法,其中开始和结束都包括在内。
,
我的图书馆Time4J根据您的期望A-(B + C + D)直接为subtraction of intervals提供支持。
ChronoFormatter<PlainTimestamp> parser =
ChronoFormatter.ofTimestampPattern("uuuu-MM-dd HH:mm",PatternType.CLDR,Locale.ROOT);
// my assumption for your input,please adjust the interval pattern if necessary
String intervalPattern = "{0} / {1}";
String sa = "2015-01-01 00:00 / 2015-01-20 00:00";
String sb = "2015-01-05 00:00 / 2015-01-10 00:00";
String sc = "2015-01-11 00:00 / 2015-01-14 00:00";
String sd = "2015-01-19 00:00 / 2015-01-25 00:00";
TimestampInterval a = TimestampInterval.parse(sa,parser,intervalPattern);
TimestampInterval b = TimestampInterval.parse(sb,intervalPattern);
TimestampInterval c = TimestampInterval.parse(sc,intervalPattern);
TimestampInterval d = TimestampInterval.parse(sd,intervalPattern);
IntervalCollection<PlainTimestamp> result =
IntervalCollection.onTimestampAxis().plus(a).minus(Arrays.asList(b,c,d));
所得的间隔集合包含期望的间隔和期望的间隔(只需对结果调用getIntervals()
,并调用PlainTimestamp.toTemporalAccessor()
转换为LocalDateTime
)。默认情况下,此处的所有间隔都是半开的,这意味着开始是包容性的,而结束是排斥性的。因此,使用天数和封闭边界char [和开放边界char):
[1-5),[10-11),[14-19)
几乎与您的期望“ {1,2,3,4,10,15,16,17,18}”相符,但14而不是15(我认为这只是您输入的错字)。 / p>
本文链接:https://www.f2er.com/3110214.html