设置 DAY_OF_WEEK 会返回意外结果
我想将给定日历实例的时间戳设置为一周的开始(星期一),而不是返回一个看似完全不相关的时间戳 - 除非我在此之前访问任何日历的字段.我在下面包含了一个示例,另请参阅 Ideone 中的这个可运行示例.
I want to set a given calendar instance's timestamp to the beginning of the week (Monday) and instead it returns a seemingly completely unrelated timestamp - unless I access any of the calendar's fields before doing so. I include a sample below, please also see this runnable example in Ideone.
这是预期的行为吗?这背后的逻辑是什么?是的,我听说过 Joda Time.
Is this expected behavior? What's the logic behind this? And yes, I've heard of Joda Time.
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
class MyTest {
private static Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("CET"), Locale.FRANCE);
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
public static void main(String[] args) {
// Set to any date.
calendar.set(2013, 10, 3);
System.out.println(dateFormat.format(calendar.getTime()));
// Set to another day.
calendar.set(2014, 0, 15);
// --- THE WTF STARTS HERE ---
// Uncommenting the line below returns the correct date in the end.
// calendar.getTime();
// Set to monday of current week.
calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek());
// Expected outdate is 20140113
System.out.println(dateFormat.format(calendar.getTime()));
}
}
推荐答案
文档中的字段操作章节解释清楚.但它只是工作起来很奇怪.
Field Manipulation chapter in the docs explains it clearly. It just works weird though.
http://docs.oracle.com/javase/6/docs/api/java/util/Calendar.html
示例:考虑一个最初设置为 1999 年 8 月 31 日的 GregorianCalendar.调用set(Calendar.MONTH, Calendar.SEPTEMBER) 将日期设置为 1999 年 9 月 31 日.这是一个临时的内部表示,解决到 1999 年 10 月 1 日,如果然后调用 getTime().但是,在之前调用 set(Calendar.DAY_OF_MONTH, 30)调用 getTime() 将日期设置为 1999 年 9 月 30 日,因为不会发生重新计算在 set() 本身之后.
Example: Consider a GregorianCalendar originally set to August 31, 1999. Calling set(Calendar.MONTH, Calendar.SEPTEMBER) sets the date to September 31, 1999. This is a temporary internal representation that resolves to October 1, 1999 if getTime()is then called. However, a call to set(Calendar.DAY_OF_MONTH, 30) before the call to getTime() sets the date to September 30, 1999, since no recomputation occurs after set() itself.
编辑
来自同一文档的日历字段解析部分
From the Calendar Fields Resolution part of the same doc
If there is any conflict in calendar field values, Calendar gives priorities to
calendar fields that have been set more recently. The following are the default
combinations of the calendar fields. The most recent combination, as determined
by the most recently set single field, will be used.
For the date fields:
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
我认为 MONTH 和 DAY_OF_WEEK 之间的区别是这样的.如果您在最后一条语句中设置 MONTH,它将与 YEAR+MONTH+DAY_OF_MONTH 匹配并覆盖所有这些.如果您设置 DAY_OF_WEEK 它与 YEAR+DAY_OF_WEEK+WEEK_OF_YEAR 匹配,因此不会覆盖月份值.或类似的东西.老实说,我越看越觉得破碎.这根本没有意义.最好继续使用 JodaTime
I think the difference between MONTH and DAY_OF_WEEK is this. If you set MONTH at the last statement it matches with YEAR+MONTH+DAY_OF_MONTH and overrides all of them. If you set DAY_OF_WEEK it matches with YEAR+DAY_OF_WEEK+WEEK_OF_YEAR so doesn't override the month value. Or something like that. To be honest, the more I look the more broken it seems. It doesn't make sense at all. Better keep using JodaTime
相关文章