4

I'm connecting my django website to an android app using json and the rest framework

The json data contains datetime like this :

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

When android receives the date, I try to format it using this code :

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

And I get the following error :

java.lang.IllegalArgumentException:

Parse error: 2018-06-14T14:30:02.982009Z

at java.util.Date.parseError(Date.java:367)

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

In a django a template I can easily do this

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

But in android I'm a bit confused

Amine Messaoudi
  • 2,141
  • 2
  • 20
  • 37
  • 2
    The `parse` method of the outdated `Date` class is deprecated, don’t use it. The whole class is long outdated too, and was never well designed. Consider adding [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP) to your Android project in order to use `java.time`, the modern Java date and time API. It is so much nicer to work with. – Ole V.V. Jun 18 '18 at 08:00

2 Answers2

3

If you are using java.time API you can use :

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

Note I don't use any formatter the default one of ZonedDateTime can parse your date.

Or as @Basil Bourque mention it's more appropriate to parse as Instance instead of ZonedDateTime :

String newFormat = Instant.parse(dt)
        .atZone(ZoneId.of("Pacific/Auckland"))
        .format(DateTimeFormatter.ofPattern("dd/MM/yyyy hh:mm"));

About your error

Your error comes from Date.parse(dt) because the default pattern of Date can't parse your date, you need to give it the correct format so it can understand how to format your date. for example :

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

But in any case I don't advice to use the SimpleDateFormat or Date.

The ThreeTen-Backport project back-ports to Java 6 & 7 most of the java.time functionality with nearly identical API syntax. Further adapted for earlier Android (<26) in the ThreeTenABP project. See How to use ThreeTenABP.

Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
  • Thanks but java.time api requires api level 26 and I didn't want to change the min sdk so I changed the date format in the serializer class – Amine Messaoudi Jun 17 '18 at 22:53
  • 2
    @AmineMessaoudi This can be helpful for others, in any case you can use the similar library http://www.threeten.org/threetenbp/index.html which offer what java.time do – Youcef LAIDANI Jun 17 '18 at 22:56
  • 1
    Good Answer, but parsing as a `Instant` rather than a `ZonedDateTime` would be more appropriate. The `Z` represents a mere offset-from-UTC, not a time zone. – Basil Bourque Jun 18 '18 at 04:20
  • Thank you @BasilBourque I find this post https://stackoverflow.com/questions/25229124/format-instant-to-string about formatting and Instance, I think it is a little complicated and long piece of code to format an Instance rather than ZoneDateTime no? – Youcef LAIDANI Jun 18 '18 at 09:00
  • 1
    @YCF_L Yes, you are correct, `Instant` is a basic class, not intended for generating strings in custom format. For custom strings, use `OffsetDateTime` and `ZonedDateTime`. But as I said, the input seen here with a `Z` is an offset-from-UTC (an offset of zero), but is *not* a time zone. A time zone is a history of past, present, and future changes to the offset-from-UTC used by the people of a particular region, with a name in `Continent/Region` format. So you it is misleading to parse the given input as a `ZonedDateTime` though that works technically. Instead, parse as a `OffsetDateTime`. – Basil Bourque Jun 18 '18 at 09:26
  • 1
    My comments above assume the intent is to perceive the date and time-of-day in UTC. If instead the goal is to adjust into a particular time zone, then parse as a `Instant`, apply a `ZoneId` to get a `ZonedDateTime`. Like this: `Instant.parse( "2018-06-05T12:42:48.545140Z" ).atZone( ZoneId.of( "Pacific/Auckland" ) ).format( DateTimeFormatter.ofPattern("dd/MM/yyyy hh:mm") )` – Basil Bourque Jun 18 '18 at 09:31
  • Thank you @BasilBourque for the information, each time new thing from you and Ole V.V. about date and time I appreciate it – Youcef LAIDANI Jun 18 '18 at 09:51
1

I solved the issue by changing the date format in the serializer class

    date = serializers.DateTimeField(format="%m/%d/%Y %H:%M", required=False, read_only=True)
Amine Messaoudi
  • 2,141
  • 2
  • 20
  • 37