Элегантный способ в Java для поиска предыдущего дня недели на основе валюты и текущей даты

В большинстве регионов мира суббота и воскресенье считаются выходными, что означает, что с понедельника по пятницу считаются рабочими днями. Однако в странах Ближнего Востока пятница и суббота считаются выходными, а с воскресенья по четверг считаются рабочими днями.

Есть ли в java элегантный способ поиска предыдущего дня недели на основе типа валюты и текущего дня?

Например, считайте, что текущий день 21-JUN-2021.

Для ближневосточной валюты днем ​​недели должно быть 20 июня 2021 г. Для всех других валют днем ​​недели должно быть 18 июня 2021 г.


person Sandy    schedule 21.06.2021    source источник
comment
Locale — это драйвер для определения выходных/будних дней.   -  person Basil Bourque    schedule 21.06.2021
comment
Я нашел очень похожий вопрос здесь, так как это поможет вам найти начало недели для данной локали   -  person Joe Ciaramitaro    schedule 21.06.2021
comment
Это кажется очень хрупким и может пойти не так для большинства необычных валют. Используйте другой способ, чтобы выяснить, какие дни являются рабочими и выходными. Если вы сомневаетесь, позвольте пользователю решить и добавить настройку.   -  person Clashsoft    schedule 21.06.2021
comment
Думаю, под валютой вы имеете в виду Locale. Со стандартным API вы получите SUNDAY в качестве первого дня недели. Проверьте System.out.println(WeekFields.of(new Locale("ar", "SA")).getFirstDayOfWeek()). Я думаю, вам может понадобиться использовать стороннюю библиотеку или написать свою собственную.   -  person Arvind Kumar Avinash    schedule 21.06.2021
comment
Я подозреваю, что вы найдете места на земле, где нет жесткого правила относительно того, когда наступают выходные или даже сколько дней они длятся. (Кроме того, вы также найдете места, где продолжительность недели отличается от 7 дней.)   -  person Ole V.V.    schedule 22.06.2021


Ответы (2)


Нет, и не из-за отсутствия API, а из-за фундаментальных проблем.

Валюта и дни недели не имеют абсолютно никакого отношения. Ясно, что просить перейти от валюты к концепции дня недели/выходных напрямую — это бред.

Вы ищете непрямой путь. Но шаги на этом пути не работают.

Общий путь, который вы ищете:

  • Перейти от валюты к локали.
  • Перейдите от локали к представлению о будних днях (которые являются «выходными» днями, которые считаются первым днем ​​недели).

Оба шага принципиально невозможны. В лучшем случае это кошмарные лайфхаки по обслуживанию и рукописные списки.

Второй шаг сложен, потому что концепция того, какие дни считаются выходными, не заложена в API — просто нет возможности спросить, например. любой класс в пакете java.time, даже если у вас есть локаль, какие дни являются выходными днями.

Первый шаг тоже сложный. Шаг «локаль -> валюта» в основном работает, но это необратимо. Например, в континентальной Европе множество регионов, но только одна валюта. Таким образом, попытка перейти с ЕВРО на какую локаль? не является единственным ответом, но выглядит как значительный список.

Это ваш лучший выстрел:

  • Перейти от одной валюты к всем языковым настройкам, в которых используется эта валюта.
  • Проверьте, имеют ли все локали единое представление о том, какие дни являются выходными. Это включает в себя ведение списка самостоятельно.
  • Если все они полностью согласны, теперь у вас есть ответ.
  • Если это не так, вам просто нужно прервать или иным образом вернуть «Я не знаю» в качестве ответа.
  • Весь код, который вызывает это «дайте мне выходные дни для этой валюты», должен учитывать тот факт, что «не знаю» может выпасть (вы можете по умолчанию использовать воскресенье/субботу, но если вы объясните кому-нибудь, что алгоритм разумно вычислит день, вы бы солгали. Это может делать это только иногда).
  • Вооружившись знаниями о том, какие дни являются выходными, вы сможете сделать расчет, что несложно.
  • Вам нужно будет принять во внимание, что локали могут свободно переключать обе валюты, а также их представление о том, что составляет «выходные», меняется с течением времени. Например, до 2002 года валютой региона nl-NL был голландский гульден. Потом евро.
  • Почти в каждом регионе есть понятие официальных выходных дней, которые считаются выходными для подавляющего большинства вопросов, которые вы хотите задать и которые требуют особого отношения к выходным: правительства закрыты, общественный транспорт ходит по расписанию воскресенья, все предприятия, которые открыты в будние дни, но закрыты в выходные дни, закрыты, рестораны со специальными тарифами в выходные дни будут взимать специальный тариф или даже больше и так далее.
  • Иногда праздники чрезвычайно трудно рассчитать, например, Пасху. Иногда праздники рассчитать буквально невозможно, потому что они зависят от решения комиссии, которое приходит всего за несколько дней до предполагаемого праздника. Например, Ид аль-Фитр, который имеет фиксированную дату «первого дня месяца Шавваль», но это по арабскому календарю, который является лунным (по сравнению с григорианским (западным) календарем, который является солнечным), и перевод 1-го числа Шавваль в григорианскую дату невозможен, так как это зависит, например, от. наблюдение полумесяца где-то на большой территории. Тем не менее, облачный покров существует, поэтому, чтобы знать, действительно ли что-то будет «выходным» (банки закрыты и т. Д.) В следующем году, вам нужно предсказать погоду на год вперед. Удачи с этим.

Если я еще не разубедил тебя, то теряю преимущество.

Но, эй, если вы хотите продолжить:

Если это приемлемо для вас (алгоритм, который попытается ответить на вопрос «учитывая эту валюту, скажите мне, какие дни считаются выходными» — но он часто будет отвечать «я не знаю»), вы можете написать это. Это нетривиально, потому что, вообще говоря, этот алгоритм никому не нужен (проблема заключается во всей части «часто оно не может сказать вам». Никому не нравится, когда приложение просто не работает во многих местах, и большая часть удобства ушел, если все, что алгоритм может дать вам, в лучшем случае является хорошим значением по умолчанию для некоторых настроек).

Как вы получили валюту в первую очередь? Если вы получили валюту из какой-то локали, возьмите эту локаль и идите оттуда, это намного, намного проще.

Сделать валюту на карте локали

Соответствующие операции:

Locale[] allLocales = java.util.Locale.getAvailableLocales();

java.util.Currency.getInstance(someLocale);

На самом деле вы не хотите Currency.getInstance, вы хотите наоборот (валюта в локаль, а не локаль в валюту). Этого метода не существует. Вам придется сначала сделать Map<Currency, List<Locale>> (и это дорогостоящая операция, поэтому сделайте это один раз и кэшируйте результаты в памяти).

Вы получите массу перекрытий. Это будет выглядеть примерно так:

/**
 * This is a best-effort attempt, many exotic combinations will simply not be in this mapping at all. Be aware that not all currency to locale mappings will be sensible */
static Map<Currency, List<Locale>> buildCurrencyToLocale() {
    var out = new HashMap<Currency, List<Locale>>();
    for (Locale locale : Locale.getAvailableLocales()) {
        Currency c = Currency.getInstance(locale);
        if (c == null) continue; // antarctica, for example.
        out.computeIfAbsent(c, x -> new ArrayList<Locale>()).add(locale);
    }
    return out;
}

Выполнить поиск валюты

Учитывая валюту, извлеките список локалей (используйте thatMap.getOrDefault(theCurrency, List.of())) и пропустите его через свой алгоритм «дай мне выходные», который представляет собой запутанный беспорядок, который я оставляю вам, который оптимально не может просто ответить на основе локали, но должен знать погода, иметь механизм для определения пасхи, все другие странные религиозные праздники, о которых я не успел подумать, и должен включать дату, о которой вы хотите знать, учитывая, что локали меняют официальные праздники и валюты и тому подобное.

Так что как ты это пишешь - меня бесит. Но если он у вас есть, перекиньте туда все локали и проверьте, получили ли вы единый набор ответов.

Как определить выходные дни с учетом локали?

Вы должны были написать это сами. Начните со списка локалей. Читайте о Пасхе и Ид аль-Фитр. Примите, что это никогда не будет идеальным.

person rzwitserloot    schedule 21.06.2021

Я предлагаю, чтобы пользователь настроил, какие дни он считает выходными. Например:

    List<DayOfWeek> userConfiguredWeekend
            = List.of(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY);
    
    LocalDate today = LocalDate.now(ZoneId.systemDefault());
    LocalDate previousWorkingDay = today.minusDays(1);
    while (userConfiguredWeekend.contains(previousWorkingDay.getDayOfWeek())) {
        previousWorkingDay = previousWorkingDay.minusDays(1);
    }
    
    System.out.format("Today: %s; previous working day: %s.%n", today, previousWorkingDay);

Вывод при запуске сегодня:

Сегодня: 21.06.2021; предыдущий рабочий день: 2021-06-18.

Предупреждение: если пользователь настроит все 7 дней недели как выходные (звучит красиво, не так ли?), код будет выполняться в бесконечном цикле. Поэтому установите разумное ограничение на количество дней, которые они могут настроить.

person Ole V.V.    schedule 21.06.2021