Java:减去日期的最简单方法

Java: Easiest Way to Subtract Dates

我创建了一个 class,其中包含两个需要日期的字段,start_datedate_passed。我一直在研究 java 中的最佳方法,使日期采用 YYYY MM DD 格式,这样可以轻松减去日期,并且能够 "make-up" 一个日期,例如将来的日期。

我希望它做什么的示例...

library.circulate_book("Chemistry", **start date here**) //actual date or random date
library.pass_book("Chemistry", **Date Passed here**) //random date such as 5 days after start date
int days_had = Date_Passed - start_date

到目前为止,我已经找到了很多使用日历和日期 classes 来格式化日期的方法,但还没有找到一种看起来可行的方法,因为大多数日期最终都是字符串。非常感谢任何 suggestions/small 个示例!此外,任何指向示例的链接都很棒!

使用Java8 DateAPI或Joda,不需要新发明。

您可以在此处找到一些示例:http://examples.javacodegeeks.com/core-java/java-8-datetime-api-tutorial/

如果您受困于较旧的 java,您可以使用 SimpleDateFormat。

    //For substraction
    long differenceInMillis = date1.getTime() - date2.getTime();

    //Date Format
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy MM dd");
    String dateAsString = dateFormat.format(date1); //To get a text representation
    Date dateParsed = dateFormat.parse(dateAsString); //To get it back as date

这是使用 Calendar 的答案:

Calendar cal = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();

cal2.setTime(cal.getTime());
cal2.add(Calendar.DAY_OF_YEAR, 5);
System.out.println((cal2.getTimeInMillis() - cal.getTimeInMillis()) / (1000d * 60 * 60 * 24));

tl;博士

从一个日期到另一个日期 adding/subtracting 几天。

LocalDate.now(
    ZoneId.of( "Pacific/Auckland" ) 
)
.minusDays( 5 )

计算两个日期之间经过的天数、月数和年数。

ChronoUnit.DAYS.between( start , stop )

正在解析

首先,您必须将字符串输入解析为日期时间对象。然后,您将使用这些对象对 business logic 进行预成型。

停止将日期时间值视为字符串,那会让您抓狂。我们在代码中使用日期时间对象;我们使用该日期时间对象的字符串表示与用户或其他应用程序交换数据。

在 Java 8 及更高版本中,使用 java.time framework. See Tutorial

您只需要日期,不需要时间,所以我们可以使用 LocalDate class.

这种时髦的双冒号语法是 method reference,一种说明其他代码应调用什么方法的方法。

String input = "2015 01 02";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "yyyy MM dd" );
LocalDate localDate = formatter.parse ( input , LocalDate :: from );

当前日期

确定今天的日期需要时区。对于任何给定的时刻,日期因地区而异。

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
LocalDate todayTunis = LocalDate.now( z ) ;

如果您想要 JVM 当前的默认时区,请调用 ZoneId.systemDefault

减去日期

这个问题已经在 StackOveflow.com 上多次提及。例如,How to subtract X days from a date using Java calendar?. For details, see other Answers such as this one by me and this one by me 了解更多详细信息。提示:“elapsed”是关键搜索词。

使用 ChronoUnit.DAYS 枚举计算经过的天数。

LocalDate weekLater = localDate.plusDays ( 7 );
long daysElapsed = java.time.temporal.ChronoUnit.DAYS.between( todayTunis , weekLater ) ;

转储到控制台。

System.out.println ( "localDate: " + localDate + " to " + weekLater + " in days: " + daysElapsed );

localDate: 2015-01-02 to 2015-01-09 in days: 7

在 Java-8 中做到这一点的最佳方法不是 Basil Bourque 的有缺陷的答案,而是这种方法:

String startDate = "2016 01 02";
String passedDate = "2016 02 29";

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy MM dd");
LocalDate date1 = LocalDate.parse(startDate, formatter);
LocalDate date2 = LocalDate.parse(passedDate, formatter);

long elapsedDays = ChronoUnit.DAYS.between(date1, date2);
System.out.println(elapsedDays); // 58 (correct)

建议使用 java.time.Period.getDays() 是危险的,而且一旦经过的持续时间超过一个月,通常就会出错。整个 Period 是 P1M27D 所以这段代码实际上只查询部分经过的天数(还有一个经过的月份):

System.out.println(Period.between(date1, date2).getDays()); // 27 (WRONG!!!)

很难找到使用 类 java.util.DateGregorianCalendar 等的令人满意的解决方案。 您可以使用 Tacktheritrix 的答案但必须注意这样一个事实,即计算的经过天数可能会因 java.util.Date 的小日部分而有所不同,并且由于忽略了夏令时开关(时钟跳动的地方),因此也不可靠在世界许多地方缩短一小时)。

旁注:至少 8 个外部库 也为您的问题提供了很好的答案。但我认为,除非您尚未使用 Java-8,否则您的简单用例并不能证明嵌入额外的库是合理的。如何计算两个日期之间经过的天数的任何替代解决方案都不会比 Java-8 更容易 - 只是相似。并且由于您接受了 Basil Bourque 的 Java-8 相关答案,我假设您确实在 Java-8 上,所以我省略了如何使用其他库解决您的问题的答案。

    LocalDate startDate = LocalDate.of(2009, 9, 1);
    LocalDate today = LocalDate.now();
    Period p = Period.between(startDate, today);
    System.out.println("Years " + p.getYears());
    System.out.println("Months " + p.getMonths());
    System.out.println("Days " + p.getDays());