我需要从日期中获得4-5-4日历周。对于4-5-4零售日历,Java中有像格鲁吉亚日历这样的实用工具吗?如果没有,我如何创建一个?所有的逻辑都需要什么?什么是第53周,如果是飞跃年?
例如,如果我传递一个日期(DD-MM-YYY) 04-03-2018作为输入,我应该得到March Week 1作为输出。或者,如果我给01-04-2018作为输入,我应该得到March Week 5作为输出。
请帮助我提供一种方法来构建这个实用程序。
发布于 2018-03-21 18:19:30
下面的课应该这样做:
public class NrfMonthWeek {
public static NrfMonthWeek getWeek(LocalDate date) {
// Determine NRF calendar year.
// The year begins on the Sunday in the interval Jan 29 through Feb 4.
LocalDate firstDayOfNrfYear = date.with(MonthDay.of(Month.JANUARY, 29))
.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
if (date.isBefore(firstDayOfNrfYear)) { // previous NRF year
firstDayOfNrfYear = date.minusYears(1)
.with(MonthDay.of(Month.JANUARY, 29))
.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
}
// 1-based week of NRF year
int weekOfNrfYear = (int) ChronoUnit.WEEKS.between(firstDayOfNrfYear, date) + 1;
assert 1 <= weekOfNrfYear && weekOfNrfYear <= 53 : weekOfNrfYear;
YearMonth firstMonthOfNrfYear = YearMonth.from(firstDayOfNrfYear)
.with(Month.FEBRUARY);
if (weekOfNrfYear == 53) {
// Special case: the last week of a 53 weeks year belongs to
// the last month, January; this makes it a 5 weeks month.
return new NrfMonthWeek(firstMonthOfNrfYear.plusMonths(11), 5);
} else {
// 1-based month of NRF year (1 = February through 12 = January).
// A little math trickery to make the 4-5-4 pattern real.
int monthOfNrfYear = (weekOfNrfYear * 3 + 11) / 13;
// Number of weeks before the NRF month: 0 for February, 4 for March, 9 for April, etc.
int weeksBeforeMonth = (monthOfNrfYear * 13 - 12) / 3;
int weekOfMonth = weekOfNrfYear - weeksBeforeMonth;
return new NrfMonthWeek(
firstMonthOfNrfYear.plusMonths(monthOfNrfYear - 1), weekOfMonth);
}
}
private YearMonth month;
/** 1 through 5 */
private int weekOfMonth;
public NrfMonthWeek(YearMonth month, int weekOfMonth) {
this.month = Objects.requireNonNull(month);
if (weekOfMonth < 1 || weekOfMonth > 5) {
throw new IllegalArgumentException("Incorrect week number " + weekOfMonth);
}
this.weekOfMonth = weekOfMonth;
}
@Override
public String toString() {
return month.getMonth().getDisplayName(TextStyle.FULL, Locale.US)
+ " Week " + weekOfMonth;
}
}我们试试看。在这里,我将两个日期从您的问题传递给getWeek方法:
System.out.println(NrfMonthWeek.getWeek(LocalDate.of(2018, Month.MARCH, 4)));
System.out.println(NrfMonthWeek.getWeek(LocalDate.of(2018, Month.APRIL, 1)));这将打印所需的内容:
March Week 1
March Week 5虽然只打印月份和周,但是从getWeek返回的对象中也包含了年份。
计算月和月周的公式是神秘的.我并没有很好的理由来解释它们的作用,尽管这样的论点可能是可以建立起来的。我已经用所有相关的价值观测试过它们,您也可以这样做。除此之外,使用java.time (现代java.time和time )并不是太糟糕。
如果是我,我将在NrfMonthWeek构造函数中进行更好的验证,只允许在可能有5周的月份中的第5周。我把这个留给你。我会进行相当彻底的单元测试。
请检查我的理解是否与您的理解一致:如果我从示例日历中正确地理解了Bourque与在他的回答中的链接,NRF 4-5-4年从2月开始。每周从周日开始,一年中的第一周是包含至少4天2月的第一周。换句话说,包含2月4日的那一周。换句话说,从1月29日到2月4日间隔的一个星期日开始的一周。三月、六月、九月和十二月总是有五个星期。如果是53周,1月份也有5周。
发布于 2018-03-19 19:45:55
没有内置的支持
现代java.time类和遗留日期时类(Date/Calendar)都不直接支持全国零售联合会4-5-4日历。
实现Chronology
我怀疑解决这个问题的最好方法是为Chronology框架实现一个java.time。
Java 8和更高版本捆绑了五个实现(HijrahChronology、IsoChronology、JapaneseChronology、MinguoChronology、ThaiBuddhistChronology)。它们的源代码可以在OpenJDK项目中获得。
http://www.threeten.org/threeten-extra/项目提供十多个年表 (AccountingChronology、BritishCutoverChronology、CopticChronology、DiscordianChronology、EthiopicChronology、InternationalFixedChronology、JulianChronology、< code >D19、Symmetry010Chronology、Symmetry454Chronology),源代码可能会有所帮助。
https://stackoverflow.com/questions/49368843
复制相似问题