简单的日期格式给出了来自纪元时间戳的错误信息

Simple Date format gives wrong info from epoch timestamp

我发现这给出了错误的日期。但我怎么解决不了。请有人帮助我。 我是 android 开发的新手。 提前致谢;

字符串时间戳 = "1538970640";

SimpleDateFormat formatter = new SimpleDateFormat("dd MMM 'at' hh:mm a z" );
String dateString = formatter.format(new Date(Long.parseLong(timestamp)));

这个returns:

19 Jan at 01:29 AM GMT+06:oo

但应该是:

8 Oct at 9:50 AM GMT+06:00

java.util.Date构造函数接受毫秒自Epoch,秒:

Allocates a Date object and initializes it to represent the specified number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT.

以下使用 ms 的代码正在运行:

String timestamp = "1538970640000";   // use ms NOT s
SimpleDateFormat formatter = new SimpleDateFormat("dd MMM 'at' hh:mm a z" );
String dateString = formatter.format(new Date(Long.parseLong(timestamp)));

08 Oct at 05:50 AM CEST

Demo

您面临的部分问题是您的日期格式省略了年份部分,实际上是 1970 年。

java.time 和 ThreeTenABP

我建议您使用 java.time,现代 Java 日期和时间 API,作为您的日期和时间工作。

    DateTimeFormatter timestampFormatter = new DateTimeFormatterBuilder()
            .appendValue(ChronoField.INSTANT_SECONDS)
            .toFormatter();
    DateTimeFormatter targetFormatter
            = DateTimeFormatter.ofPattern("d MMM 'at' h:mm a z", Locale.ENGLISH);

    String timestamp = "1538970640";
    ZonedDateTime dateTime = timestampFormatter.parse(timestamp, Instant.FROM)
            .atZone(ZoneId.systemDefault());
    String dateString = dateTime.format(targetFormatter);

    System.out.println(dateString);

输出是(当时区设置为 GMT+06:00,顺便说一句,这不是真正的时区):

8 Oct at 9:50 AM GMT+06:00

不过,我不太喜欢将日期和时间从一种字符串格式转换为另一种字符串格式。在您的应用程序中,您不应将日期和时间作为字符串处理,而应作为适当的日期和时间对象处理,例如 InstantZonedDateTime。当您从某处(服务器?)获取字符串时,首先将其解析为日期时间对象。只有当你需要给字符串输出时,例如给用户,将你的日期和时间格式化成用户时区的字符串。

也就是说,java.time 仅使用两个格式化程序即可执行您的转换。不用先解析成低级的long.

还有两点:

  • 为您的输出格式化程序提供一个区域设置来控制所使用的语言。由于 AM 和 PM 几乎不用于英语以外的其他语言,我认为 Locale.ENGLISH 可能是合适的。你来决定。
  • 因为您想要 8 Oct at 9:50 AM GMT+06:00,所以只使用一个 d 作为日期,使用一个 h 作为时钟小时。如果数字超过 9,仍将打印两位数,例如 10 Oct at 11:50 AM GMT+06:00.

你的代码出了什么问题?

您的号码,1538970640(10 位数字),表示自纪元以来 。这是 Unix 时间戳的经典定义。您使用的 Date 构造函数预计自纪元以来 毫秒 。这对于过时的 Java 日期和时间 类 和方法来说是典型的。这些年自纪元以来的毫秒数通常为 13 位数字。如您所见,现代 Java 日期和时间 类 在这里对秒数有更好的支持。

问题:java.time 不需要 Android API 26 级吗?

java.time 在新旧 Android 设备上都能很好地工作。它只需要至少 Java 6.

  • 在 Java 8 及更高版本和较新的 Android 设备上(从 API 级别 26),现代 API 是内置的。在这种情况下,而不是常量 Instant.FROM 使用方法引用 Instant::from.
  • 非Android Java 6 和 7 获得 ThreeTen Backport,现代 类 的 backport(ThreeTen 用于 JSR 310;请参阅底部的链接)。
  • 在(较旧的)Android 使用 ThreeTen Backport 的 Android 版本。它叫做 ThreeTenABP。并确保使用子包从 org.threeten.bp 导入日期和时间 类。

链接