2017-07-14 178 views
1

我必須計算事件發生次數。計算應基於經常性事件模式。經常性事件模式是基於rfc5545RFC5545。同時計算RRULE和EXDATE(EXRULE)的事件發生率

我找到了lib-recur庫來計算出現次數。以下描述我看到它們提供了使用的特定實例集(例如,rrule,exrule,rdates或exdates的列表)的實例來計算。我使用RRULE的計算,似乎有效。我需要在我的邏輯中找到正確的所有事件,包括計算EXDATE,EXRULE。但似乎最後的排除在這裏不支持。 小的代碼示例:

import org.dmfs.rfc5545.DateTime; 
import org.dmfs.rfc5545.recurrenceset.RecurrenceRuleAdapter; 
import org.dmfs.rfc5545.recurrenceset.RecurrenceSet; 
import org.dmfs.rfc5545.recurrenceset.RecurrenceSetIterator; 
@Test 
public void testSpecial() throws InvalidRecurrenceRuleException { 
    RecurrenceRule recurrenceRule = new RecurrenceRule("FREQ=YEARLY;BYMONTHDAY=23;BYMONTH=5;COUNT=3"); 
    RecurrenceRuleIterator it = recurrenceRule.iterator(DateTime.nowAndHere()); 
    int maxInstances = 10; // limit instances for rules that recur forever 
    while (it.hasNext() && (!recurrenceRule.isInfinite() || maxInstances-- > 0)) { 
     DateTime nextInstance = it.nextDateTime(); 
     // do something with nextInstance 
     System.out.println(nextInstance); 
    } 
} 

結果:

20170714T163325

20180523T163325

20190523T163325

我也知道,google based library可以提供核心HANDL RRRES,EXRULE ...基於rfc5545標準。但我還沒有找到如何在這裏計算出現次數(包括RRULES,EXDATE,EXRULE)。

更多的例子,但對於google-rfc-2445庫:

import com.google.ical.compat.jodatime.LocalDateIterable; 
import com.google.ical.compat.jodatime.LocalDateIterator; 
import com.google.ical.compat.jodatime.LocalDateIteratorFactory; 
import com.google.ical.values.RRule; 
@Test 
public void test() throws ParseException { 
    String sRule = "RRULE:FREQ=YEARLY;COUNT=3;INTERVAL=2;BYMONTH=5;BYMONTHDAY=22,23,24,25,26,27,28;BYDAY=MO"; 
    LocalDateIterable localDateIterable = LocalDateIteratorFactory 
      .createLocalDateIterable(sRule, org.joda.time.LocalDate.now(), true); 
    LocalDateIterator iterator = localDateIterable.iterator(); 
    while (iterator.hasNext()) { 
     System.out.println(iterator.next()); 
    } 
} 

結果:

2017年7月14日

2019年5月27日

2021年5月24日

2023-05-22

請分享鏈接到已具有複雜事件計算功能的開源庫(計算應包括RRULE,EXDATEs同時)。

回答

2

lib-recur確實支持計算重複集。雖然,這個組件的界面並不完美(但不是很方便)。

這裏是它如何與一個RRULE和一個EXRULE工作一個簡單的例子:

// note: recurrence expansion takes place in a specific time zone 
TimeZone tz = TimeZone.getDefault(); 
// the start of the recurring event 
DateTime start = new DateTime(tz, 2017, 5 - 1 /* zero based */, 23, 12, 0, 0); 

// parse the RRULE 
RecurrenceRule recurrenceRule = new RecurrenceRule("FREQ=YEARLY;BYMONTHDAY=23;BYMONTH=5;COUNT=30"); 
// parse the EXRULE (in this case every 3rd instance of the RRULE) 
RecurrenceRule exceptionRule = new RecurrenceRule("FREQ=YEARLY;INTERVAL=3;BYMONTHDAY=23;BYMONTH=5;COUNT=10"); 

// create an empty RecurrenceSet 
// a recurrence set is the set of all actual instance of a recurring event and may consist of multiple instance and excludes sources 
RecurrenceSet recurrenceSet = new RecurrenceSet(); 
// add the instances of the RRULE 
recurrenceSet.addInstances(new RecurrenceRuleAdapter(recurrenceRule)); 
// exclude the instances of the EXRULE 
recurrenceSet.addExceptions(new RecurrenceRuleAdapter(exceptionRule)); 

RecurrenceSetIterator recurrenceSetIterator = recurrenceSet.iterator(start.getTimeZone(), start.getTimestamp()); 

int maxInstances = 10; // limit instances for rules that recur forever 
// iterate as long as the recurrence set still has instances 
while (recurrenceSetIterator.hasNext() && (!recurrenceRule.isInfinite() || maxInstances-- > 0)) 
{ 
    // get the next instance of the recurrence set 
    DateTime nextInstance = new DateTime(start.getTimeZone(), recurrenceSetIterator.next()); 
    // do something with nextInstance 
    System.out.println(nextInstance); 
} 

你可以看到,RecurrenceSetlong時間戳,這是很不理想工作。

要支持RDATESEXDATES,您可以使用RecurrenceList適配器。RecurrenceList要麼需要時間戳的陣列或一個時區和的逗號分隔的日期 - 時間或日期值的字符串(如它們是爲RDATES和EXDATES定義):

// add more RDATES instances 
recurrenceSet.addInstances(new RecurrenceList("20171212T121212,20181212T121212", tz)); 

// add EXDATES 
recurrenceSet.addExceptions(new RecurrenceList("20180523T120000,20190523T120000", tz)); 

注意,在對比的是RecurrenceRuleIterator東西,這個組件還沒有任何測試覆蓋。

+1

此答案的第一個版本中提到的錯誤已修復。 – Marten