'Z'
is not the same as Z
'Z'
is just a character literal whereas Z
is the timezone designator for zero-timezone offset. It stands for Zulu and specifies the Etc/UTC
timezone (which has the timezone offset of +00:00
hours).
Therefore, do not use 'Z'
in pattern for parsing/formatting.
The java.time
, the modern Date-Time API
The modern Date-Time API is based on ISO 8601 and does not require using a DateTimeFormatter
object explicitly as long as the Date-Time string conforms to the ISO 8601 standards. The Date-Time string, 2013-09-29T18:46:19Z
conforms to ISO 8601 standards.
Demo:
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
Instant instant = Instant.parse("2013-09-29T18:46:19Z");
OffsetDateTime odt = OffsetDateTime.parse("2013-09-29T18:46:19Z");
ZonedDateTime zdt = ZonedDateTime.parse("2013-09-29T18:46:19Z");
System.out.println(instant);
System.out.println(odt);
System.out.println(zdt);
}
}
Output:
2013-09-29T18:46:19Z
2013-09-29T18:46:19Z
2013-09-29T18:46:19Z
ONLINE DEMO
An Instant
represents an instantaneous point on the timeline in UTC. The Z
in the output is the timezone designator for a zero-timezone offset. It stands for Zulu and specifies the Etc/UTC
timezone (which has the timezone offset of +00:00
hours).
Note#1: In case you need to find out what date and time an Instant
represents in a particular timezone, you can use Instant#atZone
e.g. the following code will print the date and time this Instant
in India:
ZonedDateTime zdtIndia = instant.atZone(ZoneId.of("Asia/Kolkata"));
System.out.println(zdtIndia);
You can even convert an object of ZonedDateTime
from one timezone to another using ZonedDateTime#withZoneSameInstant
e.g. the following code will convert zdt
to an object of ZonedDateTime
representing date and time in India:
ZonedDateTime zdtIndia = zdt.withZoneSameInstant(ZoneId.of("Asia/Kolkata"));
System.out.println(zdtIndia);
Note#2: For any reason, if you need to convert this object of Instant
to an object of java.util.Date
, you can do so as follows:
Date date = Date.from(instant);
You can even convert the object of OffsetDateTime
and ZonedDateTime
to an object of java.util.Date
, as follows:
Date date = Date.from(odt.toInstant());
&
Date date = Date.from(zdt.toInstant());
Learn more about the modern Date-Time API* from Trail: Date Time.
Why did your java.util.Date
object print the India date and time?
A java.util.Date
object simply represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). 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.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
String strDate = sdf.format(date);
System.out.println(strDate);
Demo:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX", Locale.ENGLISH);
Date date = sdf.parse("2013-09-29T18:46:19Z");
// In JVM's timezone and default format as returned by Date#toString
System.out.println(date);
// In UTC and custom format
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String strDate = sdf.format(date);
System.out.println(strDate);
// In India and custom format
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
strDate = sdf.format(date);
System.out.println(strDate);
}
}
Output (my timezone is Europe/London):
Sun Sep 29 19:46:19 BST 2013
2013-09-29T18:46:19Z
2013-09-30T00:16:19+05:30
ONLINE DEMO
* 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.