如何在Java中从日期对象中减去X天?

220

我想做这样的事情:

Date date = new Date(); // current date
date = date - 300; // substract 300 days from current date and I want to use this "date"

如何做到?


4
必须“使用Joda Time”备注。 - Steve McLeod
FYI,诸如java.util.Date之类的老旧日期时间类现在已经成为遗留系统,被Java.time类所取代。 - Basil Bourque
10个回答

394

Java 8及以后版本

随着Java 8的日期时间API改变,使用LocalDate

LocalDate date = LocalDate.now().minusDays(300);

同样地,您可以拥有

LocalDate date = someLocalDateInstance.minusDays(300);

请参考 https://dev59.com/vGIk5IYBdhLWcg3wRMNR#23885950 中有关 Java.util.Date 与 Java.time.LocalDateTime 之间转换的翻译。

Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());

Java 7及更早版本

使用Calendar类的add()方法。

Calendar cal = Calendar.getInstance();
cal.setTime(dateInstance);
cal.add(Calendar.DATE, -30);
Date dateBefore30Days = cal.getTime();

22
如果您不希望考虑当前日期时间,可以设置自定义的dateInstance。 - jmj
18
Java的日期处理非常臃肿! - digory doo
1
这是4年前的答案。最近的版本中已经对DateTime API进行了更改。我将编辑答案。 - jmj
请注意,旧的日期时间类(例如java.util.Datejava.util.Calendarjava.text.SimpleTextFormat)现在已经成为遗留系统,被Java.time类所取代。请参阅Oracle的教程 - Basil Bourque
大多数 java.time 功能已在 ThreeTen-Backport 项目中向 Java 6 和 Java 7 进行了回溯。进一步适用于早期 Android 的 ThreeTenABP 项目。请参阅 如何使用 ThreeTenABP… - Basil Bourque
显示剩余4条评论

72

@JigarJoshi这是好答案,当然也要感谢@Tim的建议使用joda-time

我只想添加更多从java.util.Date中减去天数的可能性。

Apache-commons

一种可能性是使用apache-commons-lang。你可以使用DateUtils实现如下:

Date dateBefore30Days = DateUtils.addDays(new Date(),-30);

当然要做日期减法,添加 commons-lang 依赖可能不是一个好选择,但如果您已经在使用 commons-lang,那么这是一个不错的选择。此外,还有方便的方法可以进行 addYearsaddMonthsaddWeeks 等操作,请在此处查看 API。

Java 8

另一种可能性是利用 Java 8 中的新LocalDate,使用 minusDays(long days) 方法:

LocalDate dateBefore30Days = LocalDate.now(ZoneId.of("Europe/Paris")).minusDays(30);

没有必要使用 LocalDateTime,因为该类故意没有时区或UTC偏移量的概念。仅在区域/偏移量未知或不相关时使用它。相反,使用 LocalDate 并在调用其 now 方法时传递一个 ZoneId。请参见 Jacob van Lingen 的 正确答案 - Basil Bourque
1
@BasilBourque 经过您的建议,我检查了API,您是完全正确的,因此我更新了答案。谢谢。 - albciff
Brian Montellano希望发表评论:DateUtils 中不应该有任何s,应该只是 DateUtil - Ole V.V.
@OleV.V. Brian Montellano错了,你可以查看DateUtils文档。 - albciff

43

使用此代码获取300天之前的日期,将300替换为您所需的天数:

Date date = new Date(); // Or where ever you get it from
Date daysAgo = new DateTime(date).minusDays(300).toDate();

这里,

DateTimeorg.joda.time.DateTime;

Datejava.util.Date


9
Joda-Time 项目现在处于 维护模式,建议迁移到 java.time 类。 - Basil Bourque

35

Java 8 时间 API:

Instant now = Instant.now(); //current date
Instant before = now.minus(Duration.ofDays(300));
Date dateBefore = Date.from(before);

我必须指的是Java 8 API,而不是7。提到“java.time”包可能会有所帮助。此外,在Stack Overflow上通常期望进行一些讨论/解释,而不仅仅是代码片段。您应该明确解释“Duration”,因为这是您的答案相对于van Lingen的现有答案的附加值。 - Basil Bourque
Java 8 当然没问题,已经解决了。 - Grigory Kislin
非常接近,但应该用于修改任意日期对象,而不是“现在”。 - bharal

12

正如您可以在这里看到的,有很多操作可以进行。以下是一个示例,展示了您可以做什么!

DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Calendar cal = Calendar.getInstance();

//Add one day to current date.
cal.add(Calendar.DATE, 1);
System.out.println(dateFormat.format(cal.getTime()));

//Substract one day to current date.
cal = Calendar.getInstance();
cal.add(Calendar.DATE, -1);
System.out.println(dateFormat.format(cal.getTime()));

/* Can be Calendar.DATE or
*  Calendar.MONTH, Calendar.YEAR, Calendar.HOUR, Calendar.SECOND
*/

@Jigar Joshi:我没有看到你的答案... 我应该删除我的吗? - waldyr.ar
请注意,诸如java.util.Datejava.util.Calendarjava.text.SimpleDateFormat 等极其麻烦的旧日期时间类现已成为遗留系统,已被构建在Java 8及更高版本中的java.time类所取代。请参阅Oracle的Tutorial - Basil Bourque

10

使用Java 8,现在非常简单:

 LocalDate date = LocalDate.now().minusDays(300);

一个关于新API的好指南可以在这里找到。


4
建议在调用 now 方法时始终传递可选的时区信息(或UTC偏移量)。如果忽略不传递时区信息,则 JVM 的当前默认时区会被隐式地应用,而这个默认时区是无法控制的,即使在运行时它也可能随时发生变化。例如:LocalDate.now( ZoneId.of( "America/Montreal" ) - Basil Bourque
需要根据问题使用任意日期对象,而不是“现在”。 - bharal

3

在Java 8中,您可以这样做:

Instant inst = Instant.parse("2018-12-30T19:34:50.63Z"); 

// subtract 10 Days to Instant 
Instant value = inst.minus(Period.ofDays(10)); 
// print result 
System.out.println("Instant after subtracting Days: " + value); 

1
我已经创建了一个函数来使任务更容易。
  • 计算日期字符串后的7天:dateCalculate(dateString,"yyyy-MM-dd",7);

  • 获取日期字符串前7天:dateCalculate(dateString,"yyyy-MM-dd",-7);


public static String dateCalculate(String dateString, String dateFormat, int days) {
    Calendar cal = Calendar.getInstance();
    SimpleDateFormat s = new SimpleDateFormat(dateFormat);
    try {
        cal.setTime(s.parse(dateString));
    } catch (ParseException e) {
        e.printStackTrace();
    }
    cal.add(Calendar.DATE, days);
    return s.format(cal.getTime());
}

此答案使用了一些麻烦的旧日期时间类,例如java.util.Datejava.util.Calendarjava.text.SimpleDateFormat,这些类现在已经过时,被Java.time所取代。请参阅Oracle教程 - Basil Bourque
这个问题涉及到日期时间对象,而不是生成字符串。顺便说一下,LocalDate.parse("2017-01-23").plusWeeks(1) 比编写自己的方法更简单,并且更易于自我记录。 - Basil Bourque

1

您也可以使用Duration类。例如:

Date currentDate = new Date();
Date oneDayFromCurrentDate = new Date(currentDate.getTime() - Duration.ofDays(1).toMillis());

0

你可以使用SimpleDateFormat轻松地对日历进行减法操作

 public static String subtractDate(String time,int subtractDay) throws ParseException {


        Calendar cal = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ENGLISH);
        cal.setTime(sdf.parse(time));
        cal.add(Calendar.DATE,-subtractDay);
        String wantedDate = sdf.format(cal.getTime());

        Log.d("tag",wantedDate);
        return wantedDate;

    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接