If you want the current date in UTC, you must set the timezone on the SimpleDateFormat
, not on the Calendar
. And you don't need to create a Calendar
, you can use a Date
directly:
SimpleDateFormat outputFmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
outputFmt.setTimeZone(TimeZone.getTimeZone("UTC"));
String dateAsString = outputFmt.format(new Date()); // current date/time
The X
pattern above was introduced in JDK 7, so if you are using JDK <= 6, you'll have to put a literal Z
:
SimpleDateFormat outputFmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
outputFmt.setTimeZone(TimeZone.getTimeZone("UTC"));
String dateAsString = outputFmt.format(new Date());
Try with X
first, as it's preferrable to output the correct timezone instead of a hardcoded Z
(because if you change the timezone to another one, the Z
will be wrong, because it's used only when the date/time is in UTC).
The old classes (Date
, Calendar
and SimpleDateFormat
) have lots of problems and design issues, and they're being replaced by the new APIs.
For Android, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. You'll also need the ThreeTenABP to make it work (more on how to use it here).
If you want the current date in UTC, you can use the org.threeten.bp.Instant
class (which represents an UTC instant):
String dateAsString = Instant.now().toString();
The dateAsString
variable will have a value like 2017-08-02T19:21:22.271Z
.
If you are working just with UTC values, the Instant
class is enough. But if you want to work with another timezones, you must use a org.threeten.bp.ZonedDateTime
:
// current time in UTC
dateAsString = ZonedDateTime.now(ZoneOffset.UTC).toString();
// current time in another timezone
dateAsString = ZonedDateTime.now(ZoneId.of("Asia/Kolkata")).toString();
The second case will produce a different output (such as 2017-08-03T01:05:06.631+05:30[Asia/Kolkata]
) because it's using a timezone that's not UTC. You can change it, though, by using a org.threeten.bp.format.DateTimeFormatter
:
DateTimeFormatter fmt = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
dateAsString = ZonedDateTime.now(ZoneId.of("Asia/Kolkata")).format(fmt);
This will result in 2017-08-03T01:06:19.131+05:30
. You can also create another formats with DateTimeFormatter.ofPattern("pattern")
, replacing pattern
by the corresponding pattern letters (check the javadoc for more details).
Note that he API uses IANA timezones names (always in the format Region/City
, like Asia/Kolkata
or Europe/Berlin
).
Avoid using the 3-letter abbreviations (like CST
or IST
) because they are ambiguous and not standard.
You can get a list of available timezones (and choose the one that fits best your system) by calling ZoneId.getAvailableZoneIds()
.
You can also use the system's default timezone with ZoneId.systemDefault()
, but this can be changed without notice, even at runtime, so it's better to explicity use a specific one.