【问题标题】:Schedule that runs every day at a specific time with hh:mm:ss使用 hh:mm:ss 每天在特定时间运行的计划
【发布时间】:2018-09-13 16:18:19
【问题描述】:

我试图在每天的特定时间运行代码,但使用 hh:mm:ss。我特别想每天在美国东部标准时间下午 5 点运行它,因此需要考虑时区。

这是我在 kotlin 中的尝试:

val timer = Timer()
val format = SimpleDateFormat("hh:mm:ss") 
val date = format.parse("11:07:09")
timer.schedule(object : TimerTask() {
    override fun run() {
       // code here
    }
}, date)

我无法让它工作,即使我做到了,我也不确定如何为其添加时区。

我该怎么做?

【问题讨论】:

  • 提示:EST 不是real time zone name。也许你的意思是America/New_York
  • 我建议你避免使用SimpleDateFormat 类。它不仅过时了,而且出了名的麻烦。今天我们在java.time, the modern Java date and time API 中做得更好。另外,无论您使用其中一种,请注意格式模式字符串区分大小写。

标签: java date kotlin


【解决方案1】:

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

此外,可怕的 DateSimpleDateFormat 类在几年前被 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 ) ;

您可能希望改进此代码以查看您想要的时间是否已经过去。要进行比较,请使用 isAfterisBefore 方法。

执行者

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.DateCalendarSimpleDateFormat

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 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

【讨论】:

  • 感谢罗勒写得很好的信息!一个问题,比方说,这是否每秒检查一次,直到时间到?所以,我可以在我的代码中写这个,我不需要每秒检查一次的 Runnable 计划来完成这项工作?
  • @kinx 我添加了更多信息。但是你需要做一些研究。阅读 Oracle 教程、搜索 Stack Overflow 并搜索互联网。
猜你喜欢
  • 2015-05-19
  • 1970-01-01
  • 1970-01-01
  • 2020-08-28
  • 2021-01-04
  • 2013-04-18
  • 2013-12-21
  • 2016-11-08
相关资源
最近更新 更多