得到回历日期字符串阳历日期 [英] Get a gregorian date from Hijri date strings

查看:291
本文介绍了得到回历日期字符串阳历日期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想获得从回历日期指数法阳历日期。

I would like to get a gregorian date from the Hijri date indexs.

例如

getDate(1436, "SHawwal", 18)

这应该返回

3rd August 2015

我怎么能这样做的转换?

How could I do the conversion ?

推荐答案

我很遗憾,你是不明智的。很多人盲目地推荐知名的库,例如乔达时,甚至没有检查,如果这能解决你的问题,并满足您的要求

I regret that you were ill advised. Many people blindly recommend well-known libraries like Joda-Time without even checking if this can solve your problem and fit your requirements.

哪些要求?您已经指出:

值的元组(1436的Shawwal,18)=>阳历日期为String(第三
  2015年8月)

value tuple (1436, "SHawwal", 18) => gregorian date as String ("3rd August 2015")

让我们首先证明的乔达时是不能够这样做的转换。的Shawwal(شوال)是伊斯兰农历十月份。因此,我们可以试试这个乔达时code:

Let's first demonstrate that Joda-Time is not capable of doing this conversion. Shawwal ("شَوّال") is the tenth month of islamic lunar calendar. So we can try this Joda-Time code:

Chronology hijri = 
  IslamicChronology.getInstance(DateTimeZone.UTC, IslamicChronology.LEAP_YEAR_INDIAN);
LocalDate dtHijri = new LocalDate(1436, 10, 18, hijri);

Chronology iso = ISOChronology.getInstanceUTC();
LocalDate dtIso = // Joda does not offer a direct conversion, sorry
  dtHijri.toDateTimeAtStartOfDay(DateTimeZone.UTC)
  .withChronology(iso).toLocalDate(); 
System.out.println("hijri-to-gregorian: " + dtHijri + "=>" + dtIso); 
// hijri-to-gregorian: 1436-10-18=>2015-08-04

由乔达时(LEAP_YEAR_15_BASED,LEAP_YEAR_16_BASED,LEAP_YEAR_HABASH_AL_HASIB或LEAP_YEAR_INDIAN)提供的所有闰年模式产生相同的结果2015年8月4日,这是一天中最多超出你的期望更高版本。我已经明确地测试了所有四个闰年模式。

All leap year patterns offered by Joda-Time (LEAP_YEAR_15_BASED, LEAP_YEAR_16_BASED, LEAP_YEAR_HABASH_AL_HASIB or LEAP_YEAR_INDIAN) yield the same result "2015-08-04" which is one day later than your expectation. And I have explicitly tested all four leap year patterns.

与Java 8的方法吗?

HijrahDate hd = HijrahChronology.INSTANCE.date(HijrahEra.AH, 1436, 10, 18);
LocalDate ld = LocalDate.from(hd);
System.out.println("java-8: " + ld); // java-8: 2015-08-03

这是好的,但我认为你需要在Android这项工作。还有,因为Java的8类根本就没有用,你会失败。

That is fine, but I assume you need to make this work on Android. And there you would fail because the Java-8-classes are simply not available.

顺便说一句:为什么Java的8产量正确的结果吗?它使用在沙特阿拉伯的Umalqura日历的数据,同时乔达时使用伊斯兰教历的四个半学术近似。事实上,伊斯兰历许多当地的变种存在(我的评论上面已经针对这点问你要使用的变量)。

By the way: Why does Java-8 yield the right result here? It uses the data of the Umalqura-calendar in Saudi-Arabia while Joda-Time uses four half-academic approximations of islamic calendar. In fact, the islamic calendar exists in many local variants (and my comment above had targeted this point to ask you which variant you want to use).

所以,将 ThreetenABP 做到这一点,因为它被认为是 java.time 的一个补丁包(JSR-310)在Android?

So will ThreetenABP do it since it is supposed to be a backport of java.time (JSR-310) on Android?

HijrahDate hd = HijrahChronology.INSTANCE.date(HijrahEra.AH, 1436, 10, 18);
org.threeten.bp.LocalDate ld = org.threeten.bp.LocalDate.from(hd);
System.out.println("threeten-bp: " + ld); // threeten-bp: 2015-08-04

令人惊讶的是反向移植失败。如果你看出来ThreetenBP的文档和 Java的关于回历8 然后你会看到一个很大的区别。 ThreetenBP 不使用Umalqura日历!这事实上是相当于LEAP_YEAR_16_BASED乔达时的闰年格局。嗯,(尴尬)解决方法可以配置ThreetenBP,这样你通过定义描述配置文件的此处。但我强烈怀疑这只会对Java的平台上工作,因为 ThreetenABP (ThreetenBP的Andr​​oid的迁移)不关心一个给定的Andr​​oid应用程序的资产目录定义这样的文件。

Surprisingly the backport fails. If you watch out the documentations of ThreetenBP and Java-8 regarding the Hijri calendar then you will see a big difference. ThreetenBP does NOT use the Umalqura calendar! It is de facto equivalent to the leap year pattern LEAP_YEAR_16_BASED of Joda-Time. Well, as (awkward) workaround you could configure ThreetenBP such that you tell the deviations by defining a configuration file described here. But I strongly suspect this would only work on Java-platforms because ThreetenABP (the Android migration of ThreetenBP) does not care about defining such a file in the assets-directory of a given Android app.

什么ICU4J?

ICU4J(统一为code国际组件)似乎工作,至少有三个的变种:伊斯兰,ISLAMIC_TBLA和ISLAMIC_UMALQURA。所有3变种产生2015年8月3日。因此,你必须仔细决定使用哪一个,因为这些变异会在其他日子不同!关于TBLA变,是类似于乔达时的LEAP_YEAR_16_BASED(但使用星期四划时代 - 一日差所有的时间)的半学术近似。所谓的伊斯兰变体是月亮周期的简化天文模拟。我怀疑你而想沙特阿拉伯的Umalqura日历,右???

ICU4J (International components for Unicode) seems to work, at least with three variants: ISLAMIC, ISLAMIC_TBLA and ISLAMIC_UMALQURA. All 3 variants yield "2015-08-03". So you have to carefully decide which one to use because these variants will differ on other days! About the TBLA-variant, that is a half-academic approximation similar to LEAP_YEAR_16_BASED of Joda-Time (but using Thursday epoch - one day difference all the time). The variant called ISLAMIC is a simplified astronomical simulation of moon cycles. My suspicion you rather want the Umalqura-calendar of Saudi-Arabia, right???

总之,ICU4J有一个很大的缺点。它不是精心设计的Andr​​oid平台和非常大(10.7兆字节)。有些人已经向一直无法运行在Android软件。

Anyway, ICU4J has one big disadvantage. It is not well designed for the Android platform and very big (10.7 MByte). Some people have reported to have not been able to run that software on Android.

我的建议:使用Time4A

我对Android平台的回历当前支持分析的结果是开发一种称为 Time4A <替代库/ A>,以帮助使用该平台上的回历的人,太多。这个库(版本v3.6-2015f)支持8个半学术闰年模式包括tbla变(HijriAlgorithm.WEST_ISLAMIC_ASTRO),沙特阿拉伯的Umalqura日历和ICU4J的天文仿真。而且重要的是:Time4A也会明白阿拉伯语月份名称(使用新区域(AR))。例如:

The result of my analysis of current support for Hijri calendar on Android platform has been to develop an alternative library called Time4A to help people using the Hijri calendar on that platform, too. This library (version v3.6-2015f) supports 8 half-academic leap year patterns including the tbla-variant (HijriAlgorithm.WEST_ISLAMIC_ASTRO) , the Umalqura-calendar of Saudi-Arabia and the astronomical simulation of ICU4J. And important: Time4A will also understand Arabic month names (using new Locale("ar")). Example:

HijriCalendar hijri = 
  HijriCalendar.of(HijriCalendar.VARIANT_UMALQURA, 1436, HijriMonth.SHAWWAL, 18);
PlainDate iso = hijri.transform(PlainDate.class);
System.out.println("Time4A: " + iso); // Time4A: 2015-08-03

现在最后的code溶液处理一些古怪的您的要求:

Now the final code solution handling some oddities in your requirements:

int hijriYear = 1436;
String hijriMonth = "SHawwal";
int hijriDayOfMonth = 18;

ChronoFormatter<HijriCalendar> inputFormat =
        ChronoFormatter.setUp(HijriCalendar.class, Locale.ENGLISH)
        .addPattern("yyyyMMMMd", PatternType.NON_ISO_DATE).build();
HijriCalendar hijriDate = 
        inputFormat
        .with(Attributes.PARSE_CASE_INSENSITIVE, true)
        .withCalendarVariant(HijriCalendar.VARIANT_UMALQURA)
        .parse(hijriYear + hijriMonth + hijriDayOfMonth);

PlainDate iso = hijriDate.transform(PlainDate.class);

ChronoFormatter<PlainDate> outputFormat =
    ChronoFormatter.setUp(PlainDate.class, Locale.ENGLISH)
        .addEnglishOrdinal(PlainDate.DAY_OF_MONTH)
        .addPattern(" MMMM uuuu", PatternType.CLDR).build();
String s = outputFormat.format(iso);
System.out.println(s); // 3rd August 2015

但你仍然需要考虑这回历的变种你真正想要的。没有智能软件可以决定这个给你。

But you still need to think about which variant of Hijri calendar you really want. No intelligent software can decide this for you.

这篇关于得到回历日期字符串阳历日期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆