/**
* Copyright (C) 2015-2016 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* @author: From ndn-group-encrypt src/interval https://github.com/named-data/ndn-group-encrypt
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* A copy of the GNU Lesser General Public License is in the file COPYING.
*/
/**
* An Interval defines a time duration which contains a start timestamp and an
* end timestamp. Create an Interval with one of these forms:
* Interval(isValid).
* Interval(startTime, endTime).
* Interval(interval).
* @param {boolean} isValid True to create a valid empty interval, false to
* create an invalid interval.
* @param {number} startTime The start time as milliseconds since Jan 1, 1970 UTC.
* The start time must be less than the end time. To create an empty interval
* (start time equals end time), use the constructor Interval(true).
* @param {number} endTime The end time as milliseconds since Jan 1, 1970 UTC.
* @param {Interval} interval The other interval with values to copy.
* @note This class is an experimental feature. The API may change.
* @constructor
*/
var Interval = function Interval(value, endTime)
{
if (typeof value === 'object' && value instanceof Interval) {
// Make a copy.
this.startTime_ = value.startTime_;
this.endTime_ = value.endTime_;
this.isValid_ = value.isValid_;
}
else if (typeof value === 'number') {
var startTime = value;
if (!(startTime < endTime))
throw new Error("Interval start time must be less than the end time");
this.startTime_ = startTime;
this.endTime_ = endTime;
this.isValid_ = true;
}
else {
var isValid = (value ? true : false);
this.startTime_ = -Number.MAX_VALUE;
this.endTime_ = -Number.MAX_VALUE;
this.isValid_ = isValid;
}
};
exports.Interval = Interval;
/**
* Set this interval to have the same values as the other interval.
* @param {Interval} other The other Interval with values to copy.
*/
Interval.prototype.set = function(other)
{
this.startTime_ = other.startTime_;
this.endTime_ = other.endTime_;
this.isValid_ = other.isValid_;
};
/**
* Check if the time point is in this interval.
* @param {number} timePoint The time point to check as milliseconds since
* Jan 1, 1970 UTC.
* @return {boolean} True if timePoint is in this interval.
* @throws Error if this Interval is invalid.
*/
Interval.prototype.covers = function(timePoint)
{
if (!this.isValid_)
throw new Error("Interval.covers: This Interval is invalid");
if (this.isEmpty())
return false;
else
return this.startTime_ <= timePoint && timePoint < this.endTime_;
};
/**
* Set this Interval to the intersection of this and the other interval.
* This and the other interval should be valid but either can be empty.
* @param {Interval} interval The other Interval to intersect with.
* @return {Interval} This Interval.
* @throws Error if this Interval or the other interval is invalid.
*/
Interval.prototype.intersectWith = function(interval)
{
if (!this.isValid_)
throw new Error("Interval.intersectWith: This Interval is invalid");
if (!interval.isValid_)
throw new Error("Interval.intersectWith: The other Interval is invalid");
if (this.isEmpty() || interval.isEmpty()) {
// If either is empty, the result is empty.
this.startTime_ = this.endTime_;
return this;
}
if (this.startTime_ >= interval.endTime_ || this.endTime_ <= interval.startTime_) {
// The two intervals don't have an intersection, so the result is empty.
this.startTime_ = this.endTime_;
return this;
}
// Get the start time.
if (this.startTime_ <= interval.startTime_)
this.startTime_ = interval.startTime_;
// Get the end time.
if (this.endTime_ > interval.endTime_)
this.endTime_ = interval.endTime_;
return this;
};
/**
* Set this Interval to the union of this and the other interval.
* This and the other interval should be valid but either can be empty.
* This and the other interval should have an intersection. (Contiguous
* intervals are not allowed.)
* @param {Interval} interval The other Interval to union with.
* @return {Interval} This Interval.
* @throws Error if this Interval or the other interval is invalid, or if the
* two intervals do not have an intersection.
*/
Interval.prototype.unionWith = function(interval)
{
if (!this.isValid_)
throw new Error("Interval.intersectWith: This Interval is invalid");
if (!interval.isValid_)
throw new Error("Interval.intersectWith: The other Interval is invalid");
if (this.isEmpty()) {
// This interval is empty, so use the other.
this.startTime_ = interval.startTime_;
this.endTime_ = interval.endTime_;
return this;
}
if (interval.isEmpty())
// The other interval is empty, so keep using this one.
return this;
if (this.startTime_ >= interval.endTime_ || this.endTime_ <= interval.startTime_)
throw new Error
("Interval.unionWith: The two intervals do not have an intersection");
// Get the start time.
if (this.startTime_ > interval.startTime_)
this.startTime_ = interval.startTime_;
// Get the end time.
if (this.endTime_ < interval.endTime_)
this.endTime_ = interval.endTime_;
return this;
};
/**
* Get the start time.
* @return {number} The start time as milliseconds since Jan 1, 1970 UTC.
* @throws Error if this Interval is invalid.
*/
Interval.prototype.getStartTime = function()
{
if (!this.isValid_)
throw new Error("Interval.getStartTime: This Interval is invalid");
return this.startTime_;
};
/**
* Get the end time.
* @return {number} The end time as milliseconds since Jan 1, 1970 UTC.
* @throws Error if this Interval is invalid.
*/
Interval.prototype.getEndTime = function()
{
if (!this.isValid_)
throw new Error("Interval.getEndTime: This Interval is invalid");
return this.endTime_;
};
/**
* Check if this Interval is valid.
* @return {boolean} True if this interval is valid, false if invalid.
*/
Interval.prototype.isValid = function() { return this.isValid_; };
/**
* Check if this Interval is empty.
* @return {boolean} True if this Interval is empty (start time equals end time),
* false if not.
* @throws Error if this Interval is invalid.
*/
Interval.prototype.isEmpty = function()
{
if (!this.isValid_)
throw new Error("Interval.isEmpty: This Interval is invalid");
return this.startTime_ == this.endTime_;
};