首页 > 解决方案 > Java如何以毫秒为单位获得未来的具体点?

问题描述

在我的android项目中,我试图设置一个警报(使用AlarmManager),每天早上7点和晚上7点通知用户检查应用程序。(它是一个待办事项列表,所以它基本上有 2 个提醒,比如“看看你今天的任务”和“你做完所有事情了吗”)。我弄清楚了 AlarmManager 但在这里阅读了一些帖子后,我仍然无法弄清楚如何获得正确的时间。

我正在训练实现以下目标:

当用户启用这些通知时,我想知道我们当前的当地时间,或者更好地说是一天中的什么时间。如果小于 7,我想设置今天早上 7 点的第一个闹钟和今天晚上 7 点的第二个闹钟。

如果已经过了 7 点但还没有 19,我想为今天晚上 7 点设置 1 个闹钟,为明天早上 7 点设置另一个闹钟。

如果已经过了 19 点,我想在正确的时间为明天设置两个闹钟。

最简单的工作方法是创建一个新的 Date() 并使用 getHour 检查它,但几乎每个人都说 Date 已被弃用,不应再使用。

那么有没有办法获得一个代表当地时间的现代对象,它可以a)告诉我它是一天中的哪个小时,b)被操纵,这样我就可以在最初想以毫秒为单位触发警报时获得时间?

编辑:我已经尝试过 Instant 和 OffsetDateTime,但似乎这些不能被操纵以具有不同的时间,而且我也无法弄清楚如何以毫秒为单位获取这些对象的时间。

标签: javaandroid

解决方案


在我的安卓项目中

Android 26+ 具有现代java.time类的实现。最新的工具通过“API 脱糖”过程将大部分功能带到了早期的 Android 中。如果这不适合您,请参阅 Java 库ThreeTen-Backport及其对 Android 的改编,ThreeTenABP

......我仍然无法弄清楚如何获得正确的时间。

捕获以 UTC 显示的当前时刻(零时分秒的偏移量):

Instant.now()

捕捉在特定时区看到的当前时刻。

ZoneID zoneId = ZoneId.of( "Africa/Tunis" ); 
ZonedDateTime zdt = ZonedDateTime.now( zoneId ) ;

捕获当前时刻,就像您的 JVM 的当前默认时间机器一样。

ZonedDateTime.now( ZoneId.systemDefault() )

…当用户启用这些通知时,我想知道我们当前的当地时间

捕获当前 JVM 的当前默认时区中的当前时间。

LocalTime.now( ZoneId.systemDefault() )

,或者更好地说是一天中的什么时间。

int currentHour = LocalTime.now( ZoneId.systemDefault() ).getHour() ;

如果小于 7,我想设置今天早上 7 点的第一个闹钟和今天晚上 7 点的第二个闹钟。

ZoneId zoneId = … ;
ZonedDateTime zdtNow = ZonedDateTime.now( zoneID ) ;
LocalTime firstAlarmTime = LocalTime.of( 7 , 0 ) ;    // 7 AM
LocalTime secondAlarmTime = LocalTime.of( 19 , 0 ) ;  // 7 PM
if( zdtNow.getLocalTime().isBefore( firstAlarmTime ) )
{
    ZonedDateTime zdtAlarm1 = zdtNow.with( firstAlarmTime ) ;
}
if( zdtNow.getLocalTime().isBefore( secondAlarmTime ) )
{
    ZonedDateTime zdtAlarm2 = zdtNow.with( secondAlarmTime ) ;
}

如果已经过了 7 点但还没有 19,我想为今天晚上 7 点设置 1 个闹钟,为明天早上 7 点设置另一个闹钟。

虽然我不了解一般的 Android 编程,也不了解AlarmManager具体的 Android 编程,但我怀疑更好的方法是为每个后台线程定期检查当前正在安排的适当警报。

如果已经过了 19 点,我想在正确的时间为明天设置两个闹钟。

if( ! zdtNow.getLocalTime().isBefore( secondAlarmTime ) )
{
    ZonedDateTime zdtAlarm1 = zdtNow.toLocalDate().plusDays(1).atStartOfDay( zoneId ).with( firstAlarmTime ) ;
    ZonedDateTime zdtAlarm2 = zdtAlarm1.with( secondAlarmTime ) ;
}

最简单的工作方法是创建一个新的 Date() 并使用 getHour 检查它,但几乎每个人都说 Date 已被弃用,不应再使用。

永远不要使用DateorCalendar类。这些可怕的类在几年前被JSR 310 中定义的现代java.time类所取代。

那么有没有办法获得一个代表当地时间的现代对象,可以a)告诉我它是一天中的哪个小时

int hour = LocalTime.now( ZoneId.systemDefault() ).getHour() ;

b) 被操纵,以便我在最初想以毫秒为单位触发警报时获得时间?

long millisecondsUntilAlarm1 = Duration.between( zdtNow.toInstant() , zdtAlarm1.toInstant() ).toMillis() ;

编辑:我已经尝试过 Instant 和 OffsetDateTime,但似乎这些不能被操纵以具有不同的时间,而且我也无法弄清楚如何以毫秒为单位获取这些对象的时间。

你只需要多学习。搜索堆栈溢出以了解更多信息。java.time的这些主题已经被讨论过很多次了。并免费学习Oracle 的教程

您可能不需要OffsetDateTime. 该类主要用于通过 SQL 与数据库进行数据交换。


推荐阅读