java - 在 HijrahChronology 中配置自定义变体以进行日期校正 jdk 8

标签 java javafx java-8 javafx-8 java-time

我在 javafx - JDK 8 中使用了 DatePicker 并使用了 HijrahChronology.INSTANCE - 这样日期选择器就会同时显示日历 - 一切正常,但我在公历和回历之间有 1 天的差异。回历倒退 1 天。

我正在尝试根据以下链接更改变体 https://bugs.openjdk.java.net/browse/JDK-8187987

却无法成功。请解释或引用更好或更明确的解决方案。

代码:

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

dateOfTransaction是JavaFx中DatePicker的实例 我没有使用过 Joda Time,我也不想使用,除非那是唯一的解决方案。

最佳答案

不幸的是,Java(8 到 10)不支持在运行时提供自定义 Hijrah 变体(这是我几个月前提交的相关错误报告:https://bugs.openjdk.java.net/browse/JDK-8187987)。

但是,有 2 个解决方法:

1- 操纵 JRE 附带的默认 hijrah 变体。在 Java 8 中,您可以在以下位置找到它:

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

在 Java 9 和 10 中,它被捆绑在这个位置:

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

2- 您可以使用反射 API 在运行时注入(inject)自定义 Hijrah 变体:

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

关于java - 在 HijrahChronology 中配置自定义变体以进行日期校正 jdk 8,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51016469/

相关文章:

java - 使用jar库包编译并执行java程序

java - 这段代码中的 AtomicBoolean 是否矫枉过正?

JavaFX UI 创建和进度条更新

java-8 - Java Collector.combiner 总是被供应商值调用

java - 为什么在这种情况下,单参数实例方法对 BiConsumer 的类型推断不同?

java - 使用 java 在 Apache Spark 中以平面列表形式获取单列值

java - jMeter 按条件发送 http 请求

java - 如何在 Gomoku javafx 游戏中启用轮流

java - 使用流优化列表遍历

java - 在 GWT 中比较两个 JavaScriptObject 的最佳方法是什么?