Reputation: 26364
I'm converting a UTC time to another timezone, using this method:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date parsed = format.parse("2011-03-01 15:10:37");
TimeZone tz = TimeZone.getTimeZone("America/Chicago");
format.setTimeZone(tz);
String result = format.format(parsed);
So the input is 2011-03-01 15:10:37
but the output of this (value of result) is 2011-03-01 05:40:37
. While it seems off, and according to this link, it should be 2011-03-01 09:10:37
.
What am I doing wrong?
Upvotes: 41
Views: 49962
Reputation: 1858
The simple sequence I settled for is to parse the UTC time into a LocalDateTime
and then create a ZonedDateTime
with the desired timezone. The resulting ZonedDateTime
can be used to get an Instant
to construct a new Date
object.
In the example snippet below, One can replace ZoneId.systemDefault()
with the desired time zone id.
var instant = LocalDateTime.parse(serverDateTime, DateTimeFormatter.ISO_DATE_TIME)
.atZone(ZoneId.of("UTC")) //the current zone is UTC
.withZoneSameInstant(ZoneId.systemDefault()) //the new time zone
.toInstant();
var date = Date.from(instant);
NB: To use LocalDateTime
in Android API level below 26, you can add Android desugaring lib to your codebase.
Upvotes: 0
Reputation: 86324
Consider using java.time, the modern Java date and time API, for your date and time work.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
ZoneId targetZone = ZoneId.of("America/Chicago");
LocalDateTime parsed = LocalDateTime.parse("2011-03-01 15:10:37", formatter);
ZonedDateTime converted = parsed.atOffset(ZoneOffset.UTC).atZoneSameInstant(targetZone);
String result = converted.format(formatter);
System.out.println(result);
Output is the expected:
2011-03-01 09:10:37
java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
org.threeten.bp
with subpackages.java.time
was first described.java.time
to Java 6 and 7 (ThreeTen for JSR-310).Upvotes: 2
Reputation: 5016
Following code works fine for me to change a date from one tz to another. It considers the DayLightSaving also.
public static Calendar changeTimezoneOfDate(Date date, TimeZone fromTZ, TimeZone toTZ) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
long millis = calendar.getTimeInMillis();
long fromOffset = fromTZ.getOffset(millis);
long toOffset = toTZ.getOffset(millis);
long convertedTime = millis - (fromOffset - toOffset);
Calendar c = Calendar.getInstance();
c.setTimeInMillis(convertedTime);
return c;
}
Upvotes: 10
Reputation: 1014
You can Parse your date format and time zone according to your requirements. Try this snippet of code i hope it helpful for you.
private String getFormattedDate(String OurDate) {
try {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); // According to your Server TimeStamp
formatter.setTimeZone(TimeZone.getTimeZone("UTC")); //your Server Time Zone
Date value = formatter.parse(OurDate); // Parse your date
SimpleDateFormat dateFormatter = new SimpleDateFormat("MM-dd-yyyy"); //this format changeable according to your choice
dateFormatter.setTimeZone(TimeZone.getDefault());
OurDate = dateFormatter.format(value);
} catch (Exception e) {
OurDate = "00-00-0000 00:00";
}
return OurDate;
}
Upvotes: 4
Reputation: 26364
It turns out the code was almost correct, what I didn't take into account was that when parsing the String
to get a Date
object initially, it uses default system TimeZone
, so the source date was not in UTC as I expected.
The trick was to set the timezone when parsing the date to UTC and then set it to destination TimeZone
. Something like this:
SimpleDateFormat sourceFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sourceFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date parsed = sourceFormat.parse("2011-03-01 15:10:37"); // => Date is in UTC now
TimeZone tz = TimeZone.getTimeZone("America/Chicago");
SimpleDateFormat destFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
destFormat.setTimeZone(tz);
String result = destFormat.format(parsed);
Upvotes: 76
Reputation: 313
Converting a date String of the format "2011-06-23T15:11:32" to out time zone.
private String getDate(String dateString) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
Date value = null;
try {
value = formatter.parse(dateString);
} catch (ParseException e) {
e.printStackTrace();
}
SimpleDateFormat dateFormatter = new SimpleDateFormat("dd/MM/yyyy hh:mmaa");
dateFormatter.setTimeZone(TimeZone.getDefault());
String dt = dateFormatter.format(value);
return dt;
}
Upvotes: 14
Reputation: 48871
You need to take Daylight Savings into consideration. I do this by working out the offset (from UTC) in millieseconds. Something like this should work.
int currentOffsetFromUTC = tz.getRawOffset() + (tz.inDaylightTime(parsed) ? tz.getDSTSavings() : 0);
String result = format.format(parsed.getTime() + currentOffsetFromUTC);
The inDayLightTime(...)
method returns a boolean and must be passed a Date object in order for it to decide if that 'date' represents one during a DST period or not.
Upvotes: 2