Как получить название дня недели на заданном языке в Java, используя Locale и GregorianCalendar?

Я столкнулся с некоторыми серьезными трудностями в упражнении, в котором я должен написать простую программу, которая будет выдавать название дня недели (не значение int) в качестве вывода. Более того, это должен быть день недели через 90 дней после текущей даты, и он должен отображаться на местном языке (датском).

Я новичок и ищу подсказки о том, как мне это сделать.

Важной частью упражнения является то, что я не могу использовать больше классов, чем импортировано (см. код ниже).

Что я нашел сам, так это то, как получить текущую дату и представить ее как день недели (я знаю, что она начинается с 1 с воскресенья), но я понятия не имею, как заставить ее показывать это целое число как название дня недели на местном языке. .

    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);
   }
}

Ожидаемым результатом должно быть одно имя дня недели 90 в будущем с текущей даты.


person Mutton    schedule 25.10.2019    source источник
comment
Я рекомендую вам не использовать SimpleDateFormat, Date и GregorianCalendar. Эти классы плохо спроектированы и давно устарели, первый из них, как известно, доставляет много хлопот. Вместо этого используйте LocalDate и DayOfWeek из java.time, современного API даты и времени Java.   -  person Ole V.V.    schedule 25.10.2019


Ответы (3)


Если вы должны использовать API старого стиля, то DateFormatSymbols полезен для получения названий дней.

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") ));

   }
}
person RealHowTo    schedule 25.10.2019

Это устаревший API; вместо этого вы должны использовать java.time. Если ваш учебный материал требует этого, это просто делает его плохим учебным материалом. Упражнение явно предназначено для того, чтобы научить вас знакомству с этим конкретным API.

Одна из многих причин, по которой этот API устарел, заключается в том, что он сбивает с толку и сложен в использовании. Итак, это не помогает.

В API нового стиля это очень и очень просто:

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));
}

В старом уф. Давайте посмотрим:

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);
    }
}

Без использования нового API вам придется выполнять собственный перевод, и вы не можете полагаться на то, что система сделает это за вас. Это также все основано на int, поэтому попытка отладки - это в основном попытка выяснить, что означают все произвольные числа.

Придерживайтесь нового API, верхний фрагмент. Гораздо чище.

person rzwitserloot    schedule 25.10.2019
comment
Спасибо, я думаю, что это очень информативно. Однако я получаю сообщение об ошибке Несоответствие типа: невозможно преобразовать из void в Calendar в строке: c = c.add(Calendar.DAY_OF_MONTH, 90); Я не знаю, что это значит - мне нужно изменить ключевое слово void на что-то другое? (мой редактор не показывает дополнительные подсказки) Пожалуйста, помогите. - person Mutton; 25.10.2019
comment
Справедливости ради, хотя никто и не должен этого хотеть, если ваш учитель настаивает, можно убедить заведомо проблемный SimpleDateFormat класс печатать дни недели на датском языке, так что нам не нужен switch заявление. Для ошибки компилятора в начале этой строки не должно быть c =. Пожалуйста, скажите своему учителю из числа присутствующих здесь, что эти старые классы больше не будут использоваться и что их преподавание наносит ученикам вред. - person Ole V.V.; 25.10.2019
comment
Это было очень полезно. Я смотрю на это упражнение так: возможно, оно было разработано для того, чтобы научиться решать проблемы, ограничиваясь тем, что у вас есть. Я не уверен. Еще один вопрос - почему исключение - это принудительно переключать значения int на Strings? - person Mutton; 25.10.2019
comment
Поскольку c является GregorianCalendar, мы точно знаем, что c.get(Calendar.DAY_OF_WEEK) вернет одну из констант дня недели. Поэтому, если вы введете все 7 в свой оператор switch, исключение никогда не произойдет. Однако, если что-то пойдет не так, мы захотим знать, и исключение — эффективное средство для этого. Если вы забудете один из дел (один из дней). Или если кто-то позже вызовет ваш метод и передаст 0 в качестве аргумента (что не является днем ​​недели). Или измените тип календаря на тот, в котором 10 дней в неделе. (продолжение следует) - person Ole V.V.; 26.10.2019
comment
Исключение вызовет сбой программы (если вы его где-нибудь не поймаете). Это считается менее плохим, чем предоставление неправильного вывода. Это, конечно, будет раздражать пользователя, но не вводить его в заблуждение. И повторяю от одного датчанина к другому: не используйте Calendar, он плохо спроектирован и давно устарел. - person Ole V.V.; 26.10.2019
comment
Если вы собираетесь сдать решение, используя GregorianCalendar, сделайте себе и учащимся следующего года одолжение, сдав вместе с ним и современное решение. Это никогда не может вычесть из оценки. Не стесняйтесь включать ссылку на этот вопрос о переполнении стека для справки. - person Ole V.V.; 26.10.2019

Рекомендуемое решение: java.time

Используйте первый фрагмент в ответе rzwitserloot.

Нерекомендуемое решение: Делайте то, что говорит учитель

Даже если мы ограничены использованием плохо разработанных и давно устаревших классов из Java 1.0 и 1.1, ИМХО это можно сделать немного более элегантно, чем в других ответах. Я использую общеизвестно проблемный класс SimpleDateFormat. Те, кто знает меня по Stack Overflow, могут ненавидеть меня за публикацию примера использования этого класса, и я принимаю любые отрицательные голоса!

    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);

Вывод при запуске сегодня (среда, 30 октября):

тирсдаг

(Это означает вторник.)

Передача часового пояса в GregorianCalendar гарантирует, что мы получим сегодняшнюю дату в этом часовом поясе. Во всех часовых поясах никогда не бывает одной и той же даты. В этом случае нам не нужно было указывать локаль, она определяет, в какой день недели начинается новая неделя (понедельник в Дании, поскольку мы следуем международному стандарту), который мы здесь не используем, поэтому я просто сделал это. на всякий случай.

Повторяю: не используйте это в рабочем коде. Сегодня у нас намного лучше java.time, современный API даты и времени Java.

person Ole V.V.    schedule 30.10.2019