Java:如何在不使用日历的情况下操作日期以添加天数或月数?

问题描述

我有一个简单的函数可以比较两个日期,如果两个日期相等 - 我想在其中一个日期上添加 7 天,或者根据情况添加一个月。我有两个使用 simpleDateFormat 格式化的日期,它们从字符串转换为日期,然后我像这样比较它们

Date dateExpired = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(expDate);
Date dateEffective = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(effDate);

比较方法

if(dateExpired.before(dateEffective) || dateExpired.equals(dateEffective)) {
    System.out.println("Same date for effective and expired");
    
}

在我的比较中,我想进行更新。谁能告诉我怎么做?

解决方法

永远不要使用 Calendar,这是多年前被 JSR 310 中定义的现代 java.time 类取代的可怕日期时间类的一部分。

切勿在日期时间格式模式中的 Z 周围放置单引号。该字母表示与 UTC 的零时分秒偏移量。您的报价正在丢弃有价值的信息。

您的输入字符串显然采用标准 ISO 8601 格式。 java.time 类在解析/生成文本时默认使用标准格式。所以不需要指定格式模式。

将您的输入解析为 Instant 对象,以表示在 UTC 中看到的时刻。

Instant expirationUtc = Instant.parse( x ) ;
Instant effectiveUtc = Instant.parse( y ) ;

对于任何给定时刻,日期在全球各地因时区而异。它可以是日本东京的“明天”,同时是美国俄亥俄州托莱多的“昨天”。

因此,您必须将输入调整为您想要感知日期的时区。

ZoneId z = ZoneId.of( "America/Edmonton" ) ; 
ZonedDateTime expiration = expirationUtc.atZone( z ) ;
ZonedDateTime effective = effectiveUtc.atZone( z ) ;

测试日期是否相等。提取日期部分进行比较。

if( expiration.toLocalDate().isEqual( effective.toLocalDate() ) ) {…}

使用 Period 类表示一个月或一周的时间跨度。

Period period = Period.ofWeeks( 1 ) ;
ZonedDateTime later = expiration.plus( period ) ;