Noterezeck
Noterezeck

Reputation: 422

Date() does not catch a time zone change

My application gets a response from my server with the date and time of past events. My server, however, is in another time zone and here things get a bit tricky. Server time zone is UTC +01:00, while mine is UTC +03:00. When I receive responses from the server, they come with a timestamp in UTC +01:00. First, I tried to receive the date as a String, substring it, set its time zone and then return it in a proper time format and zone. (I cut the last 4 digits of the milisec, because the DateFormat was invalid otherwise.)

private String getFormattedDate(String date) {
    DateFormat serverDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
    DateFormat finalDateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
    Calendar calendar = Calendar.getInstance();
    TimeZone timeZone = calendar.getTimeZone();
    serverDateFormat.setTimeZone(timeZone);
    String cutoutDate = date.substring(0,23);
    String cutoutZone = date.substring(27, date.length());
    String dateInProperFormat = cutoutDate + cutoutZone;
    Date finalDate = serverDateFormat.parse(dateInProperFormat);
    return finalDateFormat.format(finalDate);
}

This read and converted everything correctly:

Server response: 2018-04-30T07:26:55.1524511+01:00 -> Substringed response: 2018-04-30T07:26:55.152+01:00 -> Final format: 30-04-2018 09:26:55

However, the milisec were not always 7, so when that happened, I got an Unparsable date error. This made me read the date not as a String, but as a Date instead. This cut the code to only 5 lines:

private String getFormattedDate(Date date) {
    SimpleDateFormat finalDateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
    Calendar calendar = Calendar.getInstance();
    TimeZone timeZone = calendar.getTimeZone();
    finalDateFormat.setTimeZone(timeZone);
    return finalDateFormat.format(date);
}

But now, the time is always in UTC +01:00. I tried getting the timezone like this:

TimeZone timeZone = TimeZone.getDefault();

But that didn't change anything. What exactly am I doing wrong in my second approach? I am ready to share more of my code if needed.

Upvotes: 1

Views: 301

Answers (2)

Anonymous
Anonymous

Reputation: 86296

java.time

private static DateTimeFormatter finalDateTimeFormatter
        = DateTimeFormatter.ofPattern("dd-MM-uuuu HH:mm:ss");
private static ZoneId zone = ZoneId.of("Europe/Istanbul");

private static String getFormattedDate(String dateTime) {
    return OffsetDateTime.parse(dateTime)
            .atZoneSameInstant(zone)
            .format(finalDateTimeFormatter);
}

Let’s try it out with the example server response from your question:

    System.out.println(getFormattedDate("2018-04-30T07:26:55.1524511+01:00"));

This outputs the desired:

30-04-2018 09:26:55

Points to note:

  • The one-arg OffsetDateTime.parse accepts from 1 to 9 decimals on the seconds, so you don’t need to manipulate the string in any way before parsing.
  • Don’t use your UTC offset of UTC +03:00 as a time zone. Use a time zone like Africa/Nairobi, Europe/Moscow, Asia/Qatar or what is appropriate. It documents better why you are doing what you are doing, and it’s future-proof in case the offset is changed. Which happens more often than you may like to think.

Question: Can I use java.time on Android?

Yes, java.time works nicely on 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, I’m told) the modern API comes built-in.
  • In Java 6 and 7 get the ThreeTen Backport, the backport of the new 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

Upvotes: 2

Vinayak B
Vinayak B

Reputation: 4520

try below code. It's a workaround solution

   public String getFormattedDate(String date) {
    DateFormat serverDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
    DateFormat finalDateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
    Calendar calendar = Calendar.getInstance();
    TimeZone timeZone = calendar.getTimeZone();
    serverDateFormat.setTimeZone(timeZone);
    String[] splitTime=date.split("\\+");
    String cutoutDate="";
    if (splitTime[0].length()>23)cutoutDate = date.substring(0,23);
    else cutoutDate=splitTime[0];
    String cutoutZone = "+"+splitTime[1];
    String dateInProperFormat = cutoutDate + cutoutZone;
    Date finalDate = null;
    try {
        finalDate = serverDateFormat.parse(dateInProperFormat);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return finalDateFormat.format(finalDate);
}

Upvotes: 1

Related Questions