3

See SO 15728744 and SO 51058875.

How can the following be correct:

LocalDate gregorianDate = LocalDate.parse(gregorianString, dateFormatter);
HijrahDate islamicDate = HijrahDate.from(gregorianDate);

I thought that the Hijri day ends at sunset, not at midnight, so a gregorianDateTime should have been required.

Harish
  • 1,433
  • 9
  • 21
Jonathan Rosenne
  • 2,159
  • 17
  • 27
  • 4
    It merely tells you in general which date is the same date. If you want to be precise, you'll need more than a local date and time - you also need the time of sunset, which means you need a precise instant and geographic location. – RealSkeptic Apr 21 '19 at 14:14
  • 1
    There is no universal agreement on the calendar, so Java selected the Saudi official calendar and allows some options. A similar solution could be adopted regarding sunset. Some Muslims in Europe use the Saudi sunset times, some use the local sunset times. – Jonathan Rosenne Apr 21 '19 at 14:27
  • @JonathanRosenne Seems like your Comment is your own Answer. – Basil Bourque Apr 21 '19 at 17:10
  • But this isn’t how Java has implemented it. – Jonathan Rosenne Apr 21 '19 at 17:12

2 Answers2

2

You are right that the Hijri calendar starts days at sunset on previous western day. You are also right to say that standard Java does not support it.

Why?

I have searched in old Threeten-archives but found nothing. However, the main developer and architect of java.time-API has once stated in the documentation of the ancestor Joda-Time following sentence:

This implementation defines a day as midnight to midnight exactly as per the ISO chronology. This correct start of day is at sunset on the previous day, however this cannot readily be modelled and has been ignored.

My speculation is: The same motivation was also responsible why java.time does not take into account the time of day in conversions to or from islamic calendar. It is difficult to implement mainly because it requires astronomical calculations.

How to handle this deficiency?

In the scope of standard Java, users are advised to ignore the time of day as much as possible. So please keep in mind that such conversions are time-free abstractions. Of course, if you want to determine the CURRENT day (which indirectly involves the time of day and civil time zone) then such conversions are more or less faulty!

If you don't want to ignore sunset as start of day...

... then you can use my library Time4J (and I don't know any other lib which can handle sunset as start of day). Watch out the documentation of class HijriCalendar. Example for a generic conversion from a moment/instant to a Hijri calendar date:

// the geographic location
SolarTime meccaTime = SolarTime.ofLocation(21.4225, 39.826111); 
// or even simple: meccaTime = SolarTime.ofMecca()

// the moment to be converted
Moment now = SystemClock.currentTime();
// alternative using an explicit gregorian date:
//   now = PlainDate.of(2019, 5, 26).atTime(18, 45).inStdTimezone();
// alternative using modern Java: 
//   now = Moment.from(Instant.now());
// alternative using outdated old API: 
//   java.util.Date instant = new java.util.Date();
//   now = TemporalType.JAVA_UTIL_DATE.translate(instant);

// the conversion
HijriCalendar hcal = now.toGeneralTimestamp(
  HijriCalendar.family(),
  HijriCalendar.VARIANT_UMALQURA, // attention: there is no single islamic calendar
  Timezone.ofSystem().getID(), // or use something like: ()-> "Europe/London"
  StartOfDay.definedBy(meccaTime.sunset()));

Time4J also contains a format engine which is capable of parsing either gregorian dates or Hijri calendar date-times in many ways. The start of day at sunset can be taken into account also during formatting and parsing based on ChronoFormatter.

The reverse conversion from a Hijri calendar date to a moment is also supported. Example:

HijriCalendar hcal = ...;
Moment m = 
  hcal.atTime(18, 45).in(Timezone.ofSystem(), StartOfDay.definedBy(meccaTime.sunset()));
Meno Hochschild
  • 42,708
  • 7
  • 104
  • 126
0

It is mentioned in Java docs that LocalDate class does not consider time.

Refer : https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html

This class does not store or represent a time or time-zone. Instead, it is a description of the date, as used for birthdays.

Consider using LocalDateTime for your requirement.

Shubham Kadlag
  • 2,248
  • 1
  • 13
  • 32
  • This is precisely my point. Without the time it is not possible to convert between the Hijri and Gregorian calendars. – Jonathan Rosenne Apr 21 '19 at 14:16
  • I understand your point. But you can point out the same thing for different timezone. Consider that it is 21/04/2019 in India, it does not necessary mean that it is 21/04/2019 in Chicago as it can also be 20/04/2019. But the LocalDate class does not consider any time, it only considers absolute date. So time doesn't matter here. – Shubham Kadlag Apr 21 '19 at 14:25
  • So if I change the question to use ZonedDate, which works for the situation you mentioned, will it help? – Jonathan Rosenne Apr 21 '19 at 14:30