为什么当我今天添加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;
}
}
Run Code Online (Sandbox Code Playgroud)
"这是控制台"
Jul 30, 2012
Aug 19, 2012
Jul 10, 2012
Run Code Online (Sandbox Code Playgroud)
Oli*_*alo 52
使用日历. 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();
Run Code Online (Sandbox Code Playgroud)
Tom*_*icz 19
Date不依赖于人类使用的任何日历系统.它只代表时间点.添加30天Date毫无意义,就像添加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();
Run Code Online (Sandbox Code Playgroud)使用DateUtils.addDays()Apache Commons Lang:
DateUtils.add(date, 30);
Run Code Online (Sandbox Code Playgroud)
这不违反上面所写的内容,它会转换为Calendar下面的内容.
或者完全避免这种地狱,去Joda Time.
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
Run Code Online (Sandbox Code Playgroud)
总是建议使用日历或其他api(我听说过JodaTime,但没有使用它)来操纵日期.
LocalDate.now().plusDays( 30 )
Run Code Online (Sandbox Code Playgroud)
正如其他人指出的那样,具体问题是 32 位整数溢出。
该代码还忽略了时区的关键问题。
更大的问题是尝试滚动您自己的日期时间计算,而不是使用像样的库。
Java 8 和更高版本中内置的 java.time 类取代了麻烦的旧日期时间类。
AnInstant是 UTC 时间线上的一个时刻,分辨率为纳秒。
Instant now = Instant.now();
Run Code Online (Sandbox Code Playgroud)
应用时区以获取ZonedDateTime.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
Run Code Online (Sandbox Code Playgroud)
现在加上你的 30 天。让 java.time 处理诸如夏令时 (DST) 之类的异常情况。
ZonedDateTime zdtLater = zdt.plusDays( 30 );
Run Code Online (Sandbox Code Playgroud)
或者你的意思是一个月。让 java.time 处理有关不同长度月份的详细信息。
ZonedDateTime zdtMonthLater = zdt.plusMonths( 1 );
Run Code Online (Sandbox Code Playgroud)
有关在新旧类型之间转换的信息,请参阅此问题。查看添加到旧类的新方法,例如:
java.util.Date utilDate = java.util.Date.from( zdt.toInstant() );
java.util.Calendar utilCalendar = java.util.GregorianCalendar.from( ZonedDateTime );
Run Code Online (Sandbox Code Playgroud)
如果您想要一个仅限日期的值,请使用LocalDate. 与上述相同的想法,添加天数或月数。
该java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat。
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310。
您可以直接与您的数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC 驱动程序。不需要字符串,不需要类。java.sql.*
从哪里获得 java.time 类?
该ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如Interval,YearWeek,YearQuarter,和更多。