为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

蛊毒传说 2023-06-14 14:39:03
我试图隐藏 Java 中两个 Calendar 对象之间的确切时间量。这是我目前拥有的代码......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;}   打印时,输出看起来像这样{DAYS=1, HOURS=10, MINUTES=30, SECONDS=45}输入date1 = 19 August 2019 02:00:00和date2 = 20 August 2019 12:30:45此方法中可用的最大时间单位是DAYS,但我想找到同时包含月份和年份的内容。我意识到 TimeUnit 与特定的日历日期(而不是 24 小时间隔)没有任何关系,这就是为什么我想知道是否有任何方法可以使用 Calendar 类或类似的东西进行这种转换。我还研究了 ChronoUnit 作为 TimeUnit 的替代品,但由于 TimeUnit 不起作用的相同原因,它不起作用。会喜欢关于如何合并更大的时间单位的任何建议。谢谢你!
查看完整描述

2 回答

?
慕神8447489

TA贡献1780条经验 获得超1个赞

你不应该使用这个Calendar类,因为它已经过时了。您应该改用java.time包中的类。

为了获得所需的结果,您可以使用该类Period

您首先需要将两个Calendar实例都转换为LocalDateinstances。

然后您可以使用Period.between(startDate, endDate)to 获取一个Period实例,这使得getDays()getMonths()方法getYears()对您可用。


如果您还想包括时间组件(小时、分钟和秒),那么您可以Duration结合使用Period

这样的事情可能会起作用:

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);

请注意,Java 9 附带to…Part方法,因此您不必再使用模运算符。


请注意:由于夏令时,此代码未考虑时钟调整。


查看完整回答
反对 回复 2023-06-14
?
守候你守候我

TA贡献1802条经验 获得超10个赞

Period

.between(

    ( ( GregorianCalendar ) myCalStart ).toZonedDateTime().toLocalDate() ,

    ( ( GregorianCalendar ) myCalStop ).toZonedDateTime().toLocalDate() 

)

…或者…


Duration

.between(

    ( ( GregorianCalendar ) myCalStart ).toInstant() ,

    ( ( GregorianCalendar ) myCalStop ).toInstant() 

)

java.time

您正在使用多年前被 JSR 310 中定义的现代java.time类所取代的可怕的日期时间类。

切勿使用CalendarGregorianCalendarDate,SimpleDateFormat等。仅使用在java.time包中找到的类。

ZonedDateTime

假设您的两个Calendar对象实际上都是GregorianCalendar下面的对象,请转换。要进行转换,请调用添加到旧类的新to…/方法。from…


// start

GregorianCalendar gcStart = ( GregorianCalendar ) myCalStart ;

ZonedDateTime zdtStart = gcStart.toZonedDateTime() ;


// stop

GregorianCalendar gcStop = ( GregorianCalendar ) myCalStop ;

ZonedDateTime zdtStop = gcStop.toZonedDateTime() ;

和 都GregorianCalendar代表ZonedDateTime一个日期和一个时区上下文中的时间,结合起来确定一个时刻(时间轴上的特定点)。ZonedDateTime解析到更精细的纳秒级而不是毫秒级。

Period

如果您关心以年-月-日为单位的经过时间,请使用Period对象LocalDateLocalDate表示没有时间和时区的日期。我们可以从我们的对象中提取日期部分ZonedDateTime

LocalDate ldStart = zdtStart.toLocalDate() ;

LocalDate ldStop = zdtStop.toLocalDate() ;

Period p = Period.between( ldStart , ldStop ) ;

生成标准ISO 8601格式的字符串。


String output = p.toString() ;

询问数年、数月、数日。


int years = p.getYears() ;

int months = p.getMonths() ;

int days = p.getDays() ;

Duration

如果您以小时-分钟-秒的形式计算经过的时间,请使用Duration. 此类代表 UTC 中的一对时刻。因此,我们Instant从我们的ZonedDateTime对象对中提取对象,这些对象在内部保留自 UTC 1970 年第一时刻的纪元参考以来的整秒计数,加上小数秒作为纳秒计数。

Instant instantStart = zdtStart.toInstant() ;

Instant instantStop = zdtStop.toInstant() ;

Duration d = Duration.between( instantStart , instantStop ) ;

生成标准ISO 8601格式的字符串。


String output = d.toString() ;

查询天数(与日历无关的 24 小时时间块)、小时、分钟、秒。


long days = d.toDaysPart() ;

int hours = d.toHoursPart() ;

int minutes = d.toMinutesPart() ;

int seconds = d.toSecondsPart() ;

int nanos = d.toNanosPart() ;

PeriodDuration

如果您考虑一下,您会发现将年/月/日与 24 小时-日/小时/分钟/秒结合起来是没有意义的。

//img2.sycdn.imooc.com/648960ef00014a8606520413.jpg

查看完整回答
反对 回复 2023-06-14
  • 2 回答
  • 0 关注
  • 154 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信