Java Calendar.set(Calendar.DAY_OF_WEEK,Calendar.SUNDAY),它会向后滚动,转发还是未知?
假设以下代码在2009年8月22日(星期六)执行
Calendar c = Calendar.getInstance(); c.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
c.get(Calendar.DAY_OF_MONTH)
将返回23.我感兴趣的条件是将返回14(上周日,而不是下周日)。
是否有任何与方向相关的规则当设置DAY_OF_WEEK
时,日历将滚动DAY_OF_MONTH/YEAR
? 如果是这样,他们是什么?
它应始终保持相同的WEEK_OF_MONTH
( http://java.sun.com/j2se/1.4.2/docs/api/java/util/Calendar.html#WEEK_OF_MONTH )。 从文档:
设置或获取WEEK_OF_MONTH或WEEK_OF_YEAR字段时,日历必须将月份或年份的第一周确定为参考点。 一个月或一年的第一周定义为从getFirstDayOfWeek()开始并且至少包含该月或年的getMinimalDaysInFirstWeek()天的最早七天。 周数在第一周之前编号为……,-1,0; 周数为2,3,……跟随它。 请注意,get()返回的规范化编号可能不同。 例如,特定的Calendar子类可以将一年的第1周之前的一周指定为前一年的第n周。
以下公式在[0; 6]范围内的一周内返回“当前”日
(d + numberOfDaysInAWeek - firstDayOfWeek) % numberOfDaysInAWeek
如果你想要范围,可以加1 [1; 7]
(d + numberOfDaysInAWeek - firstDayOfWeek) % numberOfDaysInAWeek + 1
d
是Calendar.get(Calendar.DAY_OF_WEEK)
返回的内容
获取一周中的第一天,从当前日期中减去公式的结果。 以下代码执行此操作:
final int currentDayOfWeek = (calendar.get(Calendar.DAY_OF_WEEK) + 7 - cal.getFirstDayOfWeek()) % 7; cal.add(Calendar.DAY_OF_YEAR, -currentDayOfWeek);
实际上,这取决于。 请考虑以下Java代码。 它实际上很简单,我希望它打印出2011-09-18之前的星期一,即2011-09-12:
Calendar calendar = Calendar.getInstance(Locale.GERMANY); System.out.printf("First day of week: %d%n%n", calendar.getFirstDayOfWeek()); calendar.set(2011, Calendar.SEPTEMBER, 18); System.out.printf("Starting day: %tF%n", calendar); calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); System.out.printf("Last monday: %tF%n%n", calendar); calendar.set(2011, Calendar.SEPTEMBER, 18); System.out.printf("Starting day: %tF (week %d)%n", calendar, calendar.get(Calendar.WEEK_OF_YEAR)); calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); System.out.printf("Last monday: %tF (week %d)%n", calendar, calendar.get(Calendar.WEEK_OF_YEAR));
但实际上结果有点不同:
First day of week: 2 Starting day: 2011-09-18 Last monday: 2011-09-19 Starting day: 2011-09-18 (week 37) Last monday: 2011-09-12 (week 37)
换句话说,结果取决于我的日历是否知道我可能对本周感兴趣。 如果我查询WEEK_OF_YEAR
,结果实际上会改变!
来自Javadoc :
如果日历字段值中存在任何冲突,则日历会优先考虑最近设置的日历字段。 以下是日历字段的默认组合。 将使用由最近设置的单个字段确定的最新组合。
对于日期字段:
YEAR + MONTH + DAY_OF_MONTH YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK YEAR + DAY_OF_YEAR YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
我认为这意味着,假设您正在设置星期几,它将最终与一周中的一周或一周中的一周相结合,以产生实际的日期和时间。
使用java.time
现代方法是使用java.time类来取代麻烦的旧遗留日期时间类。
java.time类更容易使用。 特别是,它们消除了问题中提出的模糊性。 您可以明确询问早期星期日或晚些星期日。
LocalDate
类表示没有时间且没有时区的仅日期值。
Month
enum提供了十几个预定义的对象,一年中的每个月都有一个。 这些枚举对象使用起来更安全,但您可以使用月份的普通数字。 与传统课程不同,这几个月的编号很合理,1月至12月为1-12。
LocalDate localDate = LocalDate.of( 2009 , Month.AUGUST, 22 );
TemporalAdjuster
接口提供对日期时间值的操作。 TemporalAdjusters
类(注意复数s
)提供了几个方便的实现。
previous
和next
调整者不考虑日期本身。 previousOrSame
和nextOrSame
方法返回有问题的日期,如果它确实是所需的星期几。
DayOfWeek
枚举提供了七个预定义的对象,一个对应于一周中的每一天。
LocalDate previousSunday = localDate.with( TemporalAdjusters.previous ( DayOfWeek.SUNDAY )); LocalDate previousOrSameSunday = localDate.with( TemporalAdjusters.previousOrSame ( DayOfWeek.SUNDAY )); LocalDate nextSunday = localDate.with( TemporalAdjusters.next ( DayOfWeek.SUNDAY )); LocalDate nextOrSameSunday = localDate.with( TemporalAdjusters.nextOrSame ( DayOfWeek.SUNDAY ));
转储到控制台。
System.out.println ("localDate: " + localDate + " ( " + localDate.getDayOfWeek ().getDisplayName ( TextStyle.FULL, Locale.US ) + " )"); System.out.println ("previousSunday: " + previousSunday ); System.out.println ("nextSunday: " + nextSunday );
localDate:2009-08-22(星期六)
previousSunday:2009-08-16
nextSunday:2009-08-23
关于java.time
java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧遗留日期时间类,如java.util.Date
, Calendar
和SimpleDateFormat
。
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
要了解更多信息,请参阅Oracle教程 。 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310 。
从哪里获取java.time类?
- Java SE 8和SE 9及更高版本
- 内置。
- 带有捆绑实现的标准Java API的一部分。
- Java 9增加了一些小function和修复。
- Java SE 6和SE 7
- 许多java.timefunction都被反向移植到ThreeTen-Backport中的 Java 6和7。
- Android的
- ThreeTenABP项目特别适用于Android的ThreeTen-Backport (如上所述)。
- 请参见如何使用ThreeTenABP ….
ThreeTen-Extra项目使用其他类扩展了java.time。 该项目是未来可能添加到java.time的试验场。 您可以在这里找到一些有用的课程,如Interval
, YearWeek
, YearQuarter
等。
您还应该检查一周中的第一天。 我也认为它总是星期天,但这取决于当地的设置,在我的情况下,星期一是一周的第一天。 将星期日设置为一周的第一天解决了我的问题。
取决于一周的第一天:
/** * Gets what the first day of the week is; eg,
SUNDAY
in the US, *MONDAY
in France. * * @return the first day of the week. * @see #setFirstDayOfWeek(int) * @see #getMinimalDaysInFirstWeek() */ public int getFirstDayOfWeek() { return firstDayOfWeek; }
你可以使用这种方法。
public Integer whichDayOfWeek(Calendar calendar) { if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) { return 1; } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.TUESDAY) { return 2; } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.WEDNESDAY) { return 3; } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.THURSDAY) { return 4; } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) { return 5; } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) { return 6; } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) { return 7; } else { return null; } }