Как преобразовать григорианскую дату в исламскую (хиджру) дату без времени?

См. SO 15728744 и SO 51058875.

Как может быть правильным следующее:

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

Я думал, что день хиджры заканчивается закатом, а не полночью, поэтому нужно было указать gregorianDateTime.


person Jonathan Rosenne    schedule 21.04.2019    source источник
comment
Он просто сообщает вам в целом, какая дата является той же датой. Если вы хотите быть точным, вам понадобится больше, чем местная дата и время — вам также нужно время заката, а это значит, что вам нужно точное мгновенное и географическое местоположение.   -  person RealSkeptic    schedule 21.04.2019
comment
Универсального соглашения по календарю нет, поэтому Java выбрала официальный календарь Саудовской Аравии и допускает некоторые варианты. Аналогичное решение может быть принято в отношении захода солнца. Некоторые мусульмане в Европе используют время заката в Саудовской Аравии, некоторые используют местное время заката.   -  person Jonathan Rosenne    schedule 21.04.2019
comment
@JonathanRosenne Похоже, ваш комментарий — это ваш собственный ответ.   -  person Basil Bourque    schedule 21.04.2019
comment
Но это не так, как это реализовано в Java.   -  person Jonathan Rosenne    schedule 21.04.2019


Ответы (2)


Вы правы в том, что дни календаря хиджры начинаются с заходом солнца в предыдущий западный день. Вы также правы, говоря, что стандартная Java не поддерживает его.

Почему?

Я искал в старых Threeten-архивах, но ничего не нашел. Однако главный разработчик и архитектор java.time-API однажды заявил в документация предка Joda-Time следующим предложением:

Эта реализация определяет день от полуночи до полуночи точно в соответствии с хронологией ISO. Это правильное начало дня приходится на закат предыдущего дня, однако это нельзя легко смоделировать, и оно было проигнорировано.

Мое предположение таково: та же самая мотивация была также ответственна за то, что java.time не принимает во внимание время суток при преобразованиях в исламский календарь или из него. Его трудно реализовать главным образом потому, что он требует астрономических расчетов.

Как справиться с этим недостатком?

В рамках стандартной Java пользователям рекомендуется максимально игнорировать время суток. Поэтому имейте в виду, что такие преобразования являются абстракциями, не зависящими от времени. Конечно, если вы хотите определить ТЕКУЩИЙ день (что косвенно включает в себя время суток и гражданский часовой пояс), то такие преобразования более или менее ошибочны!

Если вы не хотите игнорировать закат как начало дня...

... тогда вы можете использовать мою библиотеку Time4J (и я не знаю никакой другой библиотеки, которая может обрабатывать закат как начало дня). Обратите внимание на документацию класса HijriCalendar. Пример для общее преобразование момента/мгновения в календарную дату по хиджре:

// 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 также содержит механизм форматирования, который может анализировать дату и время по григорианскому календарю или по календарю хиджры разными способами. Начало дня на закате также можно учитывать при форматировании и анализе на основе ChronoFormatter.

Обратное преобразование даты календаря Хиджры в момент также поддерживается. Пример:

HijriCalendar hcal = ...;
Moment m = 
  hcal.atTime(18, 45).in(Timezone.ofSystem(), StartOfDay.definedBy(meccaTime.sunset()));
person Meno Hochschild    schedule 26.05.2019

В документах Java упоминается, что класс LocalDate не учитывает время.

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

Этот класс не хранит и не представляет время или часовой пояс. Вместо этого это описание даты, используемой для дней рождения.

Рассмотрите возможность использования LocalDateTime для вашего требования.

person Shubham Kadlag    schedule 21.04.2019
comment
Это именно моя точка зрения. Без времени невозможно конвертировать между хиджрским и григорианским календарями. - person Jonathan Rosenne; 21.04.2019
comment
Я понимаю вашу точку зрения. Но вы можете указать одно и то же для разных часовых поясов. Учтите, что сейчас 21 апреля 2019 года в Индии, это не обязательно означает, что это 21 апреля 2019 года в Чикаго, поскольку это также может быть 20 апреля 2019 года. Но класс LocalDate не учитывает время, он учитывает только абсолютную дату. Так что время здесь не имеет значения. - person Shubham Kadlag; 21.04.2019
comment
Итак, если я изменю вопрос, чтобы использовать ZonedDate, который работает в упомянутой вами ситуации, это поможет? - person Jonathan Rosenne; 21.04.2019