【问题标题】:Time periods compare时间段比较
【发布时间】:2016-02-23 13:41:55
【问题描述】:

我在 javascript 中有一组对象,它们代表一段时间。 我需要迭代并知道每一个重叠。 必须有一些框架来比较 JavaScript 中的周期,但我没有给出任何框架,而且我发现执行这个功能非常困难。

你知道怎么做吗?

例如:

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
    
}
*/

【问题讨论】:

  • 你能用英文写吗? Por lo general todo es en ingles ;)
  • 我正在将帖子翻译成英文。对不起
  • Date.now 返回一个数字,没有 Number.prototype.addMinutes 方法。代码在哪里?

标签: javascript arrays date period


【解决方案1】:

您需要将每个时间段转换为开始和结束时间值,然后查看开始和结束是否在任何其他时间值的开始和结束范围内。这是一个可以做到这一点的函数,希望 cmets 就足够了。

// 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);

【讨论】:

    【解决方案2】:

    如果我理解你想要达到的目标,我认为这可能会做到。

    我是这样理解你的问题的:

    将日期传递给函数。遍历一组开始时间和结束时间,并评估传递的日期是否介于开始时间和结束时间之间。

    我自己只是在学习 JavaScript,所以我依赖于 CoffeeScript。

    这是我觉得比 JavaScript 更容易阅读的 CoffeeScript 版本:

    # 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)
    

    我将now 传递给is_between_periods 函数得到的结果如下:

    日期:2016 年 2 月 23 日星期二 16:13:38 GMT+0000 (UTC)

    开始:2016 年 2 月 23 日星期二 16:13:38 GMT+0000 (UTC)

    结束:2016 年 2 月 23 日星期二 16:43:38 GMT+0000 (UTC)

    重叠:真

    日期:2016 年 2 月 23 日星期二 16:13:38 GMT+0000 (UTC)

    开始:2016 年 2 月 23 日星期二 17:43:38 GMT+0000 (UTC)

    结束:2016 年 2 月 23 日星期二 20:13:38 GMT+0000 (UTC)

    重叠:错误

    日期:2016 年 2 月 23 日星期二 16:13:38 GMT+0000 (UTC)

    开始:2016 年 2 月 23 日星期二 18:13:38 GMT+0000 (UTC)

    结束:2016 年 2 月 23 日星期二 19:43:38 GMT+0000 (UTC)

    重叠:错误

    日期:2016 年 2 月 23 日星期二 16:13:38 GMT+0000 (UTC)

    开始:2016 年 2 月 23 日星期二 19:13:38 GMT+0000 (UTC)

    结束:2016 年 2 月 23 日星期二 19:58:38 GMT+0000 (UTC)

    重叠:错误

    日期:2016 年 2 月 23 日星期二 16:13:38 GMT+0000 (UTC)

    开始:2016 年 2 月 23 日星期二 20:13:38 GMT+0000 (UTC)

    结束:2016 年 2 月 23 日星期二 20:38:38 GMT+0000 (UTC)

    重叠:错误

    日期:2016 年 2 月 23 日星期二 16:13:38 GMT+0000 (UTC)

    开始:2016 年 2 月 23 日星期二 19:23:38 GMT+0000 (UTC)

    结束:2016 年 2 月 23 日星期二 20:23:38 GMT+0000 (UTC)

    重叠:错误

    这是从 CoffeeScript 生成的 JavaScript:

    // 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);
    

    【讨论】:

    • 这似乎非常冗长。
    • 我愿意接受一个不那么冗长的解决方案。详细程度来自 zip 函数。我刚开始学习 JavaScript。我只知道压缩是主要支柱的 Python,所以决定看看是否有 JS 等价物。 CoffeeScript 使向惯用 JS 的过渡变得更加容易。在我看来,JS 本质上是相当冗长的。
    • 较新的版本包括一些方便的数组方法,如 forEachreduce 等,但它们并没有真正减少代码,尽管它们帮助封装。箭头函数确实可以减少冗长,但尚未得到广泛支持。
    【解决方案3】:

    你试过moment.js吗,它有很多功能可以处理日期、时间和时区插件。

    【讨论】:

    • 这不是答案。您不妨用“您尝试过 jQuery 吗?”来回答每个 DOM 问题。
    • @RobG 他要求一个框架:“必须有一些框架来比较 JavaScript 中的周期,但我没有给出任何框架,我发现执行这个功能非常困难。” momentjs 是一个很好的库,可以在 javascript 中处理日期和时间跨度
    • 很好,但是接下来展示如何解决这个问题,最好先使用普通的 JS 解决方案。看看你是否可以用比 POJS 更好的可读性更少的代码来做到这一点。如果没有,那么没有太多可推荐的库。
    猜你喜欢
    • 2021-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-19
    • 2020-12-16
    • 2010-11-06
    • 1970-01-01
    相关资源
    最近更新 更多