-2

I have a collection of objects in javascript, they represent to periods of time. I need iterate and know each few overlap. There must be some framework to compare periods in JavaScript but I have not given with any and I am finding it very difficult to carry out this function.

Do you know how to do this?

for example:

function period (initDate, duration)
{
   this.initDate = initDate;
   this.duration= duration;
}

var now = Date.now();
var date2 = now.addMinutes(90);
var date3 = now.addMinutes(120);
var date4 = now.addMinutes(180);
var date5 = now.addMinutes(240);
var date6 = now.addMinutes(190);

var periods = new Array(); 
periodos.push(new period(now, 30));
periodos.push(new period(date2, 150));
periodos.push(new period(date3, 90));
periodos.push(new period(date4, 45));
periodos.push(new period(date5, 25));
periodos.push(new period(date6, 60));

// So if it is not declared at 13:00 would be:
// period[0] start=13:00  end=13:30
// period[1] start=14:30  end=17:00
// period[2] start=15:00  end=16:30
// period[3] start=16:00  end=16:45
// period[4] start=17:00  end=17:45
// period[5] start=16:10  end=17:10

// They overlap in this example:
// period[0] no overlap
// period[1] with period[2], period[3] y period[5]
// period[2] with period[1], period[3] y period[5]
// period[3] with period[1], period[2] y period[5]
// period[4] with period[5]
// period[5] with period[1], period[2], period[3] y period[4]


//var numPeriodsOverlaps = periodsOverlaps(period[5]);

/*
function periodsOverlaps(periodFind)
{
 // iterate and compare with all
    
}
*/

3 Answers3

0

If I understand what you are trying to achieve, I think that this might do it.

I understand your problem as such:

Pass a date into a function. Iterate over an array of start times and end times and evaluate if the passed date lies between the start time and end time.

I am just learning JavaScript myself, so I am relying on CoffeeScript.

Here is the CoffeeScript version which I find easier to read than JavaScript:

# Usage: zip(arr1, arr2, arr3, ...)
zip = () ->
  # zips iterables a la Python's zip
  # https://coffeescript-cookbook.github.io/chapters/arrays/zip-function
  lengthArray = (arr.length for arr in arguments)
  length = Math.min(lengthArray...)
  for i in [0...length]
    arr[i] for arr in arguments

MINUTES = 60000  # factor to convert to milliseconds
now = Date.now()  # milliseconds since epoch time
durations = new Array(90, 120, 180, 240, 190)  # minutes

start_times = new Array()
start_times.push(now)
# convert to milliseconds
start_times.push(now + (duration * MINUTES)) for duration in durations

time_periods = new Array(30, 150, 90, 45, 25, 60)  # minutes
end_times = new Array()
for time_periods__start_times in zip(time_periods, start_times)
  time_period = time_periods__start_times[0]
  start_time = time_periods__start_times[1]
  end_times.push(start_time + (time_period * MINUTES))

is_between_periods = (date)->
  for end_time__start_time in zip(end_times, start_times)
    end_time = end_time__start_time[0]
    start_time = end_time__start_time[1]
    overlaps = date >= start_time and date <= end_time
    date = new Date(date)
    start = new Date(start_time)
    end = new Date(end_time)
    console.log("date: #{date}\nstart: #{start}\nend: #{end}\noverlaps: #{overlaps}")

is_between_periods(now)

The result I get from passing now into the is_between_periods function is as follows:

date: Tue Feb 23 2016 16:13:38 GMT+0000 (UTC)

start: Tue Feb 23 2016 16:13:38 GMT+0000 (UTC)

end: Tue Feb 23 2016 16:43:38 GMT+0000 (UTC)

overlaps: true

date: Tue Feb 23 2016 16:13:38 GMT+0000 (UTC)

start: Tue Feb 23 2016 17:43:38 GMT+0000 (UTC)

end: Tue Feb 23 2016 20:13:38 GMT+0000 (UTC)

overlaps: false

date: Tue Feb 23 2016 16:13:38 GMT+0000 (UTC)

start: Tue Feb 23 2016 18:13:38 GMT+0000 (UTC)

end: Tue Feb 23 2016 19:43:38 GMT+0000 (UTC)

overlaps: false

date: Tue Feb 23 2016 16:13:38 GMT+0000 (UTC)

start: Tue Feb 23 2016 19:13:38 GMT+0000 (UTC)

end: Tue Feb 23 2016 19:58:38 GMT+0000 (UTC)

overlaps: false

date: Tue Feb 23 2016 16:13:38 GMT+0000 (UTC)

start: Tue Feb 23 2016 20:13:38 GMT+0000 (UTC)

end: Tue Feb 23 2016 20:38:38 GMT+0000 (UTC)

overlaps: false

date: Tue Feb 23 2016 16:13:38 GMT+0000 (UTC)

start: Tue Feb 23 2016 19:23:38 GMT+0000 (UTC)

end: Tue Feb 23 2016 20:23:38 GMT+0000 (UTC)

overlaps: false

Here is the JavaScript produced from the CoffeeScript:

// Generated by CoffeeScript 1.10.0
var MINUTES, duration, durations, end_times, is_between_periods, j, k, len, len1, now, ref, start_time, start_times, time_period, time_periods, time_periods__start_times, zip;

zip = function() {
  var arr, i, j, length, lengthArray, ref, results;
  lengthArray = (function() {
    var j, len, results;
    results = [];
    for (j = 0, len = arguments.length; j < len; j++) {
      arr = arguments[j];
      results.push(arr.length);
    }
    return results;
  }).apply(this, arguments);
  length = Math.min.apply(Math, lengthArray);
  results = [];
  for (i = j = 0, ref = length; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
    results.push((function() {
      var k, len, results1;
      results1 = [];
      for (k = 0, len = arguments.length; k < len; k++) {
        arr = arguments[k];
        results1.push(arr[i]);
      }
      return results1;
    }).apply(this, arguments));
  }
  return results;
};

MINUTES = 60000;

now = Date.now();

durations = new Array(90, 120, 180, 240, 190);

start_times = new Array();

start_times.push(now);

for (j = 0, len = durations.length; j < len; j++) {
  duration = durations[j];
  start_times.push(now + (duration * MINUTES));
}

time_periods = new Array(30, 150, 90, 45, 25, 60);

end_times = new Array();

ref = zip(time_periods, start_times);
for (k = 0, len1 = ref.length; k < len1; k++) {
  time_periods__start_times = ref[k];
  time_period = time_periods__start_times[0];
  start_time = time_periods__start_times[1];
  end_times.push(start_time + (time_period * MINUTES));
}

is_between_periods = function(date) {
  var end, end_time, end_time__start_time, l, len2, overlaps, ref1, results, start;
  ref1 = zip(end_times, start_times);
  results = [];
  for (l = 0, len2 = ref1.length; l < len2; l++) {
    end_time__start_time = ref1[l];
    end_time = end_time__start_time[0];
    start_time = end_time__start_time[1];
    overlaps = date >= start_time && date <= end_time;
    date = new Date(date);
    start = new Date(start_time);
    end = new Date(end_time);
    results.push(console.log("date: " + date + "\nstart: " + start + "\nend: " + end + "\noverlaps: " + overlaps));
  }
  return results;
};

is_between_periods(now);
Community
  • 1
  • 1
dmmfll
  • 2,666
  • 2
  • 35
  • 41
  • That seems extremely verbose. – RobG Feb 23 '16 at 22:56
  • I'm open to a less verbose solution. The verbosity comes from the zip function. I am just starting to learn JavaScript. I only know Python where zipping is a mainstay so decided to see if there were a JS equivalent. CoffeeScript is making the transition into idiomatic JS easier. It appears to me that JS is rather verbose by nature. – dmmfll Feb 24 '16 at 00:26
  • Newer versions include some handy array methods like *forEach*, *reduce*, etc. but they don't really cut down on code much, though they do help with encapsulation. Arrow functions can really trim verbosity but they're not widely supported yet. – RobG Feb 24 '16 at 00:34
0

You need to convert each period to a start and end time value, then see if the start and end is within the start and end of any other time value. Here's a function to do that, hopefully the comments are sufficient.

// From OP
function period (initDate, duration) {
  this.initDate = initDate;
  this.duration= duration;
}

// Function to add minutes to a time value in milliseconds
function addMinutes(timevalue, mins) {
  timevalue += mins * 6e4;
  return timevalue;
}

// Test data
var now = Date.now();
var date2 = addMinutes(now, 90);
var date3 = addMinutes(now, 120);
var date4 = addMinutes(now, 180);
var date5 = addMinutes(now, 240);
var date6 = addMinutes(now, 190);

var periods = [
  new period(now, 30), 
  new period(now, 40),
  new period(date2, 150), 
  new period(date3, 90),
  new period(date4, 45),
  new period(date5, 25),
  new period(date6, 60) 
];

// Check for overlapping periods
function checkOverlap(periods) {
  var overlappingPeriods = [];

  // For each period ...
  periods.forEach(function(p, i) {
    var pStart = p.initDate;
    var pEnd   = addMinutes(pStart, p.duration);

    // Check for overlap with all other periods
    periods.forEach(function(q, j) {
      
      // Don't test against self or previous
      if (j <= i) return; 
      
      var qStart = q.initDate;
      var qEnd   = addMinutes(qStart, q.duration);
    
      // See if start or end is within or entirely wraps previous period
      // Might only overlap by 1 millisecond
      if ((qStart > pStart && qStart < pEnd) || (qEnd > pStart && qEnd < pEnd) ||
          (qStart < pStart && qEnd > pEnd)) {
        overlappingPeriods.push([p, q]);
      }
    });
  });
  return overlappingPeriods
}

// Run the tests
var overlappingPeriods = checkOverlap(periods);

// Show results
var s = '';
overlappingPeriods.forEach(function(a) {
  s += new Date(a[0].initDate).toISOString() + ' plus ' + a[0].duration + ' overlaps with ' +
       new Date(a[1].initDate).toISOString() + ' plus ' + a[1].duration + '<br>';
});
document.write(s);
RobG
  • 142,382
  • 31
  • 172
  • 209
-1

Are you tried moment.js, It has a lot of functions to work with dates, times and an addin for timezones.

dobleUber
  • 566
  • 6
  • 22
  • That is not an answer. You might as well answer every DOM question with "Have you tried jQuery?". – RobG Feb 23 '16 at 22:50
  • @RobG he is asking for a framework: "There must be some framework to compare periods in JavaScript but I have not given with any and I am finding it very difficult to carry out this function." momentjs is a nice library to work with dates and timespans in javascript – dobleUber Feb 24 '16 at 22:10
  • Fine, but then show how to fix the issue, preferably using a plain JS solution first. See if you can do it in less code with greater readability than POJS. If not, then there's not much to recommend the library. – RobG Feb 24 '16 at 22:58