Issue
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.
Solution
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));
}
}
Answered By - Eng.Fouad
Answer Checked By - Robin (JavaFixing Admin)