首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在跨多天的每周计划中检查可用性

在跨多天的每周计划中检查可用性
EN

Stack Overflow用户
提问于 2019-06-12 17:40:56
回答 1查看 205关注 0票数 0

我每周的可用时间安排如下所示:

  • 星期六-中午12: 00 :00
  • 星期日-00:00-10:00
  • 星期四-中午12:00-21:00

例如,该用户仅在指定的时间戳之间和3天内可用。我既有时间戳,也有时间戳,需要在用户可用的可用性间隔之间。

我的问题是,如果跨越两个不同天的两个间隔是连续的,我如何检查它是否可用?例如,星期六和星期日产生一个连续的可用间隔,如何检查从周六22:00开始到周日02:00结束的间隔是否实际可用?

EN

回答 1

Stack Overflow用户

发布于 2019-06-12 21:46:05

据我理解,您遇到的问题是将两个给定日期/时间点之间的时间段与可能重叠或连续的日期/时间点之间的多个不同的可用性时间间隔进行比较,以确定所需期间是否完全由一个或多个可用期覆盖。

在过去处理类似问题时,我发现了一种很好的处理方法,那就是对多个不同的可用期进行预处理,以便将重叠或连续的周期连接到“标准化”的大周期中,这样您就可以得到一组最小的可用性周期,涵盖原始集合中定义的所有时间。然后,它变得更容易检查所需的期限与标准化的集合。

这也有一个优点(尽管您的需求中没有说明这一点),您可以添加来自多个提供者的可用性(例如,如果您正在寻找连续的“覆盖”,而不是一个特定的单一资源)。

下面是一些示例代码,说明了这种方法。请注意,这段代码没有经过详尽的测试。

代码语言:javascript
运行
复制
/**
 * A class definition for an availability period
 * @param {Date} start date/time 
 * @param {Date} end date/time
 */
var Period = function( start, end ){
    // Set the start and end dates
    this.start = start;
    this.end = end;

    // Set the start and end timestamps (for faster comparison)
    this.startTime = start.getTime();
    this.endTime = end.getTime();

    // Flag to indicate if this availability period is completely contained within another
    this.contained = false;

    // Check validity of start and end
    if( this.startTime > this.endTime ){
        throw new Error( "Start time of period cannot be later than end time");
    }

    // Function to check if this period includes a required period
    this.includes = function( period ){
        if( period.startTime >= this.startTime && period.endTime <= this.endTime ) return true;
        return false;
    }

}

/**
 * A class definition for a period store that accepts addition
 * of multiple available periods and merges overlapping periods,
 * and has a function to check if a specified period is available
 */
var PeriodStore = function(){
    this.periods = [];
    this.calllevel = 0;

    // Member function to add a new period to the collection
    // of periods - if it overlaps with an existing period
    // both will be merged into a single spanning period.
    this.addAvailabilityPeriod = function( newPeriod ){
        // wind up the call count (see below)
        this.calllevel++;

        let self = this;

        newPeriod.contained = false;

        // compare the new period to all the existing periods
        self.periods.forEach( function( oldPeriod ){

            // only check if both periods are not contained in another
            if ( !newPeriod.contained && !oldPeriod.contained ){


                if( oldPeriod.includes( newPeriod ) ){
                    newPeriod.contained = true;
                } else
                if( newPeriod.includes( oldPeriod ) ){
                    oldPeriod.contained = true;
                } else
                if( oldPeriod.startTime <= newPeriod.endTime 
                    && oldPeriod.startTime > newPeriod.startTime 
                    && oldPeriod.endTime > newPeriod.endTime ){

                    // replace the two periods with a new one spanning both
                    newPeriod.contained = true;
                    oldPeriod.contained = true;
                    // Recursive call to add the new merged period to the collection
                    self.addAvailabilityPeriod( new Period(newPeriod.start, oldPeriod.end) );

                } else 
                if( newPeriod.startTime <= oldPeriod.endTime 
                    && newPeriod.startTime > oldPeriod.startTime 
                    && newPeriod.endTime > oldPeriod.endTime ){

                    // replace the two periods with a new one spanning both
                    newPeriod.contained = true;
                    oldPeriod.contained = true;

                    // Recursive call to add the new merged period to the collection
                    self.addAvailabilityPeriod( new Period(oldPeriod.start, newPeriod.end) )

                }
            }
        } )

        // If the new period is not contained within 
        // another period, then add it to the periods 
        // collection
        if( !newPeriod.contained ) self.periods.push( newPeriod );

        // unwind the call count
        this.calllevel--;

        // Clean up the list to remove any previously-existing periods that
        // are now contained withing any new periods.
        if (this.calllevel == 0 ){
            for( var ix = self.periods.length - 1; ix >= 0; ix-- ){
                if( self.periods[ix].contained ){
                    console.log( "Removing contained period", self.periods[ix] )
                    self.periods.splice( ix, 1 );
                }
            }
        }

    }

    // Function to check if a given period is contained
    // within any of the available periods in the store
    // and return the containing period if so, null if not
    this.checkAvailability = function( checkperiod ){
        var self = this;

        console.log( "Checking availability", checkperiod );
        for( var ix = 0; ix < self.periods.length ; ix++ ){

            if( self.periods[ix].includes( checkperiod ) ){
                return self.periods[ix];
            }
        }
        return null;

    }

}

// ------------------ TESTING -------------------------


// Create array of available periods
var availablePeriods = [
    new Period( new Date( "2017-08-01T07:00:00Z"),  new Date( "2017-08-01T08:00:00Z" ) )
    , new Period( new Date( "2017-08-02T07:00:00Z"), new Date( "2017-08-02T08:00:00Z" ) )
    , new Period( new Date( "2017-08-01T08:00:00Z"), new Date( "2017-08-02T06:55:00Z" ) )
]

// Create the period store
var periodStore = new PeriodStore();

// Add all the available periods to the store
availablePeriods.forEach( function(period){

    periodStore.addAvailabilityPeriod( period );

})

// Report the available periods
console.log( periodStore );

// Check availability between two date / times
var fm = new Date( "2017-08-01T07:30:00Z" );
var to = new Date( "2017-08-01T08:30:00Z" );

console.log( periodStore.checkAvailability( new Period( fm, to ) ) );

to = new Date( "2017-08-02T09:30:00Z")

console.log( periodStore.checkAvailability( new Period( fm, to ) ) ) ;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56567691

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档