2 回答
TA贡献1780条经验 获得超1个赞
你不应该使用这个Calendar
类,因为它已经过时了。您应该改用java.time
包中的类。
为了获得所需的结果,您可以使用该类Period
。
您首先需要将两个Calendar
实例都转换为LocalDate
instances。
然后您可以使用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方法,因此您不必再使用模运算符。
请注意:由于夏令时,此代码未考虑时钟调整。
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类所取代的可怕的日期时间类。
切勿使用Calendar
, GregorianCalendar
, Date
,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
对象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 中的一对时刻。因此,我们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 小时-日/小时/分钟/秒结合起来是没有意义的。
添加回答
举报