在java中添加30天到目前为止

时间:2012-07-30 19:04:12

标签: java

为什么当我今天添加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

7 个答案:

答案 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)

  1. Date与人类使用的任何日历系统无关。它只代表时间点。向Date添加30天是没有意义的,就像在红色颜色中添加20一样。

  2. 添加1000 * 60 * 60 * 24的常用方法是错误的。您正在添加86400秒,但有一天不一定是86400秒。由于,它可以长一小时或更短。由于闰秒,它可以长一秒或更短。

  3. 要做的是将Date转换为Calendar(实际上代表某个日历系统,如GregorianCalendar。然后只需添加天数:

    Calendar calendar = new GregorianCalendar(/* remember about timezone! */);
    calendar.setTime(date);
    calendar.add(Calendar.DATE, 30);
    date = calendar.getTime();
    
  4. 使用Apache Commons Lang的DateUtils.addDays()

    DateUtils.add(date, 30);
    

    这不违反上面所写的内容,它会转换为下面的Calendar

  5. 或完全避免这种情况,然后选择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)

TL;博士

LocalDate.now().plusDays( 30 )

详细

正如其他人所指出的那样,具体问题是32位整数溢出。

该代码也忽略了时区的关键问题。

更大的问题是尝试滚动自己的日期时间计算而不是使用体面的库。

java.time

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.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance 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的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore

答案 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());
    }