【问题标题】:Java: Easiest Way to Subtract DatesJava:减去日期的最简单方法
【发布时间】:2016-02-05 10:17:44
【问题描述】:

我创建了一个类,其中有两个字段需要日期,start_datedate_passed。我一直在研究 Java 中将日期设为YYYY MM DD 格式的最佳方法,该格式允许轻松减去日期,以及“弥补”日期的能力,例如将来。

我希望它做的示例...

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

到目前为止,我已经找到了很多使用日历和日期类来格式化日期的方法,但是考虑到大多数日期最终都是字符串,我还没有找到一种看起来可以工作的方法。非常感谢任何建议/小例子!此外,任何指向示例的链接都很棒!

【问题讨论】:

    标签: java date datepicker calendar subtraction


    【解决方案1】:

    使用 Java 8 Date API 或 Joda,无需新发明。

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

    【讨论】:

    • Joda 有一个 daysBetween 方法可能会达到目的。
    • joda 到底是什么,我如何获得它?
    • 不,它实际上在我们学校的系统上被阻止了,运气对吧?
    • 要使这个成为真正的答案,而不是仅链接的答案,请展示如何使用 java 8 date api 和/或 joda time 来做到这一点。
    • 我虽然对此有所了解 - 但网络上已经有数千个完全合格的示例 - 为什么还要创建另一个...
    【解决方案2】:

    如果您被较旧的 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
    

    【讨论】:

      【解决方案3】:

      这是使用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));
      

      【讨论】:

        【解决方案4】:

        tl;博士

        通过加/减天数从一个日期移动到另一个日期。

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

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

        ChronoUnit.DAYS.between( start , stop )
        

        解析

        首先,您必须将字符串输入解析为日期时间对象。然后,您可以使用这些对象来构建您的 business logic

        不要将日期时间值视为字符串,这会让你发疯。我们在代码中使用日期时间对象;我们使用该日期时间对象的字符串表示形式与用户或其他应用交换数据。

        在 Java 8 及更高版本中,使用 java.time 框架。见Tutorial

        您只需要一个日期,没有时间,所以我们可以使用LocalDate 类。

        那个时髦的双冒号语法是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?。有关详细信息,请参阅this one by methis 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 到 2015-01-09 天数:7

        【讨论】:

        • 很好的回应,我正在查看 LocalDate 方法,我可能读错了,但是有没有只返回本地日期的方法,例如今天的2015 04 11?跨度>
        • now() 能否在程序后面的日期中减去,例如 LocalDate localDate = formatter.parse ( input , LocalDate :: from );
        • @user38254 您似乎仍然坚持将日期时间值与其字符串表示形式混为一谈。要获得“今天”,只需致电LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) ;)。时区对于确定日期至关重要(考虑一下!)。对于字符串,使用与上面相同的格式化程序:String output = today.format( formatter );。搜索有关此主题的其他 StackOveflow 页面。
        • 这个答案的问题是.getDays 不会得到两个日期之间的绝对天数,它会得到以月/年为模的天数。 ChronoUnit 方法没有这个缺点。
        • @Logister 你是对的,我的代码有缺陷。现在更正了。感谢您举报。
        【解决方案5】:

        在 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,所以我省略了如何解决您与其他库的问题的答案。

        【讨论】:

        • Java 8 中的日期时间更改本应让生活变得轻松,但有时找到这些东西确实很难:)
        猜你喜欢
        • 2018-12-27
        • 1970-01-01
        • 2010-09-07
        • 2012-10-07
        • 1970-01-01
        • 2016-08-31
        • 2018-06-11
        • 1970-01-01
        • 2018-06-08
        相关资源
        最近更新 更多