1

I am trying to create a timestamp in the format "mm/dd/yyyy hh:mm a". My app was originally crashing but I tried a different method and it doesn't crash anymore but on the chat screen it shows "java.text.SimpleDateFormat@4f47c0fb" instead of the timestamp.

Here is a screen shot of the chat screen timestamp

This is from my AdapterChat.java file

    @Override
public void onBindViewHolder(@NonNull MyHolder myHolder, int i) {
    //Get data
    String message = chatList.get(i).getMessage();
    String timeStamp = chatList.get(i).getTimestamp();

    //Convert time stamp to mm/dd/yyyy hh:mm am/pm
    //Calendar cal = Calendar.getInstance(Locale.ENGLISH);
    //cal.setTimeInMillis(Long.parseLong(timeStamp));
    String dateTime = new SimpleDateFormat("MM/dd/yyyy hh:mm a", Locale.getDefault()).toString();


    //Set data
    myHolder.messageTv.setText(message);
    myHolder.timeTv.setText(dateTime);
    try {
        Picasso.get().load(imageUrl).into(myHolder.profileIv);
    } catch (Exception e) {

    }

    //Set seen/delivered status of message
    if (i == chatList.size() - 1) {
        if (chatList.get(i).isSeen()) {
            myHolder.isSeenTv.setText("Seen");
        }
        else {
            myHolder.isSeenTv.setText("Delivered");

        }

    }
    else {
        myHolder.isSeenTv.setVisibility(View.GONE);
    }
}

I commented out the 2 lines of code that were causing it to crash and I tried the new method under it. Can someone guide me in the right direction. I'm not sure what I'm doing wrong. Any help would be appreciated. Thanks!

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Indigo
  • 167
  • 1
  • 2
  • 13
  • 1
    Used date format is incorrect. Use mm for minute and MM for month. – Vasil Lukach Dec 22 '19 at 15:48
  • As an aside consider throwing away the long outmoded and notoriously troublesome `SimpleDateFormat` and friends, and 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. Dec 22 '19 at 15:58
  • @VasilLukach thanks I edited the original post – Indigo Dec 22 '19 at 16:24
  • @OleV.V. thanks I will look into that API anything to make this less painful. It shouldn't be so complicated to establish a proper timestamp lol – Indigo Dec 22 '19 at 16:25
  • What does `chatList.get(i).getTimestamp()` return? If you can just give an example. Or even better, if you can modify it not to return a `String` but an `Instant` (from java.time; an `org.threeten.bp.Instant` if using the backport I mentioned). – Ole V.V. Dec 22 '19 at 16:30
  • @OleV.V. I think it was returning null – Indigo Dec 22 '19 at 17:25
  • So when `chatList.get(i).getTimestamp()` returns `null`, which timestamp do you want to display? Current time?? – Ole V.V. Dec 23 '19 at 13:20
  • Well the way I envision it is, there should only be a null return if there was no chat ever established. So at that point, if it's null I wouldn't want it to return anything. But if the user is is opening a previous chat, the time stamp should show when those messages were previously sent. Not the current time stamp. And that's the issue I'm having now. When I go into an existing chat, each message shows a time stamp of the current time, not when it was actually sent. @OleV.V. Sorry I'm so late with my reply btw – Indigo Dec 27 '19 at 19:45
  • Thank you for explaining. I have modified my answer a bit after the new information. – Ole V.V. Dec 27 '19 at 21:55
  • @Indigo - If one of the answers resolved your issue, you can help the community by marking it as accepted. An accepted answer helps future visitors use the solution confidently. Check https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work to learn how to do it. – Arvind Kumar Avinash May 28 '20 at 19:03

2 Answers2

1

java.time and ThreeTenABP

There are more than one unclear point about your question, but I am trying a suggestion. For my way of doing it I need two formatters:

private static DateTimeFormatter timestampFormatter = new DateTimeFormatterBuilder()
        .appendValue(ChronoField.INSTANT_SECONDS)
        .appendValue(ChronoField.MILLI_OF_SECOND, 3)
        .toFormatter();

private static DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm a");

I understand that chatList.get(i).getTimestamp() may return null, but also that in this case you haven’t got any chat message to display. We need to take this possibility into account. The code below will give you the string NA. Modify if you want something else. Next it would seem from your commented-out code (the code that crashed on the null) that it may also return a String containing a long count of milliseconds since the epoch. So I am handling that situation too.

    int i = 0;
    String timeStamp = chatList.get(i).getTimestamp();

    String dateTime;
    if (timeStamp == null) {
        dateTime = "NA";
    } else {
        Instant inst = timestampFormatter.parse(timeStamp, Instant.FROM);
        dateTime = inst.atZone(ZoneId.systemDefault()).format(dtf);
    }

    System.out.println(dateTime);

Example output in my time zone (Europe/Copenhagen) when chatList.get(i).getTimestamp() returned 1567890123456:

09/07/2019 11:02 PM

What went wrong in your code?

First case, when timeStamp is null and you try Long.parseLong(timeStamp), you will get a java.lang.NumberFormatException: null. If your code doesn’t catch this exception, it crashes.

Second case, you were calling the toString method of your SimpleDateFormat. SimpleDateFormat doesn’t define a toString method itself so Object.toStrng() is called. This returns such a string as java.text.SimpleDateFormat@4f47c0fb. The class name and a funny hex value separated by an @ sign.

However, you should probably not want to use SimpleDateFormat at all. That class is a notorious troublemaker and long outdated. Instead in my code I am using DateTimeFormatter and other classes from java.time, the modern Java date and time API.

Question: Doesn’t java.time require Android API level 26?

java.time works nicely on both older and newer Android devices. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in. In this case you need to substitute the constant Instant.FROM in the above code with the method reference Instant::from.
  • In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
  • On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
0

You have to use toLocalizedPattern() in place of toString() in

String dateTime = new SimpleDateFormat("mm/dd/yyyy hh:mm a", Locale.getDefault()).toString();

i.e you have to use it like this

String dateTime = new SimpleDateFormat("mm/dd/yyyy hh:mm a", Locale.getDefault()).toLocalizedPattern();
Amit Tiwary
  • 787
  • 1
  • 8
  • 16