Here my java code that try to get current date in UTC on Android device:
public static Date getCurrentDateUTC() {
try {
TimeZone timeZoneUTC = TimeZone.getTimeZone("UTC");
Date localTime = new Date();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss Z");
dateFormat.setTimeZone(timeZoneUTC);
String dateUTCAsString = dateFormat.format(localTime);
Debug.d(TAG, "getCurrentDateUTC: dateUTCAsString = " + dateUTCAsString);
Date dateResult = dateFormat.parse(dateUTCAsString);
Debug.d(TAG, "getCurrentDateUTC: dateResult = " + dateResult);
return dateResult;
} catch (ParseException e) {
Debug.e(TAG, "getCurrentDateUTC: ", e);
return null;
}
}
Result:
dateUTCAsString = 2017-11-15T12:54:25 +0000
dateResult = Wed Nov 15 14:54:25 EET 2017
As you can see the dateUTCAsString IS CORRECT show current date in UTC, but after parse
the dateResult is not correct. Why?
Excuse me for mentioning it, I suspect that there is no problem in your code, there’s only confusion. If you think the old
Date
class is behaving confusingly, allow me to be the first of many to agree with you. The good and sound solution to this problem is you stop usingDate
and start using the modern Java date and time API instead.Since you are coding for Android, you first step is to get the ThreeTenABP, the library for Android that offers the modern API (if you were using Java 8 or 9, you could skip this step since the modern API wold be built in). The details are described in this question: How to use ThreeTenABP in Android Project. Now you can do:
On my computer this just printed:
The
Z
at the end means Zulu time zone or UTC.As you may know,
System.out.println(dateResult)
implicitly calls thetoString
method of thedateResult
object. Objects of the classInstant
produce the above format, always in UTC, as I understood you wanted. TheInstant
class is the natural replacement for the old-fashionedDate
class for most purposes. Internally theInstant
holds the number of seconds and nanoseconds since the epoch, which is defined as January 1 1970 at 0:00 midnight UTC. I encourage you to consider this an irrelevant implementation detail. AnInstant
is a point on the time-line.What went wrong?
You asked for a date in UTC. Depending on how you look at it, you can or cannot have this.
Date
is implemented as the number of seconds and milliseconds since the epoch, so if you use the above definition of the epoch, you may say that it is always in UTC.Date
(like anInstant
) is a point on the time-line, and does not and cannot have a time zone or offset; it cannot be in UTC. To make matters more confusing, when you do"getCurrentDateUTC: dateResult = " + dateResult
, thendateResult.toString()
is implicitly called. This method grabs your JVM’s time zone setting and converts the date-time to this zone and uses it for the generated string (without modifying theDate
object). This is why you will see the time in EET on your computer or device no matter whichDate
you try to print.java.time
or JSR-310The modern date and time API is know as
java.time
or JSR-310. One good source for learning to use it is the Oracle tutorial.