How to calculate point cards

6

I'm developing an application that corresponds to the calculation of total hours worked on points cards, taking into account whether it is night time reduction or not and, if so, what is the night entry and exit.

The problem is:

To calculate the point card, I am traversing entries and exits using Calendar , and adding minute by minute 1 by 1, in the input and in an auxiliary variable, as counter.

When calculating the reduction of the night time, I calculate from second to second, and do the reduction (for those who do not know, at night, the hours worked are worth "more" in proportion to every 7 seconds, you worked 8)

But this method is "very" slow, and I have to calculate points cards for several days, which makes the application slow.

My question:

Is there a method or library that does these calculations optimally? Or is there a way to do these calculations faster? (using threads, or something of the type)

I'm going to post my code that calculates the total of the point card, I commented it for a better understanding (obs: it has an object cartãoponto as parameter, but during the code, you can understand the attributes of it)

public static synchronized String getHor(Cartaoponto c) {
    boolean isNot = c.getIsnoturnoCartaoponto();//verifico se é para reduzir ou não
    String[] entss = c.getEntradasCartaoponto().split("=");//entradas, setado como string porque não existe um valor fixo, e como string posso ir adicionando eternamente
    String[] saiss = c.getSaidasCartaoponto().split("=");//mesma coisa das entradas
    String entra = getAddIn(sdfH.format(c.getAdicionalentradaCartaoponto()), entss);//Verifica se tem que adicionar um "extra" no início do Cartão ponto
    String saia = getAddSai(sdfH.format(c.getAdicionalsaidaCartaoponto()), saiss);//mesma coisa de antes, so que no anterior
    entss = entra.split("=");//seto novamente o valor (já mudado!)
    saiss = saia.split("=");
    Date entNot = c.getEntradanoturnaCartaoponto();//entrada noturna
    Date saiNot = c.getSaidanoturnaCartaoponto();//saída noturna
    Date data = c.getDataCartaoponto();//data em relação ao cartão ponto
    StringTools stT = new StringTools();
    int cont = 0;
    int aux1 = 0, aux2 = 0;
    for (String s : entss) {
        if (!s.trim().equals(":")) {//verifico quantas batidas estão preenchidas
            cont += 1;
        }
        if (s.trim().equals("00:00")) {
            aux1 += 1;
        }
    }
    for (String s : saiss) {//verifico se a batida não é 0,
        if (s.trim().equals("00:00")) {
            aux2 += 1;
        }
    }
    for (int i = 0; i < entss.length; i++) {
        if (!entss[i].trim().equals(":")) {
            if (saiss[i].trim().equals(":")) {//se tiver entrada, mas não tiver saída, retorna erro!
                return "ERRO";
            }
        }
    }
    if (aux1 + aux2 > 4) {//se tiver mais de 4 batidas que é "00:00"
        cont = 0;
    }
    if (cont == 0) {//se não houver batidas (estiver vazio) retorna 0
        return "00:00";
    }
    String[] ents = new String[cont];//seta uma nova variável, com o número de batidas (tirando as vazias)
    String[] saids = new String[cont];
    cont = 0;
    for (String s : entss) {//seta o valor para os Arrays
        if (!s.trim().equals(":")) {
            ents[cont] = s;
            cont += 1;
        }
    }
    cont = 0;
    for (String s : saiss) {
        if (!s.trim().equals(":")) {
            saids[cont] = s;
            cont += 1;
        }
    }
    String a = "";
    try {
        SimpleDateFormat sdfh = new SimpleDateFormat("HH:mm");
        Calendar tot = Calendar.getInstance();
        tot.set(data.getYear(),//total
                data.getMonth(),
                data.getDay(),
                0,
                0,
                0);
        Calendar datIn = Calendar.getInstance();
        datIn.set(tot.get(Calendar.YEAR),//data de Início (para verificar depois, pois pode ser mais que 24h e o Calendar não ajuda nesse quesito)
                tot.get(Calendar.MONDAY),
                tot.get(Calendar.DAY_OF_MONTH),
                tot.get(Calendar.HOUR_OF_DAY),
                tot.get(Calendar.MINUTE),
                tot.get(Calendar.SECOND)
        );
        datIn.set(Calendar.MILLISECOND, 0);//millisegundos = 0, porque tem verificações e isso já me deu dor de cabeça
        tot.set(Calendar.MILLISECOND, aux2);

        for (int i = 0; i < ents.length; i++) {//laço de repetição entre as batidas
            if (saids[i].trim().equals(":")) {//se a saída estiver vazia
                if (ents[i].trim().equals(":")) {//se a entrada estiver vazia, vá para o próximo (mesmo tendo a verificação anterior, resolvi ter certeza)
                    continue;
                } else {//se tiver entrada, mas não tiver saída, retorna erro
                    return "ERRO";
                }
            }
            Calendar saiNotu = Calendar.getInstance();//saida noturna
            saiNotu.setTime(saiNot);
            saiNotu.set(Calendar.MILLISECOND, 0);
            Calendar entNotu = Calendar.getInstance();//entrada noturna
            entNotu.setTime(entNot);
            entNotu.set(Calendar.MILLISECOND, 0);
            if (entNotu.get(Calendar.HOUR_OF_DAY) >= 00 && entNotu.get(Calendar.HOUR_OF_DAY) < saiNotu.get(Calendar.HOUR_OF_DAY)) {
                entNotu.add(Calendar.DAY_OF_YEAR, 1);//seto assim, pois na lei brasileira, a entrada é 22:00 do dia x, e a saída é 05:00 do dia x+1
            }
            Calendar sai = Calendar.getInstance();//saída
            sai.setTime(data);
            sai.set(Calendar.HOUR_OF_DAY, sdfh.parse(saids[i]).getHours());
            sai.set(Calendar.MINUTE, sdfh.parse(saids[i]).getMinutes());
            sai.set(Calendar.MILLISECOND, 0);
            if (sai.get(Calendar.HOUR_OF_DAY) >= 00 && sai.get(Calendar.HOUR_OF_DAY) < saiNotu.get(Calendar.HOUR_OF_DAY)) {
                sai.add(Calendar.DAY_OF_YEAR, 1);
            }
            Calendar ent = Calendar.getInstance();//entrada
            ent.setTime(data);
            ent.set(Calendar.HOUR_OF_DAY, sdfh.parse(ents[i]).getHours());
            ent.set(Calendar.MINUTE, sdfh.parse(ents[i]).getMinutes());
            ent.set(Calendar.MILLISECOND, 0);
            if (ent.get(Calendar.HOUR_OF_DAY) >= 00 && ent.get(Calendar.HOUR_OF_DAY) < saiNotu.get(Calendar.HOUR_OF_DAY)) {
                ent.add(Calendar.DAY_OF_YEAR, 1);
            }
            while (ent.after(sai)) {
                sai.add(Calendar.DAY_OF_MONTH, 1);
            }//se a saída for antes da entrada (como 23:30 e 00:00 por exemplo) adiciona 1 à saída
            int aux = 0;
            while (!ent.equals(sai)) {//percorre o tempo (entre ent e sai)
                Date entras = sdfH.parse(sdfH.format(ent.getTime()));//fiz isso para ajudar na verificação
                Date entraNot = sdfH.parse(sdfH.format(entNot.getTime()));
                int day2 = entraNot.getDate() + 1;
                String day1 = String.valueOf(day2);
                if (day2 < 10) {
                    day1 = "0" + day1;
                }
                Date saiaNot = sdfHd.parse(day1 + "-" + sdfH.format(saiNot.getTime()));//até aqui, foi pelo seguinte quesito:
                //A entrada e saída, pode dar um erro de verificação se eu deixar para o dia atual, por isso tenho
                //que deixar toda hora como válida, ou seja, se fosse sem essa verificação anterior, quando tivesse
                //03:00 até 06:00 ele ia contar como hora normal, não hora reduzida, mas já se tivesse
                //22:00 até as 00:00 ele funcionava, por isso eu tive que fazer essa "gambiarra"
                if (entras.before(entraNot)) {//se entrada for antes da entrada noturna
                    day2 = entraNot.getDate() - 1;
                    day1 = String.valueOf(day2);
                    if (day2 < 10) {
                        day1 = "0" + day1;
                    }
                    entraNot = sdfHd.parse(day1 + "-" + sdfH.format(entNot.getTime()));
                    day2 = saiaNot.getDate() - 1;
                    day1 = String.valueOf(day2);
                    if (day2 < 10) {
                        day1 = "0" + day1;
                    }
                    saiaNot = sdfHd.parse(day1 + "-" + sdfH.format(saiNot.getTime()));
                }//removo 1 dia da entrada e da saída noturna
                if ((entras.after(entraNot) || entras.equals(entraNot)) && entras.before(saiaNot)) {//se a entrada for entre entrada noturna e a saída noturna
                    if (isNot) {//calculo o total como hora noturna reduzida se o cartãoponto pedir isso
                        ent.add(Calendar.SECOND, 1);
                        aux += 1;
                        if (aux == 7) {
                            tot.add(Calendar.SECOND, 8);
                            aux = 0;
                        }
                    } else {//senão, adiciono minuto a minuto
                        ent.add(Calendar.MINUTE, 1);
                        tot.add(Calendar.MINUTE, 1);
                    }
                } else {//se não estiver dentro da hora noturna (fora de entrada noturna e saída noturna)
                    ent.add(Calendar.MINUTE, 1);//adiciona minuto a minuto
                    tot.add(Calendar.MINUTE, 1);
                }
            }
        }
        boolean teste = false;//verificação de erro
        int multiplicador = stT.dataDiff(datIn.getTime(), tot.getTime());//multiplicador de dias (pega a diferença de data entre data de Início e o total)
        if (multiplicador < 0) {//se o multiplicador for menor que 0 (data de Início for depois da data final) (deu erro, por isso o teste)
            multiplicador = multiplicador * (-1);//multiplicador fica normal, teste=true
            teste = true;
        }
        multiplicador = multiplicador * 24;//multiplica os dias para ter as horas
        multiplicador = multiplicador + tot.get(Calendar.HOUR_OF_DAY);//adiciona o total de horas ao dia
        if (multiplicador > 24) {//verificação de erro também, porque se for mais que 24, o teste é true.
            multiplicador = multiplicador - 24;
        }
        if (multiplicador >= 10 && multiplicador <= 25) {//daqui para frente eu deixo o total no formato ("HH:mm:ss") para o SimpleDateFormat
//para logo em seguida arredondar os segundos para ficar no formato ("HH:mm")
            if (tot.get(Calendar.MINUTE) < 10) {
                if (tot.get(Calendar.SECOND) < 10) {
                    a = String.valueOf(multiplicador)
                            + ":0"
                            + String.valueOf(tot.get(Calendar.MINUTE))
                            + ":0"
                            + String.valueOf(tot.get(Calendar.SECOND));
                } else {
                    a = String.valueOf(multiplicador)
                            + ":0"
                            + String.valueOf(tot.get(Calendar.MINUTE))
                            + ":"
                            + String.valueOf(tot.get(Calendar.SECOND));
                }
            } else if (tot.get(Calendar.SECOND) < 10) {
                a = String.valueOf(multiplicador)
                        + ":"
                        + String.valueOf(tot.get(Calendar.MINUTE))
                        + ":0"
                        + String.valueOf(tot.get(Calendar.SECOND));
            } else {
                a = String.valueOf(multiplicador)
                        + ":"
                        + String.valueOf(tot.get(Calendar.MINUTE))
                        + ":"
                        + String.valueOf(tot.get(Calendar.SECOND));
            }
            a = String.valueOf(multiplicador)
                    + ":"
                    + String.valueOf(tot.get(Calendar.MINUTE))
                    + ":"
                    + String.valueOf(tot.get(Calendar.SECOND));
        } else if (multiplicador < 10) {
            if (tot.get(Calendar.MINUTE) < 10) {
                if (tot.get(Calendar.SECOND) < 10) {
                    a = "0" + String.valueOf(multiplicador)
                            + ":0"
                            + String.valueOf(tot.get(Calendar.MINUTE))
                            + ":0"
                            + String.valueOf(tot.get(Calendar.SECOND));
                } else {
                    a = "0" + String.valueOf(multiplicador)
                            + ":0"
                            + String.valueOf(tot.get(Calendar.MINUTE))
                            + ":"
                            + String.valueOf(tot.get(Calendar.SECOND));
                }
            } else if (tot.get(Calendar.SECOND) < 10) {
                a = "0" + String.valueOf(multiplicador)
                        + ":"
                        + String.valueOf(tot.get(Calendar.MINUTE))
                        + ":0"
                        + String.valueOf(tot.get(Calendar.SECOND));
            } else {
                a = "0" + String.valueOf(multiplicador)
                        + ":"
                        + String.valueOf(tot.get(Calendar.MINUTE))
                        + ":"
                        + String.valueOf(tot.get(Calendar.SECOND));
            }
        }
        a = arredondaSegundos(a);//aqui ele arredonda os segundos, se for maior que 30, para cima, senão, para baixo
        if (teste) {//se deu erro, posta o valor do total
            System.out.println("A: " + a);
        }
    } catch (Exception E) {
        E.printStackTrace();
    }
    return a;//retorna o total
}
    
asked by anonymous 21.06.2016 / 16:08

1 answer

-1

I think the best way would be:

  • Find out the number of hours worked in the evening (no reduction)
  • Transfore to decimal. Ex: 3h25m gets 3.42 (25/60 = 0.42)
  • Multiply this value by 1.142857142857143. This is the value of the ratio between the normal time and the night time given by 60 / 52.5: Ex: 3.42 * 1.142857142857143 = 3,908571
  • Convert back to hh: mm: Ex: 0,908571 * 60 = 54,5142 = 3h: 55m
  • 14.07.2016 / 15:31