package javase1day05;import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;public class DateCalDemo {
public static void main(String[] args) {
//时间计算的原理
long now = System.currentTimeMillis();
long l = now+1000L*60*60*24;//明天
System.out.println(l);
SimpleDateFormat fmt =
new SimpleDateFormat("yyyy-MM-dd");
Calendar cal = new GregorianCalendar();
cal.add(Calendar.MONTH, 5);
System.out.println(fmt.format(cal.getTime()));
cal.add(Calendar.YEAR, 5);//1387260478395
System.out.println(fmt.format(cal.getTime()));
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
System.out.println(fmt.format(cal.getTime()));
}}大家帮我看看,如果我注释掉这里(第二个输出)System.out.println(fmt.format(cal.getTime()));,得到的结果是2018年12月10日,但是从日历上来看应该 是2018年12月17日。如果我把fmt.format(cal.getTime())单独提出去的话,得到的结果是正确的。
另外,如果我注释掉第一个输出System.out.println(fmt.format(cal.getTime()));,对结果却是没有影响的,
跪求大家给我看看是为什么,难道是闰年的原因?
public static void main(String[] args) {
// 时间计算的原理
long now = System.currentTimeMillis();
long l = now + 1000L * 60 * 60 * 24;// 明天
System.out.println(l);
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd"); Calendar cal = new GregorianCalendar();
cal.add(Calendar.MONTH, 5);
System.out.println(fmt.format(cal.getTime()));
cal.add(Calendar.YEAR, 5);// 1387260478395
System.out.println(fmt.format(cal.getTime()));
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
System.out.println(fmt.format(cal.getTime())); }
}
/*
* 输出结果:
* 1374133763448
* 2013-12-17
* 2018-12-17
* 2018-12-17
*
*/我用的是JDK1.7,楼主再试试看,调试一下编译环境等,应该没有什么问题的。
set(f, value) 将日历字段 f 更改为 value。此外,它设置了一个内部成员变量,以指示日历字段 f 已经被更改。尽管日历字段 f 是立即更改的,但是直到下次调用 get()、getTime()、getTimeInMillis()、add() 或 roll() 时才会重新计算日历的时间值(以毫秒为单位)。API里看到Calendar类的说明里有这段,不是太懂,应该是你把第二个getTime()注释掉的话,set()在重新计算毫秒数前改变了日期
具体的也不太懂,坐等高人
API中说add后是立即重新计算时间的,但是单步跟踪代码,如果add后不调用getTime,这个时间是一直不变的。继续关注。
cal1.set(2000, 7, 31, 0, 0 , 0); //2000-8-31
cal1.set(Calendar.MONTH, Calendar.SEPTEMBER); //应该是 2000-9-31,也就是 2000-10-1
cal1.set(Calendar.DAY_OF_MONTH, 30); //如果 Calendar 转化到 2000-10-1,那么现在的结果就该是 2000-10-30
System.out.println(cal1.getTime()); //输出的是2000-9-30,说明 Calendar 不是马上就刷新其内部的记录大家可以参考下这一段,我大致知道为什么会出错了,但是就是不知道为什么API里明明说了调用add()方法会立即计算时间值,但是结果却是没有立即调用,很费解
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
public class DateCalDemo {
public static void main(String[] args) {
// 时间计算的原理
long now = System.currentTimeMillis();
long l = now + 1000L * 60 * 60 * 24;// 明天
System.out.println(l);
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(fmt.format(new Date(l)));
Calendar cal = new GregorianCalendar();
cal.add(Calendar.MONTH, 5);
System.out.println(fmt.format(cal.getTime()));
cal.add(Calendar.YEAR, 5);
//System.out.println(fmt.format(cal.getTime()));
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
System.out.println(fmt.format(cal.getTime()));
}
}
/*
* 输出结果:
*1374195228233
*2013-07-19
*2013-12-18
*2018-12-10
*/这是把倒数第二个输出注释掉的的,package javase1day05;import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;public class DateCalDemo {
public static void main(String[] args) {
// 时间计算的原理
long now = System.currentTimeMillis();
long l = now + 1000L * 60 * 60 * 24;// 明天
System.out.println(l);
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(fmt.format(new Date(l))); Calendar cal = new GregorianCalendar();
cal.add(Calendar.MONTH, 5);
System.out.println(fmt.format(cal.getTime()));
cal.add(Calendar.YEAR, 5);
System.out.println(fmt.format(cal.getTime()));
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
System.out.println(fmt.format(cal.getTime()));
}
}
/*1374195414804
*2013-07-19
*2013-12-18
*2018-12-18
*2018-12-17
*/
这是不注释掉倒数第二个输出语句的结果,前后结果相差一周。
当返回值的时间单位是毫秒时,值的粒度取决于底层操作系统,并且粒度可能更大。例如,许多操作系统以几十毫秒为单位测量时间
所以你运算一下这个代码
long now = System.currentTimeMillis();
long time = new Date().getTime();
System.out.println(now + "___" + time);
你会发现有时候这两个值不一样,会有几十毫秒的差距。
* 官方的说法是,当你设置某个值的时候,比如cal.add(Calendar.YEAR, 5); 这时候只是更新了Calendar对象的某个field值,并没有让Calendar对象全局生效。而查看源代码发现确实如此。
* 在调用内部computeFields 方法的时候设置的值才生效,而调用getTime方法就会调用computeFields
============================================
cal.add(Calendar.YEAR, 5);cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); //这时候取的年份并不是五年后的。
============================================
* 为了找出规律我调试了无数次,结果是没有找到规律,也没办法证实是由于源码中的哪一块造成的。
不过我找了两编文章有解释这种情况的,而且解释的比较清楚,我E文半桶水。就发原文地址供大家参考
http://stackoverflow.com/questions/6722542/java-calendar-date-is-unpredictable-after-setting-day-of-week
http://bugs.sun.com/view_bug.do?bug_id=4655637
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18083#c6
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