【问题标题】:Organise number of days into separate sections for year, months, days, hours. Java将天数组织成年、月、日、小时的不同部分。爪哇
【发布时间】:2012-09-26 23:46:09
【问题描述】:

有没有办法将通过计算两个日期之间的差异来计算的天数组织到不同的部分,例如对于 364 天,它将是:0 年、11 个月、30 天、小时、分钟等。 我认为使用逻辑运算符可能像 % 和 / 一样工作,但由于不同的月份有不同的天数,有些年份是闰年,我不知道该怎么做。任何帮助将非常感激。我的代码:

import java.util.*;

public class CleanDate {

    public static void main(String[] args) {
        Calendar cDate = GregorianCalendar.getInstance();
        cDate.set(2011, 0, 31, 00, 00, 00);
        Date date1 = cDate.getTime();
        Date date2 = new Date();
        Calendar calendar1 = Calendar.getInstance();
        Calendar calendar2 = Calendar.getInstance();
        calendar1.setTime(date1);
        calendar2.setTime(date2);
        long milliseconds1 = calendar1.getTimeInMillis();
        long milliseconds2 = calendar2.getTimeInMillis();
        long diff = milliseconds2 - milliseconds1;
        long diffSeconds = diff / 1000;
        long diffMinutes = diff / (60 * 1000);
        long diffHours = diff / (60 * 60 * 1000);
        long diffDays = diff / (24 * 60 * 60 * 1000);
        System.out.println("Time in minutes: " + diffMinutes + " minutes.");
        System.out.println("Time in hours: " + diffHours + " hours.");
        System.out.println("Time in days: " + diffDays + " days.");
    }
}

【问题讨论】:

  • 学习和使用JODA时间。这不是一个好主意。
  • 一个时间段有多长,比如说,“两个月,十一天”
  • 我希望用户定义时间段,因此用户输入日期并输出自该日期以来的年、月、日。我会调查乔达时间。感谢您的帮助
  • 顺便说一下,不要在文字数字上使用前导零,因为它在 Java 中读作 octal number

标签: java date calendar gregorian-calendar


【解决方案1】:

您可以像这样有效地使用 Joda Time: Interval 允许获取两个日期之间的时间间隔。

DateTime end = new DateTime(2006, 1, 1, 0, 0, 0, 0);
Interval interval = new Interval(start, end);
Period period = interval.toPeriod();
System.out.println(period.getYears()+" years, "
period.getMonths()+" months, "+period.getWeeks()+" weeks, "+period.getDays()+", days");

【讨论】:

【解决方案2】:

tl;博士

Duration.between(          // Represent a span-of-time unattached to the timeline, on scale of days-hours-minutes-seconds.
    ZonedDateTime          // Represent a moment in the wall-clock time used by the people of a particular region (a time zone). 
    .of( 2011 , 1 , 31 , 0 , 0 , 0 , 0 , ZoneId.of( "Africa/Tunis" ) )
    ,
    ZonedDateTime.of( … ) 
)                          // Returns a `Duration` object.
.toDaysPart()              // Or `toHoursPart`, `toMinutesPart`, `toSecondsPart`, `toNanosPart`. These return either a `long` or an `int`. 

java.time

现代方法使用 java.time 类,而不是可怕的旧 DateCalendar 类。在other Answer 中看到的Joda-Time 库也被java.time 所取代。

指定日期和时间需要时区来确定准确的时刻。对于任何给定的时刻,日期和时间都因全球区域而异。

continent/region 的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用 3-4 个字母的缩写,例如 ESTIST,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。

ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;

如果您想要一天的第一时间,让 java.time 确定该日期在该区域中的时间。一天总是从00:00:00开始。

LocalDate ld = LocalDate.of( 2011 , Month.JANUARY , 31 ) ;
ZonedDateTime start = ld.atStartOfDay( z ) ;  // Let java.time determine the first moment of the day. Never assume 00:00:00.

使用 Duration 类计算经过的天数(实际上是 24 小时的时间块)、小时、分钟和秒。对于年-月-日(日历日,而不是 24 小时时间段),请使用 Period 类。

ZonedDateTime stop = … ;
Duration d = Duration.between( start , stop ) ;

使用标准ISO 8601 格式的文本生成String 对象。

String output = d.toString() ;  // Generate standard ISO 8601 text.

PT2H3M42.725S

提取各个部分。

long days = d.toDaysPart() ;       // 24-hour chunks of time, *not* calendar days.
int hours = d.toHoursPart() ;
int minutes = d.toMinutesPart() ;
int seconds = d.toSecondsPart() ;
int nanos = d.toNanosPart() ;      // Fractional second as a count of nanoseconds, from 0 to 999,999,999.

年-月-日与日-时-分-秒

如果您考虑一下,尝试用年-月-日-小时-分钟-秒来表示时间跨度几乎没有意义。涉及到一些棘手的问题,例如日历天与 24 小时时间段,以及日期长度不同的事实,例如 23、24、25 或其他小时数。

但如果你真的坚持这种方法,请将ThreeTen-Extra 库添加到你的项目中以访问PeriodDuration 类。此类尝试将这两个概念结合起来。

ISO-8601 日历系统中的时间量,它结合了周期和持续时间。

此类根据 Period 和 Duration 对时间量或时间量进行建模。期间是基于日期的时间量,由年、月和日组成。持续时间是基于时间的时间量,由秒和纳秒组成。有关详细信息,请参阅 Period 和 Duration 类。

一段时间内的天数考虑了夏令时的变化(23 或 25 小时天)。执行计算时,首先添加期间,然后添加持续时间。


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。

从哪里获得 java.time 类?

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-14
    • 2018-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多