I am trying to convert UTC Date to IST. But to my surprise, after converting everything, it is still returning me UTC only. How is it possible?
INPUT:
StartDateTimeUtc='2017-09-15T14:00:00',
EndDateTimeUtc='2017-09-15T15:00:00'
Code:
public static final String DATE_FORMATE_CURRENT = "yyyy-MM-dd'T'HH:mm:ss";
Date meetingStartDate = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT, Locale.ENGLISH).parse(model.StartDateTimeUtc);
Date meetingEndDate = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT, Locale.ENGLISH).parse(model.EndDateTimeUtc);
//Convert Date to String
DateFormat df = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT);
String meetinStartDateString = df.format(meetingStartDate);
String meetingEndDateString = df.format(meetingEndDate);
//Convert String Date to IST
SimpleDateFormat dftwo = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT);
dftwo.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
Date date = null;
Date datetwo = null;
try {
date = dftwo.parse(meetinStartDateString);
datetwo = dftwo.parse(meetingEndDateString);
} catch (ParseException e) {
e.printStackTrace();
}
dftwo.setTimeZone(TimeZone.getDefault());
String formattedStartDate = dftwo.format(date);
String formattedEndDate = dftwo.format(datetwo);
//Convert String Date back to Date format so that we can pass into Calendar code
Date meetingStartDateFinal = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT, Locale.ENGLISH).parse(formattedStartDate);
Date meetingEndDateFinal = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT, Locale.ENGLISH).parse(formattedEndDate);
OUTPUT again in UTC:
Start Date : Fri Sep 15 14:00:00 GMT+05:30 2017
End Date : Fri Sep 15 15:00:00 GMT+05:30 2017
A
java.util.Datedoesn't have any timezone information. It just contains one value: the number of milliseconds since unix epoch (1970-01-01T00:00Z, or January 1st 1907, at midnight in UTC).This number of milliseconds is the same, everywhere in the world. What's is different is the corresponding date and time in each timezone. Example: right now, this millis value is
1505481835424, which corresponds, in UTC, to2017-09-15T13:23:55.424Z. This same value corresponds to 10:23 AM in São Paulo, 18:53 in Kolkata, 14:23 in London and so on. The local date/time is different in each timezone, but the millis value is the same for everyone.That's why you don't convert a
Dateitself: the millis value is the same, and there's no need to change it. What you can change is the representation of this date in different timezones.SimpleDateFormat, by default, uses the JVM default timezone to parse dates. But if you know that the inputs are in a specific zone, you must set in the formatter. So, to parse your inputs, you must do:The 2
Dateobjects above will correspond to 14:00 and 15:00 UTC (which is the same as 19:30 and 20:30 in Kolkata timezone).But if you just print the
Dateobjects directly (usingSystem.out.println, logging, or even checking their values in a debugger), it'll implicity call thetoString()method, which uses the JVM default timezone behind the scenes, resulting in the output you're seeing (Fri Sep 15 14:00:00 GMT+05:30 2017).If you want to print in a specific format, and in a specific timezone, you'll need another formatter:
The output will be:
Which corresponds to the same UTC dates in Kolkata timezone.
Just remember: you don't convert the
Date's between timezones (because their millis values are "absolute" - they are the same for everyone in the world). You just change theStringrepresentation of those dates (the corresponding date/time in a specific timezone).Java new Date/Time API
The old classes (
Date,CalendarandSimpleDateFormat) have lots of problems and design issues, and they're being replaced by the new APIs.In Android you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. To make it work, you'll also need the ThreeTenABP (more on how to use it here).
This new API has lots of different date/time types for each situation. In this case, the inputs have date and time, but no timezone information, so first I parse them to a
org.threeten.bp.LocalDateTime, using aorg.threeten.bp.format.DateTimeFormatter:Then I use a
org.threeten.bp.ZoneOffsetto convert them to UTC, and later aorg.threeten.bp.ZoneIdto convert this to another timezone. The result will be aorg.threeten.bp.ZonedDateTime:Then I use the same
DateTimeFormatterto format the output:The output is:
Note that I don't need to set the timezone in the formatter, because the timezone information is in the objects (they are responsible to do the conversion).