参见SO 15728744和SO 51058875。
以下内容如何正确:
LocalDate gregorianDate = LocalDate.parse(gregorianString, dateFormatter);
HijrahDate islamicDate = HijrahDate.from(gregorianDate);
我以为回教日在日落而不是午夜结束,因此应该使用gregorianDateTime。
最佳答案
您是对的,回历日历是在上一个西方日的日落开始的日子。您还可以说标准Java不支持它。
为什么?
我搜索了旧的Threeten存档,但一无所获。但是,java.time
-API的主要开发人员和架构师曾经在documentation of the ancestor Joda-Time的以下句子中指出:
此实现将一天定义为从午夜到午夜,与
按照ISO年表。正确的开始时间是日落时
前一天,但是这不能轻易建模并且已经
忽略了。
我的猜测是:为什么java.time
不在伊斯兰历法转换中也考虑了一天中的时间,所以也是出于同样的动机。主要由于需要天文计算而难以实施。
如何处理此缺陷?
在标准Java范围内,建议用户尽可能忽略一天中的时间。因此,请记住,此类转换是无时间的抽象。当然,如果您想确定当前日期(间接涉及一天中的时间和民用时区),那么这种转换或多或少都是错误的!
如果您不想在开始时忽略日落...
...然后您可以使用我的库Time4J(而且我不知道其他任何可以在一天开始时处理日落的库)。请注意HijriCalendar类的文档。从瞬间/即时到回历日历日期的generic conversion的示例:
// 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()));