Subtrair horas (24 horas) [RESOLVIDO]

13 respostas
B

[color=darkblue]Oi pessoal!! Há dois dias estou quebrando a cabeça e até agora nada…

É o seguinte:: Neste sistema de ponto que estou desenvolvendo, o funcionário pode ter várias marcações e trocar turno e tals…
Eu preciso fazer o seguinte:

marcação1 = 08:30
marcação2 = 12:05
marcaçao3 = 13:38
marcação4 = 18:00

marcação2 - marcação1 = m1
marcação4 - marcaçao3 = m2

total = m1+m2

se (total - cargaHoraria) > 0 = Hora Extra
se (total - cargaHoraria) < 0 = Atraso

Até ai beleza to calculando direitinho![/color]

[color=red]O problema é nessa situação aqui oolha:[/color]

[color=darkred]

marcação1 = 08:30
marcação2 = 12:05
marcaçao3 = 15:00
marcação4 = 01:00

Na terceira e quarta marcação, não posso subtrair, preciso pegar a diferença, mas não está dando certo. Entre 15:00 e 01:00 deve dar 10:00…
[/color]

Alguém poderia me ajudar neste caso?

13 Respostas

V

Se você tem só as horas:

se (marcacao4 &gt;= marcacao3) m2 = marcacao4 - marcacao3 senao m2 = (24:00 - marcacao3) + marcacao4

B

ViniGodoy:
Se você tem só as horas:

se (marcacao4 &gt;= marcacao3) m2 = marcacao4 - marcacao3 senao m2 = (24:00 - marcacao3) + marcacao4

Tenho as horas em Timestamp e estou dando getTime pra fazer os cálculos com long e depois transformo milisegundos em hora pra apresentar!

Vou tentar fazer isso que vc me passou!
Muuuito obrigada ViniGodoy!!!

Volto aqui com a resposta…

V

Você tem o timestamp completo, com a data também?
Se tiver, é bem mais fácil fazer os calculos.

Melhor ainda se você usar o Joda-Time (recomendo fortemente, se vc precisa trabalhar muito com horários).

A classe Period faz esses calculos automaticamente:
http://joda-time.sourceforge.net/

Há exemplos no link que passei ali em cima também.

V

Esqueci de comentar, o método getDateDiffMillis() do outro post seria implementado assim:

public long getDateDiffMillis(Date inicio, Date fim) { return data2.getTime() - date1.getTime(); }

Aquele calculo só transforma esse retorno em HH:MM:SS

B

ViniGodoy:
Esqueci de comentar, o método getDateDiffMillis() do outro post seria implementado assim:

public long getDateDiffMillis(Date inicio, Date fim) { return data2.getTime() - date1.getTime(); }

Aquele calculo só transforma esse retorno em HH:MM:SS

ViniGodoy valeu mesmo!! Vou ler tudo!!! Depois te conto!

Bju

B

ViniGodoy:
Esqueci de comentar, o método getDateDiffMillis() do outro post seria implementado assim:

public long getDateDiffMillis(Date inicio, Date fim) { return data2.getTime() - date1.getTime(); }

Aquele calculo só transforma esse retorno em HH:MM:SS

Vini, seguinte!!! Montei este método no qual tenho que subtrair aquelas marcações que citei no post. ta assim:

public String substractHorasMarcacao(ArrayList&lt;Timestamp&gt; marcacoes, Timestamp data) throws ParseException{  
            SimpleDateFormat dFormat    =  new SimpleDateFormat("yyyy-MM-dd");  
            long tempoFinal                = 0;  
            int dia             = Integer.parseInt(data.toString().substring(8, 10));  
            int mes                 = Integer.parseInt(data.toString().substring(5, 7));  
            int ano             = Integer.parseInt(data.toString().substring(0, 4));  
              
            int x  =  0;  
            for(int i = 0; i &lt; (marcacoes.size()/2); i++){  
                 
               Timestamp horaAnt   = marcacoes.get(x);  
               Timestamp horaSeg   = marcacoes.get(1+x);  
                 
               int horaA           = Integer.parseInt(horaAnt.toString().substring(11, 13));  
               int minA            = Integer.parseInt(horaAnt.toString().substring(14, 16));  
               int segA            = Integer.parseInt(horaAnt.toString().substring(17, 19));  
     
               int horaS           = Integer.parseInt(horaSeg.toString().substring(11, 13));  
               int minS            = Integer.parseInt(horaSeg.toString().substring(14, 16));  
               int segS            = Integer.parseInt(horaSeg.toString().substring(17, 19));  
                 
               DateTime inicio = new DateTime(ano, mes, dia, horaA, minA, segA, 0);  
                 
               DateTime fim    = new DateTime(ano, mes, dia, horaS, minS, segS, 0);  
                 
               if( horaSeg.getTime() &lt;  horaAnt.getTime() ){  
                   Calendar addDia = new GregorianCalendar();  
                   addDia.setTime(data);    
                   addDia.add(Calendar.DATE, 1);   
                   String dataAux = dFormat.format(addDia.getTime());  
     
                   fim     = new DateTime(Integer.parseInt(dataAux.toString().substring(0, 4)), Integer.parseInt(dataAux.toString().substring(5, 7)), Integer.parseInt(dataAux.toString().substring(8, 10)), horaS, minS, segS, 0);  
               }  
                 
               long subMarcacao = (Minutes.minutesBetween(inicio, fim).getMinutes());  
               // 2250  
     
               x += 2;  
                 
               tempoFinal += subMarcacao;  
                 
           }  
             
           return // TRansformar milisegundos para hora  
       }

Agora pra finalizar, eu preciso tranformar os minutos de diferença encontrado em milisegundos e depois converter os milisegundos no formato HH:mm.
Como faço isso com o Joda? Pode me dar uma mão nisso?

Muito obrigada pela atenção!

Bjão

V

Que classe Timestamp é essa? E como é o formato dos dados dela?
É a java.sql.Timestamp?

B

ViniGodoy:
Que classe Timestamp é essa? E como é o formato dos dados dela?
É a java.sql.Timestamp?

Istu!! java.sql.Timestamp

Acabei misturando né… É que eu ja to tão cansada de olhar pra esse fonte e não conseguir deixar 100%!!!

V

Aqui está o método para subtrair dois TimeStamps e retornar no formato HH:MM:

public String subTimeStamps(TimeStamp inicio, TimeStamp fim) {
   //Calcula o tempo transcorrido em milissegundos, entre dois horários
   long tempo = fim.getTime() - inicio.getTime();
   
   tempo = tempo / 60000;      //Converte o tempo para minutos
   int minutos = tempo % 60;   //Retira os minutos da hora
   tempo = tempo / 60;         //Deixa em tempo apenas as horas

   return String.format("%02d:%02d", tempo, minutos);
}

Se quiser fazer com vários timestamps, basta calcular o total da diferença, antes de formatar.

O exemplo abaixo faz isso aos pares:
public String calcularTempoMarcacoes(List&lt;Timestamp&gt; marcacoes) {
   //Calcula o tempo total entre pares de marcações
   long tempo = 0;
   for (int i = 0; i &lt; marcacoes.size() / 2; i++) {
      tempo += marcacoes.get(i*2+1).getTime() - marcacoes.get(i*2).getTime();
   }

   tempo = tempo / 60000;     
   int minutos = tempo % 60; 
   tempo = tempo / 60;        

   return String.format(&quot;%02d:%02d&quot;, tempo, minutos);
}
V

Aqui vai um exemplo funcional:

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * Esse programa mostra como calcular quantas horas transcorreram entre
 * marcações de uma folha ponto.
 *
 * @author ViniGodoy
 */
public class TimestampSample {
    public static class Tempo {
        private int horas;
        private int minutos;

        public Tempo(int horas, int minutos) {
            this.horas = horas;
            this.minutos = minutos;
        }

        public int getHoras() {
            return horas;
        }

        public int getMinutos() {
            return minutos;
        }

        @Override
        public String toString() {
            return String.format("%02d:%02d", horas, minutos);
        }
    }
    public List&lt;Timestamp&gt; timestamps = new ArrayList&lt;Timestamp&gt;();

    public TimestampSample() {
        timestamps.add(new Timestamp(2011, 1, 20, 8, 30, 0, 0));
        timestamps.add(new Timestamp(2011, 1, 20, 12, 05, 0, 0));
        timestamps.add(new Timestamp(2011, 1, 20, 15, 00, 0, 0));
        timestamps.add(new Timestamp(2011, 1, 21, 01, 00, 0, 0));
    }

    /**
     * Retorna uma data em milisegundos.
     * Não considera os segundos e milisegundos dessa data na hora de fazer a conversão.
     * 
     * @param data Data para remover
     * @return A data sem os segundos e milisegundos
     */
    public long toMillis(Date data) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(data);

        //Despreza os segundos e milisegundos
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTimeInMillis();
    }

    /**
     * Aceita um array de marcações de tempo do ponto. O array deve conter um
     * número par de marcações no formato. Cada cada par, uma marcação é
     * considerada a hora de entrada e a seguinte a hora de saída.
     * @param marcacoes Marcações do ponto
     *
     * @return O total de horas no formato HH:MM
     */
    public Tempo calcularTempoMarcacoes(List&lt;? extends Date&gt; marcacoes) {
        //Calcula o tempo total entre pares de marcações
        int tempo = 0;
        for (int i = 0; i &lt; marcacoes.size() / 2; i++) {
            tempo += (int)(toMillis(marcacoes.get(i * 2 + 1)) - //Entrada
                    toMillis(marcacoes.get(i * 2)));        //Saída
        }

        //Formata os misegundos calculados em HH:MM
        tempo = tempo / 60000;
        int minutos = tempo % 60;
        tempo = tempo / 60;

        return new Tempo(tempo, minutos);
    }

    public void calcular() {
        System.out.println("Tempo entre marcações:");
        System.out.println(calcularTempoMarcacoes(timestamps));
    }

    public static void main(String args[]) {
        new TimestampSample().calcular();
    }
}
B

Muuitíssimo obrigada pela atenção [color=darkblue] ViniGodoy[/color]

Ficou assim:

/**
 *  Trecho do método que lê as marcações do funcionário naquele dia preenche o arraylist
 */
ArrayList&lt;Timestamp&gt; marcacoes = new ArrayList&lt;Timestamp&gt;();

/* Preenche o ArrayList com as marcações (Timestamp) do banco  */
int tam = marcacoes.size();
				
CalculoController calcControll 	= new CalculoController();
SimpleDateFormat horaFormat  	= new SimpleDateFormat("HH:mm");

/* Se for número par de marcações */
f((tam % 2 == 0) && (tam != 0)){
		      		
	Timestamp totalHoras = calcControll.totalDeHoras(marcacoes);
		      		
	long horas = totalHoras.getTime() - rs.getTimestamp("carga").getTime();
					
	if(horas &lt; 0){
		String formatada = (new Timestamp(horaFormat.parse(Utils.substractHoras( rs.getTimestamp("carga"), totalHoras)).getTime())).toString();
		
                ocorrenciasBean.setAtraso(formatada.substring(11, 16));
		ocorrenciasBean.setExtra("00:00");
						
	}else if(horas &gt; 0){
		String formatada = (new Timestamp(horaFormat.parse(Utils.substractHoras(totalHoras, rs.getTimestamp("carga"))).getTime())).toString();
		
                ocorrenciasBean.setExtra(formatada.substring(11,16));
		ocorrenciasBean.setAtraso("00:00");
			
	}else{
		ocorrenciasBean.setExtra("00:00");
		ocorrenciasBean.setAtraso("00:00");
	}
	
	/* Senão, marca tudo com zeros */
}else{
	ocorrenciasBean.setExtra("00:00");
	ocorrenciasBean.setAtraso("00:00");
}
/**
 *  Método que lê as marcações do arraylist, faz o cálculo das horas trabalhadas naquele dia
 */
	public Timestamp totalDeHoras(List&lt;Timestamp&gt; array) throws ParseException{

		Timestamp alocHora              = null;
		Timestamp value                 = null;
		SimpleDateFormat horaFormat     = new SimpleDateFormat("HH:mm");
		Timestamp cargaHoraria          = new Timestamp(horaFormat.parse("00:00").getTime());
		
		if(array.size() % 2 == 0){
				
				for (Timestamp marcacaoCarga : array) {
					
					alocHora = marcacaoCarga;
					
					if(value != null){
						
						Timestamp sub1 = new Timestamp(horaFormat.parse(Utils.substractHoras(alocHora, value)).getTime());
						
						 if(cargaHoraria != null){
							 
							cargaHoraria = Utils.somaHoras(cargaHoraria, sub1);
						 
						 }else{

							 cargaHoraria = sub1;
							 
						 }
						 
						 value = null;
						
					}else{
						value = alocHora; 
					}
				}
			}
		
		return cargaHoraria;
	}
public static String substractHoras(Timestamp hora1 , Timestamp hora2) throws ParseException{
		
		SimpleDateFormat horaFormat    =  new SimpleDateFormat("HH:mm");
		
		Calendar gcHora1 = new GregorianCalendar();
		Calendar gcHora2 = new GregorianCalendar();
		
		Calendar gcDiff = new GregorianCalendar();

		long tempo = 0;
		
		gcHora1.setTimeInMillis(hora1.getTime());
		gcHora2.setTimeInMillis(hora2.getTime());
		
		gcDiff.setTime(new Timestamp(horaFormat.parse("00:00").getTime()));
	
		Integer hora1s = gcHora1.get(Calendar.HOUR_OF_DAY);
		Integer hora2s = gcHora2.get(Calendar.HOUR_OF_DAY);
		
		Integer min1 = gcHora1.get(Calendar.MINUTE);
		Integer min2 = gcHora2.get(Calendar.MINUTE);
		
		String comp = hora1s + ":" + min1;
		String comp2 = hora2s + ":" + min2;
		
		while(!comp.equals(comp2)){
			
			gcHora2.add(Calendar.MINUTE, 1);
			gcDiff.add(Calendar.MINUTE, 1);
			
			hora2s = gcHora2.get(Calendar.HOUR_OF_DAY);
			min2 = gcHora2.get(Calendar.MINUTE);
			
			comp2 = hora2s + ":" + min2;
		}
		
		tempo = gcDiff.getTime().getTime();
		
		String hora = milisegundosParaHora(tempo);
		
		if(hora.equals("0")){
			
			hora = "00:00";
			
		}
		
		return hora;
	}

Obs: Tudo isso que faço é para preencher um Bean que utilizo para montar o relatório de ponto diário em pdf. (Jasper)

V

Você viu que meu método ali faz a conta sem aquele while de 1 em 1?

B

Opa vi sim, está bem mais otimizado!

Mas este método foi desenvolvido por outro programador da equipe que já estava utilizando-o só estou aproveitando!

valeu mesmo! :smiley:

Criado 19 de janeiro de 2011
Ultima resposta 20 de jan. de 2011
Respostas 13
Participantes 2