我正在寻找一种方法,例如计算从现在到特定日期的天数,并且可以用来确定我是否处于特定时间段(例如Muharram + - 5天)。
我已经搜索了超过10个小时,最好的结果是" HijrahDate "库"java.time.chrono.HijrahDate"和称为"Joda Date"的东西,但我使用起来有困难。
如果您选择沙特阿拉伯官方历法,则可以使用基于java.time.HijrahDate的解决方案。但是,该类需要在Android上至少具有API 26级别。例如:
HijrahDate hd1 = HijrahDate.now();
HijrahDate hd2 = HijrahDate.from(LocalDate.of(2020, 5, 1));
long days = ChronoUnit.DAYS.between(hd1, hd2);
还有比较方法,如继承自接口ChronoLocalDate
的isAfter()
或isBefore()
以及标准的plus()
方法,用于确定您的日期是否在特定时间段中。
java.time的回退:
还有一个名为ThreetenABP的回退版本可用于较低版本的Android。但要注意陷阱,其实现的HijrahDate
与沙特阿拉伯的日历不同(因此您必须容忍日期转换中的差异)。
关于Joda-Time:
如果您选择使用那个相当过时的库,则应选择专门针对Android的库版本adapted for android。然而,它也不支持沙特阿拉伯的日历,但提供了四种不同的其他变体。您需要指定算法的闰年模式。
ICU4J(嵌入在Android中):
它的类IslamicCalendar提供了类似于旧日历类java.util.Calendar
的样式,还包括沙特阿拉伯的多个变体。最低所需的API级别为24。
Time4A:
这是我编写的一个库(作为适用于Android的Time4J的改编)。它提供了类HijriCalendar,其中包括Joda变量以及沙特阿拉伯的日历(变体ummalqura)。它提供了所有需要的功能,如日期算术(通过plus()或minus()方法)、日期比较(通过isAfter()等方法)。例如:
String variant = HijriCalendar.VARIANT_UMALQURA;
StartOfDay startOfDay = StartOfDay.definedBy(SolarTime.ofMecca().sunset());
HijriCalendar today = HijriCalendar.nowInSystemTime(variant, startOfDay);
HijriCalendar hcal = // gregorian to Hijri conversion
PlainDate.of(2020, 5, 1).transform(HijriCalendar.class, variant);
long days = CalendarDays.between(today, hcal).getAmount();
其他库不支持类似日落作为一天开始的特性。例如,对于您的穆哈兰姆(Muharram)+-5天请求,可能如下所示:
CalendarDays tolerance = CalendarDays.of(5);
HijriCalendar htemp = today.with(HijriCalendar.MONTH_OF_YEAR, HijriMonth.MUHARRAM);
HijriCalendar h1 = htemp.with(HijriCalendar.DAY_OF_MONTH.minimized()).minus(tolerance);
HijriCalendar h2 = htemp.with(HijriCalendar.DAY_OF_MONTH.maximized()).plus(tolerance);
boolean inTimePeriod = !(today.isBefore(h1) || today.isAfter(h2));
HijrahDate
.from
(
LocalDate.of( 2020 , Month.JANUARY , 23 )
)
.plus
(
Period.ofDays( 5 )
)
.isBefore
(
someOtherDate
)
现代方法使用内置在Java 8及更高版本和Android 26及更高版本中的java.time类。 对于早期版本,请参阅ThreeTen-Backport和ThreeTenABP项目。
Joda-Time项目是java.time的前身。两者均由同一人Stephen Colebourne创建和领导。
HijrahChronology
是java.time的一部分。 HijrahChronology
遵循Hijrah日历系统的规则。 Hijrah日历是支持伊斯兰教日历的农历日历。
HijrahDate
类表示Hijrah日历系统中的日期。
搜索Stack Overflow以获取更多信息,因为这已经多次涉及到该问题。
我不是伊斯兰教历或的专家,但我相信您可以通过调用和类上的方法,在Hijrah日期和公历(推算)日期之间进行转换。
LocalDate localDate1 = LocalDate.of( 2020 , Month.JANUARY , 23 ) ;
HijrahDate hijrahDate = HijrahDate.from( localDate1 ) ;
LocalDate localDate2 = LocalDate.from( hijrahDate ) ;
两个日期类都提供了plus
和minus
方法,可以接受一个Period
对象。
LocalDate later = localDate2.plus( Period.ofDays( 5 ) ) ;
isEqual
、isBefore
和 isAfter
进行比较。boolean match = localDate1.isEqual( localDate2 ) ;
转储到控制台。
System.out.println( "localDate1.toString(): " + localDate1 ) ;
System.out.println( "hijrahDate.toString(): " + hijrahDate ) ;
System.out.println( "localDate2.toString(): " + localDate2 ) ;
System.out.println( "match: " + localDate1.isEqual( localDate2 ) ) ;
System.out.println( "later.toString(): " + later ) ;
查看这个在IdeOne.com上运行代码。
localDate1.toString(): 2020-01-23
hijrahDate.toString(): Hijrah-umalqura AH 1441-05-28
localDate2.toString(): 2020-01-23
match: true
later.toString(): 2020-01-28
以下是一个完整的示例。此处使用的时间跨度比较方法是半开放式,即开始时间是包含的,而结束时间是不包含的。这种方法通常在日期时间处理中最好。这种方法可以使日期范围整齐地相邻,没有间隙或重叠。
LocalDate localDate = LocalDate.of( 2020 , Month.JANUARY , 23 );
HijrahDate hijrahDate = HijrahDate.from( localDate );
// Target range is five days before and after some specific date.
HijrahDate target = HijrahDate.from( LocalDate.of( 2020 , Month.MARCH , 14 ) );
Period period = Period.ofDays( 5 );
LocalDate start = LocalDate.from( target ).minus( period );
LocalDate end = LocalDate.from( target ).plus( period );
// Tip: A shorter way of asking "Is equal to or later" is "Is not before".
boolean withinTargetRange = ( ! hijrahDate.isBefore( start ) ) && hijrahDate.isBefore( end );
转储到控制台。
System.out.println( "localDate = " + localDate );
System.out.println( "hijrahDate = " + hijrahDate );
System.out.println( "target = " + target );
System.out.println( "withinTargetRange = " + withinTargetRange );
localDate = 2020-01-23
hijrahDate = Hijrah-umalqura AH 1441-05-28
target = Hijrah-umalqura AH 1441-07-19
withinTargetRange = false
如果要进行大量此类工作,建议添加ThreeTen-Extra库,该库也由Stephen Colebourne创立和领导。该库中的LocalDateRange
类将时间段表示为一对LocalDate
对象。该类包括contains
、abuts
、overlaps
等方法。我不知道这个库在Android上的表现如何。如果在Android上无法正常工作,您可以将该类的源代码复制到您的代码库中,前提是您能遵守其BSD-3许可证条款。
这里是一个使用LocalDateRange::contains
的例子。
LocalDate localDate = LocalDate.of( 2020 , Month.JANUARY , 23 );
HijrahDate hijrahDate = HijrahDate.from( localDate );
HijrahDate target = HijrahDate.from( LocalDate.of( 2020 , Month.MARCH , 14 ) );
Period period = Period.ofDays( 5 );
LocalDate start = LocalDate.from( target ).minus( period );
LocalDate end = LocalDate.from( target ).plus( period );
LocalDateRange range = LocalDateRange.of( start , end );
boolean withinTargetRange = range.contains( LocalDate.from( hijrahDate ) );
localDate = 2020-01-23
hijrahDate = Hijrah-umalqura AH 1441-05-28
target = Hijrah-umalqura AH 1441-07-19
range = 2020-03-09/2020-03-19
withinTargetRange = false
了解日期和时间在计算机内部的表示方式是相对于一个纪元的偏移量:https://en.wikipedia.org/wiki/Epoch_(computing)。
在Java中,您可以使用System.currentTimeMillis()获取此值;
您还可以通过减去两个日期数字并应用除法来进行单位转换以计算天数差异。
long days = (date2 - date1)
/ 1000 // MS
/ 60 // Secs
/ 60 // Mins
/ 24 // Hours
java.time
中:LocalDate.from(HijrahDate.of(1441, 7, 1));
(在 Time4A 中:HijriCalendar.ofUmalqura(1441, 7, 1).transform(PlainDate.class)
) - Meno Hochschild