Kotlin无法解析的日期-ParseException错误

时间:2019-02-01 08:50:54

标签: java date datetime kotlin simpledateformat

尝试解析日期字符串时看到以下错误,有人可以指出正确的方向来解析此日期字符串吗?

"2019-01-22T12:43:01Z"

错误:

java.text.ParseException: Unparseable date: "2019-01-22T12:43:01Z"

代码:

package ch02.ex1_1_HelloWorld

import java.lang.Exception
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.Date
import java.util.concurrent.TimeUnit

const val SERVER_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss:SS'Z'" 
val sdf = SimpleDateFormat(SERVER_TIME_FORMAT, Locale.US)

fun main(args: Array<String>) {
    timeSince("2019-01-22T12:43:01Z")
}

fun timeSince(dateStr: String) {
    var diff : Long = 0
    try {
        diff = sdf.parse(dateStr).time - Date().time      
    } catch (e: Exception) {
        print(e)
    }
    "${TimeUnit.HOURS.convert(diff, TimeUnit.MILLISECONDS)} h ago"
} 

3 个答案:

答案 0 :(得分:3)

由于您的输入不包含毫秒,因此可以删除模式中的:SS

const val SERVER_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'" 

我建议使用java.time软件包。

答案 1 :(得分:3)

java.time

import java.time.Instant;
import java.time.temporal.ChronoUnit;

fun timeSince(dateStr: String): String {
    val diffHours = ChronoUnit.HOURS.between(Instant.parse(dateStr), Instant.now())
    return "%d h ago".format(diffHours)
}

让我们尝试一下:

fun main() {
    println(timeSince("2019-01-22T12:43:01Z"))
}

这只是打印出来的:

  

236小时前

我正在使用java.time(现代Java日期和时间API)。与旧的类Date相比,尤其是SimpleDateFormat,我发现它更适合使用。如果传递给它的字符串不是ISO 8601格式,则上述方法将抛出DateTimeParseException。对于大多数目的,这可能比返回0 h ago更好。该方法可以容忍秒上存在和不存在(最多9个)小数,因此可以接受2019-01-22T12:43:01.654321Z

我们不需要格式化程序吗?不,我利用了您的字符串为ISO 8601格式的事实,这是现代日期和时间类将其默认解析(并打印)的格式。

我希望我可以使用ChronoUnitInstant

编辑:

  

我希望我可以使用ChronoUnit&Instant,但它需要Android的最低V26版本。我目前的下限是23。

java.time很好地工作在较旧的Android设备了。它只需要至少 Java 6

  • 在Java 8和更高版本以及更新的Android设备(API级别26以上)中,内置了现代API。
  • 在Java 6和7中,获得了ThreeTen反向端口,这是现代类的反向端口(JSR 310的ThreeTen;请参见底部的链接)。
  • 在(较旧的)Android上,使用Android版本的ThreeTen Backport。叫做ThreeTenABP。并确保您使用子包从org.threeten.bp导入日期和时间类。

您的代码出了什么问题?

我看到两个代码错误在你的问题:

  1. 作为竹杖芒鞋轻胜马已经指出in this answer,您的格式要求4份之间TZ,由冒号分开,但你的串仅具有三个部分有。随着SimpleDateFormat使用两个SS的几分之一秒也是错误的,因为大写S是毫秒,所以只有三个SSS将使意义(相比之下,与现代{ {1}} DateTimeFormatter仅用秒表示,因此任何数字(最多9 S)才有意义。)
  2. 您正在将字符串中的SSSSSSSSS当作文字。 UTC偏移量为零,需要进行这样的解析,否则您将获得错误的时间(在绝大多数JVM上)。

链接

答案 2 :(得分:0)

我来自服务器的原始值是:

2021-04-08T11:27:40.278Z

您可以简单地将其缩短。 使用 kotlin,2021 年:

// Read the value until the minutes only
val pattern = "yyyy-MM-dd'T'HH:mm"
val serverDateFormat = SimpleDateFormat(pattern, Locale.getDefault())
// Format the date output, as you wish to see, after we read the Date() value
val userPattern = "dd MMMM, HH:mm"
val userDateFormat = SimpleDateFormat(userPattern, Locale.getDefault())

val defaultDate = serverDateFormat.parse(INPUT_DATE_STRING)
if ( defaultDate != null ) {
   val userDate = userDateFormat.format(defaultDate)
   textView.text = userDate
}

结果:

<块引用>

4 月 8 日,11:27