Android如何从Django中格式化日期时间

4
我将翻译如下:

我正在使用JSON和REST框架将我的Django网站连接到Android应用程序。

JSON数据中包含类似于以下格式的日期时间:

{
   date: "2018-06-05T12:42:48.545140Z"
}

当Android接收到日期时,我尝试使用以下代码进行格式化:

    String dt="2018-06-05T12:42:48.545140Z";
    DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy hh:mm");
    String date=formatter.format(Date.parse(dt));

我遇到了以下报错:

java.lang.IllegalArgumentException:

解析错误: 2018-06-14T14:30:02.982009Z

位于 java.util.Date.parseError(Date.java:367)

在 java.util.Date.parse(Date.java:448)

在 Django 模板中,我可以轻松地完成这个操作:

{{article.date|date:'d-m-Y H:i'}}

但是在 Android 中,我有点困惑。


2
Date类过时的parse方法已经被弃用,请不要使用它。整个类早已过时,而且从未被很好地设计。考虑在您的Android项目中添加ThreeTenABP,以便使用现代Java日期和时间API java.time。这样做会让您的工作更加愉快。 - Ole V.V.
2个回答

3
如果您正在使用 java.time API,您可以使用以下内容:
String dt = "2018-06-05T12:42:48.545140Z";
ZonedDateTime zdt = ZonedDateTime.parse(dt); 
String newFormat = zdt.format(DateTimeFormatter.ofPattern("dd/MM/yyyy hh:mm"));
System.out.println(newFormat);//05/06/2018 12:42

注意,我没有使用任何格式化程序,ZonedDateTime 的默认程序可以解析您的日期。
或者如@Basil Bourque所述,更适合解析为Instance而不是ZonedDateTime
String newFormat = Instant.parse(dt)
        .atZone(ZoneId.of("Pacific/Auckland"))
        .format(DateTimeFormatter.ofPattern("dd/MM/yyyy hh:mm"));

关于您的错误

您的错误来自于Date.parse(dt),因为Date的默认格式无法解析您的日期,您需要提供正确的格式,以便它能够理解如何格式化您的日期。例如:

String date = formatter.format(
        new SimpleDateFormat("the pattern which match your string date (dt)").format(dt)
);

但无论如何,我不建议使用SimpleDateFormatDate

ThreeTen-Backport项目将几乎相同的API语法向Java 6和7进行了回溯,实现了大部分java.time功能。同时在ThreeTenABP项目中适配了早期的Android(<26)。请参见如何使用ThreeTenABP


谢谢,但是java.time API需要API级别26,我不想更改最小SDK,所以我在序列化器类中更改了日期格式。 - Amine Messaoudi
2
@AmineMessaoudi 这对其他人可能有所帮助,在任何情况下,您都可以使用类似的库http://www.threeten.org/threetenbp/index.html,它提供了java.time所做的功能。 - Youcef LAIDANI
1
回答不错,但将其解析为“Instant”而不是“ZonedDateTime”可能更合适。 “Z”表示仅为UTC偏移量,而不是时区。 - Basil Bourque
1
@YCF_L 是的,你说得对,Instant是一个基本类,不适用于生成自定义格式的字符串。对于自定义字符串,请使用OffsetDateTimeZonedDateTime。但正如我所说,这里看到的带有Z的输入是一个偏移量(偏移量为零),但它不是一个时区。时区是一个特定地区的人们使用的过去、现在和未来偏移量更改的历史记录,并以Continent/Region格式的名称命名。因此,虽然从技术上讲可以将给定的输入解析为ZonedDateTime,但这样会产生误导。相反,应将其解析为OffsetDateTime - Basil Bourque
1
我上面的评论假设意图是以UTC感知日期和时间。如果目标是调整到特定时区,则解析为“Instant”,应用“ZoneId”以获取“ZonedDateTime”。像这样:Instant.parse(“2018-06-05T12:42:48.545140Z”)。atZone(ZoneId.of(“Pacific / Auckland”))。format(DateTimeFormatter.ofPattern(“dd / MM / yyyy hh:mm”)) - Basil Bourque
显示剩余2条评论

1

我通过更改序列化器类中的日期格式来解决了这个问题。

    date = serializers.DateTimeField(format="%m/%d/%Y %H:%M", required=False, read_only=True)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接