检查日期范围与其他日期范围的缺失天数

3
这是我想做的事情: 我有一个日期范围,例如从2013年03月04日到2013年04月23日 - 这是我的主要时间范围。
现在我有可能创建自己的一些时间范围(例如从2013年04月04日到2013年04月09日和从2013年04月11日到2013年04月23日)。这些范围必须覆盖整个主要范围,因此每天的主要范围(不包括周末)需要在我的时间范围内对应一天。
我的计划是为主要范围创建一个数组。然后我会检查我的每个时间范围对主要范围进行比较。如果存在符合条件的日期,则会将该日期从主要范围中删除。所以最终结果,如果一切正常,将得到一个空数组,因为所有日期都被自己的时间范围覆盖。如果不是这样,那么未被覆盖的日期仍然存在于主要范围中,并且可以使用它们(在本例中:2013年03月04日,2013年04月10日)。
是否有更好的解决此问题的方法?NotesDateTimeRanges?

嗯,真的很想知道为什么有人给这个问题打了一个负一分...而且我觉得你的答案还不错。不过别忘了回收你的Notes对象... - Lothar Mueller
2个回答

2
我会将日期添加到一个排序集合中,然后使用“海盗算法”。向左看,向右看,如果任何一个方向找不到,就可以停止搜索(除非你想找到所有缺失的日期)。
以下是我的建议(您可能需要调整最终列表以将值存回):
var AbsenctSince:NotesDateTime; //Start Date - stored in the NotesItem
var endDate:NotesDateTime; // Return, could be in Notes or Today
var wfDoc:NotesDocument = docApplication.getDocument();
var responseCDs:NotesDocumentCollection = wfDoc.getResponses();
var docResponse:NotesDocument;
var nextResponse:NotesDocument;

//Get the date, which limits the function - if there is a return information, then this is the limit, else today
AbsenctSince = wfDoc.getDateTimeValue("AbsentSince") ;
if (wfDoc.hasItem("ReturnInformationDat")) {
    endDate = wfDoc.getDateTimeValue("ReturnInformationDat");
} else {
    endDate = session.createDateTime("Today");
}

//Get all days between two dates - as pure Java!
var dateList:java.util.List = getWorkDayList(AbsenctSince.toJavaDate(), endDate.toJavaDate());

// Looping once through the reponse documents
var docResponse = responseCDs.getFirstDocument();
while (docResponse != null) {
    nextResponse = responseCDs.getNextDocument(docResponse);
    var CDValidSince:NotesDateTime = docResponse.getDateTimeValue("CDValidSince");
    var CDValidTill:NotesDateTime = docResponse.getDateTimeValue("CDValidTill");
    // Now we need get all days in this range
    var removeDates:java.util.List = getWorkDayList(CDValidSince.toJavaDate(),CDValidTill.toJavaDate());
    dateList.removeAll(removeDates);
    docResponse.recycle();
    docResponse = nextResponse;  
}   
// Both docs are null - nothing to recycle left
// Now we only have uncovered dates left in dateList

docApplication.replaceItemValue("openDates", dateList);

// Cleanup
try {
 AbsenctSince.recycle();
 endDate.recyle();
 wfDoc.recycle();
 responseCDs.recycle(); 
} catch (e) {
dBar.error(e);
}

function getWorkDayList(startDate, endDate) {
var dates:java.util.List = new java.util.ArrayList();
var calendar:java.util.Calendar = new java.util.GregorianCalendar();
    calendar.setTime(startDate);
    while (calendar.getTime().before(endDate)) {
   var workDay = calendar.get(calendar.DAY_OF_WEEK);
   if (workDay != calendar.SATURDAY && workDay != calendar.SUNDAY) {
        var result = calendar.getTime();    
        dates.add(result);
   }
     calendar.add(java.util.Calendar.DATE, 1);
   }
   return dates;   
}

完成后请发布您的解决方案。需要注意的事项:边缘条件-> getWorkDayList是否包括最后一天(应该吗)?您可能需要将dateList中的条目转换回NotesDateTime对象。 - stwissel

1
我现在是这样做的(目前似乎有效):

var dateArray = new Array();
var responseCDs:NotesDocumentCollection = docApplication.getDocument().getResponses();
var dt:NotesDateTime = session.createDateTime("Today");
var wfDoc = docApplication.getDocument();
dt.setNow();

//Get the date, which limits the function - if there is a return information, then this is the limit, else today
var AbsenctSince:NotesDateTime = session.createDateTime(wfDoc.getItemValue("AbsentSince").toString().substr(0,19));
if (wfDoc.hasItem("ReturnInformationDat")) {
    var endDate:NotesDateTime = session.createDateTime(wfDoc.getItemValue("ReturnInformationDat").toString().substr(0,19));
} else {
    var endDate:NotesDateTime = session.createDateTime("Today");
}

//Get all days between two dates
dateArray = getDates(AbsenctSince, endDate);

for (var i=dateArray.length-1; i >= 0 ; i--) {
    var checkDate:NotesDateTime = session.createDateTime(dateArray[i].toString().substr(0,19));
    var day = checkDate.toJavaDate().getDay();

    //Remove weekends first
    if ((day == 6) || (day == 0)) { //6 = Saturday, 0 = Sunday
        dBar.info("splice: " + dateArray[i]);
        dateArray = dateArray.splice(i,1);
    } else {
        var docResponse = responseCDs.getFirstDocument();
        //Work through all response docs to check if any date is covered
        while (docResponse != null) {
            var CDValidSince:NotesDateTime = session.createDateTime(docResponse.getItemValue("CDValidSince").toString().substr(0,19));
            var CDValidTill:NotesDateTime = session.createDateTime(docResponse.getItemValue("CDValidTill").toString().substr(0,19));

            //checkDate covered? If yes, it will be removed
            if (checkDate.timeDifference(CDValidSince)/86400 >= 0 && checkDate.timeDifference(CDValidTill)/86400 <= 0 ) {
                dBar.info("splice: " + dateArray[i]);
                dateArray = dateArray.splice(i,1);
            }

            docResponse = responseCDs.getNextDocument();
        }
    }   
}

docApplication.replaceItemValue("openDates", dateArray);

我正在使用这个函数(采用自此问题):

function getDates(startDate:NotesDateTime, endDate:NotesDateTime) {
    var dateArray = new Array();
    var currentDate:NotesDateTime = startDate;
    while (endDate.timeDifference(currentDate) > 0) {
        dateArray.push( currentDate.getDateOnly() );
        currentDate.adjustDay(1);
    }
    return dateArray;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接