java.time
java.time, the modern Java date and time API, can do this:
DateTimeFormatter hijrahFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy")
.withChronology(HijrahChronology.INSTANCE);
try {
HijrahDate date = hijrahFormatter.parse("30/02/1403", HijrahDate::from);
System.out.println("A valid date: " + date);
} catch (DateTimeParseException dtpe) {
System.out.println("Not a valid date: " + dtpe.getMessage());
}
The output from this snippet is:
A valid date: Hijrah-umalqura AH 1403-02-30
Format pattern letters are case sensitive. You need lowercase yyyy
for calendar year (or uuuu
for proleptic year).
Java 6? Three options.
I want to validate in Java 6. I can't use in Java 8.
That’s old now (Java 11 is out). My suggestions are:
- Use ThreeTen Backport, the backport of java.time to Java 6 and 7. It turns out that it doesn’t work perfectly for your case, but you can.
- Use Joda-Time as you asked about from the outset.
- Use Time4J.
The first two options will reject your date of 30/02/1403, though, believing there are only 29 days in the 2nd month of 1403.
ThreeTen Backport
DateTimeFormatter hijrahFormatter = DateTimeFormatter.ofPattern("dd/MM/uuuu")
.withChronology(HijrahChronology.INSTANCE);
String dateString = "30/02/1403";
try {
TemporalAccessor parsed = hijrahFormatter.parse(dateString);
HijrahDate date = HijrahChronology.INSTANCE.date(parsed.get(ChronoField.YEAR),
parsed.get(ChronoField.MONTH_OF_YEAR),
parsed.get(ChronoField.DAY_OF_MONTH));
if (date.format(hijrahFormatter).equals(dateString)) {
System.out.println("A valid date: " + date);
} else {
System.out.println("Not a valid date: " + dateString);
}
} catch (DateTimeParseException dtpe) {
System.out.println("Not a valid date: " + dtpe.getMessage());
}
Output:
Not a valid date: 30/02/1403
According to my understanding the following simpler way to construct the date ought to work, but doesn’t:
HijrahDate date = HijrahDate.from(parsed);
I get org.threeten.bp.DateTimeException: Field not found: EpochDay
. The way I construct the date instead is lenient, that is, it accepts that the day of month is out of range and produces a date of Hijrah-umalqura AH 1403-03-01
. So to complete the validation I format the date back and require that I get the original string again.
If instead of 30/02/1403
I try with 29/02/1403
, I get
A valid date: Hijrah-umalqura AH 1403-02-29
Joda-Time
DateTimeFormatter islamicFormatter = DateTimeFormat.forPattern("dd/MM/yyyy")
.withChronology(IslamicChronology.getInstance());
try {
LocalDate date = LocalDate.parse("30/02/1403", islamicFormatter);
System.out.println("A valid date: " + date);
} catch (IllegalArgumentException iae) {
System.out.println("Not a valid date: " + iae.getMessage());
}
Joda-Time too thinks there are 29 days in this month and states that very clearly:
Not a valid date: Cannot parse "30/02/1403": Value 30 for dayOfMonth
must be in the range [1,29]
With a string of 29/02/1403
I got:
A valid date: 1403-02-29
Joda-Time’s Islamic chronology comes with four different leap year patterns. I tried all four. They all yield 29 days in the second month of 1403. I am sorry, this as close as I can get.
From the Joda-Time homepage:
Note that Joda-Time is considered to be a largely “finished” project.
No major enhancements are planned. If using Java SE 8, please migrate
to java.time
(JSR-310).
Time4J
I refer you to the knowledgeable answer by Meno Hochschild, the author of Time4J. It would seem to me that Time4J version 3.50 solves your issue according to your requirements and on Java 6.
But is that date valid or not?
But If you will check the Islamic calendar it is a valid date of 2nd month.
You’re much more an expert than I am. I seem to understand that variants of the Hijri calendar exist. According to your variant 30/02/1403 is a perfectly valid date. The version given by alhabib Islamic web services agrees with yours: Safar 30, 1403 is the same day as December 16, 1982 in the Gregorian calendar. On the other hand according to searchtruth.com, there are only 29 days in the month of Safar 1403 (Safar 29, 1403 corresponds to December 15, 1982 Gregorian and is followed by Rabi Al-Awwal 1, 1403 corresponding to December 16).
Links