java.time
The java.util
Date-Time API and their formatting API, SimpleDateFormat
are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.
Solution using java.time
, the modern Date-Time API:
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Month;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
ZonedDateTime zdtUtc = LocalDate.of(2014,Month.NOVEMBER, 18)
.atTime(LocalTime.of(20, 0))
.atZone(ZoneId.of("Etc/UTC"));
System.out.println(zdtUtc);
}
}
Output:
2014-11-18T20:00Z[Etc/UTC]
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time.
Explanation of the problem you are facing:
A java.util.Date
object simply represents an instant on the timeline — a wrapper around the number of milliseconds since the UNIX epoch (January 1, 1970, 00:00:00 GMT). Since it does not hold any timezone information, its toString
function applies the JVM's timezone to return a String
in the format, EEE MMM dd HH:mm:ss zzz yyyy
, derived from this milliseconds value. To get the String
representation of the java.util.Date
object in a different format and timezone, you need to use SimpleDateFormat
with the desired format and the applicable timezone e.g.
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String strDateNewYork = sdf.format(date);
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String strDateUtc = sdf.format(date);
A valuable comment from Ole V.V.:
If we cannot avoid getting an old-fashioned Calendar
object, by all
likelihood it’s really a GregorianCalendar
, and we can convert it to
ZonedDateTime
simply by using ((GregorianCalendar) cal).toZonedDateTime()
. Then we’re set.
Another one:
Or if using a backport: DateTimeUtils.toZonedDateTime(cal)
.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.