configure a custom variant in HijrahChronology for date correction jdk 8

拥有回忆 提交于 2020-01-02 09:58:27

问题


I have used DatePicker in javafx - JDK 8 and used HijrahChronology.INSTANCE - so that the date picker shows both the calendar - everything work good enough but I am having a difference of 1 day between gregorian calendar and hijri calendar. Hijri Calendar is 1 day backward.

I am trying to change the variant as per the following link https://bugs.openjdk.java.net/browse/JDK-8187987

but unable to succeed in it. Kindly explain or refer a better or a clear solution to this issue.

Code:

HijrahChronology hijriChronology = HijrahChronology.INSTANCE;
    dateOfTransaction.setChronology(hijriChronology);

dateOfTransaction is the instance of DatePicker in JavaFx I have not used Joda Time, neither I wish to, unless that is the only solution.


回答1:


Unfortunately, Java (8 to 10) does not support providing custom Hijrah variant at runtime (here is the related bug report I submitted few months ago: https://bugs.openjdk.java.net/browse/JDK-8187987).

However, there are 2 workarounds:

1- Manipulate the default hijrah variant shipped with the JRE. In Java 8, you can find it at this location:

C:\Program Files\Java\jdk1.8.0_162\jre\lib\hijrah-config-umalqura.properties

In Java 9 and 10, it is bundled at this location:

/java/time/chrono/hijrah-config-islamic-umalqura.properties

2- You can inject custom Hijrah variant at runtime using Reflection API:

public static void injectCustomHijriVariant(Map<Integer, int[]> yearMonthsMap, long isoStartDate)
        throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException
{
    int minYear = Integer.MAX_VALUE;
    int maxYear = Integer.MIN_VALUE;

    for(int year : yearMonthsMap.keySet())
    {
        maxYear = Math.max(maxYear, year);
        minYear = Math.min(minYear, year);
    }

    int isoStart = (int) LocalDateTime.ofInstant(Instant.ofEpochMilli(isoStartDate),
                                                 ZoneId.systemDefault()).toLocalDate().toEpochDay();

    Field initCompleteField = HijrahChronology.class.getDeclaredField("initComplete");
    initCompleteField.setAccessible(true);
    initCompleteField.set(HijrahChronology.INSTANCE, true);

    Field hijrahStartEpochMonthField = HijrahChronology.class.getDeclaredField("hijrahStartEpochMonth");
    hijrahStartEpochMonthField.setAccessible(true);
    hijrahStartEpochMonthField.set(HijrahChronology.INSTANCE, minYear * 12);

    Field minEpochDayField = HijrahChronology.class.getDeclaredField("minEpochDay");
    minEpochDayField.setAccessible(true);
    minEpochDayField.set(HijrahChronology.INSTANCE, isoStart);

    Method createEpochMonthsMethod = HijrahChronology.class.getDeclaredMethod("createEpochMonths", int.class,
                                                                              int.class, int.class, Map.class);
    createEpochMonthsMethod.setAccessible(true);
    int[] hijrahEpochMonthStartDays = (int[]) createEpochMonthsMethod.invoke(HijrahChronology.INSTANCE, isoStart, minYear, maxYear, years);

    Field hijrahEpochMonthStartDaysField =
                                        HijrahChronology.class.getDeclaredField("hijrahEpochMonthStartDays");
    hijrahEpochMonthStartDaysField.setAccessible(true);
    hijrahEpochMonthStartDaysField.set(HijrahChronology.INSTANCE, hijrahEpochMonthStartDays);

    Field maxEpochDayField = HijrahChronology.class.getDeclaredField("maxEpochDay");
    maxEpochDayField.setAccessible(true);
    maxEpochDayField.set(HijrahChronology.INSTANCE, hijrahEpochMonthStartDays[hijrahEpochMonthStartDays.length - 1]);

    Method getYearLengthMethod = HijrahChronology.class.getDeclaredMethod("getYearLength", int.class);
    getYearLengthMethod.setAccessible(true);

    Field minYearLengthField = HijrahChronology.class.getDeclaredField("minYearLength");
    minYearLengthField.setAccessible(true);

    Field maxYearLengthField = HijrahChronology.class.getDeclaredField("maxYearLength");
    maxYearLengthField.setAccessible(true);

    for(int year = minYear; year < maxYear; year++)
    {
        int length = (int) getYearLengthMethod.invoke(HijrahChronology.INSTANCE, year);
        int minYearLength = (int) minYearLengthField.get(HijrahChronology.INSTANCE);
        int maxYearLength = (int) maxYearLengthField.get(HijrahChronology.INSTANCE);
        minYearLengthField.set(HijrahChronology.INSTANCE, Math.min(minYearLength, length));
        maxYearLengthField.set(HijrahChronology.INSTANCE, Math.max(maxYearLength, length));
    }
}


来源:https://stackoverflow.com/questions/51016469/configure-a-custom-variant-in-hijrahchronology-for-date-correction-jdk-8

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!