-4

This is my SimpleDateFormat instance:

public static final SimpleDateFormat DD_MMM_YYYY =
                new SimpleDateFormat("dd MMM yyyy");

I'm converting timestamps in milliseconds to this date format.

Sometimes it returns the correct date like:

22 Feb 2018

But sometimes (in rare cases) it returns an incorrect date like:

0022 Feb 2018

Why is it adding two leading zeros?

My method is below-

public static String convertLongToDate(long timestamp) {
        Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
        long todaysTimestamp = calendar.getTimeInMillis();
        calendar.add(Calendar.DAY_OF_YEAR, -1);
        long yesterdayTimestamp = calendar.getTimeInMillis();
        calendar.setTimeInMillis(timestamp);
        String timeString;

        String todaysDateStr = DD_MMM_YYYY.format(todaysTimestamp);
        String givenDateStr = DD_MMM_YYYY.format(calendar.getTimeInMillis());

        Log.d("Check", "date-> todaysDateStr=" + todaysDateStr + ", givenDateStr=" + givenDateStr+", todayLength="+todaysDateStr.length()+", givenLength="+givenDateStr.length());
        if (todaysDateStr.equalsIgnoreCase(givenDateStr)) {
            timeString = AppConstants.TODAY;
        } else if (DD_MMM_YYYY.format(yesterdayTimestamp).equalsIgnoreCase(givenDateStr)) {
            timeString = AppConstants.YESTERDAY;
        } else {
            timeString = givenDateStr;
        }
        timeString = timeString.trim();
        return timeString;
    }
  • never gonna happen so i think its ur mistake – duggu Feb 22 '18 at 12:23
  • What do you mean by sometimes? You run the same code 1000 times and a few times it's just with leading zeroes? Anything modifying the value in between? – Andreas Hartmann Feb 22 '18 at 12:23
  • Nothing is modifying value, there is a function which takes timestamp in milliseconds and convert it in given format. – Mohit Rajput Feb 22 '18 at 12:27
  • 2
    Can you show some code that produces this? – Michael Seiler Feb 22 '18 at 12:33
  • Michael - Edit my question with method – Mohit Rajput Feb 22 '18 at 13:02
  • The `SimpleDateFormat` class is long outdated and notoriously troublesome. Consider adding [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP) to your Android project so you can use [`java.time`, the modern Java date and time API,](https://docs.oracle.com/javase/tutorial/datetime/) instead. It is so much nicer to work with. And its classes are thread-safe; my guess is that this fact will solve your problem. – Ole V.V. Feb 22 '18 at 13:03
  • 1
    **This Question is now moot**, as the terrible `Calendar` and `SimpleDateformat` classes are supplanted by the *java.time* classes. Much of the *java.time* functionality is back-ported to Java 6 & Java 7 in the [***ThreeTen-Backport***](http://www.threeten.org/threetenbp/) project. Further adapted for earlier Android in the [***ThreeTenABP***](https://github.com/JakeWharton/ThreeTenABP) project. See [*How to use ThreeTenABP…*](http://stackoverflow.com/q/38922754/642706). – Basil Bourque Feb 23 '18 at 00:53

2 Answers2

3

Without more info about how you're using the formatter, it's hard to tell what the problem is.

But my guess is that it happens because SimpleDateFormat is not thread-safe.

When running it in a multi-thread environment, strange things start to happen. Just check at google and you'll find lots of articles about that: https://www.google.com/search?q=simpledateformat+not+thread+safe

Update:

Using your code, I can't reproduce the problem, but I still think it's related to using a non-threadsafe class in a multithread environment - it's the only situation I know that problems like this can happen, specially the "sometimes" factor.

Silly question: does any of the AppConstants values have leading zeroes? Just asking, who knows...

Alternatives

You can use a better API for that, such as ThreeTen Backport: https://stackoverflow.com/a/48911470

With that, your code becomes much more clear and easy to understand/maintain:

public static String convertLongToDate(long timestamp) {
    DateTimeFormatter f = DateTimeFormatter.ofPattern("dd MMM yyyy");
    ZonedDateTime today = ZonedDateTime.now(ZoneId.systemDefault());
    ZonedDateTime yesterday = today.minusDays(1);

    ZonedDateTime givenDate = Instant.ofEpochMilli(timestamp).atZone(ZoneId.systemDefault());

    String timeString;
    // compare just the date (day, month, year)
    // no need to convert to string to compare if dates are the same
    if (today.toLocalDate().equals(givenDate.toLocalDate())) {
        timeString = AppConstants.TODAY;
    } else if (yesterday.toLocalDate().equals(givenDate.toLocalDate())) {
        timeString = AppConstants.YESTERDAY;
    } else {
        timeString = givenDate.format(f);
    }
    timeString = timeString.trim();
    return timeString;
}

This API is threadsafe and those strange things that happen sometimes with SimpleDateFormat don't happen here.

Or, if you don't want to use another API, you can use the solutions of this post: http://fahdshariff.blogspot.com.br/2010/08/dateformat-with-multiple-threads.html

ddd
  • 65
  • 4
  • AppConstants doesn't have any zeros. The problem can be thread-safety. Will implement your code and let you know. – Mohit Rajput Feb 22 '18 at 13:51
  • +1. The code using ThreeTen Backport (and on Android, [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP)) is not only clearer to read, quite importantly it’s thread-safe because the modern classes are. You can make it still a bit simpler by using `LocalDate` everywhere, the only place you need one `ZonedDateTime` is in the conversion of the `long` timestamp, so just convert on to `LocalDate` immediately. – Ole V.V. Feb 22 '18 at 13:52
  • @MohitRajput You can also use the solutions with ThreadLocal, as explained here: http://fahdshariff.blogspot.com.br/2010/08/dateformat-with-multiple-threads.html – ddd Feb 22 '18 at 13:53
  • `DateTimeFormatter` being thread-safe you can safely let it be `public static final` as the formatter in the question. – Ole V.V. Feb 22 '18 at 13:55
0

if you show current date and specific format then used below code.

Date c = Calendar.getInstance().getTime(); // get current date and time.
    System.out.println("Current time => " + c);

    SimpleDateFormat df = new SimpleDateFormat("dd MMM yyyy"); // define your format.
    String formattedDate = df.format(c);
    System.out.println("New Date To Show::"+formattedDate);
Android Team
  • 11,274
  • 2
  • 26
  • 46