Search code examples
javajavafxarabicjava-timejavafx-datepicker

Set the first day of the week in JavaFX's DatePicker


Is it possible to change the first day of week on JavaFX's DatePicker when applying Arabic locale? I need to change it from Saturday to Sunday.

enter image description here


Solution

  • I was able to change the first date of the week by injecting the following class within my application:

    package sun.util.resources.ar;
    
    import sun.util.resources.LocaleNamesBundle;
    
    public final class CalendarData_ar_SA extends LocaleNamesBundle
    {
        protected final Object[][] getContents()
        {
            return new Object[][] { { "firstDayOfWeek", "1" }, { "minimalDaysInFirstWeek", "1" } };
        }
    }
    

    enter image description here


    Do not forget to change the default locale:

    public static final Locale SAUDI_AR_LOCALE = new Locale.Builder().setLanguageTag("ar-SA-u-nu-arab").build(); // nu is for numbers
    
    // ....
    
    Locale.setDefault(SAUDI_AR_LOCALE);
    

    EDIT:

    The previous solution does not work on latest updates of Java 8 (u152). The proper way to achieve that is to use something called "Locale Sensitive Service Provider".

    First, create a custom implementation of CalendarDataProvider:

    package io.fouad.utils;
    
    import java.time.DayOfWeek;
    import java.util.Locale;
    import java.util.spi.CalendarDataProvider;
    
    public class ArabicCalendarDataProvider extends CalendarDataProvider
    {
        private static final DayOfWeek FIRST_DAY_OF_WEEK = DayOfWeek.SUNDAY;
    
        @Override
        public int getFirstDayOfWeek(Locale locale)
        {
            return (FIRST_DAY_OF_WEEK.getValue() + 1) % 7;
        }
    
        @Override
        public int getMinimalDaysInFirstWeek(Locale locale)
        {
            return 1;
        }
    
        @Override
        public Locale[] getAvailableLocales()
        {
            return new Locale[]{new Locale("ar", "SA")};
        }
    
        @Override
        public boolean isSupportedLocale(Locale locale)
        {
            return locale != null && "ar".equals(locale.getLanguage()) && "SA".equals(locale.getCountry());
        }
    }
    

    Then create a jar file and package ArabicCalendarDataProvider as a service provider. i.e. The jar file will have the following files:

    META-INF/services/java.util.spi.CalendarDataProvider io/fouad/utils/ArabicCalendarDataProvider.class

    The file java.util.spi.CalendarDataProvider contains the following line:

    io.fouad.utils.ArabicCalendarDataProvider

    Now, in order to make it working you need to install this jar as an extension either by putting the jar into the default extension directory or by passing the following JVM argument at launch time:

    -Djava.ext.dirs=path/to/the/folder/that/contains/the/jar

    Note that in Java 9 the locale sensitive services implementations will work directly if the jar is on the application's classpath.

    Last, you need to modify the order of locale providers used in your application. i.e. pass the following JVM argument:

    -Djava.locale.providers=SPI,CLDR,JRE,HOST

    SPI should be first.

    You can test it as follows:

    DayOfWeek firstDayOfWeek = WeekFields.of(new Locale("ar", "SA")).getFirstDayOfWeek();
    System.out.println("firstDayOfWeek = " + firstDayOfWeek);
    

    In the default behavior the output would be:

    firstDayOfWeek = SATURDAY

    When applying the custom locale provider and put SPI as first one the output would be:

    firstDayOfWeek = SUNDAY

    See: