55

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

Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timeStamp);

但我需要在 Jalali 日历中有日期。我搜索但没有找到任何好的图书馆。您知道用于转换(或创建 Jalali 格式的日期timeStamp)的可靠且良好的库吗?我不需要实现或算法,因为这个问题太麻烦而且有很多规则,我需要一个可靠的解决方案

4

5 回答 5

83

为了获得更好的本地化和语言支持,使用 IBM 的ICU(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));

这将输出:

چهارشنبه ۱۰ اردیبهشت ۱۳۹۳ ه‍.ش.

于 2014-04-30T10:48:16.697 回答
25

看看这个:https ://github.com/amirmehdizadeh/JalaliCalendar

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

于 2014-04-30T10:21:31.577 回答
10

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

https://github.com/razeghi71/JalaliCalendar

于 2016-04-21T10:08:13.253 回答
8

我在我的库Time4J 中用Java 开发了我自己的波斯 (jalali) 日历。该实现部署了Borkowski的算法(至少在 gregorian 年 2129 之前有效 - 没有 2025-bug)。

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

当然,日历提供了更多功能,例如日期算术(添加天数或月数,以天数、月数计算增量等)或字段/元素操作(轻松转到一个月的最后一天等)。

到目前为止,关于此处提出的其他库的旁注:

amirmehdizadeh /JalaliCalendar 以及ICU4J都使用从零开始的月份。这可能非常令人困惑。使用 amirmehdizadeh 库的非直观示例:

YearMonthDate jalali = new YearMonthDate(1394, 10, 5); // 11th month (Bahman)
YearMonthDate gregorian = JalaliCalendar.jalaliToGregorian(jalali);
System.out.println(gregorian); // 2016/0/25 => 1st month (January)

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

于 2016-02-09T13:55:59.693 回答
4

您可以在 Java 中使用JalCal即 Jalali(Persian) 日历转换器:

<dependency>
    <groupId>com.github.sbahmani</groupId>
    <artifactId>jalcal</artifactId>
    <version>1.0</version>
</dependency>

1. Jalali 到 Gregorian

  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());

2. 公历到贾拉里

    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");
于 2017-08-29T10:09:36.867 回答