tl;博士
java.util.Date
.from(
ZonedDateTime.of(
LocalDate.now( ZoneId.of( "America/Montreal" ) ) ,
LocalTime.parse( "11:07:09" ) ,
ZoneId.of( "America/Montreal" )
)
.toInstant()
)
详情
java.util.Date 表示日期采用 UTC 时间。
您忽略了日期和区域/偏移量。
您的结果显然默认为 1970 年 1 月 1 日上午 11 点。
java.time
此外,可怕的 Date 和 SimpleDateFormat 类在几年前被 java.time 类所取代。
表示您的目标时间。
LocalTime lt = LocalTime.parse( "11:07:09" ) ;
获取当前日期,今天的日期。需要时区。对于任何给定的时刻,日期在全球范围内因区域而异。
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
LocalDate today = LocalDate.now( z ) ;
将这些放在一起确定一个时刻。
ZonedDateTime zdt = ZonedDateTime.of( today , lt , z ) ; // Time-of-day will be adjusted if not valid on that date in that zone.
调整为 UTC。同一时刻,时间轴上的同一点,不同的挂钟时间。
Instant instant = zdt.toInstant() ; // Adjust from zone to UTC.
避免使用旧的日期时间类。但是如果你必须互操作,你可以通过调用添加到旧类的新方法来回转换。
java.util.Date d = java.util.Date.from( instant ) ;
您可能希望改进此代码以查看您想要的时间是否已经过去。要进行比较,请使用 isAfter 和 isBefore 方法。
执行者
Timer 类已被执行器框架取代。搜索 Oracle Java 教程和 Stack Overflow 以了解更多信息。
使用执行器,您可以安排任务在特定时刻运行。但是您通过指定等待期而不是一天中的时间来间接地这样做。调度执行器接受初始延迟的参数。您可以将该延迟计算为当前时刻和所需时刻之间的时间跨度。
要计算该时间跨度,请使用Duration 类。
Duration d = Duration.between( Instant.now() , instant ) ;
请记住,您不能期望在瞬间完成任务的完美时机。主机操作系统上的 JVM 以及 JVM 中的 Java 线程的调度可能会涉及延迟。
当然,您还需要在完成任务时记录您的任务历史。当您的应用程序关闭然后重新启动时,它需要研究历史以确定如何设置新的时间表。这个问题超出了本答案的范围。阅读有关写入文件、使用数据库或依赖其他一些persistence 方案的内容。
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、Calendar 和 SimpleDateFormat。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。
从哪里获得 java.time 类?
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval、YearWeek、YearQuarter 和more。