Traversing Dates using Calendar

Asked

Viewed 620 times

4

I’m making a report on java, I spend a period specified by the user. In my DAO I’m doing the treatment.

Here I take the last date.

String data1 = DateUtil.toString(dto.getDataInicio(), "MM/yyyy");
        String data2 =  DateUtil.toString(dto.getDataFim(), "MM/yyyy");

        Calendar c1 = DateUtil.parseCal (data1);
        Calendar c2 = DateUtil.parseCal (data2);

Here I do a treatment to check the past months.

for (Calendar c = (Calendar) c1.clone(); c.compareTo (c2) <= 0; c.add (Calendar.DATE, +1)) {
           if (c.get (Calendar.MONTH) == Calendar.JANUARY  && c.get (Calendar.DAY_OF_MONTH) == 01){
                     mesesql += "total_faturado_mensal(cs.id_corp, '"+c1.get(Calendar.YEAR)+"-01-01', '"+c2.get(Calendar.YEAR)+"-01-01', to_char('"+c1.get(Calendar.YEAR)+"-01-01'::date, 'yyyy-mm'), cl.id_convenio) as janeiro, ";       
                       nomesMeses.add("Janeiro");
               }
             if (c.get (Calendar.MONTH) == Calendar.FEBRUARY && c.get (Calendar.DAY_OF_MONTH) == 01){
                            mesesql += "total_faturado_mensal(cs.id_corp, '"+c1.get(Calendar.YEAR)+"-02-01', '"+c2.get(Calendar.YEAR)+"-02-01', to_char('"+c1.get(Calendar.YEAR)+"-02-01'::date, 'yyyy-mm'), cl.id_convenio) as fevereiro, ";     
                            nomesMeses.add("Fevereiro");
               }     
             if (c.get (Calendar.MONTH) == Calendar.MARCH && c.get (Calendar.DAY_OF_MONTH) == 01){
                            mesesql += "total_faturado_mensal(cs.id_corp, '"+c1.get(Calendar.YEAR)+"-03-01', '"+c2.get(Calendar.YEAR)+"-03-01', to_char('"+c1.get(Calendar.YEAR)+"-03-01'::date, 'yyyy-mm'), cl.id_convenio) as marco, ";
                            nomesMeses.add("Março");
               }
             if (c.get (Calendar.MONTH) == Calendar.APRIL && c.get (Calendar.DAY_OF_MONTH) == 01){
                            mesesql += "total_faturado_mensal(cs.id_corp, '"+c1.get(Calendar.YEAR)+"-04-01', '"+c2.get(Calendar.YEAR)+"-04-01', to_char('"+c1.get(Calendar.YEAR)+"-04-01'::date, 'yyyy-mm'), cl.id_convenio) as abril, ";
                            nomesMeses.add("Abril");
               }
             if (c.get (Calendar.MONTH) == Calendar.MAY && c.get (Calendar.DAY_OF_MONTH) == 01){
                           mesesql += "total_faturado_mensal(cs.id_corp, '"+c1.get(Calendar.YEAR)+"-05-01', '"+c2.get(Calendar.YEAR)+"-05-01', to_char('"+c1.get(Calendar.YEAR)+"-05-01'::date, 'yyyy-mm'), cl.id_convenio) as maio, ";
                            nomesMeses.add("Maio");
               }
             if (c.get (Calendar.MONTH) == Calendar.JUNE && c.get (Calendar.DAY_OF_MONTH) == 01){
                           mesesql += "total_faturado_mensal(cs.id_corp, '"+c1.get(Calendar.YEAR)+"-06-01', '"+c2.get(Calendar.YEAR)+"-06-01', to_char('"+c1.get(Calendar.YEAR)+"-06-01'::date, 'yyyy-mm'), cl.id_convenio) as junho,  ";
                            nomesMeses.add("Junho");
               }
             if (c.get (Calendar.MONTH) == Calendar.JULY && c.get (Calendar.DAY_OF_MONTH) == 01){
                           mesesql += "total_faturado_mensal(cs.id_corp, '"+c1.get(Calendar.YEAR)+"-07-01', '"+c2.get(Calendar.YEAR)+"-07-01', to_char('"+c1.get(Calendar.YEAR)+"-07-01'::date, 'yyyy-mm'), cl.id_convenio) as julho, ";
                            nomesMeses.add("Julho");
               }
             if (c.get (Calendar.MONTH) == Calendar.AUGUST && c.get (Calendar.DAY_OF_MONTH) == 01){
                           mesesql += "total_faturado_mensal(cs.id_corp, '"+c1.get(Calendar.YEAR)+"-08-01', '"+c2.get(Calendar.YEAR)+"-08-01', to_char('"+c1.get(Calendar.YEAR)+"-08-01'::date, 'yyyy-mm'), cl.id_convenio) as agosto, ";
                            nomesMeses.add("Agosto");
               }
             if (c.get (Calendar.MONTH) == Calendar.SEPTEMBER && c.get (Calendar.DAY_OF_MONTH) == 01){
                           mesesql += "total_faturado_mensal(cs.id_corp, '"+c1.get(Calendar.YEAR)+"-09-01', '"+c2.get(Calendar.YEAR)+"-09-01', to_char('"+c1.get(Calendar.YEAR)+"-09-01'::date, 'yyyy-mm'), cl.id_convenio) as setembro, ";
                            nomesMeses.add("Setembro");
               }
             if (c.get (Calendar.MONTH) == Calendar.OCTOBER && c.get (Calendar.DAY_OF_MONTH) == 01){
                           mesesql += "total_faturado_mensal(cs.id_corp, '"+c1.get(Calendar.YEAR)+"-10-01', '"+c2.get(Calendar.YEAR)+"-10-01', to_char('"+c1.get(Calendar.YEAR)+"-10-01'::date, 'yyyy-mm'), cl.id_convenio) as outubro, ";
                            nomesMeses.add("Outubro");
               }
             if (c.get (Calendar.MONTH) == Calendar.NOVEMBER && c.get (Calendar.DAY_OF_MONTH) == 01){
                           mesesql += "total_faturado_mensal(cs.id_corp, '"+c1.get(Calendar.YEAR)+"-11-01', '"+c2.get(Calendar.YEAR)+"-11-01', to_char('"+c1.get(Calendar.YEAR)+"-11-01'::date, 'yyyy-mm'), cl.id_convenio) as novembro, ";
                            nomesMeses.add("Novembro");
               }
             if (c.get (Calendar.MONTH) == Calendar.DECEMBER && c.get (Calendar.DAY_OF_MONTH) == 01){
                           mesesql += "total_faturado_mensal(cs.id_corp, '"+c1.get(Calendar.YEAR)+"-12-01', '"+c2.get(Calendar.YEAR)+"-12-01', to_char('"+c1.get(Calendar.YEAR)+"-12-01'::date, 'yyyy-mm'), cl.id_convenio) as dezembro, "; 
                            nomesMeses.add("Dezembro");
               }

            }

It is working, however when reporting a period for example from 01/2016 there 12/2016 it is not entering within the if (c.get (Calendar.MONTH) == Calendar.DECEMBER bringing then only from January to November. But if I put only 11/2016 and 12/2016 appears December. And to appear the 12 months of 2016, I have to put a month more for example: 01/2016 á 01/2017 ai sim ele me traz o mês de dezembro.... and so consequently, with longer dates. I don’t mean much as Calendar works, I’m doing something wrong?

  • Month returns number -1, that is, 11 will be December.

  • 1

    Recommended: http://answall.com/q/177129/132

  • yes @diegofm, so I compare it to Calendar.DECEMBER which is an int 11. But it usually works from January to October. Only the latter is like this. I found cases similar to this problem but did not solve.

  • Arthur, I think the problem here is more basic than that, the condition c.compareTo (c2) <= 0 is strict and the Calendar takes into account fields beyond the month and year, whether they are present at the initial date or not. If you want the survey to be inclusive it is necessary to use the last millisecond of the last second of the last minute of the last hour of the last day of the month in question (similarly it is important to reset all these values for the first day).

  • What a class you’re wearing: DateUtil?

  • 1

    If you really want to use Calendar (why? () a workaround known is to make the crease open and use the first day of the following month if you need other options a look in that question. That said, I would read the link @Victorstafusa shared and on Oracle Official Tutorial on Date Time API

Show 1 more comment

1 answer

5


One detail I found suspicious is that in for, you are incrementing days, not months. On any day other than a 01 day, the iteration of the for will do nothing, just jump day after day. Also, the amount of repeated code is immense. So we will redo your code:

String data1 = DateUtil.toString(dto.getDataInicio(), "MM/yyyy");
String data2 = DateUtil.toString(dto.getDataFim(), "MM/yyyy");

Calendar c1 = DateUtil.parseCal(data1);
Calendar c2 = DateUtil.parseCal(data2);

String[] meses = {
    "zero",
    "Janeiro", "Fevereiro", "Março", "Abril",
    "Maio", "Junho", "Julho", "Agosto",
    "Setembro", "Outubro", "Novembro", "Dezembro"
};

String template = "total_faturado_mensal(cs.id_corp, '$A-$I-01', '$B-$I-01', to_char('$A-$I-01'::date, 'yyyy-mm'), cl.id_convenio) as $M, ";

StringBuilder sb = new StringBuilder(8192);
sb.append(mesesql);

Calendar c = (Calendar) c1.clone();
while (c.compareTo(c2) <= 0) {
    int mes = c.get(Calendar.MONTH) + 1;
    sb.append(template
            .replace("$A", String.valueOf(c1.get(Calendar.YEAR)))
            .replace("$B", String.valueOf(c2.get(Calendar.YEAR)))
            .replace("$M", meses[mes])
            .replace("$I", mes < 10 ? "0" + mes : "" + mes));
    nomesMeses.add(meses[mes]);
    c.add(Calendar.MONTH, 1);
    c.set(Calendar.DATE, 1);
}

mesesql = sb.toString();

In this code above, I’m guessing the class DateUtil works and has no bug or surprise. If this is not the case, it may go wrong, but then you will have to post at least the methods toString and parseCal of her to take a look at.

Another alternative is using the classes of the package java.time, much better than wearing the hideous java.util.Calendar. Here’s what the code looks like in this case:

Date a = dto.getDataInicio();
Date b = dto.getDataFim();

LocalDate c1 = a.toInstant().atOffset(ZoneOffset.UTC).toLocalDate().withDayOfMonth(1);
LocalDate c2 = b.toInstant().atOffset(ZoneOffset.UTC).toLocalDate().withDayOfMonth(1);

String[] meses = {
    "zero",
    "Janeiro", "Fevereiro", "Março", "Abril",
    "Maio", "Junho", "Julho", "Agosto",
    "Setembro", "Outubro", "Novembro", "Dezembro"
};

String template = "total_faturado_mensal(cs.id_corp, '$A-$I-01', '$B-$I-01', to_char('$A-$I-01'::date, 'yyyy-mm'), cl.id_convenio) as $M, ";

StringBuilder sb = new StringBuilder(8192);
sb.append(mesesql);

for (LocalDate c = c1; c.compareTo(c2) <= 0; c = c.plusMonths(1)) {
    int mes = c.getMonth().getValue();
    sb.append(template
            .replace("$A", String.valueOf(c1.getYear()))
            .replace("$B", String.valueOf(c2.getYear()))
            .replace("$M", meses[mes])
            .replace("$I", mes < 10 ? "0" + mes : "" + mes));
    nomesMeses.add(meses[mes]);
}

mesesql = sb.toString();

And in this code, of course if you can change the dto.getDataInicio() and the dto.getDataFim() to return LocalDate instead of Date, gets easier.

  • 1

    Both methods worked. Thank you. It really got cleaner and bunito the code.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.