【问题标题】:Find available days within a date range查找日期范围内的可用天数
【发布时间】:2016-04-16 21:26:11
【问题描述】:

假设有一个系统可以显示活动的日期可用性。我们有一个主要的日期范围,所有事件都会发生。事件本身也可以是日期范围。

例子:

[Date X]========================================[Date Y]
        [A]=====[A]        [B]=====[B][C]=====[C]
        [ Event A ][ Open ][ Event B ][ Event C ]

日期 X 和日期 Y 是事件发生的主要日期范围。 A、B 和 C 是已安排好的活动。

如何有效地检索开放日期范围?

示例 2:

var rangeStart = new Date("04-01-2016");
var rangeEnd = new Date("04-31-2016");

var eventAStart = new Date("04-01-2016");
var eventAEnd = new Date("04-06-2016");

var eventBStart = new Date("04-15-2016");
var eventBEnd = new Date("04-30-2016");

我需要返回类似:

var availableRangeStart = "04-07-2015";
var availableRangeEnd = "04-14-2016";

因为这些是主要范围内的日期,没有与“事件”范围重叠。

确切地说我正在尝试做的事情:

我的应用是一个旅行计划器,用户可以在其中设置旅行日期,然后将不同的目的地添加到具有自己日期的旅行中。 (用户4月1日至4月30日去欧洲旅行,4月1日至4月6日在巴黎,4月15日至4月30日在伦敦)。但用户在 4 月 7 日至 4 月 14 日期间没有任何计划。我正在尝试返回这些日期,以便在他们添加新目的地时预先填写日期。

【问题讨论】:

  • 我不太明白你的意思
  • @YehiaAwad 对不起,我应该更清楚。可以说四月份有 3 场活动。事件 A 是 4 月 1 日 - 4 月 6 日,事件 B 是 4 月 15 日 - 4 月 20 日,事件 C 是 4 月 21 日 - 4 月 30 日。我需要检索 4 月 7 日 - 4 月 14 日(因为没有安排任何活动)。
  • @trincot 我添加了一些代码示例。我不太关心格式和语法(如果它不能更容易解决的话)我正在寻找解决这个问题的逻辑。我感谢您的帮助!事件可以重叠。
  • 又一个没有解释的反对票 - 人们应该写下为什么反对票以提高网站的质量 - 而不仅仅是增加挫败感并产生猜谜游戏。
  • @cbronson 感谢您的耐心等待和您的编辑。你的问题描述得很好,我觉得它很有挑战性。我在下面发布了一个答案。希望对你有帮助! PS:我喜欢你的 ASCII 模式。 :)

标签: javascript algorithm date


【解决方案1】:

我只是给你一个算法,因为最终的实现取决于你的代码。

var aprilAvailableDays = [true, true, true, etc...] // a boolean for each day

aprilEvents.forEach(function (event) {
    for (var i = event.startDay; i <= event.endDay; i++) {
        aprilAvailableDays[i] = false;
    }
});

【讨论】:

  • 最简单的解决方案往往也是最简单的。填充所有可用日期的数组,并在输入每个日期时,将日期标记为不可用,如果它位于要添加的范围内。您可以在添加之前预先检查这些日期是否已被占用。简洁大方。
  • 哇,我真的想多了。非常感谢您的帮助!
【解决方案2】:

这是一个从/返回空闲时段的解决方案:

// Helper function
function addDays(date, days) {
    return new Date(date.getTime() + days * 24*60*60*1000);
}

// Main function
function gaps(period, events) {
    events = events.slice(0).filter(function (a) {
        // Exclude events which are outside the main period
        return a.to >= period.from && a.from <= period.to;
    }).sort(function (a, b) {
        // Sort events by their starting date
        return a.from - b.from;
    });
    var result = events.reduce(function (result, curr) {
        if (curr.from - result.free > 0) {
            // gap found
            result.gaps.push({
                from: result.free, 
                to:   addDays(curr.from, -1)
            });
        }
        if (curr.to - result.free >= 0) {
            // first free day is after this event
            result.free = addDays(curr.to, 1)
        }
        return result;
    }, { gaps: [], free: period.from } );
    // Potentially add gap between last event end period-end
    if (period.to - result.free >= 0) {
        result.gaps.push({
            from: result.free,
            to:   period.to
        });
    }
    return result.gaps;
}


// Sample data:

var period = {
    from: new Date('2016-01-01'),
    to: new Date('2016-12-31')
};

var events = [
    { from: new Date('2016-02-01'), to: new Date('2016-02-29') },
    { from: new Date('2016-03-01'), to: new Date('2016-03-15') },
    { from: new Date('2016-04-16'), to: new Date('2016-04-30') },
];

// Call to function
var res = gaps(period, events);

// Output in snippet
document.write('<pre>' + JSON.stringify(res, null, 4));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-26
    • 2016-09-22
    • 2016-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多