如何使用Java日历从日期中减去X天?


Answers:


308

文档中获取

根据日历的规则,在给定的日历字段中添加或减去指定的时间量。例如,要从日历的当前时间中减去5天,可以通过调用以下方法来实现:

Calendar calendar = Calendar.getInstance(); // this would default to now
calendar.add(Calendar.DAY_OF_MONTH, -5).

1
请小心执行此操作,因为它并不总是像您期望的那样滚动。
卡森,

1
这个答案有很多支持,但是使用安全吗?还是比较好:stackoverflow.com/a/10796111/948268
Kuldeep Jain 2014年

44
Calendar.DAY_OF_MONTH在这种情况下,您不会使用它,因为它将无法按您希望的那样在几个月之间处理滚动。使用Calendar.DAY_OF_YEAR替代
算法

4
这应该是安全的,显然,在添加时,不管是DAY_OF_MONTH还是DAY_OF_YEAR stackoverflow.com/q/14065198/32453
rogerdpack 2014年

@carson这种方法有什么问题?
tatmanblue

38

您可以使用该add方法并将其传递为负数。但是,您也可以编写一个不使用Calendar此类的更简单的方法,如下所示

public static void addDays(Date d, int days)
{
    d.setTime( d.getTime() + (long)days*1000*60*60*24 );
}

这将获取日期的时间戳值(自纪元以来的毫秒数),并添加适当的毫秒数。您可以为days参数传递一个负整数以进行减法。这比“适当的”日历解决方案更简单:

public static void addDays(Date d, int days)
{
    Calendar c = Calendar.getInstance();
    c.setTime(d);
    c.add(Calendar.DATE, days);
    d.setTime( c.getTime().getTime() );
}

请注意,这两个解决方案都更改了Date作为参数传递的对象,而不是返回一个全新的对象Date。如果需要,可以很容易地将任一功能更改为另一种功能。


3
不要相信.setTime和.add是Calendar的静态方法。您应该使用实例变量c。
爱德华

@爱德华:您是对的,感谢您指出我的错误,我已经修复了代码,现在可以正常工作了。
伊莱·考特赖特

3
注意第一种方法,例如在处理leap年时可能会失败:stackoverflow.com/a/1006388/32453
rogerdpack

仅供参考,麻烦的旧日期时间类(例如java.util.Calendar现在已被遗留的类)已由java.time类取代。请参见Oracle教程
罗勒·布尔克

36

Anson的答案在简单的情况下会很好用,但是如果您要进行更复杂的日期计算,我建议您查看Joda Time。这将使您的生活更加轻松。

仅供参考,您可以在Joda做

DateTime dt = new DateTime();
DateTime fiveDaysEarlier = dt.minusDays(5);

1
@ShahzadImam,签出DateTimeFormat。它将允许您使用任意格式将DateTime实例转换为字符串。它与java.text.DateFormat类非常相似。
Mike Deck 2012年

1
从Java 8中考虑使用java.time docs.oracle.com/javase/8/docs/api/java/time/...
toidiu

仅供参考,Joda-Time项目现在处于维护模式,团队建议迁移到java.time类。请参见Oracle教程
罗勒·布尔克

19

tl; dr

LocalDate.now().minusDays( 10 )

最好指定时区。

LocalDate.now( ZoneId.of( "America/Montreal" ) ).minusDays( 10 )

细节

旧的日期时间类与Java的早期版本捆绑在一起,例如java.util.Date/.Calendar事实证明是麻烦,混乱和有缺陷的。避免他们。

java.time

Java 8和更高版本用新的java.time框架取代了那些旧类。请参阅教程。由JSR 310定义,受Joda-Time启发,并由ThreeTen-Extra项目扩展。ThreeTen-Backport项目将类反向移植到Java 6和7。Android的ThreeTenABP项目。

该问题含糊不清,不清楚是要求仅日期还是日期时间。

LocalDate

对于仅日期而没有时间的日期,请使用LocalDate该类。请注意,时区对于确定日期(例如“今天”)至关重要。

LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );
LocalDate tenDaysAgo = today.minusDays( 10 );

ZonedDateTime

如果您指的是日期时间,请使用Instant该类在UTC的时间轴上获取时间。从那里调整到时区以获取ZonedDateTime对象。

Instant now = Instant.now();  // UTC.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
ZonedDateTime tenDaysAgo = zdt.minusDays( 10 );

Java中的日期时间类型表,包括现代的和传统的。


关于java.time

java.time框架是建立在Java 8和更高版本。这些类取代麻烦的老传统日期时间类,如java.util.DateCalendar,和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,和更多


与其他选项相比,这是一个更好的改进(它也很新,并且使用了新方法)。如果您现在正在访问此问题,这就是方法。
Shourya Bansal


5

而不是写我自己addDays的礼的建议,我会更喜欢使用DateUtils来自Apache的。它非常方便,特别是当您必须在项目中的多个位置使用它时。

API说:

addDays(Date date, int amount)

在返回新对象的日期中增加天数。

请注意,它返回一个新Date对象,并且不会更改前一个对象本身。


2

通过以下操作可以轻松完成

Calendar calendar = Calendar.getInstance();
        // from current time
        long curTimeInMills = new Date().getTime();
        long timeInMills = curTimeInMills - 5 * (24*60*60*1000);    // `enter code here`subtract like 5 days
        calendar.setTimeInMillis(timeInMills);
        System.out.println(calendar.getTime());

        // from specific time like (08 05 2015)
        calendar.set(Calendar.DAY_OF_MONTH, 8);
        calendar.set(Calendar.MONTH, (5-1));
        calendar.set(Calendar.YEAR, 2015);
        timeInMills = calendar.getTimeInMillis() - 5 * (24*60*60*1000);
        calendar.setTimeInMillis(timeInMills);
        System.out.println(calendar.getTime());

这个答案是不明智的,它使用了现在已经遗留下来的可怕的旧日期时间类,被java.time类取代了。此外,该代码忽略了时区这一至关重要的问题,它天真地假设是24小时制。另一个问题是使用日期时间类来解决仅日期问题。使用LocalDate起来更简单,更合适。
罗勒·布尔克

1

有人推荐Joda Time,所以-我一直在使用CalendarDatehttp://calendardate.sourceforge.net

对于Joda Time而言,这是一个颇具竞争性的项目,但仅2节课就更为基础。它非常方便,并且可以很好地满足我的需求,因为我不想使用比我的项目更大的软件包。与Java语言不同,它的最小单位是天,因此它实际上是一个日期(不包括毫秒)。创建日期后,您要做的所有事情就是减去myDay.addDays(-5)来返回5天。您可以使用它来查找星期几以及类似的内容。另一个例子:

CalendarDate someDay = new CalendarDate(2011, 10, 27);
CalendarDate someLaterDay = today.addDays(77);

和:

//print 4 previous days of the week and today
String dayLabel = "";
CalendarDate today = new CalendarDate(TimeZone.getDefault());
CalendarDateFormat cdf = new CalendarDateFormat("EEE");//day of the week like "Mon"
CalendarDate currDay = today.addDays(-4);
while(!currDay.isAfter(today)) {
    dayLabel = cdf.format(currDay);
    if (currDay.equals(today))
        dayLabel = "Today";//print "Today" instead of the weekday name
    System.out.println(dayLabel);
    currDay = currDay.addDays(1);//go to next day
}

1

我相信可以使用java.time.Instant类实现一种干净而又不错的方法来进行任何时间单位(月,日,小时,分钟,秒,...)的减法或加法。

从当前时间中减去5天并将结果作为日期的示例:

new Date(Instant.now().minus(5, ChronoUnit.DAYS).toEpochMilli());

减去1小时加15分钟的另一个示例:

Date.from(Instant.now().minus(Duration.ofHours(1)).plus(Duration.ofMinutes(15)));

如果您需要更高的精度,那么Instance的测量时间可以达到纳秒。操纵纳秒部分的方法:

minusNano()
plusNano()
getNano()

另外,请记住,日期不如即时准确。


1
还是取决于口味,短一些:Date.from(Instant.now().minus(5, ChronoUnit.DAYS))
Ole VV

1
真好!你是对的。我实际上更新了答案以使用此方法,并且还展示了java.time.Duration类的用法,在这种情况下,该类也非常有效。
Yordan Boev

0

Eli Courtwright第二种解决方案是错误的,应该是:

Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(Calendar.DATE, -days);
date.setTime(c.getTime().getTime());

2
Eli解决方案中的函数名称为addDays; 他的解决方案是正确的。如果您想从日期中减去天数,请输入的负值days
Thomas Upton 2010年

好吧,这是程序员在创建函数时必须指定的东西,不是吗?:P
user178973
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.