-1

Most of the regions in the world consider Saturday and Sunday as Weekends which means Monday to Friday are considered as weekdays. However, in middle-eastern countries, Friday and Saturday are considered as Weekends whereas Sunday to Thursday are considered as weekdays.

Is there an elegant way in java to lookup a previous weekday based on the currency type and current day?

For example, Consider current day is 21-JUN-2021

For middle-eastern currency, the weekday should be 20-JUN-2021 For all other currencies, the weekday should be 18-JUN-2021.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Sandy
  • 459
  • 2
  • 6
  • 19
  • `Locale` is the driver for determining weekend/weekdays. – Basil Bourque Jun 21 '21 at 17:50
  • I found a very similar question [here](https://stackoverflow.com/questions/52365194/how-to-get-the-first-day-of-week-for-a-certain-locale-country) in that it helps you to find the start of the week for a given Locale – Joe Ciaramitaro Jun 21 '21 at 17:52
  • This seems very fragile and likely to go wrong for most uncommon currencies. Use a different way to figure out which days are weekday and weekend. If in doubt, let the user decide and add a setting. – Clashsoft Jun 21 '21 at 17:59
  • I think by currency, you mean `Locale`. With the standard API, you will get `SUNDAY` as the first day of the week. Check `System.out.println(WeekFields.of(new Locale("ar", "SA")).getFirstDayOfWeek())`. I think you may need to use a 3rd party library or write your own. – Arvind Kumar Avinash Jun 21 '21 at 18:02
  • I suspect that you will find places on the earth where there isn’t any hard rule for when the weekend is or even how many days it lasts. (As an aside you will also find places where the week has a length different from 7 days.) – Ole V.V. Jun 21 '21 at 21:18

2 Answers2

2

There isn't, and not because of missing APIs, but because of fundamental issues.

Currency and weekdays have absolutely no relationship whatsoever. Clearly, asking to go from currency to the concept of weekday/weekend directly is crazy talk.

You're looking for an indirect path. But, the steps along that path don't work.

The general path you're looking for is:

  • Go from currency to a locale.
  • Go from locale to a view on weekdays (which are 'weekend' days, which day is considered first day of the week).

Both steps are essentially impossible. At best there are maintenance nightmare hacks and handwritten lists.

The second step is hard because the concept of which days are considered weekends are not baked into the APIs - there simply is no way to ask e.g. any class in the java.time package, even if you have a locale, which days are weekend days.

The first step is hard as well. The step 'locale -> currency' mostly works, but it's not reversible. For example, mainland europe has a ton of locales, but only one currency. Thus, trying to go from "EURO" to "which locale is that?" is not a single answer, but would look like a sizable list.

This is your best shot:

  • Go from 1 currency to all locales that use that currency.
  • Check if all locales have a unified idea on which days are weekends. This involves maintaining a list yourself.
  • If they all are in total agreement, you now have an answer.
  • If they are not, you just have to abort or otherwise return 'I do not know' as an answer.
  • All code that calls this 'gimme the weekend days for this currency' needs to account for the fact that 'dunno' may fall out (you could default to sunday/saturday, but if you explain to somebody that the algorithm will intelligently figure out the right day, you'd be lying. It can only do that some of the time).
  • Armed with knowledge of what days are weekend, you can do the calculation, which is easy.
  • You'll need to take into consideration that locales are free to switch both currency as well as their notion of what constitutes 'weekend' changes over time. For example, before 2002, the currency for locale nl-NL was the dutch guilder. Afterwards, it was the euro.
  • Just about every locale has a notion of government-officially-mandated holidays, which are treated as weekends for the vast majority of any question you care to ask that needs special weekend treatment: Governments are closed, public transport runs on the sunday schedule, all businesses that are open on weekdays but closed on weekends are closed, restaurants with special tariffs in the weekend will be charging the special tariff or even more, etcetera.
  • Sometimes holidays are extremely hard to calculate, such as easter. Sometimes holidays are literally impossible to calculate, because they depend on a panel decision that only arrives a few days before the supposed holiday. Such as Eid al-Fitr, which has a fixed date of 'first day of the month Shawwal', but that's on the arabic calendar, which is lunar (vs. the gregorian (western) calendar, which is solar), and translating "1st of Shawwal" to a gregorian date is not possible as it depends on e.g. observing the crescent moon somewhere in a large area. Still, cloud cover exists, so to know if something is effectively a 'weekend' (banks closed, etc) next year, you need to predict the weather a year in advance. good luck with that.

If I haven't dissuaded you yet, I'm losing my edge.

But, hey, if you wanna go on:

If that is palatable to you (an algorithm that will attempt to answer the question 'given this currency, tell me about which days are considered weekends' - but it will often answer "I do not know"), you could write it. It's non-trivial because generally speaking nobody wants this algorithm (the whole 'often it cannot tell you' part is the problem. Nobody likes it if the app just flat out doesn't work in many places, and a lot of the convenience is gone if all the algorithm can give you is a nice default for some setting at best).

How did you get at currency in the first place? If you got a currency from a locale, then take that locale and go from there, that's much, much simpler.

Make a currency to locale map

Relevant operations:

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

java.util.Currency.getInstance(someLocale);

You don't actually want Currency.getInstance, you want the reverse (currency to locale, not locale to currency). This method does not exist. You'd have to make a Map<Currency, List<Locale>> first (and this is a pricey operation, so do it once and cache the results in memory).

You'll get a ton of overlap. It'll look something like:

/**
 * 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;
}

Do a lookup for a currency

Given a currency, fetch the list of locales (use thatMap.getOrDefault(theCurrency, List.of())), and throw it through your 'give me the weekends' algorithm, which is a convoluted mess I leave to you that optimally cannot just answer based on a locale, but needs to know the weather, have an engine to determine easter, all the other weird religious holidays I didn't manage to think of, and needs to include the date around which you wanna know, given that locales switch official holidays and currencies and the like.

So, how you write that - beats me. But if you have it, throw all locales through there, and check if you get a single set of answers.

How do I determine the weekend days given a locale?

You'd have to write that yourself. Start with a list of locales. Read up on easter and eid-al-fitr. Accept it'll never be perfect.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
0

I suggest that you have the user configure which days they consider belonging to the weekend. For example:

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

Output when running today:

Today: 2021-06-21; previous working day: 2021-06-18.

Warning: if the user configures all 7 days of the week as weekend (sounds nice, doesn’t it?), the code will run in an infinite loop. So put a reasonable limit on how many days they may configure.

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