0

I've read many answers to this issue but couldn't figure out why this is happening. Below is the code.

Creating date format instance variable in the constructor of a class:

format = new SimpleDateFormat("ddMMyy",Locale.US); 
format.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));

Then, used it this way:

Date d = format.parse("280218");

Calling d.toString() gives:

  • on Lenovo K5 Android 5.1 -> "Wed Feb 28 00:00:00 IST 2018"
  • on Nexus emulator Android 7.1 -> "Wed Feb 28 00:00:00 GMT+05:30 2018"
  • on Xiaomi Android 4.4 -> "Wed Feb 28 00:00:00 IST 2018"
  • on Xiaomi Redmi Android 4.4 -> "Wed Feb 28 00:00:00 GMT+05:30 2018"

Parsing the IST date string in subsequent code gives ParseException whereas string with GMT gets parsed successfully.

Any idea about why this is happening?

Community
  • 1
  • 1
  • 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. Jan 19 '18 at 21:17
  • IST is ambiguous, could mean Irish Summer Time, Israel Standard Time or India Standard Time. This may explain why you cannot parse it back. But why are you converting to string through `toString()` just to parse back to a `Date` again later? Asking in an attempt to understand what your real problem is. – Ole V.V. Jan 19 '18 at 21:26
  • 1
    Don’t use Date.toString if want to handle that string later in some way. toString is usually for logging or producing a text for human. If you need a strict string representation of Date use SimpleDateFormat or other stuff like that. – algrid Jan 19 '18 at 21:58

1 Answers1

0
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ddMMyy", Locale.US);
    LocalDate d = LocalDate.parse("280218", formatter);

    String dToString = d.toString();
    System.out.println(dToString);

    LocalDate parsedBack = LocalDate.parse(dToString);
    System.out.println(parsedBack);

Prints (two identical lines):

2018-02-28
2018-02-28

The result will be the same on all devices.

I’m not sure exactly why you are doing what you are doing, so I may not have hit exactly what you are after. I have tried to mimic your code as closely as possible only using java.time instead of the long outdated Date and SimpleDateFormat classes. It goes a lot more smoothly. java.time is the modern Java date and time API and is generally much nicer to work with.

Since a LocalDate is a date without time of day or time zone, your issue with the time zone differences is eliminated from the outset. LocalDate.toString() always gives the same string on all devices. And as a further plus, LocalDate parses the same string back without an explicit formatter. It could hardly be easier.

If your Android level is not high enough to use java.time natively, add ThreeTenABP to your project and make sure to import org.threeten.bp.LocalDate and org.threeten.bp.format.DateTimeFormatter.

What went wrong in your code?

The time zone that Date.toString() uses for generating the string hasn’t got anything to do with the formatter you used for parsing the date. Though not officially documented, the method uses the JVM’s time zone setting. I cannot guarantee it will work on your devices, but at least on my Mac I can control the result of Date.toString() through either

    System.setProperty("user.timezone", "Asia/Kolkata");

or

    System.setProperty("user.timezone", "GMT+05:30");

This way I can get the results you got from your different devices. The three and four letter time zone abbreviations are ambiguous and often not true time zones, though, so don’t rely on them for parsing the string from Date.toString() back. BTW TimeZone.setDefault() has the same effect and may be considered more high-level; it’s just me having made a habit of avoiding the outdated date-time classes including TimeZone.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • Why do you think `LocalDate` would be of some use to the OP? It looks like he wants the time **with** the time zone information. – algrid Jan 19 '18 at 22:10
  • Good question, @algrid, thanks. I had to make a guess, it can be correct or incorrect, the OP only can tell. The date-time came out of the string `280218` without any time of day, and time zone was only printed because the `Date.toString()` always does that. This was why I guessed the way I did. – Ole V.V. Jan 19 '18 at 22:14
  • If it’s required to keep time zone information, use `d.atStartOfDay(ZoneId.of("Asia/Kolkata"))` to obtain s `ZonedDateTime` and then use this for the rest in quite a similar way. – Ole V.V. Jan 19 '18 at 22:18