代码之家  ›  专栏  ›  技术社区  ›  Farhan stands with Palestine

Joda time-IllegalFieldValueException:dayOfMonth的值30必须在[1,29]范围内

  •  1
  • Farhan stands with Palestine  · 技术社区  · 7 年前

    有一个对某个外部系统的调用,该系统返回hijri中的日期。在Production env中,我们将其作为 '30-02-1436' .

    考虑一下将回历转换为公历日期的片段,但它没有做到这一点。

        public static String convertHijriToGregorianDate(String hijriDate){
            Chronology iso = ISOChronology.getInstanceUTC(); // get the ISO standard chronology which we follow now
            Chronology hijri = IslamicChronology.getInstanceUTC(); // the hijri based chronology
            //String hijriDate = "19-08-1435"; // example/format which is received as a parameter in the method from response
    
            if(null != hijriDate && !hijriDate.isEmpty()){
                String[] parts = hijriDate.trim().split("-"); // you will get an array of size 3 by splitting with regex '-'
                String hijriYear = parts[2];
                String hijriMonth = parts[1];
                String hijriDay = parts[0];
    
                // Construct the Local Date corresponding to the hijri chronology
                LocalDate todayHijri = new LocalDate(Integer.parseInt(hijriYear), Integer.parseInt(hijriMonth), Integer.parseInt(hijriDay), hijri);
    
                // Construct the Local Date corresponding to the iso chronology based on the hijri date
                LocalDate todayIso = new LocalDate(todayHijri.toDateTimeAtStartOfDay(), iso);
                return String.valueOf(todayIso);
            }
            return null;
        }
    

    请说明代码有什么问题。我们在stacktrace中得到了这个问题-

    组织。乔达。时间IllegalFieldValueException:dayOfMonth的值30必须 在[1,29]范围内 在org。乔达。时间领域FieldUtils。verifyValueBounds(FieldUtils.java:252) 在org。乔达。时间计时。基本年代学。getDateMidnightMillis(基本年代学。java:632) 在org。乔达。时间计时。基本年代学。getDateTimeMillis0(BasicChronology.java:186) 在org。乔达。时间计时。基本年代学。getDateTimeMillis(基本时态。java:160) 在org。乔达。时间计时。有限年表。getDateTimeMillis(LimitChronology.java:177) 在org。乔达。时间计时。基本年代学。getDateTimeMillis(基本年代学。java:155) 在org。乔达。时间本地日期。(LocalDate.java:457)

    使用的Joda时间版本为 2.9.1

    2 回复  |  直到 7 年前
        1
  •  2
  •   Meno Hochschild    7 年前

    我已经通过表达式检查了乔达时间中所有可用的闰年模式(=4)

    Chronology hijri = 
        IslamicChronology.getInstance(DateTimeZone.UTC, IslamicChronology.LEAP_YEAR_15_BASED);
    

    不幸的是,没有什么对你有效。然而 沙特阿拉伯的《乌马尔古拉历法》认为“30-02-1436”有效

    Joda Time不支持伊斯兰历法的这种变体,因此,除非您愿意迁移到包含umalqura变体的Java-8,否则您不能在这里做任何事情。

    System.out.println(HijrahDate.of(1436, 2, 30)); // Hijrah-umalqura AH 1436-02-30
    
    DateTimeFormatter fh =
        DateTimeFormatter.ofPattern(
            "dd-MM-yyyy",
            Locale.forLanguageTag("en")
        ).withChronology(HijrahChronology.INSTANCE);
    System.out.println(HijrahDate.from(fh.parse(input))); 
    // Hijrah-umalqura AH 1436-02-30
    System.out.println(LocalDate.from(HijrahDate.from(fh.parse(input)))); 
    // 2014-12-22
    

    注意:unicode扩展名 Locale.forLanguageTag("en-u-ca-islamic-umalqura") 不幸的是,在我的实验中似乎不起作用,因此明确指定时间是必要的。

    备选方案:

    如果您无法迁移到Java-8,或者甚至不需要伊斯兰日历的更多功能(例如其他变体,如Joda Time中使用的变体),那么您也可以试试我的库 Time4J :

    String input = "30-02-1436";
    ChronoFormatter<HijriCalendar> hf =
        ChronoFormatter.ofPattern(
            "dd-MM-yyyy",
            PatternType.CLDR,
            Locale.ROOT,
            HijriCalendar.family()
        ).withCalendarVariant(HijriCalendar.VARIANT_UMALQURA).with(Leniency.STRICT);
    System.out.println(hf.parse(input)); // AH-1436-02-30[islamic-umalqura]
    System.out.println(hf.parse(input).transform(PlainDate.axis())); // 2014-12-22
    
        2
  •  1
  •   TRH    5 年前

    日期被解释为2月30日,但本月必须少于30天。这解释了错误消息。因此,请更正输入,使其与可能的日期相对应。

    推荐文章