Return day of week from date in dd/mm/yyy format

Asked

Viewed 2,358 times

6

I have this function that brings me the day of the week:

public static String getWeek(String date){ //ex 07/03/2017
    String dayWeek = "---";
    GregorianCalendar gc = new GregorianCalendar();
    try {
        gc.setTime(new SimpleDateFormat("MM/dd/yyyy", BRAZIL).parse(date));
        switch (gc.get(Calendar.DAY_OF_WEEK)) {
            case Calendar.SUNDAY:
                dayWeek = "DOM";
                break;
            case Calendar.MONDAY:
                dayWeek = "SEG";
                break;
            case Calendar.TUESDAY:
                dayWeek = "TER";
            break;
            case Calendar.WEDNESDAY:
                dayWeek = "QUA";
                break;
            case Calendar.THURSDAY:
                dayWeek = "QUI";
                break;
            case Calendar.FRIDAY:
                dayWeek = "SEX";
                break;
            case Calendar.SATURDAY:
                dayWeek = "SAB";

        }
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return dayWeek;
}

But she is bringing me the day of the previous week, ex: 07/03/2017 Tuesday he brings as Monday.

4 answers

7

Your date formatting mask is wrong. You are using the format MM/dd/yyyy when your string takes a format dd/MM/yyyy. Just change the mask:

public static String getWeek(String date){ //ex 07/03/2017
    String dayWeek = "---";
    GregorianCalendar gc = new GregorianCalendar();
    try {
        gc.setTime(new SimpleDateFormat("dd/MM/yyyy").parse(date));
        switch (gc.get(Calendar.DAY_OF_WEEK)) {
            case Calendar.SUNDAY:
                dayWeek = "DOM";
                break;
            case Calendar.MONDAY:
                dayWeek = "SEG";
                break;
            case Calendar.TUESDAY:
                dayWeek = "TER";
            break;
            case Calendar.WEDNESDAY:
                dayWeek = "QUA";
                break;
            case Calendar.THURSDAY:
                dayWeek = "QUI";
                break;
            case Calendar.FRIDAY:
                dayWeek = "SEX";
                break;
            case Calendar.SATURDAY:
                dayWeek = "SAB";

        }
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return dayWeek;
}

This change was enough and it worked correctly, see: https://ideone.com/LLcvyr

3

Your mask is wrong, as Articuno replied.

You can also shorten your code to:

public static String getWeek(String date){ //ex 07/03/2017
        String dayWeek = "---";
        GregorianCalendar gc = new GregorianCalendar();
        try {
            gc.setTime(new SimpleDateFormat("dd/MM/yyyy", new Locale("pt", "BR")).parse(date));
           return new SimpleDateFormat("EEE", new Locale("pt", "BR")).format(gc.getTime()).toUpperCase();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return dayWeek;
    }
  • 1

    Interesting alternative, +1 :)

2

From Java 8, you can use API java.time

import java.time.DayOfWeek;
import java.time.format.DateTimeFormatter;
import java.time.format.TextStyle;
import java.util.Locale;

public static String getDayOfWeek(String data) {
    DateTimeFormatter parser = DateTimeFormatter.ofPattern("dd/MM/uuuu");
    DayOfWeek dow = DayOfWeek.from(parser.parse(data));
    return dow.getDisplayName(TextStyle.SHORT, new Locale("pt", "BR")).toUpperCase();
}

System.out.println(getDayOfWeek("07/03/2017")); // TER

I could also do LocalDate.parse(data, parser).getDayOfWeek() to obtain the DayOfWeeek, but if you just want the day of the week, you don’t have to create a LocalDate for nothing.

And I changed the name of the method because getWeek gives the impression that will return all week, but you just want a day of the week, so I left as getDayOfWeek.


Another detail is that in your method you are capturing the exception (ParseException if the date is invalid), by printing the stack trace and then returning "---". Without getting into the merit of not treating error, one way to have the same behavior is:

public static String getDayOfWeek(String data) {
    try {
        DateTimeFormatter parser = DateTimeFormatter.ofPattern("dd/MM/uuuu")
                                      .withResolverStyle(ResolverStyle.STRICT);
        DayOfWeek dow = DayOfWeek.from(parser.parse(data));
        return dow.getDisplayName(TextStyle.SHORT, new Locale("pt", "BR")).toUpperCase();
    } catch (DateTimeException e) {
        e.printStackTrace();
    }
    return "---";
}

System.out.println(getDayOfWeek("31/02/2017")); // ---

The ResolverStyle, as explained here, serves to ensure that dates such as February 29 in non-leap years and April 31 are considered invalid - has a more detailed explanation in this answer, in the section "Modes of Parsing".


But this method is not very efficient, because every time it is called, it creates two instances of DateTimeFormatter: one explicitly, and another implicitly, within getDisplayName (see in the source code).

Therefore, an alternative is to store these instances in static variables, so they are created only once:

public static DateTimeFormatter DOW_FMT = DateTimeFormatter.ofPattern("E", new Locale("pt", "BR"));

public static DateTimeFormatter PARSER = DateTimeFormatter.ofPattern("dd/MM/uuuu").withResolverStyle(ResolverStyle.STRICT);

public static String getDayOfWeek(String data) {
    try {
        return DOW_FMT.format(PARSER.parse(data)).toUpperCase();
    } catch (DateTimeException e) {
        e.printStackTrace();
    }
    return "---";
}

Notice that so you don’t even have to create the DayOfWeek, because the result of Parsing is passed directly to the formatter, who already takes the day of the week and formats.


If you want to keep using SimpleDateFormat, there is one important detail: by default, this class accepts invalid dates like "33/22/2017", making some very strange adjustments:

// 33/22/2017 vira 2 de novembro de 2018
System.out.println(new SimpleDateFormat("dd/MM/yyyy").parse("33/22/2017")); // Fri Nov 02 00:00:00 BRT 2018

To avoid this problem, just set it as nonlenient:

public static String getWeek(String date) { // ex 07/03/2017
    String dayWeek = "---";
    GregorianCalendar gc = new GregorianCalendar();
    SimpleDateFormat parser = new SimpleDateFormat("dd/MM/yyyy");
    parser.setLenient(false); // <- setar como não-leniente, assim não aceita datas inválidas
    try {
        gc.setTime(parser.parse(date));
        switch (gc.get(Calendar.DAY_OF_WEEK)) {
            etc...

One another answer suggested using DateFormatSymbols, but it was used getWeekdays, which returns the full names ("Sunday", "Monday", etc). Not to mention that if you create it without specifying a Locale, as suggested, she will use the default that is configured in the JVM (for example, if the JVM is configured with some locale in English, names will be returned in this language - "Sunday", "Monday", etc).

So if you want to use that solution, you need to specify the locale to use Portuguese, and to use getShortWeekdays to have the names abbreviated. And since this array is fixed and will be used whenever the method is called, you can create it only once as well:

public static String[] WEEKDAYS = new DateFormatSymbols(new Locale("pt", "BR")).getShortWeekdays();

public static String getDayOfWeek(String data) {
    try {
        SimpleDateFormat parser = new SimpleDateFormat("dd/MM/yyyy");
        parser.setLenient(false);
        Calendar cal = Calendar.getInstance();
        cal.setTime(parser.parse(data));
        return WEEKDAYS[cal.get(Calendar.DAY_OF_WEEK)].toUpperCase();
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return "---";
}

Or, if you want to optimize further, leave the array with the names uppercase, so you don’t have to call toUpperCase:

public static String[] WEEKDAYS;
static {
    WEEKDAYS = new DateFormatSymbols(new Locale("pt", "BR")).getShortWeekdays();
    for (int i = 0; i < WEEKDAYS.length; i++) {
        WEEKDAYS[i] = WEEKDAYS[i].toUpperCase();
    }
}

public static String getDayOfWeek(String data) {
    try {
        SimpleDateFormat parser = new SimpleDateFormat("dd/MM/yyyy");
        parser.setLenient(false);
        Calendar cal = Calendar.getInstance();
        cal.setTime(parser.parse(data));
        return WEEKDAYS[cal.get(Calendar.DAY_OF_WEEK)];
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return "---";
}

And of course you also have the option to use an array with the fixed values:

public static String[] WEEKDAYS = {"DOM", "SEG", "TER", "QUA", "QUI", "SEX", "SAB"};

public static String getDayOfWeek(String data) {
    try {
        SimpleDateFormat parser = new SimpleDateFormat("dd/MM/yyyy");
        parser.setLenient(false);
        Calendar cal = Calendar.getInstance();
        cal.setTime(parser.parse(data));
        return WEEKDAYS[cal.get(Calendar.DAY_OF_WEEK) - 1];
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return "---";
}

The detail is that arrays start from zero index, but the values of DAY_OF_WEEK from 1 to 7 (Sunday to Saturday), so I need to subtract 1 to get the correct value (in the case of getShortWeekdays is not needed because it returns an array whose first position is an empty string).

0

I usually use the Datechooser component in the interface. The Datechooser component returns a java.util.Calendar. With this, you can use methods like these:

public String diaDaSemana(Calendar calendar) {
    return new DateFormatSymbols().getWeekdays()[calendar.get(Calendar.DAY_OF_WEEK)];
}

public String nomeDoMes(Calendar calendar) {
    return new DateFormatSymbols().getMonths()[calendar.get(Calendar.MONTH)];
}
  • This does not return in the given format ("SEC", "R", etc), because getWeekdays returns the full names ("Sunday", "Monday", etc) - should be getShortWeekdays for abbreviated names - and if the JVM is configured with a locale other than in English, the names will come in another language - see the details on my answer :-)

Browser other questions tagged

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