Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Isabela C.

[Resolvido] array, comparação com datas e loop

Recommended Posts

Bom dia/tarde/noite,

 

Estou com um problema que tenho certeza que é facil resolver, mas não consigo :upset:

 

 

Resumindo:

Preciso reproduzir com php a seguinte planilha:

planilha.png

 

A parte que está selecionada (Status) é o que está me dando problema.

 

preciso fazer as seguintes comparações:

$totaldeparcelas - parcelaspagas

O restante preciso comparar com a data atual pra saber se é vincenda ou vencida.

$datadaparcela>$daatual, então: a parcela tá vencida
$datadaparcela<$daatual: a parcela está vincenda

 

Ou seja, pra saber se está vencida/vincenda/paga preciso comparar com a coluna anterior (a data), que no caso seria essa aqui:

http://pastebin.com/x0JU24gz

 

Eu não estava conseguindo fazer a verificação através da data que é gerada com esse code.

Porém, com esse aqui eu consigo:

http://pastebin.com/26fMf1Su

 

O que eu preciso é, tirar aquela parte do array e usar como base o meu outro script, que gera a data conforme a quantidade de parcelas.

 

Eu acho que preciso converter em array com os mesmos comandos usados no exemplo

array('vencimento' => '09/10/2012', 'status' => 'paga'),

Ou então, reconstruir o código que gera o status, pra que eu consiga fazer a parte das parcelas pagas (tenho a quantidade já definida, não preciso de nenhuma conta pra fazê-lo) parcelas vencidas e vincendas (comparando com a data atual).

 

Me perdoem se não fui clara o sufiente, mas essa problema me assombra a alguns dias já :cry:

Compartilhar este post


Link para o post
Compartilhar em outros sites

Isabela C.

 

eu não entendi, mas vamos na logica

 

1 - você precisa saber qual o valor total

2 - quantidade de parcelas

3 - parcelas já pagas

4 - parcelas a vencer ou que já esta vencido.

 

bom os números 1 e 2 acho que você não tem problemas com ele ?

 

3 e o 4 seria melhor se você fala como esta gravando no banco de dados ou não esta usando ?

 

eu to no caminho certo ?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu ñ entendi muito bem quais são todas as suas dúvidas, mas acho que você pode trabalhar com a função strtotime para verificar as datas.

 

você só precisa formatar as datas para que fiquem na ordem de ano, mês e dia e depois compará-las, pois o tipo é inteiro, ou seja, pode realizar as operações matemáticas que quiser.

 

Por exemplo:

$sua_data = strtotime( '2012-10-1' );
$data_atual  = strtotime( date("Y-m-d") );

 

Vlw.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Primeiramente obrigado por responder.

 

 

1 - você precisa saber qual o valor total

o valor total eu tenho sim.

2 - quantidade de parcelas

também já tenho.

 

3 - parcelas já pagas

já tenho a quantidade de parcelas, tem um campo onde a pessoa vai digitar isso.

4 - parcelas a vencer ou que já esta vencido.

meu problema é exatamente esse.

 

3 e o 4 seria melhor se você fala como esta gravando no banco de dados ou não esta usando ?

não uso bd, na verdade tem um form onde a pessoa digita os dados que eu preciso, e uso eles pra fazer a conta.

o caso é pegar a quantidade de parcelas e fazer o loop, dividindo entre pagas/vencidas/vincendas. como na planilha que postei.

 

eu to no caminho certo ?

Sim, meu problema é o loop entre as datas.

 

Eu ñ entendi muito bem quais são todas as suas dúvidas, mas acho que você pode trabalhar com a função strtotime para verificar as datas.

 

você só precisa formatar as datas para que fiquem na ordem de ano, mês e dia e depois compará-las, pois o tipo é inteiro, ou seja, pode realizar as operações matemáticas que quiser.

 

Por exemplo:

$sua_data = strtotime( '2012-10-1' );
$data_atual  = strtotime( date("Y-m-d") );

 

Vlw.

Obrigado pela resposta, Juliano =)

Sim, essa parte das operações eu consigo fazer, no segundo link do pastebin tem a resposta do meu problema, só que não consigo juntar os dois códigos que tenho ( o que gera a data e o que gera o status).

Compartilhar este post


Link para o post
Compartilhar em outros sites

Isabela C.

você não esta conseguindo escrever o parâmetro do STATUS se é pago - vencido - a vencer

dentro do array

$parcelas = array(

array('vencimento' => '09/10/2012', 'status' => 'paga'),

array('vencimento' => '10/10/2012', 'status' => 'paga'),

array('vencimento' => '11/10/2012', 'status' => 'paga'),

array('vencimento' => '05/10/2012', 'status' => 'vencido'),

array('vencimento' => '03/10/2012', 'status' => 'a vencer'),

array('vencimento' => '20/10/2012', 'status' => ''),

array('vencimento' => '12/10/2012', 'status' => ''),

array('vencimento' => '13/10/2012', 'status' => ''),

array('vencimento' => '09/10/2012', 'status' => ''),

array('vencimento' => '02/10/2012', 'status' => '')

);

 

e isto que você esta querendo ?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Dentre tudo o que a classe DateTime faz, ela computa diferença entre intervalos.

 

Supondo que você já tenha uma estrutura como o junaooaks postou no post #5, basta você criar um objeto DateTime vazio, que o fará assumir a data e hora atuais, iterar o array das parcelas (com um foreach mesmo) e dentro desse loop verificar o resultado da diferença produzida por DateTime::diff()

 

Esse método vai te retornar um objeto DateInterval com as várias propriedades públicas preenchidas com o resultado da diferença computada.

 

Com base nessas informações, você monta as condições e preenche o índice $parcelas['status'] caso este esteja vazio, assim você não sobrescreve nada acidental ou desnecessariamente.

 

Prefiro deixar você tentar sozinha antes de postar o código pronto. A única dica que te dou de imediato é como você vai saber se é uma dívida vincenda ou vencida.

 

Normalmente, esperaríamos que, caso a data informada fosse menor que a data-base, definida fora do loop, os valores computados e listados neste DateInterval seriam negativos.

 

Mas não é isso que acontece. Quando a data é menor, a propriedade DateInterval::invert é setada para o valor 1.

 

Quando a data é posterior a atual (vincenda), ela vêm setada como zero.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Entendi bruno,

com o resultado 0 ou 1 consigo saber se foi vencida ou vincenda.

 

Obrigado, vou tentar fazer da forma que ensinou hj a noite, e posto o resultado.

 

Muito obrigado pela luz...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Boa tarde,

Bruno, eu consegui refazer a parte que verifica se foi vencida ou não, mas meu problema continua sendo o mesmo.

 

Eu preciso colocar os dados dessa minha função, pra ser usado no array. e não sei como fazê-lo

 

<?php

function calcularParcelas($nParcelas, $dataPrimeiraParcela = null){
 if($dataPrimeiraParcela != null){
   $dataPrimeiraParcela = explode( "/",$dataPrimeiraParcela);
   $dia = $dataPrimeiraParcela[0];
   $mes = $dataPrimeiraParcela[1];
   $ano = $dataPrimeiraParcela[2];
 } else {
   $dia = date("d");
   $mes = date("m");
   $ano = date("Y");
 }

 for($x = 0; $x < $nParcelas; $x++){
   echo date("d/m/Y",strtotime("+".$x." month",mktime(0, 0, 0,$mes,$dia,$ano))),"<br/>";
 }
}


echo "Vencimento<br/>";
calcularParcelas($quantidadeparcelas, $primeirovect);

 

Ao invés de usar o array que tem abaixo pronto, eu preciso pegar o resultado que tem acima, e usa-lo pra gerar a data abaixo.

 

$parcelas = array(
   array('vencimento' => '09/10/2012', 'status' => 'paga'),
   array('vencimento' => '10/10/2012', 'status' => 'paga'),
   array('vencimento' => '11/10/2012', 'status' => 'paga'),
   array('vencimento' => '05/10/2012', 'status' => ''),
   array('vencimento' => '03/10/2012', 'status' => ''),
   array('vencimento' => '20/10/2012', 'status' => ''),
   array('vencimento' => '12/10/2012', 'status' => ''),
   array('vencimento' => '13/10/2012', 'status' => ''),
   array('vencimento' => '09/10/2012', 'status' => ''),
   array('vencimento' => '02/10/2012', 'status' => '')
);

$dataAtual = new \DateTime();

foreach($parcelas as $parcela) {
   echo $parcela['vencimento'] . ' » ';
   if ($parcela['status'] == 'paga') {
       echo "paga";
   } else {
       $data = DateTime::createFromFormat('d/m/Y', $parcela['vencimento']);

       if ($data >= $dataAtual) {
           echo "A vencer";
       } else {
           echo "Vencida";
       }
   }
   echo "<br>";
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

Me parece que você não leu minha resposta inteira, mas como você mostrou iniciativa ao usar DateTime::createFromFormat() (diferente de muita gente) eu vou te mostrar o que você não fez certo.

 

Destaquei esse trecho porque eu aprendi uma coisa com sua resposta: É possível comparar objetos DateTime com os operadores lógicos normais. :clap:

 

Se você está trabalhando com a DateTime muito provavelmente você já passou pelo bê-a-bá do PHP, certo?

 

Sendo assim, para cumprir sua tarefa, você precisa:

 

- Que o argumento a ser informado ao foreach seja um array

 

- Que o foreach seja usado na sua sintaxe completa, para manipular a estrutura do array de entrada em tempo de execução.

 

Função que ecoa alguma coisa é, 90% das vezes, uma má idéia porque você nem sempre conseguirá controlar onde que a informação será mostrada.

 

Como você precisa de um array com os intervalos para o foreach trabalhar, esse intervalo é gerado pela sua função e ecoar dados dentro de uma função é ma ídeia, chegamos a conclusão que sua função deve retornar um array.

 

Eu vou aproveitar a leva e reescrever seu código para estimular seus estudos referentes à classe DateTime:

 

function calcularParcelas( $installments, $firstInstallment = null ) {

   $date = DateTime::createFromFormat(

       'd/m/Y',

       ( ! is_null( $firstInstallment ) ? $firstInstallment : date( 'd/m/Y' ) )
   );

   $oneMonth = new DateInterval( 'P1M' ); // +1 Month

   $interval = array( $date -> format( 'd/m/Y' ) );

   for( $i = 0; $i < ( $installments - 1 ); $i += 1 ) {

       $interval[] = $date -> add( $oneMonth ) -> format( 'd/m/Y' );
   }

   return $interval;
}

Quais foram as mudanças:

 

Ao invés de usar mktime() em conjunto com strtotime() eu usei a própria DateTime para criar o intervalo.

 

Eu crio um objeto com a data inicial passada (se passada) e crio um objeto DateInterval com o valor de 1 mês.

 

Daí eu itero itero N vezes e a cada iteração eu adiciono esse intervalo de um mês. Mas atente ao detalhe que a iteração "dura" uma vez a menos que o total de parcelas por dois motivos:

 

1. A iteração começa em zero

 

2. Nós já adicionamos a primeira parcela ao array de retorno, caso contrário o primeiro pagamento seria só no mês subseqüente.

 

Se você tiver como alterar isso, melhor, mas é opcional.

 

Você pode fazer do seu jeito, claro, eu só acho que assim seja, além de mais eficiente, mais legível (eu tive de indentar e espaçar seu código para lê-lo com clareza o.O).

 

Seja qual for a forma que você for fazer, o que interessa é o retorno em array.

 

A cada iteração eu uso a [sintaxe de colchetes] para adicionar um novo valor à um array definido antes do loop começar (senão ele é esvaziado a cada nova iteração).

 

Atente, também, que eu uso DateInterval::format() para que o valor a ser adicionado seja uma string no formato que você precisa e não o objeto DateInterval em si.

 

No entanto eu particularmente acho isso ruim pois te obriga a repetir o DateTime:createFromFormat() na segunda parte do código e ainda te limita a descrever se uma parcela não paga está Vencida ou é Vincenda, ao invés de te permitir dizer que ela venceu há X dias ou vencerá daqui há Y meses.

 

Enfim... Com isso temos:

 

var_dump( calcularParcelas( 10, '01/12/2012' ) );

Saída:

 

array
 0 => string '01/01/2013' (length=10)
 1 => string '01/02/2013' (length=10)
 2 => string '01/03/2013' (length=10)
 3 => string '01/04/2013' (length=10)
 4 => string '01/05/2013' (length=10)
 5 => string '01/06/2013' (length=10)
 6 => string '01/07/2013' (length=10)
 7 => string '01/08/2013' (length=10)

Agora, a segunda parte do problema que é usar a sintaxe completa do foreach.

 

A sintaxe completa do foreach é:

 

foreach( $array as $key => $value ) {}

O que significa que, a cada iteração $key armazenará o índice do array e, $value, o valor.

 

No array mostrado acima, na primeira iteração os valores seriam, respectivamente: 0 e 01/01/2013.

Na segunda iteração, também respectivamente, 1 e 01/03/2013

 

E por aí vai.

 

Com a informação de $key você vai alterar a estrutura do array e com $value operar o que será acrescido/alterado nele.

 

Como sua função não monta a mesma estrutura do array que estava usando, consequentemente o código da segunda parte muda um pouco:

 

$parcelas = calcularParcelas( 10, '09/10/2012' );

$dataAtual = new \DateTime();

foreach($parcelas as $index => $parcela) {

   $parcelas[ $index ] = array( 'vencimento' => $parcela );

   $data = DateTime::createFromFormat( 'd/m/Y', $parcela );

   if( $data >= $dataAtual ) {

       $parcelas[ $index ]['status'] = 'Vincenda';

   } else {

       $parcelas[ $index ]['status'] = 'Vencida';
   }
}

var_dump( $parcelas );

Saída:

 

array
 0 => 
   array
     'vencimento' => string '09/10/2012' (length=10)
     'status' => string 'Vencida' (length=7)
 1 => 
   array
     'vencimento' => string '09/11/2012' (length=10)
     'status' => string 'Vincenda' (length=8)
 2 => 
   array
     'vencimento' => string '09/12/2012' (length=10)
     'status' => string 'Vincenda' (length=8)
 3 => 
   array
     'vencimento' => string '09/01/2013' (length=10)
     'status' => string 'Vincenda' (length=8)
 4 => 
   array
     'vencimento' => string '09/02/2013' (length=10)
     'status' => string 'Vincenda' (length=8)
 5 => 
   array
     'vencimento' => string '09/03/2013' (length=10)
     'status' => string 'Vincenda' (length=8)
 6 => 
   array
     'vencimento' => string '09/04/2013' (length=10)
     'status' => string 'Vincenda' (length=8)
 7 => 
   array
     'vencimento' => string '09/05/2013' (length=10)
     'status' => string 'Vincenda' (length=8)
 8 => 
   array
     'vencimento' => string '09/06/2013' (length=10)
     'status' => string 'Vincenda' (length=8)
 9 => 
   array
     'vencimento' => string '09/07/2013' (length=10)
     'status' => string 'Vincenda' (length=8)

 

O que mudou?

 

Antes de computar o status da parcela, eu digo que naquela posição do array $parcelas eu não vou mais ter uma string e sim array.

 

E logo de cara eu já adiciono o índice vencimento e o associo à parcela da iteração corrente, para não perdê-la devido à substituição feita.

 

Como você só tem as parcelas propriamente ditas, sem nenhum índice adicional nem nada, DateTime::createFromFormat() não usa mais um índice e sim a própria variável $parcela do foreach.

 

E por fim, no teste lógico, ao invés de ecoar a informação (que é ruim), adiciono um novo índice nesse array criado nessa posição, mas agora com nome de status e associo a mensagem de referência.

 

Desculpa pelo longo post, mas eu quis explicar tudo bem direitinho com máximo de detalhes possível.

 

O que eu sugiro que você estude com carinho é a classe DateInterval pois ela não é preparada para o trabalho com número "normal" e sim com uma coisa chamada Período, delineado pelo padrão ISO 8601, que é um pouquinho diferente.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Nossa, sua resposta foi perfeita, não teria uma explicação tão completa nem mesmo com um professor.Consegui entender todas as dicas e como vou chegar no resultado, e já estava quebrando a cabeça.

 

 

Muito obrigada, vou começar a trabalhar no projeto agora mesmo.

E desculpe pelo código ilegível, haha.

 

perfeito

:clap:

Compartilhar este post


Link para o post
Compartilhar em outros sites

Que bom que pude me fazer entender. Às vezes é tão difícil :ermm:

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.