我正在尝试为列表中的对象创建时间限制。这可能意味着元素的保质期可能为 23、24 或 25 小时。有没有有用的 Java 库?这就是我到目前为止所拥有的。
我的问题是,例如,当我在上午 9:30 创建记录时,必须在第二天上午 9:30 将其删除。当 DST 生效期间,我会遇到差异。该记录要么在 8:30 要么 10:30 被删除,具体取决于我是向前还是向后跳。
//baseValue = object that I want to check
Date dt = new Date();
Calendar c = Calendar.getInstance();
c.setTime(dt);
c.add(Calendar.DATE, -1);
if(baseValue.getTime() < c.getTime()){
array.remove(baseValue);
}
最佳答案
旧类(Date
、Calendar
和 SimpleDateFormat
)有 lots of problems和 design issues ,包括处理 DST 更改的困难,并且它们正在被新的 API 取代。
如果您使用的是 Java 8,请考虑使用 new java.time API 。更容易,less bugged and less error-prone than the old APIs .
如果您使用的是 Java <= 7,则可以使用 ThreeTen Backport ,Java 8 新日期/时间类的一个很好的向后移植。对于 Android,有 ThreeTenABP (更多关于如何使用它 here )。
下面的代码适用于两者。
唯一的区别是包名称(在 Java 8 中是java.time
,而在 ThreeTen Backport(或 Android 的 ThreeTenABP)中是org. Threeten.bp
) >),但类和方法名称是相同的。
为了处理 DST 更改,理想的类是 ZonedDateTime
,它表示特定时区的日期和时间。我还使用 ZoneId
类,它代表时区本身。
我使用的是我的时区 (America/Sao_Paulo
),因为这里也有夏令时,但您可以替换为您的时区(更多信息见下文):
// create a date 1 day before DST change in Sao Paulo, at 9 AM
ZoneId zone = ZoneId.of("America/Sao_Paulo");
ZonedDateTime z = ZonedDateTime.of(2017, 10, 14, 9, 0, 0, 0, zone);
// get the next day, at 9 AM
ZonedDateTime nextDay = z.plusDays(1);
System.out.println(z);
System.out.println(nextDay);
输出为:
2017-10-14T09:00-03:00[America/Sao_Paulo]
2017-10-15T09:00-02:00[America/Sao_Paulo]
请注意,偏移量从 -03:00
更改为 -02:00
- 这是由于圣保罗时区开始实行夏令时(时钟向前移动 1 小时)。但还要注意,时间(上午 9 点)已正确保存。
如果我们计算小时数的差异,我们可以看到它是正确的:
System.out.println(ChronoUnit.HOURS.between(z, nextDay));
输出为:
23
这正确地意味着这两个日期之间已经过去了 23 小时(因为时钟向前移动 1 小时,因此“丢失”了 1 小时)。
就您而言,您需要知道 1 天是否已经过去,因此您只需调用:
long days = ChronoUnit.DAYS.between(z, nextDay);
在这种情况下,days
将为 1(即使上面计算的小时差为 23,因为 API 足够智能,可以考虑 DST 影响)。
因此,就您的情况而言,您只需检查天数差异是否为 1(或大于 1,我不知道)并执行所有需要完成的操作。
如果需要获取当前日期/时间,可以调用ZonedDateTime.now(zone)
。
要使用您的时区而不是我的时区,首先请注意 API 使用 IANA timezones names (始终采用Continent/City
格式,例如America/Sao_Paulo
或Europe/Berlin
)。
避免使用 3 个字母的缩写(例如 CST
或 PST
),因为它们是 ambiguous and not standard .
您可以使用 ZoneId.getAvailableZoneIds()
获取时区名称列表 - 然后选择最适合您情况的一个。
您还可以使用ZoneId.systemDefault()
- 它返回系统的默认时区。但这可能会在不通知的情况下更改 - 即使在运行时 - 因此建议使用显式时区。
关于java - 如何向日历对象添加一天并考虑夏令时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45222363/