Reputation: 397
Function to convert server date to device local time:
public static String convertIntoLocalTime(String strTime, String whichTimeZone, String dateFormat) {
String strLocalTime = null;
try {
SimpleDateFormat sdf = getSimpleDateFormat(dateFormat, whichTimeZone);
Date date = sdf.parse(strTime);
AppLog.e(TAG,"Timezone = " + whichTimeZone);
AppLog.e(TAG,"Date = " + strTime);
AppLog.e(TAG,"Date in CET = " + date.toString());
AppLog.e(TAG,"inDaylightTime = " + sdf.getTimeZone().inDaylightTime(date));
AppLog.e(TAG,"DST savings = " + sdf.getTimeZone().getDSTSavings());
if (sdf.getTimeZone().getDSTSavings() == 3600000) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.HOUR, 1);
Date oneHourBack = cal.getTime();
SimpleDateFormat local = getLocalSimpleDateFormat(dateFormat);
strLocalTime = local.format(oneHourBack);
} else {
SimpleDateFormat local = getLocalSimpleDateFormat(dateFormat);
strLocalTime = local.format(date);
}
} catch (ParseException e) {
AppLog.e(TAG, e.getMessage(), e);
}
AppLog.e(TAG,"Local Time = " + strLocalTime);
return strLocalTime;
}
Function to get simple date format:
private static SimpleDateFormat getSimpleDateFormat(String format, String tz) {
TimeZone timeZone = TimeZone.getTimeZone(tz);
timeZone.useDaylightTime();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format, Locale.getDefault());
simpleDateFormat.setTimeZone(timeZone);
return simpleDateFormat;
}
Function to get simple date format for local device conversion:
/**
* @param format
* @return
*/
private static SimpleDateFormat getLocalSimpleDateFormat(String format) {
TimeZone timeZone = TimeZone.getDefault();
timeZone.useDaylightTime();
SimpleDateFormat localSdf = new SimpleDateFormat(format, Locale.getDefault());
localSdf.setTimeZone(timeZone);
return localSdf;
}
Output:
Date = 2018-04-22 14:30
Date in CET = Sun Apr 22 13:30:00 GMT+01:00 2018
inDaylightTime = true
DST savings = 3600000
Local Time = 2018-04-22 14:30
The above code was working perfectly fine earlier, for example we have 1 event on 1st of April where it was showing time correctly but at the moment starting from 21 April its showing additional 1 hour time.
I have tried to convert the date coming from server using UTC as well as CET but in both the cases its showing me additional one hour when converting it to device local time.
The above example is based on London timezone, whereas when we tried it in IST timezone it was returning the correct time.
We have handled DST time different by checking inDaylightTime
function of timezone but it's not working.
I am sure that there is something related to DST but I am not able to figure it out. Thanks for your help?
Upvotes: 1
Views: 3788
Reputation: 86324
First, you are using the old and long outdated date and time classes: SimpleDateFormat
, Date
, Calendar
and TimeZone
. These are renowned for being poorly designed and sometimes troublesome to work with. My first suggestion is you rewrite your code using java.time
, the modern Java date and time API. It is much less buggy, and I expect that you will more easily develop correct code.
That said, no matter if you use the old-fashioned or the modern classes, don’t handle summer time yourself. The library classes will do it for you. Your job is to get the time zones correct. Don’t add or subtract an hour to compensate for summer time. Look at other questions about converting from one time zone to another, there are many.
Don’t use three and four letter time zone abbreviations. CET is not a time zone. IST is ambiguous, it may mean Irish Summer Time, Israel Standard Time or India Standard Time. The countries in Europe that use CET in winter have used CEST (Central European Summer Time) since March 26, 2018.
Instead give server time zone as continent/city such as Europe/London
if this is the server time zone. It’s unambiguous.
Also make sure to set your device time zone to a true time zone. It seems you’ve got it set to GMT+01:00, which is a GMT offset, not a time zone. It agrees with Europe/London time zone and with CET in winter, but not after March 26.
Finally, you are adding 1 hour to your Calendar
, turning it 1 hour forward, and then calling the Date
you get from it oneHourBack
. This looks wrong. Did you mean to subtract 1 hour, or did you mean that the variable should be oneHourForward
?
EDIT: I probably haven’t understood exactly which time zones are the correct ones for you, and therefore not what would be the correct output for your code. So take the following only as a guess at what you were trying to accomplish. And please fill in the correct time zones.
public static String convertIntoLocalTime(
String strTime, String serverTimeZone, String dateFormat) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormat);
ZonedDateTime serverDateTime = LocalDateTime.parse(strTime, formatter)
.atZone(ZoneId.of(serverTimeZone));
AppLog.e(TAG, "Server timezone = " + serverTimeZone);
AppLog.e(TAG, "Date = " + strTime);
AppLog.e(TAG, "Date in server timezone = " + serverDateTime.toString());
ZonedDateTime deviceTime = serverDateTime
.withZoneSameInstant(ZoneId.systemDefault());
String strLocalTime = deviceTime.format(formatter);
AppLog.e(TAG, "Device Time = " + deviceTime);
AppLog.e(TAG, "Local Time = " + strLocalTime);
return strLocalTime;
}
I tried setting my time zone to Europe/London and issuing the following call:
convertIntoLocalTime("2018-04-22 14:30", "Europe/Berlin", "yyyy-MM-dd HH:mm")
The output I got was:
Server timezone = Europe/Berlin
Date = 2018-04-22 14:30
Date in server timezone = 2018-04-22T14:30+02:00[Europe/Berlin]
Device Time = 2018-04-22T13:30+01:00[Europe/London]
Local Time = 2018-04-22 13:30
Yes, java.time
works nicely on older and newer Android devices. It just requires at least Java 6.
org.threeten.bp
with subpackages.java.time
.java.time
was first described.java.time
to Java 6 and 7 (ThreeTen for JSR-310).Upvotes: 2
Reputation: 2127
I was not tested so try it first.
public String convertIntoLocalTime(String strTime, String whichTimeZone, String dateFormat) {
String strLocalTime = null;
strLocalTime=convertDateToUserTimeZone(strTime,whichTimeZone,dateFormat);
return strLocalTime;
}
public String convertDateToUserTimeZone(String strTime, String whichTimeZone, String dateFormat) {
String ourdate;
try {
SimpleDateFormat formatter = new SimpleDateFormat(dateFormat, Locale.UK);
formatter.setTimeZone(TimeZone.getTimeZone(whichTimeZone));
Date value = formatter.parse(strTime);
TimeZone timeZone = TimeZone.getTimeZone("Asia/Kolkata");
SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat, Locale.UK); //this format changeable
dateFormatter.setTimeZone(timeZone);
ourdate = dateFormatter.format(value);
//Log.d("OurDate", OurDate);
} catch (Exception e) {
ourdate = "00-00-0000 00:00";
}
return ourdate;
}
Upvotes: 0