Java中用于Jalali日历的一个好的日期转换器?

Java中用于Jalali日历的一个好的日期转换器?,java,date,localization,calendar,jalali-calendar,Java,Date,Localization,Calendar,Jalali Calendar,我正在开发一个Java应用程序,我有一个时间戳(在long)。我可以轻松地使用此代码将其更改为公历日期: Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(timeStamp); 但我需要把日期记在Jalali日历上。我搜索了一下,但没有找到任何好的图书馆。您是否知道一个可靠且好的转换库(或从时间戳以Jalali格式创建日期)?我不需要一个实现或算法,因为这个问题有太多的bug,并且有很多规则,我需要一个可

我正在开发一个Java应用程序,我有一个
时间戳
(在
long
)。我可以轻松地使用此代码将其更改为公历日期:

Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timeStamp);
但我需要把日期记在Jalali日历上。我搜索了一下,但没有找到任何好的图书馆。您是否知道一个可靠且好的转换库(或从
时间戳
以Jalali格式创建日期)?我不需要一个实现或算法,因为这个问题有太多的bug,并且有很多规则,我需要一个可靠的解决方案

看看这个:


代码看起来不错,基于maven的项目,有很多单元测试

为了获得更好的本地化和语言支持,通常可以方便地使用IBM的(Unicode国际组件)库

这些API与标准Java API类似,但增加了对本地化和国际化的额外支持(例如,时间和日历问题、排序、格式化规则以及带有适当Unicode支持的正则表达式实现)

要创建波斯日历并以波斯语输出格式化日期,您可以执行以下操作:

import com.ibm.icu.text.DateFormat;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.ULocale;

...

ULocale locale = new ULocale("fa_IR@calendar=persian");

Calendar calendar = Calendar.getInstance(locale);
DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, locale);

System.out.println(df.format(calendar));
这将输出:


چ‍.ش。

我在我的图书馆里用Java开发了自己的波斯语(jalali)日历。该实现部署了算法(至少在公历2129年之前有效-无2025错误)

OP具体问题的解决方案:

// conversion from jalali to gregorian by constructed input
PersianCalendar jalali = PersianCalendar.of(1394, 11, 5);
// or use a safe enum instead of the month number:
// PersianCalendar jalali = PersianCalendar.of(1394, PersianMonth.BAHMAN, 5);

PlainDate gregorian = jalali.transform(PlainDate.class); 
System.out.println(gregorian); // 2016-01-25

// conversion to millis-since-unix (timezone-dependent)
Moment moment1 = gregorian.atStartOfDay().inTimezone(ASIA.TEHRAN);
long millisSinceUnix = TemporalType.MILLIS_SINCE_UNIX.from(moment1);
System.out.println(millisSinceUnix); // 1453667400000L

// conversion of millis-since-unix to jalali (timezone-dependent)
Moment moment2 = TemporalType.MILLIS_SINCE_UNIX.translate(millisSinceUnix);
PlainDate gregorian2 = moment2.toZonalTimestamp(ASIA.TEHRAN).toDate();
System.out.println(gregorian2.transform(PersianCalendar.class)); // AP-1394-11-05

// formatting and parsing in Farsi language using full style
ChronoFormatter<PersianCalendar> f1 = 
    ChronoFormatter.ofStyle(DisplayMode.FULL, new Locale("fa"), PersianCalendar.axis());
System.out.println(f1.format(jalali)); // ه‍.ش. ۱۳۹۴ بهمن ۵, دوشنبه
System.out.println(f1.parse("ه‍.ش. ۱۳۹۴ بهمن ۵, دوشنبه")); // AP-1394-11-05

// formatting in English language using custom pattern
ChronoFormatter<PersianCalendar> f2 = 
    ChronoFormatter.ofPattern(
        "d. MMMM yyyy", PatternType.CLDR, Locale.ENGLISH, PersianCalendar.axis());
System.out.println(f2.format(jalali)); // 5. Bahman 1394

关于国际化,我认为ICU4J在波斯日历领域提供的功能不比Time4J多,因为后者也是基于最新的CLDR版本v28。Time4J实际上支持大约25种波斯语和波斯语(包括波斯语和普什图语)。

github上有一个很好的库,它有一个非常简单的API,它有很多功能,而且它也可以在mavenCentral上使用:

您可以在Java中使用Jalali(波斯)日历转换器:

<dependency>
    <groupId>com.github.sbahmani</groupId>
    <artifactId>jalcal</artifactId>
    <version>1.0</version>
</dependency>
二,。格里高利至贾拉里

    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.DAY_OF_MONTH, 5);
    cal.set(Calendar.MONTH, 6);
    cal.set(Calendar.YEAR, 2014);
    cal.set(Calendar.HOUR_OF_DAY, 10);
    cal.set(Calendar.MINUTE, 25);
    cal.set(Calendar.SECOND, 1);
    cal.set(Calendar.MILLISECOND, 0);
    assertThat(JalCal.gregorianToJalali(cal.getTime(), true)).isEqualTo("14/04/1393   10:25:01");
    assertThat(JalCal.gregorianToJalali(new Date(1426883400000l), true)).isEqualTo("01/01/1394   00:00:00");

另外:你指的是传统的贾拉里历法还是伊朗目前使用的简化的衍生历法(伊朗历法)?@jarnbjo我指的是第二种历法请看一看:你使用的是哪种版本的ICU?@ППа能给出转换的代码片段吗?上面的示例只是将当前的公历日期显示为波斯语。@ampofila现在稍微晚了一点
com.ibm.icu.util.Calendar=com.ibm.icu.util.Calendar.getInstance(区域设置);日历。设置时间(日期);com.ibm.icu.text.DateFormat df=com.ibm.icu.text.DateFormat.getDateInstance(DateFormat.FULL,locale)
6MB库大小?????太多了。@mohamadaligharat考虑到可能有数以百万计的ICU图书馆用户在增加一年这样的琐碎任务上没有任何问题,我仍然坚信问题出在您的代码中。除非你确切地透露你在做什么,ICU图书馆归还什么以及你希望它归还什么,否则你声称图书馆不可靠对任何人都没有帮助。我试图使用YearMonthDate.jallitogregorian将1394年11月5日转换为格里高利,但转换是错误的。它返回的不是2016年1月25日,而是2016年1月24日。@ampofila好吧,这个库按设计工作,但您已经进入了它可怕的API风格的陷阱。它使用基于零的月份-请看我最后在哪里展示了amirmehdizadeh库的工作原理。@MenoHochschild,很高兴知道有一个替代Joda的方法。只需注意,Joda与
java.util.Calendar
相比有很大的优点(避免了基于零的月份或不变的设计)但在这方面无能为力,因为a)没有波斯日历,b)国际化是出了名的糟糕(其他地区日历示例:)。此类有一些错误,例如在Jalali闰日。我建议使用insteadit会给我以下错误:将字节码转换为dex时出错:原因:dex无法解析版本52字节码。这是由使用Java8或更高版本编译的库依赖项引起的。如果在库子模块中使用“java”gradle插件,请将targetCompatibility='1.7'sourceCompatibility='1.7'添加到该子模块的build.gradle文件中。有什么帮助吗?这个解决了我的问题。简单的解决方案。简单的API。谢谢你的图书馆谢谢sajjad。但是你解释你正在使用
com.ibm.icu:icu4j
不是更好吗?这可能有助于更多地使用它。
  Calendar expected4 = Calendar.getInstance(TimeZone.getDefault());
  expected4.set(2014, 7, 5, 1, 23, 1);
  assertThat(JalCal.jalaliToGregorian(1393, 5, 14, 1, 23, 1).toString()).isEqualTo(expected4.getTime().toString());
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.DAY_OF_MONTH, 5);
    cal.set(Calendar.MONTH, 6);
    cal.set(Calendar.YEAR, 2014);
    cal.set(Calendar.HOUR_OF_DAY, 10);
    cal.set(Calendar.MINUTE, 25);
    cal.set(Calendar.SECOND, 1);
    cal.set(Calendar.MILLISECOND, 0);
    assertThat(JalCal.gregorianToJalali(cal.getTime(), true)).isEqualTo("14/04/1393   10:25:01");
    assertThat(JalCal.gregorianToJalali(new Date(1426883400000l), true)).isEqualTo("01/01/1394   00:00:00");