Autor Tópico: Calcular dias úteis entre datas  (Lida 1714 vezes)

GCONTABIL2015

  • Novato
  • *
  • Mensagens: 14
Calcular dias úteis entre datas
« Online: Janeiro 19, 2016, 02:48:01 am »
Sou iniciante no ScriptCase e gostaria de saber se alguém já desenvolver aplicação de calcule os dias úteis entre determinadas datas, exemplo:

Tenho duas tabelas:
* Feriados Fixo (Id, dia/mês) <> dados 02/02
* Feriados Móvel (Id, dia/mês) <> dados 04/02

dtinicial: 01/02/2016
dtfinal: 05/02/2016

Então retorna-se: 03 dias úteis, já que dia 02/02 e 04/02 são feriado.


Tinha o VB este modulo que calcula, mas no PHP não sei como funciona:

</code>

Option Compare Database
Option Explicit

Function ProximaDataUtil(dtDataInicial As Date, intDias As Integer) As Date
    'criada por Alexandre Neves e Avelino Sampaio
    'em 2012-12-27
    'para GContabil
    'do fórum MaximoAccess
Dim RstFeriadosFixos    As DAO.Recordset
Dim RstFeriadosMoveis   As DAO.Recordset
Dim RstRecesso          As DAO.Recordset
Static varFF As Variant
Static varFM As Variant
Static varRE As Variant
Dim I%, D%, A%
Static K(3) As Byte
Static booCarregado As Boolean
Dim j As Boolean

j = False
If booCarregado = False Then
    '----------------------------
    'Abre recordsets
    '----------------------------
    Set RstFeriadosFixos = CurrentDb.OpenRecordset("SELECT * FROM tabFeriadosFixos")
    Set RstFeriadosMoveis = CurrentDb.OpenRecordset("SELECT * FROM tabFeriadosMóveis")
    Set RstRecesso = CurrentDb.OpenRecordset("SELECT * FROM tabRecesso")
    '------------------------------------------------------------------------
    'Movimenta ponteiros dos recordset para realizar a contagem de registros
    '------------------------------------------------------------------------
    RstFeriadosFixos.MoveLast: RstFeriadosFixos.MoveFirst
    RstFeriadosMoveis.MoveLast: RstFeriadosMoveis.MoveFirst
    RstRecesso.MoveLast: RstRecesso.MoveFirst
    '---------------------------------------------------------------------------------------
    'Passa para a variável K a quantidade de registros de cada recordset
    'passa para as variáves respectivas (varFF,varFM e verRe) os registros de cada tabela
    '---------------------------------------------------------------------------------------
    K(0) = RstFeriadosFixos.RecordCount: varFF = RstFeriadosFixos.GetRows(K(0))
    K(1) = RstFeriadosMoveis.RecordCount: varFM = RstFeriadosMoveis.GetRows(K(1))
    K(2) = RstRecesso.RecordCount: varRE = RstRecesso.GetRows(K(2))
    '----------------------------------------------
    'Fecha os recordset's e limpa a memoria
    '----------------------------------------------
    RstFeriadosFixos.Close
    RstFeriadosMoveis.Close
    RstRecesso.Close
    Set RstFeriadosFixos = Nothing
    Set RstFeriadosMoveis = Nothing
    Set RstRecesso = Nothing
    '----------------------------------------------------------------------------------
    'Passando a variável booCarregado para true não será mais carregado os recordset's
    'Os dados serão lidos das variáveis varFF, varFE e VarRE
    'Assim evitamos ter que realizar viagens as tabelas do back-end
    '----------------------------------------------------------------------------------
    booCarregado = True
End If
A = 0
    '------------------------------------------------------------------------------
    'Soma a data de acordo com o prazo, descontando os dias de recesso, se houver.
    '------------------------------------------------------------------------------
    Do While Not intDias <= A
        dtDataInicial = dtDataInicial + 1
        For I = 0 To (K(2) - 1)
            Select Case CLng(dtDataInicial)
                Case CLng(varRE(2, I)) To CLng(varRE(3, I)): j = True
            End Select
        Next
        A = A + IIf(j = True, 0, 1)
        j = False
    Loop

    '----------------------------------------------
    'Ajusta a data final caso caia em um feriado
    '----------------------------------------------
    For I = 0 To (K(0) - 1)
        If varFF(0, I) = Format(dtDataInicial, "d-m") Then dtDataInicial = dtDataInicial + 1
    Next
    For I = 0 To (K(1) - 1)
        If varFM(0, I) = dtDataInicial Then dtDataInicial = dtDataInicial + 1
    Next

    '----------------------------------------------------
    'Ajusta a data final caso caia em um final de semana.
    '----------------------------------------------------
    dtDataInicial = dtDataInicial + IIf(Weekday(dtDataInicial) = 7, 2, IIf(Weekday(dtDataInicial) = 1, 1, 0))

    '------------------------------------------------------------------------------------------
    'Ajusta a data final caso caia um feriado na segunda-feira, após ajuste de final de semana
    '------------------------------------------------------------------------------------------
    For I = 0 To (K(0) - 1)
        If varFF(0, I) = Format(dtDataInicial, "d-m") Then dtDataInicial = dtDataInicial + 1
    Next
    For I = 0 To (K(1) - 1)
        If varFM(0, I) = dtDataInicial Then dtDataInicial = dtDataInicial + 1
    Next
    ProximaDataUtil = dtDataInicial
     
End Function

<code/>

Desde já agradeço.


Att.

Gilson



« Última modificação: Janeiro 19, 2016, 03:01:06 am por GCONTABIL2015 »

Jailton

  • Expert
  • *****
  • Mensagens: 2038
Re:Calcular dias úteis entre datas
« Responder #1 Online: Janeiro 19, 2016, 07:09:54 am »
O Código em VB é tão 'gordo' hehe, por isso que a MS caiu na real e mudou para C#.

Em PHP é menos código e mais resultado:

//Nesse exemplo usamos o mês de Novembro e o ano de 2015
$mes = 11;
$ano = 2015;

// Feriados de Novembro
$feriados = array(2 => 'Finados', 15 => 'Proclamação da Republica');

// Total de dias no mês
$dias_do_mes = cal_days_in_month(CAL_GREGORIAN, $mes, $ano);

$dias_uteis = 0;

for($d=1; $d<=$dias_do_mes; $d++) {
   $dia_da_semana = jddayofweek(cal_to_jd(CAL_GREGORIAN, $mes, $d, $ano) , 0);

   // 0 = domingo e 6 = sábado
   if (!($dia_da_semana == 0 || $dia_da_semana == 6 || in_array($d, $feriados))) {
      $dias_uteis++;
   }
}

echo $dias_uteis;
O Princípio da Vibração. "Nada está parado, tudo se move, tudo vibra". Caibalion.

GCONTABIL2015

  • Novato
  • *
  • Mensagens: 14
Re:Calcular dias úteis entre datas
« Responder #2 Online: Janeiro 20, 2016, 09:02:07 pm »
Jailton,

O seu código estar perfeito, mas não é exatamente o que preciso ou tentar explicar novamente:

Preciso calcular a Data Final de determinado prazo, retirando os finais de semanas (sábado e domingo e os feriados):

Questão: Calcule da Data Final do Prazo?
Vejamos os dados: Data Inicial= 01/11/2016 e Prazo = 20 dias úteis.
Lembrando que em novembro termos dois feriados 02/11> finados, 15/11>proclamação e 17/11> feriado municipal.

Resposta:
Data Inicial: 01/11/2016
Prazo:20 dias úteis
Feriados: 03
Data Final:??? 

{Data Inicial} + {20 dias úteis} - {3 feriados} - {sábado e domingo} = Data Final

A Data Final seria o dia  01/12/2016.

Lembrando que tenho uma tabela onde os feriados municipais são cadastrados.


Espero que possa ajudar.




Att.

Gilson
« Última modificação: Janeiro 20, 2016, 09:25:57 pm por GCONTABIL2015 »

Jailton

  • Expert
  • *****
  • Mensagens: 2038
Re:Calcular dias úteis entre datas
« Responder #3 Online: Janeiro 20, 2016, 11:01:20 pm »
Jailton,

O seu código estar perfeito, mas não é exatamente o que preciso ou tentar explicar novamente:

Preciso calcular a Data Final de determinado prazo, retirando os finais de semanas (sábado e domingo e os feriados):

Questão: Calcule da Data Final do Prazo?
Vejamos os dados: Data Inicial= 01/11/2016 e Prazo = 20 dias úteis.
Lembrando que em novembro termos dois feriados 02/11> finados, 15/11>proclamação e 17/11> feriado municipal.

Resposta:
Data Inicial: 01/11/2016
Prazo:20 dias úteis
Feriados: 03
Data Final:??? 

{Data Inicial} + {20 dias úteis} - {3 feriados} - {sábado e domingo} = Data Final

A Data Final seria o dia  01/12/2016.

Lembrando que tenho uma tabela onde os feriados municipais são cadastrados.


Espero que possa ajudar.




Att.

Gilson

Essa rotina que te passei faz isso, só alterando uma linha... você nunca programou??
O Princípio da Vibração. "Nada está parado, tudo se move, tudo vibra". Caibalion.

GCONTABIL2015

  • Novato
  • *
  • Mensagens: 14
Re:Calcular dias úteis entre datas
« Responder #4 Online: Janeiro 31, 2016, 09:01:44 pm »
Boa noite, conseguir como este código resolver o primeiro problema:

Código: [Selecionar]
<?
//CALCULANDO DIAS NORMAIS
      //LISTA DE FERIADOS NO ANO
      function Feriados($ano,$posicao){
         $dia = 86400;
         $datas = array();
         $datas['pascoa'] = easter_date($ano);
         $datas['sexta_santa'] = $datas['pascoa'] - (2 * $dia);
         $datas['carnaval'] = $datas['pascoa'] - (47 * $dia);
         $datas['corpus_cristi'] = $datas['pascoa'] + (60 * $dia);
         $feriados = array (
            '01/01',
            '02/02', // Navegantes
            date('d/m',$datas['carnaval']),
            date('d/m',$datas['sexta_santa']),
            date('d/m',$datas['pascoa']),
            '21/04',
            '01/05',
            date('d/m',$datas['corpus_cristi']),
            '20/09', // Revolução Farroupilha \m/
            '12/10',
            '02/11',
            '15/11',
'25/12',
         );
         
      return $feriados[$posicao]."/".$ano;
      }     

      //FORMATA COMO TIMESTAMP
      function dataToTimestamp($data){
         $ano = substr($data, 6,4);
         $mes = substr($data, 3,2);
         $dia = substr($data, 0,2);
      return mktime(0, 0, 0, $mes, $dia, $ano); 
      }

      //SOMA 01 DIA
      function Soma1dia($data){
         $ano = substr($data, 6,4);
         $mes = substr($data, 3,2);
         $dia = substr($data, 0,2);
      return   date("d/m/Y", mktime(0, 0, 0, $mes, $dia+1, $ano));
      }
     
      function SomaDiasUteis($xDataInicial,$xSomarDias){
         for($ii=1; $ii<=$xSomarDias; $ii++){
           
            $xDataInicial=Soma1dia($xDataInicial); //SOMA DIA NORMAL
           
            //VERIFICANDO SE EH DIA DE TRABALHO
            if(date("w", dataToTimestamp($xDataInicial))=="0"){
               //SE DIA FOR DOMINGO OU FERIADO, SOMA +1
               $xDataInicial=Soma1dia($xDataInicial);
               
            }else if(date("w", dataToTimestamp($xDataInicial))=="6"){
               //SE DIA FOR SABADO, SOMA +2
               $xDataInicial=Soma1dia($xDataInicial);
               $xDataInicial=Soma1dia($xDataInicial);
               
            }else{
               //senaum vemos se este dia eh FERIADO
               for($i=0; $i<=12; $i++){
                  if($xDataInicial==Feriados(date("Y"),$i)){
                     $xDataInicial=Soma1dia($xDataInicial);
                  }
               }
            }
         }
      return $xDataInicial;
      }
 
 
?>   
<HTML>     
<?
$DataInicial = "01/11/2016";
$QtdDia = '20';
$diasSomados = SomaDiasUteis($DataInicial,$QtdDia);


?>
   
   <BODY>
      <br />
      O calculo da Data Inicial <?=$DataInicial?> + <?=$QtdDia?> dia(s) e - feriados e finais de semana é igual ao resultado =: <?=$diasSomados?> 
  <br />
      <br />
      Somar dias normais, mas de cair no final de semana ou feriado ir para o próximo dia util= <??>
  <br />
   </BODY>
</HTML>


Agora preciso de uma função de calculo o prazo da seguinte forma: DtInicial + prazo = DtFinal (Se data final for sabado, domingo ou feriado a DtFinal passa para o primeiro dia útil seguinte).

Alguém pode ajudar? desde já agradeço.

Kleyber

  • Expert
  • *****
  • Mensagens: 2237
    • Email
Re:Calcular dias úteis entre datas
« Responder #5 Online: Fevereiro 01, 2016, 07:47:37 am »
Bom dia.

Use o sc_date do SC e com a data final, use o date('w') pra checar qual é o dia da semana. Daí é só usar o sc_date novamente pra adicionar 1 ou 2 dias.
Kleyber Derick

ITIL® V3 Foundation Certified
Analista de Sistemas
São Luís - Maranhão
www.tkinformidia.net

GCONTABIL2015

  • Novato
  • *
  • Mensagens: 14
Re:Calcular dias úteis entre datas
« Responder #6 Online: Fevereiro 01, 2016, 04:11:42 pm »
Bom dia.

Use o sc_date do SC e com a data final, use o date('w') pra checar qual é o dia da semana. Daí é só usar o sc_date novamente pra adicionar 1 ou 2 dias.

Kleyber,

Não sei como verificar usando o sc_date do SC, sou iniciando em SC, como verifico se é sabado, domingo ou feriado...??? poderia montar uma condições onde tivesse os três elementos, inclusive os feriados que constam da função que passei? Desde já agradeço.

Kleyber

  • Expert
  • *****
  • Mensagens: 2237
    • Email
Re:Calcular dias úteis entre datas
« Responder #7 Online: Fevereiro 01, 2016, 04:28:23 pm »
Gilson,

Eu sei muito bem como é isso. Então aqui vão algumas dicas:

1 - Leia bem o Webhelp que tem no teu SC e se não conseguires, tem Webhelp online, pra ver a questão do SC_DATE: http://www.scriptcase.com.br/docs/pt_br/manual_mp.htm#macros-scriptcase/macros-scriptcase

2 - A função date('w') é uma função do PHP que retorna um número informando a que dia da semana se refere. Então 0 - Domingo, 1 - Segunda... e por aí vai. Dá uma olhada no Google sobre essa função. Se não tiveres um certo conhecimento de PHP procure pelas funções e vais descobrindo. Estou sem tempo no momento e se algum dos colegas puder criar um exemplo, seria bom. Senão assim que tiver um tempinho monto um exemplo pra você.

3 - Assista os videos do Scriptcase que existem no site da Netmake. Vai te ajudar bastante.
Kleyber Derick

ITIL® V3 Foundation Certified
Analista de Sistemas
São Luís - Maranhão
www.tkinformidia.net

GCONTABIL2015

  • Novato
  • *
  • Mensagens: 14
Re:Calcular dias úteis entre datas
« Responder #8 Online: Fevereiro 01, 2016, 04:48:28 pm »
Gilson,

Eu sei muito bem como é isso. Então aqui vão algumas dicas:

1 - Leia bem o Webhelp que tem no teu SC e se não conseguires, tem Webhelp online, pra ver a questão do SC_DATE: http://www.scriptcase.com.br/docs/pt_br/manual_mp.htm#macros-scriptcase/macros-scriptcase

2 - A função date('w') é uma função do PHP que retorna um número informando a que dia da semana se refere. Então 0 - Domingo, 1 - Segunda... e por aí vai. Dá uma olhada no Google sobre essa função. Se não tiveres um certo conhecimento de PHP procure pelas funções e vais descobrindo. Estou sem tempo no momento e se algum dos colegas puder criar um exemplo, seria bom. Senão assim que tiver um tempinho monto um exemplo pra você.

3 - Assista os videos do Scriptcase que existem no site da Netmake. Vai te ajudar bastante.

Kleyber,

Obrigado pela atenção tenho estudado muito sobre o SC, mas quando passamos a desenvolver fica dificil pela falta de conhecimento de PHP e SC.
Sou iniciante mas gosto de estudar. Tentei várias vezes antes de postar... Vou tentar novamente para ver  se consigo. Obrigado. 

Kleyber

  • Expert
  • *****
  • Mensagens: 2237
    • Email
Re:Calcular dias úteis entre datas
« Responder #9 Online: Fevereiro 01, 2016, 05:35:30 pm »
Gilson,

Assim que chegar em casa eu vejo se consigo montar um exemplo do que tu precisas e posto aqui.
Kleyber Derick

ITIL® V3 Foundation Certified
Analista de Sistemas
São Luís - Maranhão
www.tkinformidia.net

GCONTABIL2015

  • Novato
  • *
  • Mensagens: 14
Re:Calcular dias úteis entre datas
« Responder #10 Online: Fevereiro 02, 2016, 11:46:03 am »
Gilson,

Assim que chegar em casa eu vejo se consigo montar um exemplo do que tu precisas e posto aqui.

Kleyber,

Fico muito grato pela ajuda... fico aguardando.

Jean Matos

  • Expert
  • *****
  • Mensagens: 956
    • Gestão de Construtoras
    • Email
Re:Calcular dias úteis entre datas
« Responder #11 Online: Fevereiro 03, 2016, 10:15:10 pm »
<?php
//CALCULANDO DIAS NORMAIS
/*Abaixo vamos calcular a diferença entre duas datas. Fazemos uma reversão da maior sobre a menor
para não termos um resultado negativo. */
function CalculaDias($xDataInicial, $xDataFinal){
   $time1 = dataToTimestamp($xDataInicial); 
   $time2 = dataToTimestamp($xDataFinal); 

   $tMaior = $time1>$time2 ? $time1 : $time2; 
   $tMenor = $time1<$time2 ? $time1 : $time2; 

   $diff = $tMaior-$tMenor; 
   $numDias = $diff/86400; //86400 é o número de segundos que 1 dia possui 
   $numDias = $numDias +1;//ATENÇÃO NESSA PARTE - FOI ACRESCENTADO PORQUE PRECISO CONTAR COM O DIA ESCOLHIDO, LOGO SEM ISSO PEGA ENTRE AS DATAS DESCARTANDO O DIA INICIAL.
   return $numDias;
}

//LISTA DE FERIADOS NO ANO
/*Abaixo criamos um array para registrar todos os feriados NACIONAIS existentes durante o ano.*/
function Feriados($ano,$posicao){
   $dia = 86400;
   $datas = array();
   $datas['pascoa'] = easter_date($ano);
   $datas['sexta_santa'] = $datas['pascoa'] - (2 * $dia);
   $datas['carnaval'] = $datas['pascoa'] - (47 * $dia);
   $datas['corpus_cristi'] = $datas['pascoa'] + (60 * $dia);
   $feriados = array (                       
                  
                  '01/01',
                   '02/02', // Navegantes
                   date('d/m',$datas['carnaval']),
                   date('d/m',$datas['sexta_santa']),
                   date('d/m',$datas['pascoa']),
                   '21/04',
                   '01/05',
                   date('d/m',$datas['corpus_cristi']),
                   '20/09', // Revolução Farroupilha \m/
                   '12/10',
                   '02/11',
                   '15/11',
                   '25/12',
        );
   
return $feriados[$posicao]."/".$ano;
}     

//FORMATA COMO TIMESTAMP
/*Esta função é bem simples, e foi criada somente para nos ajudar a formatar a data já em formato  TimeStamp facilitando nossa soma de dias para uma data qualquer.*/
function dataToTimestamp($data){
   $ano = substr($data, 6,4);
   $mes = substr($data, 3,2);
   $dia = substr($data, 0,2);
return mktime(0, 0, 0, $mes, $dia, $ano); 
}

//SOMA 01 DIA   
function Soma1dia($data){   
   $ano = substr($data, 6,4);
   $mes = substr($data, 3,2);
   $dia = substr($data, 0,2);
return   date("d/m/Y", mktime(0, 0, 0, $mes, $dia+1, $ano));
}


//CALCULA DIAS UTEIS
/*É nesta função que faremos o calculo. Abaixo podemos ver que faremos o cálculo normal de dias ($calculoDias), após este cálculo, faremos a comparação de dia a dia, verificando se este dia é um sábado, domingo ou feriado e em qualquer destas condições iremos incrementar 1*/

function DiasUteis($yDataInicial,$yDataFinal){

   $diaFDS = 0; //dias não úteis(Sábado=6 Domingo=0)
   $calculoDias = CalculaDias($yDataInicial, $yDataFinal); //número de dias entre a data inicial e a final
   $diasUteis = 0;
   
   while($yDataInicial!=$yDataFinal){
      $diaSemana = date("w", dataToTimestamp($yDataInicial));
      if($diaSemana==0 || $diaSemana==6){
         //se SABADO OU DOMINGO, SOMA 01
         $diaFDS++;
      }else{
      //senão vemos se este dia é FERIADO
         for($i=0; $i<=12; $i++){
            if($yDataInicial==Feriados(date("Y"),$i)){
               $diaFDS++;   
            }
         }
      }
      $yDataInicial = Soma1dia($yDataInicial); //dia + 1
   }
return $calculoDias - $diaFDS;
}
?>
Sc - 6.xxx , 7.xxx e V8
Windows Server 2008 Enterpriser 64 bits
SqlServer 2008 Express 64 bits
Sistema Integrado de Gestão de Construtoras]WaveTOR - Sistema Integrado de Gestão de Construtoras
Teófilo Otoni - MG
(33)8824-2775

Kleyber

  • Expert
  • *****
  • Mensagens: 2237
    • Email
Re:Calcular dias úteis entre datas
« Responder #12 Online: Fevereiro 03, 2016, 10:34:58 pm »
Show, Jean. Eu não faria melhor.
Kleyber Derick

ITIL® V3 Foundation Certified
Analista de Sistemas
São Luís - Maranhão
www.tkinformidia.net

Celso R.

  • Expert
  • *****
  • Mensagens: 941
Re:Calcular dias úteis entre datas
« Responder #13 Online: Fevereiro 04, 2016, 11:50:57 am »
E ainda fala que não sabe programar nos webnar...... kkkkk
Parabéns Jean.
Celso R.
________________________________
SC - V 8

Kleyber

  • Expert
  • *****
  • Mensagens: 2237
    • Email
Re:Calcular dias úteis entre datas
« Responder #14 Online: Fevereiro 04, 2016, 12:26:03 pm »
kkkkkkkkkkk
Kleyber Derick

ITIL® V3 Foundation Certified
Analista de Sistemas
São Luís - Maranhão
www.tkinformidia.net