【问题标题】:Convert Human Date (Local Time GMT) to date将人类日期(格林威治标准时间)转换为日期
【发布时间】:2018-12-01 14:23:09
【问题描述】:

我在服务器上工作,服务器正在向我发送 GMT 本地日期的日期,如字符串格式的 Fri Jun 22 09:29:29 NPT 2018,我将其转换为如下日期:

SimpleDateFormat simpleDateFormat=new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy",Locale.English);
Date newDate=simpleDateFormat.parse("Fri Jun 22 09:29:29 NPT 2018");
TimeAgo ta=new TimeAgo();
Log.d(TAG,""+ta.timeAgo(newDate));

我需要的是像 5 hours ago 这样取出 Time in Ago,因为我使用的是 github project on which returns TimeAgo on passing date

我已经查看了this answer,但没有解决我的问题。

异常:Err java.text.ParseException:无法解析的日期:“Fri Jun 22 09:29:29 NPT 2018”(偏移量 20) 错误 java.text.ParseException:无法解析的日期:“Fri Jun 22 09:29:29 NPT 2018”(偏移量 20)

【问题讨论】:

  • @ScaryWombat 对不起兄弟,那是我的错误。我写的代码只有几行,而不是复制和粘贴。现在请看一下。我来自尼泊尔,所以 NPT 意味着尼泊尔时间
  • 哦,是的,这是一个愚蠢的错误!妈的!
  • 我无法在 Java 7 中重现该问题。您确定这是您正在运行的确切代码吗?
  • @DawoodibnKareem 是的,这正是我正在使用的代码

标签: java android date parsing


【解决方案1】:

NPT 未被识别为时区缩写

您的日期时间字符串的解析(显然是Date.toString() 的输出)是问题所在(不是TimeAgo 的后续使用,您可以从问题中省略以使其更清楚)。无法解析的部分在索引 20 处,即NPT 的位置,我认为它是指尼泊尔时间。因此,您的 Android 设备或模拟器上的 SimpleDateFormat 无法将 NPT 识别为时区缩写。

时区缩写是语言环境数据的一部分。我不是 Android 开发人员,也不知道 Android 从哪里获取语言环境数据。一个快速的网络搜索提到了 ICU 和 CLDR。您可以更彻底地搜索,无疑会找到我没有找到的信息。

我提出三个建议供您尝试。我马上承认前两个不太可能解决你的问题,但我仍然觉得它们值得一试。我保证,如果前两个不行,第三个会起作用。

1。使用 ThreeTenABP 和 java.time

我同意 the answer by notyou 的观点,即 DateSimpleDateFormat 类已经过时,最好使用现代 Java 日期和时间 API java.time。你能在 Android O 之前的 Android 上做到这一点吗?是的,大部分java.time 已被反向移植。向后移植的 Android 版本称为 ThreeTenABP。使用底部的链接。然后试试:

    DateTimeFormatter formatter 
            = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ROOT);
    ZonedDateTime newDateTime
            = ZonedDateTime.parse("Fri Jun 22 09:29:29 NPT 2018", formatter);
    System.out.println(newDateTime);

确保将导入用于反向移植:

import org.threeten.bp.ZonedDateTime;
import org.threeten.bp.format.DateTimeFormatter;

我使用相同的反向端口进行了测试,但不是 Android 版本。我得到了:

2018-06-22T09:29:29+05:45[亚洲/加德满都]

不过,我怀疑 ThreeTenABP 使用相同的语言环境数据,如果是这样,这并不能解决您的问题。

2。在格式化程序上设置时区

    DateTimeFormatter formatter = DateTimeFormatter
            .ofPattern("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ROOT)
            .withZone(ZoneId.of("Asia/Kathmandu"));

如果它有效,我觉得它简单明了。如果您坚持使用SimpleDateFormat,您可以尝试类似的技巧。我得到与上面相同的输出。

3。将 NPT 作为文字处理

这是一个技巧:要求三个字母 NPT 出现在字符串中,而不将它们解释为时区。这消除了将缩写识别为时区的需要,因此会起作用。

    DateTimeFormatter formatter = DateTimeFormatter
            .ofPattern("EEE MMM dd HH:mm:ss 'NPT' yyyy", Locale.ROOT)
            .withZone(ZoneId.of("Asia/Kathmandu"));

我们还需要设置时区,因为现在这是 Java 可以从中获取时区的唯一位置。

但 TimeAgo 需要一个日期

要为TimeAgo 获取老式的Date 对象,请按如下方式转换:

    Date newDate = DateTimeUtils.toDate(newDateTime.toInstant());

链接

【讨论】:

  • 感谢您的回答,您没有android环境来测试代码。如果您注意到我在下面对@notyou 回答的评论,则 DateTimeFormatter 类需要 API 版本 26 (Android O),它是最新版本的 Android。如果我在我的项目中实现此代码,则只有带有 Oreo 版本的 Android 手机才能使其正常工作,并且所有之前的版本都将失败。我正在使用 minSDK 到 16 (Api 16 kitkat) 到 MaxSDK Oreo (26 Oreo ) 所以,我认为这不会是未来 4-5 年的完美解决方案。
  • 我确实读过那条评论。看来您没有正确阅读我的答案?至少我尝试解释了我的代码将如何在较旧的 Android 设备上运行。我建议您使用的 ThreeTenABP 完全适用于 Oreo 之前的 Android 版本。特别是如果你想提前 4 年思考,我应该说我提出了面向未来的发展方向。
  • 非常感谢您的回答和时间。最后,我让它工作了。我喜欢你的黑客。 ^_^ 。正如你上面所说的,第 1 步和第 2 步对我不起作用,但第 3 步是完美的。我终于从这个问题中挣扎了 3 天,你救了我的命。
【解决方案2】:

Date 类主要被弃用,所以我建议不要使用它。

也许考虑使用类似ZonedDateTime 的类来解决您的问题。

如果您只是在String 发送给您之前的 5 小时内寻找,您可以使用类似:

String time = "Fri Jun 22 09:29:29 NPT 2018";
DateTimeFormatter format = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz uuuu");
ZonedDateTime zdt = ZonedDateTime.parse(time, format);
System.out.println(zdt.minusHours(5));

【讨论】:

  • 在 Android 上是否已弃用?
  • 袋熊会在树梢上跳舞吗?
  • @ScaryWombat AFAIK,大多数方法和构造函数都是。
  • 这个 DateTimeFormatter.ofPattern() 需要 Android O。所以,这现在完全没用。
  • OP 没有尝试使用 Date 类的任何已弃用的方法或构造函数。许多方法已被弃用的事实与为什么 OP 的代码不起作用完全无关。在 JSR310 库中添加只是为了做一些 SimpleDateFormat 应该 能够做的事情是没有意义的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-11
  • 1970-01-01
  • 2018-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-25
相关资源
最近更新 更多