我每周的可用时间安排如下所示:
例如,该用户仅在指定的时间戳之间和3天内可用。我既有时间戳,也有时间戳,需要在用户可用的可用性间隔之间。
我的问题是,如果跨越两个不同天的两个间隔是连续的,我如何检查它是否可用?例如,星期六和星期日产生一个连续的可用间隔,如何检查从周六22:00开始到周日02:00结束的间隔是否实际可用?
发布于 2019-06-12 21:46:05
据我理解,您遇到的问题是将两个给定日期/时间点之间的时间段与可能重叠或连续的日期/时间点之间的多个不同的可用性时间间隔进行比较,以确定所需期间是否完全由一个或多个可用期覆盖。
在过去处理类似问题时,我发现了一种很好的处理方法,那就是对多个不同的可用期进行预处理,以便将重叠或连续的周期连接到“标准化”的大周期中,这样您就可以得到一组最小的可用性周期,涵盖原始集合中定义的所有时间。然后,它变得更容易检查所需的期限与标准化的集合。
这也有一个优点(尽管您的需求中没有说明这一点),您可以添加来自多个提供者的可用性(例如,如果您正在寻找连续的“覆盖”,而不是一个特定的单一资源)。
下面是一些示例代码,说明了这种方法。请注意,这段代码没有经过详尽的测试。
/**
* 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 ) ) ) ;
https://stackoverflow.com/questions/56567691
复制相似问题