为什么当我今天添加30天到达今天的时候 - 30,当我加20时它会增加??
这是一个示例
import java.text.DateFormat;
import java.util.Date;
public class DatePlus
{
public static void main(String[] args)
{
Date now = new Date();
Date now1 = new Date();
Date now2 = new Date();
DateFormat currentDate = DateFormat.getDateInstance();
Date addedDate1 = addDays(now2, 20);
Date addedDate2 = addDays(now1, 30);
System.out.println(currentDate.format(now));
System.out.println(currentDate.format(addedDate1));
System.out.println(currentDate.format(addedDate2));
}
public static Date addDays(Date d, int days)
{
d.setTime(d.getTime() + days * 1000 * 60 * 60 * 24);
return d;
}
}
“这是控制台”
Jul 30, 2012
Aug 19, 2012
Jul 10, 2012
答案 0 :(得分:50)
使用日历。 http://docs.oracle.com/javase/6/docs/api/java/util/GregorianCalendar.html
伪代码:
Calendar c=new GregorianCalendar();
c.add(Calendar.DATE, 30);
Date d=c.getTime();
答案 1 :(得分:28)
这是因为30 * 1000 * 60 * 60 * 24
溢出Integer.MAX_VALUE
,而20 * 1000 * 60 * 60 * 24
则没有。{/ p>
答案 2 :(得分:18)
Date
与人类使用的任何日历系统无关。它只代表时间点。向Date
添加30天是没有意义的,就像在红色颜色中添加20一样。
添加1000 * 60 * 60 * 24
的常用方法是错误的。您正在添加86400秒,但有一天不一定是86400秒。由于dst,它可以长一小时或更短。由于闰秒,它可以长一秒或更短。
要做的是将Date
转换为Calendar
(实际上代表某个日历系统,如GregorianCalendar
。然后只需添加天数:
Calendar calendar = new GregorianCalendar(/* remember about timezone! */);
calendar.setTime(date);
calendar.add(Calendar.DATE, 30);
date = calendar.getTime();
使用Apache Commons Lang的DateUtils.addDays()
:
DateUtils.add(date, 30);
这不违反上面所写的内容,它会转换为下面的Calendar
。
或完全避免这种情况,然后选择Joda Time。
答案 3 :(得分:5)
days
是一个整数。
30 * 1000 * 60 * 60 * 24为2,592,000,000,大于2,147,483,647(Java中最大的int)。你有一个缓冲区溢出,你的结果是一个相当小的负数(检查它是二进制,转换回int作为2补充)
简单的解决方法是将其中一个值转换为long,以便将表达式的结果存储为long,它可以保存该值而不会溢出。
(long) days * 1000L * 60 * 60 * 24
始终建议使用日历或其他api(我听说过JodaTime,但未使用它)来操纵日期。
答案 4 :(得分:4)
您在计算中遇到整数溢出。天* 1000 * 60 * 60 * 24的值大于天数= 30时有符号int允许的最大值,但是当天= 20时则不大。当你增加一个有符号整数时,它的最大可能值是,而不是增加价值,标志翻转,它变为负面!这就是为什么你的日期倒退 - 你正在为它添加一个负数。
要解决此问题,您可以使用long数据类型,其最大值大于整数,如下所示:
long secondsToAdd = days;
secondsToAdd *= (1000*60*60*24);
d.setTime(d.getTime() + secondsToAdd);
答案 5 :(得分:3)
LocalDate.now().plusDays( 30 )
正如其他人所指出的那样,具体问题是32位整数溢出。
该代码也忽略了时区的关键问题。
更大的问题是尝试滚动自己的日期时间计算而不是使用体面的库。
Java 8及更高版本中内置的java.time类取代了麻烦的旧日期时间类。
Instant
是UTC时间轴上的一个时刻,分辨率为纳秒。
Instant now = Instant.now();
应用时区以获得ZonedDateTime
。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
现在添加你的30天。让java.time处理异常,例如夏令时(DST)。
ZonedDateTime zdtLater = zdt.plusDays( 30 );
或许你的意思是一个月。让java.time处理有关不同长度的月份的详细信息。
ZonedDateTime zdtMonthLater = zdt.plusMonths( 1 );
有关在新旧类型之间进行转换的信息,请参阅this Question。查看添加到旧类的新方法,例如:
java.util.Date utilDate = java.util.Date.from( zdt.toInstant() );
java.util.Calendar utilCalendar = java.util.GregorianCalendar.from( ZonedDateTime );
如果您想要仅限日期的值,请使用LocalDate
。与上述相同,添加天或月。
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和& SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。
答案 6 :(得分:0)
使用此功能:
public static String addToCurrentDate(String format,int day,int month,int year){
DateFormat dateFormat = new SimpleDateFormat(format);
Calendar calendarInstance = Calendar.getInstance();
calendarInstance.add(Calendar.YEAR, year);
calendarInstance.add(Calendar.MONTH, month);
calendarInstance.add(Calendar.DATE, day);
return dateFormat.format(calendarInstance.getTime());
}