![](/img/trans.png)
[英]How to create a single expression displaying time difference between two Date's as years, months, days, hours, minutes, seconds
[英]How would I convert the exact amount of time (years, months, days, hours, minutes, seconds) between two Calendar objects?
我试图隐瞒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;
}
打印时,对于输入date1 = 19 August 2019 02:00:00
和date2 = 20 August 2019 12:30:45
,输出看起来像这样{DAYS=1, HOURS=10, MINUTES=30, SECONDS=45}
此方法中可用的最大时间单位是DAYS
,但是我想找到包含月份和年份的东西。 我意识到TimeUnit与特定的日历日期(实际上是24小时间隔)并没有任何关系,这就是为什么我想知道是否有任何方法可以使用Calendar类或类似的方法进行这种转换。 我还研究了ChronoUnit作为TimeUnit的替代品,但由于TimeUnit不能使用的相同原因而无法使用。
希望有任何有关如何合并较大时间单位的建议。 谢谢!
您不应该使用Calendar
类,因为它已经过时了。 您应该改用java.time
包中的类。
为了获得所需的结果,可以使用Period
类。
您首先需要将两个Calendar
实例都转换为LocalDate
实例 。
然后,您可以使用Period.between(startDate, endDate)
获得一个Period
实例,该实例使getDays()
, getMonths()
和getYears()
方法可用。
如果您还想包括时间部分(小时,分钟和秒),则可以将Duration
与Period
结合使用。 但首先阅读由Sweeper链接的帖子 。
这样的事情可能会起作用:
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
方法,因此您不必再使用模运算符。
请注意:由于夏令时,此代码未考虑时钟调整。
Period
.between(
( ( GregorianCalendar ) myCalStart ).toZonedDateTime().toLocalDate() ,
( ( GregorianCalendar ) myCalStop ).toZonedDateTime().toLocalDate()
)
…要么…
Duration
.between(
( ( GregorianCalendar ) myCalStart ).toInstant() ,
( ( GregorianCalendar ) myCalStop ).toInstant()
)
您使用的是可怕的日期时间类,而该类在几年前已被JSR 310中定义的现代java.time类所取代。
切勿使用Calendar
, GregorianCalendar
, Date
, SimpleDateFormat
等。 仅使用java.time包中的类。
ZonedDateTime
假设您的两个Calendar
对象实际上都是其下方的GregorianCalendar
对象,请进行转换。 要进行转换,请to…
添加到旧类的方法中调用new 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
与LocalDate
对象一起使用。 LocalDate
表示没有日期和时区的日期。 我们可以从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中的两个时刻。 因此,我们从一对ZonedDateTime
对象中提取了Instant
对象,这些对象从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小时/天/小时/分钟/秒结合起来是没有意义的。 请参阅此堆栈溢出页面,以供深思。
但是,如果您坚持要结合这两个不同的概念,请参见在ThreeTen-Extra库中找到的PeriodDuration
类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.