简体   繁体   English

如何在两个Calendar对象之间转换确切的时间量(年,月,日,小时,分钟,秒)?

[英]How would I convert the exact amount of time (years, months, days, hours, minutes, seconds) between two Calendar objects?

I am trying to covert the exact amount of time between two Calendar objects in Java. 我试图隐瞒Java中两个Calendar对象之间的确切时间。

This is the code that I currently have... 这是我目前拥有的代码...

public static Map<TimeUnit, Long> computeDifference(Calendar date1, Calendar date2) { 

    long diffInMillies = date2.getTimeInMillis() - date1.getTimeInMillis();

    //create the list
    List<TimeUnit> units = new ArrayList<TimeUnit>();
    units.add(TimeUnit.SECONDS);
    units.add(TimeUnit.MINUTES);
    units.add(TimeUnit.HOURS);
    units.add(TimeUnit.DAYS);
    Collections.reverse(units);

    //create the result map of TimeUnit and difference
    Map<TimeUnit,Long> result = new LinkedHashMap<TimeUnit,Long>();
    long milliesRest = diffInMillies;

    for ( TimeUnit unit : units ) {

        //calculate difference in millisecond 
        long diff = unit.convert(milliesRest,TimeUnit.MILLISECONDS);
        long diffInMilliesForUnit = unit.toMillis(diff);
        milliesRest = milliesRest - diffInMilliesForUnit;

        //put the result in the map
        result.put(unit,diff);
    }

    return result;
}   

When printed, the output looks like this {DAYS=1, HOURS=10, MINUTES=30, SECONDS=45} for input date1 = 19 August 2019 02:00:00 and date2 = 20 August 2019 12:30:45 打印时,对于输入date1 = 19 August 2019 02:00:00date2 = 20 August 2019 12:30:45 ,输出看起来像这样{DAYS=1, HOURS=10, MINUTES=30, SECONDS=45}

The largest time unit available in this method is DAYS , but I want to find something that includes both months and years. 此方法中可用的最大时间单位是DAYS ,但是我想找到包含月份和年份的东西。 I realize that TimeUnit doesn't really have anything to do with specific calendar dates (rather a 24-hour interval), which is why I was wondering if there is any way to make this conversion using the Calendar class or something similar. 我意识到TimeUnit与特定的日历日期(实际上是24小时间隔)并没有任何关系,这就是为什么我想知道是否有任何方法可以使用Calendar类或类似的方法进行这种转换。 I've also looked into ChronoUnit as a substitute for TimeUnit, but that won't work for the same reason TimeUnit doesn't. 我还研究了ChronoUnit作为TimeUnit的替代品,但由于TimeUnit不能使用的相同原因而无法使用。

Would love any suggestions for how to incorporate larger time units. 希望有任何有关如何合并较大时间单位的建议。 Thank you! 谢谢!

You shouldn't use the Calendar class, since it's obsolete. 您不应该使用Calendar类,因为它已经过时了。 You should use classes from the java.time package instead. 您应该改用java.time包中的类。

In order to get the desired result, you could use the Period class. 为了获得所需的结果,可以使用Period类。

You first need to convert both Calendar instances to LocalDate instances . 您首先需要将两个Calendar实例都转换为LocalDate实例

Then you could use Period.between(startDate, endDate) to get a Period instance, which makes the getDays() , getMonths() and getYears() methods available to you. 然后,您可以使用Period.between(startDate, endDate)获得一个Period实例,该实例使getDays()getMonths()getYears()方法可用。


If you also want to include time components (hours, minutes and seconds), then you could use Duration in combination with Period . 如果您还想包括时间部分(小时,分钟和秒),则可以将DurationPeriod结合使用。 But then first read the post linked to by Sweeper. 但首先阅读由Sweeper链接的帖子

Something like this would probably work: 这样的事情可能会起作用:

LocalDateTime start = LocalDateTime.of(2019, 1, 1, 12, 0, 0);
LocalDateTime end = LocalDateTime.of(2021, 4, 26, 5, 56, 40);

Duration d = Duration.between(start.toLocalTime(), end.toLocalTime());
Period p = Period.between(start.toLocalDate(), end.toLocalDate());

// If the startdate's time component lies behind the enddate's time component,
// then we need to correct both the Period and Duration
if (d.isNegative()) {
    p = p.minusDays(1);
    d = d.plusDays(1);
}

System.out.printf("y %s m %s d %s h %s m %s s %s%n",
    p.getYears(),
    p.getMonths(),
    p.getDays(),
    d.toHours() % 24,
    d.toMinutes() % 60,
    d.getSeconds() % 60);

Note that Java 9 comes with to…Part methods, so you don't have to use the modulo operator anymore. 请注意,Java 9带有to…Part方法,因此您不必再使用模运算符。


Be advised: this code does not take into account clock adjustments due to daylight savings time. 请注意:由于夏令时,此代码未考虑时钟调整。

tl;dr tl; dr

Period
.between(
    ( ( GregorianCalendar ) myCalStart ).toZonedDateTime().toLocalDate() ,
    ( ( GregorianCalendar ) myCalStop ).toZonedDateTime().toLocalDate() 
)

…or… …要么…

Duration
.between(
    ( ( GregorianCalendar ) myCalStart ).toInstant() ,
    ( ( GregorianCalendar ) myCalStop ).toInstant() 
)

java.time java.time

You are using terrible date-time classes that were supplanted years ago by the modern java.time classes defined in JSR 310. 您使用的是可怕的日期时间类,而该类在几年前已被JSR 310中定义的现代java.time类所取代。

Never use Calendar , GregorianCalendar , Date , SimpleDateFormat , and such. 切勿使用CalendarGregorianCalendarDateSimpleDateFormat等。 Use only the classes found in the java.time packages. 仅使用java.time包中的类。

ZonedDateTime

Assuming both your Calendar objects are actually GregorianCalendar objects underneath, convert. 假设您的两个Calendar对象实际上都是其下方的GregorianCalendar对象,请进行转换。 To convert, call new to… / from… methods added to the old classes. 要进行转换,请to…添加到旧类的方法中调用new to… / from…方法。

// start
GregorianCalendar gcStart = ( GregorianCalendar ) myCalStart ;
ZonedDateTime zdtStart = gcStart.toZonedDateTime() ;

// stop
GregorianCalendar gcStop = ( GregorianCalendar ) myCalStop ;
ZonedDateTime zdtStop = gcStop.toZonedDateTime() ;

Both GregorianCalendar and ZonedDateTime represent a date with a time-of-day placed in the context of a time zone, combined to determine a moment (a specific point on the timeline). GregorianCalendarZonedDateTime代表一个日期,该日期中的一个时区放置在时区的上下文中,结合起来确定一个时刻(时间轴上的特定点)。 ZonedDateTime resolves to a finer level of nanoseconds rather than milliseconds. ZonedDateTime解析为更好的纳秒级别,而不是毫秒。

Period

If you care about elapsed time in terms of years-months-days, use Period with LocalDate objects. 如果您关心的是以年-月-日为单位的经过时间,则将PeriodLocalDate对象一起使用。 LocalDate represents a date without a time-of-day and without a time zone. LocalDate表示没有日期和时区的日期。 We can extract the date portion from our ZonedDateTime objects. 我们可以从ZonedDateTime对象中提取日期部分。

LocalDate ldStart = zdtStart.toLocalDate() ;
LocalDate ldStop = zdtStop.toLocalDate() ;
Period p = Period.between( ldStart , ldStop ) ;

Generate a string in standard ISO 8601 format. 生成标准ISO 8601格式的字符串。

String output = p.toString() ;

Interrogate for a count of years, months, days. 询问数年,数月,数天。

int years = p.getYears() ;
int months = p.getMonths() ;
int days = p.getDays() ;

Duration

If you cane about elapsed time in terms of hours-minutes-seconds, use Duration . 如果您希望以小时-分钟-秒为单位来计算经过时间,请使用Duration This class represent a pair of moments in UTC. 此类代表了UTC中的两个时刻。 So we extract Instant objects from our pair of ZonedDateTime objects, which internally keep a count of whole seconds since the epoch reference of first moment of 1970 in UTC, plus a fractional second as a count of nanoseconds. 因此,我们从一对ZonedDateTime对象中提取了Instant对象,这些对象从UTC 1970年第一时刻的纪元参考开始在内部保留整秒的计数,再加上小数秒(以纳秒为单位)。

Instant instantStart = zdtStart.toInstant() ;
Instant instantStop = zdtStop.toInstant() ;
Duration d = Duration.between( instantStart , instantStop ) ;

Generate a string in standard ISO 8601 format. 生成标准ISO 8601格式的字符串。

String output = d.toString() ;

Interrogate for a count of days (as 24-hour chunks of time unrelated to the calendar), hours, minutes, seconds. 询问数天(与日历无关的24小时时间段),小时,分钟,秒。

long days = d.toDaysPart() ;
int hours = d.toHoursPart() ;
int minutes = d.toMinutesPart() ;
int seconds = d.toSecondsPart() ;
int nanos = d.toNanosPart() ;

PeriodDuration

If you think about it, you will see that it does not make sense to combine years/months/days with 24-hour-days/hours/minutes/seconds. 如果您考虑一下,您会发现将年/月/日与24小时/天/小时/分钟/秒结合起来是没有意义的。 See this Stack Overflow page as food for thought. 请参阅此堆栈溢出页面,以供深思。

But if you insist on combining these two different concepts, see the PeriodDuration class found in the ThreeTen-Extra library. 但是,如果您坚持要结合这两个不同的概念,请参见在ThreeTen-Extra库中找到的PeriodDuration类。


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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何创建一个单个表达式来显示两个日期之间的时差,如年,月,日,小时,分钟,秒 - How to create a single expression displaying time difference between two Date's as years, months, days, hours, minutes, seconds 是否有API方法将BigDecimal(seconds)转换为年,月,日,小时,分钟,秒? - Is there API methods to convert BigDecimal(seconds) to years, months, days, hours, minutes, seconds? 计算年,月,日,小时,分钟和秒的年龄 - Calculate age in Years, Months, Days, Hours, Minutes, and Seconds Joda时间计算两个日期时间对象之间的天,小时,分钟和秒 - Joda time calculating the days, hours, minutes, and seconds between two datetime objects 使用JodaTime自动将秒数转换为年/日/小时/分钟? - Convert seconds to years/days/hours/minutes automatically, using JodaTime? 如何将时间单位从秒更改为天/月/年 - How to change time unit from seconds to days/months/years 如何在天数,小时数,分钟数和秒数之间获得2个日期之间的差异 - How to get difference between 2 dates in number of days,hours,minutes and seconds Java代码将秒转换为分钟,小时和天 - Java Code to convert seconds into minutes, hours and days 如何使用Joda-Time计算两个日期之间的年,月和天数 - How to calculate No of Years, Months and days between two dates using Joda-Time Java 将秒转换为具有独特输出的天、小时、分钟、秒 - Java convert seconds to days, hours, minutes, seconds with unique outputs
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM