2

I am facing some serious difficulties with an exercise where I am to write a simple program which would give a weekday name (not an int value) as an output. What`s more, it should be a weekday 90 days in the future from current date and it should be displayed in a local language (Danish).

I am a beginner and am seeking hints on how I should do this.

The important part of the exercise is that I cannot use more classes, than those imported (see below code).

What I found by myself is how to get the current date and present it as a weekday (I know it starts counting from 1 since Sunday), but I have no clue how to force it to show this integer as a weekday name in local language.

    package days01;

import java.text.SimpleDateFormat;
import java.util.Scanner;
import java.util.Locale;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Calendar;

public class Dates {
   public static void main(String[] argv) {
      Calendar one = new GregorianCalendar();
      int day = one.get(Calendar.DAY_OF_WEEK);
      System.out.println(day);
   }
}

The expected output should be a single weekday name 90 in future from current date.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Mutton
  • 33
  • 1
  • 5
  • 2
    I recommend you don’t use `SimpleDateFormat`, `Date` and `GregorianCalendar`. Those classes are poorly designed and long outdated, the first in particular notoriously troublesome. Instead use `LocalDate` and `DayOfWeek`, both from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Oct 25 '19 at 19:30

3 Answers3

7

If you must use the old-style API then DateFormatSymbols is useful to retrieve the day names.

import java.text.DateFormatSymbols;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;

public class DayNameExample {

   public static String getDayName(int day, Locale locale) {
      DateFormatSymbols symbols = new DateFormatSymbols(locale);
      String[] dayNames = symbols.getWeekdays();
      return dayNames[day];
    }

   public static void main(String[] args) {
      Calendar c = new GregorianCalendar();
      c.add(Calendar.DAY_OF_MONTH, 90);
      int dow = c.get(Calendar.DAY_OF_WEEK);

      System.out.println (DayNameExample.getDayName(dow, new Locale("da", "DK") ));

   }
}
RealHowTo
  • 34,977
  • 11
  • 70
  • 85
5

This is an obsolete API; you should be using java.time instead. If your course material enforces this, that.. just makes it bad course material. The exercise is clearly meant to teach you familiarity with this specific API.

One of the many reasons this API has been obsoleted is because it is confusing and hard to use. So, that doesn't help.

In the new style API, this is very, very simple:

void go() {
    LocalDate today = LocalDate.now();
    LocalDate ninetyDaysLater = today.plusDays(90);
    DayOfWeek dayOfWeek = ninetyDaysLater.getDayOfWeek();
    Locale danish = new Locale("da", "DK");
    System.out.println(dayOfWeek.getDisplayName(TextStyle.FULL, danish));
}

In the old one, oof. Let's see:

void go() {
    Calendar c = new GregorianCalendar();
    c.add(Calendar.DAY_OF_MONTH, 90); // Why day of month? Just cuz. I mentioned this API is bad, right?
    int dow = c.get(Calendar.DAY_OF_WEEK);
    System.out.println(weekDayInDanish(dow));
}

static String weekDayInDanish(int dow) {
    switch (dow) {
        case Calendar.MONDAY: return "Mandag";
        case Calendar.TUESDAY: return "Tirsdag";
        // the rest of the cases here
        default: throw new IllegalArgumentException("Unexpected day: " + dow);
    }
}

Without using the new API, you have to do your own translate and can't rely on the system doing it for you. It's also all int based, so trying to debug is mostly an exercise of trying to figure out what all the arbitrary numbers mean.

Stick to the new API, the top snippet. Much cleaner.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • Thank you, I think this is very informative. However, I get an error "Type mismatch: cannot convert from void to Calendar" at the line: c = c.add(Calendar.DAY_OF_MONTH, 90); I don`t know what that means - do i have to change the keyword void to something else? (my editor does not show additional clues) Please help. – Mutton Oct 25 '19 at 18:51
  • In all fairness, while no one should want to, if your teacher insists, it *is* possible to persuade the notoriously troublesome `SimpleDateFormat` class to print the days of the week in Danish, so we don’t need the `switch` statement. For the compiler error, there shouldn’t be any `c =` in the beginning of that line. Please tell your teacher from a number of us here that those old classes are not to be used anymore and that teaching them is doing the students a disfavour. – Ole V.V. Oct 25 '19 at 19:39
  • This has been very helpful. The way I look at this exercise is that maybe it was designed to learn solving problems while being limited to what you have. I `m not sure. One more question - why there is an exception - is it to forcibly switch int values to Strings? – Mutton Oct 25 '19 at 20:36
  • 1
    Since `c` is a `GregorianCalendar`, we know for a fact that `c.get(Calendar.DAY_OF_WEEK)` will return one of the day-of-week constants. So if you pur all 7 into your `switch` statement, the exception will never happen. However, if something goes wrong, we will want to know, and an exception is an effective means for that. If you forget one of the cases (one of the days). Or if someone later calls your method and passes 0 as an argument (which isn’t a day of week). Or changes the calendar type to one that has 10 days in a week. (to be continued) – Ole V.V. Oct 26 '19 at 04:13
  • 1
    The exception will call the program to crash (unless you catch it somewhere). This is considered less bad than delivering a wrong output. It will annoy the user, of course, but not mislead him or her. And I repeat from one Dane to another: don’t use `Calendar`, it’s poorly designed and long outdated. – Ole V.V. Oct 26 '19 at 04:15
  • 1
    If you are going to hand in the solution using `GregorianCalendar`, do yourself and next year’s students the favour of handing in the modern solution along with it. It can never subtract from the assessment. Feel free to include a link to this Stack Overflow question too for reference. – Ole V.V. Oct 26 '19 at 04:52
1

Recommended solution: java.time

Use the first snippet in the answer by rzwitserloot.

Discouraged solution: Do what the teacher says

Even if we’re restricted to using the poorly designed and long outdated classes from Java 1.0 and 1.1, it can IMHO be done slightly more elegantly than in the other answers. I am using the notoriously troublesome SimpleDateFormat class. Those who know me on Stack Overflow may hate me for posting an example of using this class, and I accept any downvotes!

    TimeZone denmark = TimeZone.getTimeZone("Europe/Copenhagen");
    Locale danish = Locale.forLanguageTag("da-DK");
    DateFormat dayOfWeekFormatter = new SimpleDateFormat("EEEE", danish);
    Calendar one = new GregorianCalendar(denmark, danish);
    one.add(Calendar.DATE, 90);
    String dayOfWeekString = dayOfWeekFormatter.format(one.getTime());
    System.out.println(dayOfWeekString);

Output when running today (Wednesday October 30):

tirsdag

(It means Tuesday.)

Passing a time zone to the GregorianCalendar makes sure we get today’s date in that time zone. It is never the same date in all time zones. We hadn’t needed to specify a locale in this case, it controls on which day of the week a new week begins (Monday in Denmark since we follow the international standard), which we don’t use here, so I just did it for good measure.

I repeat: Don’t use this in production code. Today we have so much better in java.time, the modern Java date and time API.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161