如何显示本地伊斯兰(hijri)日历?
How to show native Islamic(hijri) Calendar?
我想在 Android 上显示日期选择器对话框。现在我只能选择正常日期。如何将其转换为回历(伊斯兰)日历?这是我用来显示对话框的代码,
显示日期选择器对话框的代码
private void showDOBPickerDialog(Context context, String DateString) {
try {
String defaltDate = getCurrentDate_MMDDYYYY();
if (DateString == null || DateString.isEmpty() || DateString.length() < 10)
DateString = defaltDate;
int monthOfYear, dayOfMonth, year;
monthOfYear = Integer.parseInt(DateString.substring(0, DateString.indexOf("/"))) - 1;
dayOfMonth = Integer.parseInt(DateString.substring(DateString.indexOf("/") + 1, DateString.lastIndexOf("/")));
year = Integer.parseInt(DateString.substring(DateString.lastIndexOf("/") + 1));
DatePickerDialog datePickerDialog = new DatePickerDialog(context, new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
monthOfYear = monthOfYear + 1;
String Month = String.valueOf(monthOfYear), Day = String.valueOf(dayOfMonth);
if (monthOfYear < 10)
Month = "0" + monthOfYear;
if (dayOfMonth < 10)
Day = "0" + dayOfMonth;
String selectedDate = Month + "/" + Day + "/" + year;
edtTxtDateOfId.setText(selectedDate);
}
}, year, monthOfYear, dayOfMonth);
datePickerDialog.setTitle("Select Date");
datePickerDialog.show();
} catch (Exception e) {
}
}
要获取当前日期,
public static String getCurrentDate_MMDDYYYY() {
String DATE_FORMAT_NOW = "MM/dd/yyyy";
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
Calendar cal = GregorianCalendar.getInstance(Locale.FRANCE);
cal.setTime(new Date());
return sdf.format(cal.getTime());
}
, you can take a look at the source code of this implementation: https://github.com/ThreeTen/threetenbp/tree/master/src/main/java/org/threeten/bp/chrono
看看 HijrahChronology
、HijrahDate
和 HijrahEra
类,也许你能得到一些想法,看看所有的数学是如何在两者之间进行转换的这个日历和 ISO8601 日历。
但老实说,IMO 日历的实现太复杂了,在大多数情况下不值得自己动手做。这是添加库完全值得的情况之一。
使用 ThreeTen-Backport lib - and - 将为您提供一种简单的方法来转换日期并设置日期格式:
// get ISO8601 date (the "normal" date)
int dayOfMonth = 20;
int monthOfYear = 3;
int year = 2018;
// March 20th 2018
LocalDate dt = LocalDate.of(year, monthOfYear, dayOfMonth);
// convert to hijrah
HijrahDate hijrahDate = HijrahDate.from(dt);
// format to MM/DD/YYYY
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy");
String formatted = formatter.format(hijrahDate); // 07/03/1439
也可以调用HijrahDate.now()
直接获取当前日期
并且您可以使用 LocalDate.from(hijrahDate)
.
将 hijrahDate
转换回 "normal" 日期
你也可以使用time4j:
// get ISO8601 date (the "normal" date)
int dayOfMonth = 20;
int monthOfYear = 3;
int year = 2018;
PlainDate dt = PlainDate.of(year, monthOfYear, dayOfMonth);
// convert to Hijri, using different variants
HijriCalendar hijriDateUmalqura = dt.transform(HijriCalendar.class, HijriCalendar.VARIANT_UMALQURA);
HijriCalendar hijriDateWest = dt.transform(HijriCalendar.class, HijriAlgorithm.WEST_ISLAMIC_CIVIL);
// format to MM/DD/YYYY
ChronoFormatter<HijriCalendar> fmt = ChronoFormatter.ofPattern("MM/dd/yyyy", PatternType.CLDR, Locale.ENGLISH, HijriCalendar.family());
String formatted = fmt.format(hijriDateUmalqura); // 07/03/1439
// get current date
HijriCalendar now = HijriCalendar.nowInSystemTime(HijriCalendar.VARIANT_UMALQURA, StartOfDay.MIDNIGHT);
// convert back to "normal" date
PlainDate date = hijriDateUmalqura.transform(PlainDate.class);
考虑到您在一条评论中给出的声明您只想要一个本地解决方案并拒绝任何额外的库,我建议使用 ICU4J-classIslamicCalendar.
当然,您必须接受两个主要缺点:
- API-level24(在手机上不是很普遍)
- Old-fashioned API-style(例如不是不可变的)
另一个缺点(仅当您对时钟时间也感兴趣时才相关)是 ICU4J 不支持在前一天日落的晚上开始伊斯兰教日。此功能仅在我的 lib Time4J 中受支持,其他任何地方均不支持。但是您可能不需要在日期选择器对话框中使用此功能。
优点:
- API-style 类似于包
java.util
中的 "traditional",所以我假设你已经习惯了它(但是 many/most 人们认为这种风格而不是是否定的,你必须自己做出决定)
- 至少 umalqura-variant-提供 Saudi-Arabia 的变体(注意:其他库如 Threeten-BP 或 Joda-Time-Android 不提供该变体)
- 可接受甚至良好的国际化程度(也优于 ThreetenBP 或 Joda-Time-Android)
为了完整起见,如果您愿意将 Android 应用程序限制在 26 级或更高级别,那么您也可以使用 java.time.chrono.HijrahChronology。但我认为这在 2018 年还为时过早,因为手机对 26 级的支持实际上非常小。虽然它确实提供 Umalqura 变体(Saudi-Arabia),但它不提供任何其他变体。
否则没有可用的本机解决方案。仅使用本机解决方案也是一个限制,恕我直言。
我想在 Android 上显示日期选择器对话框。现在我只能选择正常日期。如何将其转换为回历(伊斯兰)日历?这是我用来显示对话框的代码,
显示日期选择器对话框的代码
private void showDOBPickerDialog(Context context, String DateString) {
try {
String defaltDate = getCurrentDate_MMDDYYYY();
if (DateString == null || DateString.isEmpty() || DateString.length() < 10)
DateString = defaltDate;
int monthOfYear, dayOfMonth, year;
monthOfYear = Integer.parseInt(DateString.substring(0, DateString.indexOf("/"))) - 1;
dayOfMonth = Integer.parseInt(DateString.substring(DateString.indexOf("/") + 1, DateString.lastIndexOf("/")));
year = Integer.parseInt(DateString.substring(DateString.lastIndexOf("/") + 1));
DatePickerDialog datePickerDialog = new DatePickerDialog(context, new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
monthOfYear = monthOfYear + 1;
String Month = String.valueOf(monthOfYear), Day = String.valueOf(dayOfMonth);
if (monthOfYear < 10)
Month = "0" + monthOfYear;
if (dayOfMonth < 10)
Day = "0" + dayOfMonth;
String selectedDate = Month + "/" + Day + "/" + year;
edtTxtDateOfId.setText(selectedDate);
}
}, year, monthOfYear, dayOfMonth);
datePickerDialog.setTitle("Select Date");
datePickerDialog.show();
} catch (Exception e) {
}
}
要获取当前日期,
public static String getCurrentDate_MMDDYYYY() {
String DATE_FORMAT_NOW = "MM/dd/yyyy";
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
Calendar cal = GregorianCalendar.getInstance(Locale.FRANCE);
cal.setTime(new Date());
return sdf.format(cal.getTime());
}
看看 HijrahChronology
、HijrahDate
和 HijrahEra
类,也许你能得到一些想法,看看所有的数学是如何在两者之间进行转换的这个日历和 ISO8601 日历。
但老实说,IMO 日历的实现太复杂了,在大多数情况下不值得自己动手做。这是添加库完全值得的情况之一。
使用 ThreeTen-Backport lib - and
// get ISO8601 date (the "normal" date)
int dayOfMonth = 20;
int monthOfYear = 3;
int year = 2018;
// March 20th 2018
LocalDate dt = LocalDate.of(year, monthOfYear, dayOfMonth);
// convert to hijrah
HijrahDate hijrahDate = HijrahDate.from(dt);
// format to MM/DD/YYYY
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy");
String formatted = formatter.format(hijrahDate); // 07/03/1439
也可以调用HijrahDate.now()
直接获取当前日期
并且您可以使用 LocalDate.from(hijrahDate)
.
hijrahDate
转换回 "normal" 日期
你也可以使用time4j:
// get ISO8601 date (the "normal" date)
int dayOfMonth = 20;
int monthOfYear = 3;
int year = 2018;
PlainDate dt = PlainDate.of(year, monthOfYear, dayOfMonth);
// convert to Hijri, using different variants
HijriCalendar hijriDateUmalqura = dt.transform(HijriCalendar.class, HijriCalendar.VARIANT_UMALQURA);
HijriCalendar hijriDateWest = dt.transform(HijriCalendar.class, HijriAlgorithm.WEST_ISLAMIC_CIVIL);
// format to MM/DD/YYYY
ChronoFormatter<HijriCalendar> fmt = ChronoFormatter.ofPattern("MM/dd/yyyy", PatternType.CLDR, Locale.ENGLISH, HijriCalendar.family());
String formatted = fmt.format(hijriDateUmalqura); // 07/03/1439
// get current date
HijriCalendar now = HijriCalendar.nowInSystemTime(HijriCalendar.VARIANT_UMALQURA, StartOfDay.MIDNIGHT);
// convert back to "normal" date
PlainDate date = hijriDateUmalqura.transform(PlainDate.class);
考虑到您在一条评论中给出的声明您只想要一个本地解决方案并拒绝任何额外的库,我建议使用 ICU4J-classIslamicCalendar.
当然,您必须接受两个主要缺点:
- API-level24(在手机上不是很普遍)
- Old-fashioned API-style(例如不是不可变的)
另一个缺点(仅当您对时钟时间也感兴趣时才相关)是 ICU4J 不支持在前一天日落的晚上开始伊斯兰教日。此功能仅在我的 lib Time4J 中受支持,其他任何地方均不支持。但是您可能不需要在日期选择器对话框中使用此功能。
优点:
- API-style 类似于包
java.util
中的 "traditional",所以我假设你已经习惯了它(但是 many/most 人们认为这种风格而不是是否定的,你必须自己做出决定) - 至少 umalqura-variant-提供 Saudi-Arabia 的变体(注意:其他库如 Threeten-BP 或 Joda-Time-Android 不提供该变体)
- 可接受甚至良好的国际化程度(也优于 ThreetenBP 或 Joda-Time-Android)
为了完整起见,如果您愿意将 Android 应用程序限制在 26 级或更高级别,那么您也可以使用 java.time.chrono.HijrahChronology。但我认为这在 2018 年还为时过早,因为手机对 26 级的支持实际上非常小。虽然它确实提供 Umalqura 变体(Saudi-Arabia),但它不提供任何其他变体。
否则没有可用的本机解决方案。仅使用本机解决方案也是一个限制,恕我直言。