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

Ely*_* M. 26 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;
    }
}
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)

  • 对于不起作用的代码,这是很多赞成!DAY_OF_WEEK_IN_MONTH是要添加的错误字段.日期 (3认同)

Ste*_*cke 28

这是因为30 * 1000 * 60 * 60 * 24溢出Integer.MAX_VALUE,而20 * 1000 * 60 * 60 * 24不是.


Tom*_*icz 19

  1. Date不依赖于人类使用的任何日历系统.它只代表时间点.添加30天Date毫无意义,就像添加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();
    
    Run Code Online (Sandbox Code Playgroud)
  4. 使用DateUtils.addDays()Apache Commons Lang:

    DateUtils.add(date, 30);
    
    Run Code Online (Sandbox Code Playgroud)

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

  5. 或者完全避免这种地狱,去Joda Time.


SJu*_*n76 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
Run Code Online (Sandbox Code Playgroud)

总是建议使用日历或其他api(我听说过JodaTime,但没有使用它)来操纵日期.


Bas*_*que 5

tl;博士

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.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 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多