Javascript或PHP创建新日期但仅计算营业时间

时间:2015-12-11 17:34:35

标签: javascript php date

我想创建一个脚本来计算基于今天的日期+ X小时数的新日期是否会超过某个日期或更早。但是,我想只考虑营业时间(上午8点到下午18点)和工作日(不是周六或周日)。

Ex:今天的日期 - 2015年12月11日+ 30小时将导致我的日期只有10个小时且我不算周六或周日的日期?

我有一个脚本可以做到这一点,但是非常不可靠。有人有一个简单的解决方案吗?我在网上找不到任何东西。

function Diferenca($data1, $data2, $tipo){
if($data2==""){
    $data2 = date("d/m/Y H:i");
}
if($tipo==""){
    $tipo = "h";
}
for($i=1;$i<=2;$i++){
    ${"dia".$i} = substr(${"data".$i},0,2);
    ${"mes".$i} = substr(${"data".$i},3,2);
    ${"ano".$i} = substr(${"data".$i},6,4);
    ${"horas".$i} = substr(${"data".$i},11,2);
    ${"minutos".$i} = substr(${"data".$i},14,2);
}
$segundos = mktime($horas2,$minutos2,0,$mes2,$dia2,$ano2) - mktime($horas1,$minutos1,0,$mes1,$dia1,$ano1);
switch($tipo){
    case "m": $difere = $segundos/60;    break;
    case "H": $difere = $segundos/3600;    break;
    case "h": $difere = round($segundos/3600);    break;
    case "D": $difere = $segundos/86400;    break;
    case "d": $difere = round($segundos/86400);    break;
    case "s": $difere = $segundos;    break;
}
return $difere; }

function dec_Data($data){
$dia = substr($data, 8, 2);
$mes = substr($data, 5, 2);
$ano = substr($data, 0, 4);
$hr = substr($data, 11, 2);
$m = substr($data, 14, 2);
$data_retorno = $dia.'/'.$mes.'/'.$ano." ".$hr.":".$m;
return $data_retorno; }

if($data_cadastro_enc != '0000-00-00' and $data_cadastro_enc != '' and $sla_atend > 0 and $_POST["hora_abertura"] > 0 and $_POST["ativ_realizada"] != 'Projeto'){

    $data_cadastro_atend = $data_cadastro_enc." ".$_POST["hora_abertura"];  
    $ano_data_cadastro_atend = substr($data_cadastro_atend, 0, 4);
    $mes_data_cadastro_atend = substr($data_cadastro_atend, 5, 2);
    $dia_data_cadastro_atend = substr($data_cadastro_atend, 8, 2);
    $hr_data_cadastro_atend = substr($data_cadastro_atend, 11, 2);
    $mn_data_cadastro_atend = substr($data_cadastro_atend, 14, 2);

    $timestamp_atend = mktime($hr_data_cadastro_atend + $sla_atend, $mn_data_cadastro_atend, 0, $mes_data_cadastro_atend, $dia_data_cadastro_atend, $ano_data_cadastro_atend);

    $diaSemana = getDate($timestamp_atend);
    $diaValor = $diaSemana[weekday];

    $nova_data_atend = date("Y-m-d H:i", $timestamp_atend);

    $ano_nova_data_atend = substr($nova_data_atend, 0, 4);
    $mes_nova_data_atend = substr($nova_data_atend, 5, 2);
    $dia_nova_data_atend = substr($nova_data_atend, 8, 2);
    $hr_nova_data_atend = substr($nova_data_atend, 11, 2);
    $mn_nova_data_atend = substr($nova_data_atend, 14, 2);

    switch ($diaValor){     
        case "Saturday": $timestamp_atend = mktime($hr_nova_data_atend, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend + 2, $ano_nova_data_atend);
        break;

        case "Sunday": $timestamp_atend = mktime($hr_nova_data_atend, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend + 1, $ano_nova_data_atend);
        break;

        default: $timestamp_atend = mktime($hr_nova_data_atend, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend, $ano_nova_data_atend);
    }

    $nova_data_atend = date("Y-m-d H:i", $timestamp_atend);
    $val_hora_atend = $data_cadastro_enc." 18:00";

    while($nova_data_atend > $val_hora_atend){

        $data_dif = dec_Data($nova_data_atend);
        $data_dif_com = dec_Data($val_hora_atend);      

        $agora = Diferenca($data_dif_com, $data_dif, "m");

        $soma = $agora + 840;

        $ano_data_cadastro_atend_com = substr($val_hora_atend, 0, 4);
        $mes_data_cadastro_atend_com = substr($val_hora_atend, 5, 2);
        $dia_data_cadastro_atend_com = substr($val_hora_atend, 8, 2);
        $hr_data_cadastro_atend_com = substr($val_hora_atend, 11, 2);
        $mn_data_cadastro_atend_com = substr($val_hora_atend, 14, 2);

        $timestamp_atend = mktime($hr_data_cadastro_atend_com, $mn_data_cadastro_atend_com + $soma, 0, $mes_data_cadastro_atend_com, $dia_data_cadastro_atend_com, $ano_data_cadastro_atend_com);

        $diaSemana = getDate($timestamp_atend);
        $diaValor = $diaSemana[weekday];

        $nova_data_atend = date("Y-m-d H:i", $timestamp_atend);

        $ano_nova_data_atend = substr($nova_data_atend, 0, 4);
        $mes_nova_data_atend = substr($nova_data_atend, 5, 2);
        $dia_nova_data_atend = substr($nova_data_atend, 8, 2);
        $hr_nova_data_atend = substr($nova_data_atend, 11, 2);
        $mn_nova_data_atend = substr($nova_data_atend, 14, 2);

        switch($diaValor){      
            case "Saturday": $timestamp_atend = mktime($hr_nova_data_atend, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend + 2, $ano_nova_data_atend);
            break;

            case "Sunday": $timestamp_atend = mktime($hr_nova_data_atend, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend + 1, $ano_nova_data_atend);
            break;

            default: $timestamp_atend = mktime($hr_nova_data_atend, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend, $ano_nova_data_atend);
        }

        $nova_data_atend = date("Y-m-d H:i", $timestamp_atend);
        $val_hora_atend = substr($nova_data_atend, 0, 10)." 18:00";

    }

    $hr_nova_data = substr($nova_data_atend, 11, 2);

    if($hr_nova_data == 0){
        $ano_nova_data_atend = substr($nova_data_atend, 0, 4);
        $mes_nova_data_atend = substr($nova_data_atend, 5, 2);
        $dia_nova_data_atend = substr($nova_data_atend, 8, 2);
        $hr_nova_data_atend = substr($nova_data_atend, 11, 2);
        $mn_nova_data_atend = substr($nova_data_atend, 14, 2);

        $timestamp_atend = mktime($hr_nova_data_atend + 14, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend, $ano_nova_data_atend);

        $nova_data_atend = date("Y-m-d H:i", $timestamp_atend);
    } else if($hr_nova_data == 1) {
        $ano_nova_data_atend = substr($nova_data_atend, 0, 4);
        $mes_nova_data_atend = substr($nova_data_atend, 5, 2);
        $dia_nova_data_atend = substr($nova_data_atend, 8, 2);
        $hr_nova_data_atend = substr($nova_data_atend, 11, 2);
        $mn_nova_data_atend = substr($nova_data_atend, 14, 2);

        $timestamp_atend = mktime($hr_nova_data_atend + 15, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend, $ano_nova_data_atend);

        $nova_data_atend = date("Y-m-d H:i", $timestamp_atend);
    } else if($hr_nova_data == 2) {
        $ano_nova_data_atend = substr($nova_data_atend, 0, 4);
        $mes_nova_data_atend = substr($nova_data_atend, 5, 2);
        $dia_nova_data_atend = substr($nova_data_atend, 8, 2);
        $hr_nova_data_atend = substr($nova_data_atend, 11, 2);
        $mn_nova_data_atend = substr($nova_data_atend, 14, 2);

        $timestamp_atend = mktime($hr_nova_data_atend + 16, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend, $ano_nova_data_atend);

        $nova_data_atend = date("Y-m-d H:i", $timestamp_atend);
    } else if($hr_nova_data == 3) {
        $ano_nova_data_atend = substr($nova_data_atend, 0, 4);
        $mes_nova_data_atend = substr($nova_data_atend, 5, 2);
        $dia_nova_data_atend = substr($nova_data_atend, 8, 2);
        $hr_nova_data_atend = substr($nova_data_atend, 11, 2);
        $mn_nova_data_atend = substr($nova_data_atend, 14, 2);

        $timestamp_atend = mktime($hr_nova_data_atend + 17, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend, $ano_nova_data_atend);

        $nova_data_atend = date("Y-m-d H:i", $timestamp_atend);
    } else if($hr_nova_data == 4) {
        $ano_nova_data_atend = substr($nova_data_atend, 0, 4);
        $mes_nova_data_atend = substr($nova_data_atend, 5, 2);
        $dia_nova_data_atend = substr($nova_data_atend, 8, 2);
        $hr_nova_data_atend = substr($nova_data_atend, 11, 2);
        $mn_nova_data_atend = substr($nova_data_atend, 14, 2);

        $timestamp_atend = mktime($hr_nova_data_atend + 32, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend, $ano_nova_data_atend);

        $diaSemana = getDate($timestamp_atend);
        $diaValor = $diaSemana[weekday];

        switch($diaValor){      
            case "Saturday": $timestamp_atend = mktime($hr_nova_data_atend + 32, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend + 2, $ano_nova_data_atend);
            break;

            case "Sunday": $timestamp_atend = mktime($hr_nova_data_atend + 32, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend + 1, $ano_nova_data_atend);
            break;

            default: $timestamp_atend = mktime($hr_nova_data_atend + 32, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend, $ano_nova_data_atend);
        }

        $nova_data_atend = date("Y-m-d H:i", $timestamp_atend);
    } else if($hr_nova_data == 5) {
        $ano_nova_data_atend = substr($nova_data_atend, 0, 4);
        $mes_nova_data_atend = substr($nova_data_atend, 5, 2);
        $dia_nova_data_atend = substr($nova_data_atend, 8, 2);
        $hr_nova_data_atend = substr($nova_data_atend, 11, 2);
        $mn_nova_data_atend = substr($nova_data_atend, 14, 2);

        $timestamp_atend = mktime($hr_nova_data_atend + 33, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend, $ano_nova_data_atend);

        $diaSemana = getDate($timestamp_atend);
        $diaValor = $diaSemana[weekday];

        switch($diaValor){      
            case "Saturday": $timestamp_atend = mktime($hr_nova_data_atend + 33, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend + 2, $ano_nova_data_atend);
            break;

            case "Sunday": $timestamp_atend = mktime($hr_nova_data_atend + 33, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend + 1, $ano_nova_data_atend);
            break;

            default: $timestamp_atend = mktime($hr_nova_data_atend + 33, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend, $ano_nova_data_atend);
        }

        $nova_data_atend = date("Y-m-d H:i", $timestamp_atend);
    } else if($hr_nova_data == 6) {
        $ano_nova_data_atend = substr($nova_data_atend, 0, 4);
        $mes_nova_data_atend = substr($nova_data_atend, 5, 2);
        $dia_nova_data_atend = substr($nova_data_atend, 8, 2);
        $hr_nova_data_atend = substr($nova_data_atend, 11, 2);
        $mn_nova_data_atend = substr($nova_data_atend, 14, 2);

        $timestamp_atend = mktime($hr_nova_data_atend + 34, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend, $ano_nova_data_atend);

        $diaSemana = getDate($timestamp_atend);
        $diaValor = $diaSemana[weekday];

        switch($diaValor){      
            case "Saturday": $timestamp_atend = mktime($hr_nova_data_atend + 34, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend + 2, $ano_nova_data_atend);
            break;

            case "Sunday": $timestamp_atend = mktime($hr_nova_data_atend + 34, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend + 1, $ano_nova_data_atend);
            break;

            default: $timestamp_atend = mktime($hr_nova_data_atend + 34, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend, $ano_nova_data_atend);
        }

        $nova_data_atend = date("Y-m-d H:i", $timestamp_atend);
    } else if($hr_nova_data == 7) {
        $ano_nova_data_atend = substr($nova_data_atend, 0, 4);
        $mes_nova_data_atend = substr($nova_data_atend, 5, 2);
        $dia_nova_data_atend = substr($nova_data_atend, 8, 2);
        $hr_nova_data_atend = substr($nova_data_atend, 11, 2);
        $mn_nova_data_atend = substr($nova_data_atend, 14, 2);

        $timestamp_atend = mktime($hr_nova_data_atend + 35, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend, $ano_nova_data_atend);

        $diaSemana = getDate($timestamp_atend);
        $diaValor = $diaSemana[weekday];

        switch($diaValor){      
            case "Saturday": $timestamp_atend = mktime($hr_nova_data_atend + 35, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend + 2, $ano_nova_data_atend);
            break;

            case "Sunday": $timestamp_atend = mktime($hr_nova_data_atend + 35, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend + 1, $ano_nova_data_atend);
            break;

            default: $timestamp_atend = mktime($hr_nova_data_atend + 35, $mn_nova_data_atend, 0, $mes_nova_data_atend, $dia_nova_data_atend, $ano_nova_data_atend);
        }

        $nova_data_atend = date("Y-m-d H:i", $timestamp_atend);
    }

    $sla_atend_data = $nova_data_atend;
}

4 个答案:

答案 0 :(得分:1)

也许是这样的?

function foo(start_time, plus_hours) {
    var time = new Date(+start_time),
        day;
    // rewind to the start of the hour
    time.setMinutes(0, 0, 0);
    // then
    if (time.getHours() < 8) { // if before work day
        time.setHours(8); // fast forward to start of work hours
    }
    if (time.getHours() >= 18) { // if after work day
        time.setDate(time.getDate() + 1);  // fast forward to tomorrow
        time.setHours(8); // start of work hours
    }
    if ([0, 6].indexOf(time.getDay()) !== -1) { // if it is weekend
        day = (time.getDay() && 2) || 1; // (no setDay method)
        time.setDate(time.getDate() + day); // fast foward to monday
        time.setHours(8); // start of work hours
    }
    // now convert plus_hours into day-length equivalents (i.e. add 14 hours for each 10 hours)
    plus_hours = plus_hours + (plus_hours - Math.floor(plus_hours % (18 - 8))) * (24 - (18 - 8)) / (18 - 8);
    // now work out how many hours we have until saturday
    day = time.getDay();
    day = (6 - day) * 24;
    day = day - time.getHours();
    // then
    if (plus_hours > day) { // if we are going to cross into future weeks
        // add 48 hours for each week (i.e. each 5 days)
        plus_hours = plus_hours - day;
        plus_hours = (plus_hours - Math.floor(plus_hours % (5 * 24))) * (2 * 24) / 5;
        plus_hours = plus_hours + day + 2 * 24;
    }
    return new Date(+time + plus_hours * 60 * 60 * 1000);
}

跨越时区等可能会遇到一些麻烦,可能需要熨烫,但我已对其进行了评论,以便您了解这些概念。

答案 1 :(得分:0)

如果日期符合您的条件,您可以编写一个接受两个Date(内置JavaScript类)和一些小时的函数,并返回true

它会涉及到Date()类的争论,但可以做到。

var currentDate = new Date(); // new Date object with current date/time
currentDate; // "Fri Dec 11 2015 09:45:39 GMT-0800 (PST)"
currentDate.getHours(); // returns hours past midnight, in this case '9'
currentDate.getMinutes(); // returns minutes past last whole hour, in this case 45
currentDate.getDay(); // returns a number 1-7 representing Monday through Sunday

// creating a future date
var futureDate = new Date(2015, 12, 14, 9, 30); // 12/14/2015 at 9:30 AM
// the format is (year, month, date, hour, minute)

getDay()是你的面包和黄油,因为它会告诉你你是否在周末(但不是假期,你需要外部数据)。

我要做的是从您尝试计算的小时数开始,并在currentDatefutureDate之间的每一天进行迭代,逐步减去小时数。如果您在到达0之前futureDate小时到达,那么您就知道它超出了范围。

答案 2 :(得分:0)

您可以使用此功能:

function getDateCompleted($date, $hours, $hoursPerDay) {
  if ($hoursPerDay == 0) {
    // Will never reach and prevent division by zero
    return null;
  }

  $daysToComplete = ceil((float)$hours / $hoursPerDay);
  $days = 0;
  $time =strtotime($date);
  while ($days < $daysToComplete) {
    // Check for weekend
     if (!(date('N', $date) >= 6)) {
        $current = $time;
        $days++;
    }
    $time = strtotime("+1 day", $time);
  }
  return date("Y-m-d", $current);
}

echo getDateCompleted("11/12/2015", 30, 10);

打印2015-11-16

答案 3 :(得分:0)

希望以下内容类似于您的需求(免费代码是免费代码......)。有很多关于日期的怪癖,所以下面尝试一个非常简单的算法来增加块的小时数,跳过周末,并处理任何超支。有一些业务规则:

  1. 如果开始时间是在一个工作日结束之后和下一个工作日的开始时间之前,则开始时间将移至下一个工作日的开始。因此,如果开始时间是周日的18:00,那么它将在周一的08:00移动。
  2. 如果提供的日期不是几小时,则会保留分钟和秒数
  3. 返回的日期可能是18:00的时间,例如如果一个工作日的开始时间是08:00,并且添加了10个小时,那么返回的日期将是同一天的18:00。
  4. 如果开始时间为09:00且已添加10小时,则返回的日期将是第二天的09:00
  5. 它使用循环来添加日期和小时。它可以使用像Paul S这样的逻辑来计算出多少天并且这样做(我宁愿使用 setDate 而不是 setHours ,但我猜这&#39;只是我)但这对我的大脑来说更简单。既然算法是正确的,那么很容易简化代码(也许可以做非循环时间的事情)。

    希望代码中的注释足够。开始时间,结束时间和周末天数是可配置的。

    &#13;
    &#13;
    /*  Add work hours to date, but only from 08:00 up to 18:00
    **  and skip weekends (Saturday, Sunday)
    **  Work in whole hours, bus
    **
    **  @param   {Date} date  - Date to add hours to
    **  @param {number} hours - Integer number of hours to add
    **  @returns {Date}       - new Date with work hours added.
    */
    function addWorkHours(date, hours) {
      // Setable parameters
      var startHour = 8;
      var endHour = 18;
      // Weekend days to skip, one day for Sunday (0), two for Saturday (6)
      var weekendDays = {'6':2, '0':1};  // Western: Saturday, Sunday 
    //  var weekendDays = {'4':2, '5':1};  // Arabic: Thursday, Friday
      
      // Calculated values
      var date = new Date(+date);  // Copy of provided date
      var hrsPerDay = endHour - startHour;
      var hrsToAdd, hrsLeftToday;
      // Make sure hours is a number
      hours = +hours;
    
      // If before start time, set to start
      if (date.getHours() < startHour) {
        date.setHours(startHour,0,0,0);
        
      // If after end time, set to start on next day
      } else if (date.getHours() > endHour) {
        date.setDate(date.getDate() + 1);
        date.setHours(startHour,0,0,0);
      }
      
      // If on a weekend, skip to start hour on next working day
      if (date.getDay() in weekendDays) {
        date.setDate(date.getDate() + weekendDays[date.getDay()]);
        date.setHours(startHour, 0,0,0);
      }
      
      // Add hours to date during business hours until exhaused
      while (hours) {
      
        // Get number of work hours left today
        hrsLeftToday = endHour - date.getHours();
        
        // If hrsLeftToday is 0 and there are hours to add, go to start tomorrow
        if (!hrsLeftToday && hours) {
          date.setDate(date.getDate() + 1);
          date.setHours(startHour);
        }
        
        // Get hours to end time or remaining hours, whichever is less
        hrsToAdd = hrsLeftToday > hours? hours : hrsLeftToday;
        
        // Adjust hours
        hours -= hrsToAdd;
        
        // Add the hours, but don't go past end time
        // If hours to add is equal the hours in a day, and there are
        // more hours to add, just add one day
        if (hrsToAdd == hrsPerDay && hours) {
          date.setDate(date.getDate() + 1);
        } else {
        
          // Otherwise, set the hours
          date.setHours(date.getHours() + hrsToAdd);
        }
        
        // If hours are zero, tidy any overlap past end hour if there is any
        if (!hours) {
        
          // If gone past end time in hours, run into next day
          if (date.getHours() > endHour) {
          
            // Get overrun, add a day and add back overrun
            date.setDate(date.getDate() + 1);
            date.setHours(startHour + date.getHours() - endHour);
          }
    
          // Do the same with minutes
          if (date.getHours() == endHour && (date.getMinutes() || date.getSeconds())) {
            date.setDate(date.getDate() + 1);
            date.setHours(startHour);
          }
        }
    
        // If now on a weekend, skip to next working day
        if (date.getDay() in weekendDays) {
          date.setDate(date.getDate() + weekendDays[date.getDay()]);
        }
      }
      return date;
    }
    // Helper to parse ISO input date string as local
    function parseDate(s) {
      var b = s.split(/\D/);
      return new Date(b[0],b[1]-1,b[2],b[3]||0,b[4]||0);
    }
    
    var d = parseDate(document.getElementById('startdate').value);
    var h = document.getElementById('hrs').value;
    document.getElementById('result').innerHTML = 'Start: ' + d + '<br>End: ' + addWorkHours(d, h);
    &#13;
    Date (yyyy-mm-dd [hh:mm:ss])<input type="text" id="startdate" value="2015-12-07"><br>
    Hours to add (integer)<input type="text" id="hrs" value="100"><br>
    <button onclick="
     var d = parseDate(document.getElementById('startdate').value);
     var h = document.getElementById('hrs').value;
     document.getElementById('result').innerHTML = 'Start: ' + d + '<br>End: ' + addWorkHours(d, h); 
    ">Add hours</button>
    <div id="result"></div>
    &#13;
    &#13;
    &#13;