如何获取日期的剩余天数并打印小时分钟和秒Java8

Stu*_*DTO 2 java datetime android date kotlin

例如,我从服务器获取 UTC 日期

"endValidityDate": "2021-11-18T22:59:59Z"
Run Code Online (Sandbox Code Playgroud)

我想知道计算从现在起剩余天数的最佳方法是什么。

这是我现在得到的:

我正在创建一个 2天后的日期:

DateTime.now().plusSeconds(172800)
Run Code Online (Sandbox Code Playgroud)

我正在将其解析为DateTimejoda,如果您这么说,我可以使用其他内容。

当做不同的日子时,我这样做

val diff = endValidityDate.toDate().time - Date().time
val daysRemaining = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS)
return if (daysRemaining > 1) "$daysRemaining days}"
       else TimeUnit.DAYS.convert(diff, TimeUnit.SECONDS).toString()
Run Code Online (Sandbox Code Playgroud)

我想要实现的场景是:

如果剩余天数超过 1(24 小时),则打印“剩余 2 天”,而不是显示“剩余 1 天”,然后只需添加一个计时器,如下所示:

“0小时43米3秒”。

为了做计时器,我只需减去现在剩余的时间

val expireDate = LocalDateTime.now()
                   .plusSeconds(uiState.endValidityDate.timeLeft.toLong())
                   .toEpochSecond(ZoneOffset.UTC)
val currentTime = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC)
Run Code Online (Sandbox Code Playgroud)

然后每一秒发生的时候我都会像这样打印它:

val duration = Duration.ofSeconds(it)
binding.myTextView.text = String.format(
    "%02dh: %02dm: %02ds",
    duration.seconds / 3600,
    (duration.seconds % 3600) / 60,
    duration.seconds % 60,
)
Run Code Online (Sandbox Code Playgroud)

但我没有得到 2 天的时间,我只是得到输出:

00h: 33m: 50s
Run Code Online (Sandbox Code Playgroud)

所以,我在这里遇到一些问题,例如:

这是一个最优解吗?如果没有,您能否描述一个更好的地方,让我可以实现我的目标?为什么我的计时器显示为00h: 13m: 813s?我是否错误地执行了正则表达式,或者是因为 epochSeconds ?

实现

当尝试将其打印到设备时,给出来自服务器的 UTC 日期,那么它应该遵循此规则。

1.- 如果剩余天数大于 1 天,则打印“剩余 N 天”

2.- 如果剩余天数 <= 1,则打印一个计时器(它已经完成,问题是如何正确打印它)。

  • 最小 1 位数字 (0h 2m 1s)
  • 最多 2 位数字(1h 23m 3s)

笔记 :

我正在使用Java 8, 如果这是问题所在,我还可以更改倒计时的方式以使用 millis 而不是 epochSeconds。

deH*_*aar 6

您可以使用 a 表示ZonedDateTime现在未来的日期时间,然后计算 aDuration.between而不是先计算剩余秒数,然后使用 a Duration.ofSeconds()

这是 Kotlin 示例:

fun main() {
    val utc = ZoneId.of("UTC")
    val now = ZonedDateTime.now(utc)
    val twoDaysFromNow = now.plusDays(2)
    
    val remaining = Duration.between(now, twoDaysFromNow)
    
    println(
        String.format("%02dh: %02dm: %02ds",
                        remaining.seconds / 3600,
                        (remaining.seconds % 3600) / 60,
                        remaining.seconds % 60
                     )
    )
}
Run Code Online (Sandbox Code Playgroud)

输出:48h: 00m: 00s


如果您只对剩余的整天感兴趣,那么考虑使用ChronoUnit.DAYS.between,也许像这样:

fun main() {
    val utc = ZoneId.of("UTC")
    val now = ZonedDateTime.now(utc)
    val twoDaysFromNow = now.plusDays(2)
    
    val remainingDays = ChronoUnit.DAYS.between(now, twoDaysFromNow)
    
    println(
        String.format("%d days", remainingDays)
    )
}
Run Code Online (Sandbox Code Playgroud)

输出:2 days


额外的:

由于我不清楚您尝试使用哪种数据类型来计算有效期结束前的剩余时间,因此您必须选择在问题中提供更详细的信息或使用以下其中一种fun

通过一个ZonedDateTime

private fun getRemainingTime(endValidityDate: ZonedDateTime): String {
    // get the current moment in time as a ZonedDateTime in UTC
    val now = ZonedDateTime.now(ZoneId.of("UTC"))
    // calculate the difference directly
    val timeLeft = Duration.between(now, endValidityDate)
    // return the messages depending on hours left
    return if (timeLeft.toHours() >= 24) "${timeLeft.toDays()} days"
    else String.format("%02dh: %02dm: %02ds",
                        timeLeft.toHours(),
                        timeLeft.toMinutes() % 60,
                        timeLeft.toSeconds() % 60)
}
Run Code Online (Sandbox Code Playgroud)

通过一个Instant

private fun getRemainingTime(endValidityDate: Instant): String {
    // get the current moment in time, this time as an Instant directly
    val now = Instant.now()
    // calculate the difference
    val timeLeft = Duration.between(now, endValidityDate)
    // return the messages depending on hours left
    return if (timeLeft.toHours() >= 24) "${timeLeft.toDays()} days"
    else String.format("%02dh: %02dm: %02ds",
                        timeLeft.toHours(),
                        timeLeft.toMinutes() % 60,
                        timeLeft.toSeconds() % 60)
}
Run Code Online (Sandbox Code Playgroud)

String直接通过

private fun getRemainingTime(endValidityDate: String): String {
    // get the current moment in time as a ZonedDateTime in UTC
    val now = ZonedDateTime.now(ZoneId.of("UTC"))
    // parse the endValidtyDate String
    val then = ZonedDateTime.parse(endValidityDate)
    // calculate the difference
    val timeLeft = Duration.between(now, then)
    // return the messages depending on hours left
    return if (timeLeft.toHours() >= 24) "${timeLeft.toDays()} days"
    else String.format("%02dh: %02dm: %02ds",
                        timeLeft.toHours(),
                        timeLeft.toMinutes() % 60,
                        timeLeft.toSeconds() % 60)
}
Run Code Online (Sandbox Code Playgroud)