1.背景:
百度知道上有人咨询了 Calendar 设置 Calendar.DAY_OF_WEEK不正确的问题
参见 http://zhidao.baidu.com/question/748936560786113052
他的入职时间是
"2006-02-14"
,要计算20年后的所在周的周六
理论上, 2026-02-14
所在周的周六,正好就是 2026-02-14
他写的代码是
public class Test {
public static void main(String[] args) throws ParseException {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
Date date=sdf.parse("2006-02-14");
System.out.println(sdf.format(date));
//********************************************************************
Calendar c=Calendar.getInstance();
c.setTime(date);
c.add(Calendar.YEAR, 20);
c.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
//********************************************************************
System.out.println("入职20周年纪念日派对日期:"+sdf.format(c.getTime()));
}
}
看上去没毛病,但是结果死活就是 2026-02-21
但是,在中间插入一行代码 System.out.println(c.get(Calendar.DAY_OF_WEEK));
public class Test {
public static void main(String[] args) throws ParseException {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
Date date=sdf.parse("2006-02-14");
System.out.println(sdf.format(date));
//********************************************************************
Calendar c=Calendar.getInstance();
c.setTime(date);
c.add(Calendar.YEAR, 20);
System.out.println(c.get(Calendar.DAY_OF_WEEK));//有就正确,没有就错误:输出2026-02-21
c.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY); //正确日期2026-02-14
//********************************************************************
System.out.println("入职20周年纪念日派对日期:"+sdf.format(c.getTime()));
}
}
结果就是正确的 2026-02-14
是不是很神奇?颠覆世界观,觉得不可思议?
2.原因
原因在于,当你设置 DAY_OF_WEEK
的时候, 你需要设置 WEEK_OF_MONTH
或者 DAY_OF_WEEK_IN_MONTH
或者 WEEK_OF_YEAR
, 否则会使用老的WEEK_OF_MONTH
字段
When computing time (milliseconds), GregorianCalendar leaves some fields inconsistent.
Then, after the last set(DAY_OF_WEEK), an invalid (older) WEEK_OF_MONTH value is used in the last getTime() call.When you set DAY_OF_WEEK, the calendar expects a week field (
WEEK_OF_MONTH
,DAY_OF_WEEK_IN_MONTH
orWEEK_OF_YEAR
) has also been set.
So, avoid setting DAY_OF_WEEK without setting one of the week fields.
原先的这段代码
public class Test {
public static void main(String[] args) throws ParseException {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
Date date=sdf.parse("2006-02-14");
System.out.println(sdf.format(date));
//********************************************************************
Calendar c=Calendar.getInstance();
c.setTime(date);
c.add(Calendar.YEAR, 20);
c.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
//********************************************************************
System.out.println("入职20周年纪念日派对日期:"+sdf.format(c.getTime()));
}
}
由于只设置了 Calendar.DAY_OF_WEEK
,那么计算的时间结果是 20年后的第3周的周六 (因为没有设置WEEK_OF_MONTH
,那么取的是老的"2006-02-14" 的WEEK_OF_MONTH
)
而 "2006-02-14" 是所在月的第3周, 那么 20年后的第3周的周六 结果就是 2026-02-21
了
3. 为毛中间插入了一段 System.out.println(c.get(Calendar.DAY_OF_WEEK));
结果就正确了呢?
我在问题里面也回答了,
- 换成
System.out.println(c.get(Calendar.ERA));
结果也会对 - 换成
System.out.println("啦啦啦啦:" + sdf.format(c.getTime()));
结果也对
原因在于,
调用这些方法的时候 ,Calendar
会调用 java.util.Calendar.complete()
方法,
这个方法会依照已经设置的参数,把 Calendar 的 17 个字段(包括 WEEK_OF_MONTH
) 都重新计算一下 ,
此时, "2006-02-14" 20年后的日期是 2026-02-14 , 他的 WEEK_OF_MONTH
是当月的第二周, 都算完成了
4.最佳实践 (推荐指南)
真心不建议自己来写 Calendar SimpleDateFormat 来操作 ,坑比较多.
建议使用 apache commons-lang3
jar 或者 joda-time
示例: 对我来说就三步
public static void main(String[] args) throws ParseException{
//1.转成date
Date date = DateUtils.parseDate("2006-02-14", "yyyy-MM-dd");
//2.20年后的日期
Date d20 = DateUtils.addYears(date, 20);
//3.20年后的日期所在周的 周六 ,
Calendar calendar = DateUtils.toCalendar(d20);
calendar.set(DAY_OF_WEEK, SATURDAY);
System.out.println("入职20周年纪念日派对日期:" + DateFormatUtils.format(calendar.getTime(), "yyyy-MM-dd"));
}
你也可以使用 feilong-core jar
示例: 对我来说就三步
public static void main(String[] args){
//1.转成date
Date date2 = DateUtil.toDate("2006-02-14", DatePattern.COMMON_DATE);
//2.20年后的日期
Date d20 = DateUtil.addYear(date2, 20);
//3.20年后的日期所在周的 周六
System.out.println("入职20周年纪念日派对日期:" + DateUtil.toString(getLastDateOfThisWeek(d20), DatePattern.COMMON_DATE));
}
相关推荐
`WEEK_OF_YEAR` int(10) NOT NULL COMMENT '获得指定日期是所在年份的第几周', `WEEK_OF_MONTH` int(10) NOT NULL COMMENT '获得指定日期是所在月份的第几周', `DAY_OF_MONTH` int(10) NOT NULL COMMENT '获得...
c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek()); // Monday System.out.println(c.getTime()); c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek() + 6); // Sunday //本周第一天,以星期日开始 。。。...
int first_day_of_week = now.get(Calendar.DATE) + 2 - today; // 星期一 now.set(Calendar.DATE, first_day_of_week); return now.getTime(); } /** * 获得所在星期的最后一天 */ public static ...
$(obj).addClass("calendar_day_act").siblings().removeClass("calendar_day_act"); } }); 点击上方显示当前年份和周的DOM部分可选择并跳转到指定年份和周。 插件提供的方法: //获取周第一天方法weekfirstdate...
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); cal.add(Calendar.DAY_OF_MONTH, 6); return cal.getTime(); } /** * 获取指定时间范围的第一天 * * @param dateRangeType * 时间范围类型 * ...
a program to prompt for the Grogorian calendar day, (i) the total number of days January 1st, year 1 to this day, (ii) the total number of days January 1st of the year to the day, and (iii) the day of...
In the Gregorian calendar, which is widely used now, the year AD 1 is directly preceded by the year 1 BC; a year 0 does not exist in this system. In contrast, astronomical reckoning indeed uses a year...
通过Calendar对象的get(Calendar.DAY_OF_WEEK)方法可以获得Calendar对象为星期几(星期天为1,星期六为7)。 注意: Calendar中的月份从0开始(1月为0,12月为11),日期从1开始(1日为1,28日为28); 12生肖的...
java时间格式大全(算法源码) java,date,时间,时间格式,算法源码 * * @return */ public static String getTimeShort() { SimpleDateFormat formatter = new ... if (cal1.get(Calendar.WEEK_OF_YEAR) == ...
swift实现的Week & Day 日历控件.zip,Calendar Week & Day View in iOS Swift
// table of short day names var ar = new Array(); for (var i = 8; i > 0;) { ar[--i] = Calendar._DN[i].substr(0, 3); } Calendar._DN3 = ar; // table of short month names ar = new Array(); for ...
int i=calendar.get(Calendar.DAY_OF_WEEK)-1; if(i==0) i=7; return i; } static boolean in_term(Date date){ int[] term=WeekInfStore.get_term_date(); Calendar c1=Calendar.getInstance()...
但Calendar类Calendar.WEEK_OF_MONTH属性,即这一周在一个月中属于第几周这一属性设计的很不合我们的习惯,他是以周六作为一周的结束,比如19年的6月1日,恰好在周六,那么第一周就只有这一天,而作为周日的2号就在第...
int firstIndex = thisMonth.get(Calendar.DAY_OF_WEEK) - 1; int maxIndex = thisMonth.getActualMaximum(Calendar.DAY_OF_MONTH); for (int i = 0; i ; i++) { days[firstIndex + i] = String.valueOf(i + 1);...
Android Week View is an android library to display calendars (week view or day view) within the app. It supports custom styling. Features Week view calendar Day view calendar Custom styling ...
The events can be displayed in different views (Day, Week, Month, Year, Agenda, etc.) Advanced drag-and-drop functionality allows users to change date and time of an event by easily moving or ...
在得到日期的同时判断DAY OF WEEK星期几,在窗体上显示 5为各个按钮及标签添加监听 通过ActionPerform MousePressed实现其动作 6 保存日志 显示日志及删除日志,总过创建哈希表来进行文件的读写
day of the week 1 Hz and 32.768 kHz clock outputs Serial interface supports Motorola Serial Peripheral Interface (SPI) serial data ports or standard 3-wire interface Burst Mode for reading/...
calendar-converter 是 JavaScript 版本的公历和农历的互转库。 示例代码: var cc =new CalendarConverter; cc.lunar2solar(new Date(2011, 0, 3)); ---> 2010,11,29 cc.solar2lunar(new Date(2010, 10, 29...
Java程序设计 课程设计报告 设计题目:电子日历设计 班级: 学号: 姓名: 1. 需求分析 设计并实现一个电子日历,当用户在下拉列表中选择年份... int week=date.get(Calendar.DAY_OF_WEEK)-1; int day=0; if(month==1