tl;dr
Instant.ofEpochMilli( 1_317_816_735_000L )
.atZone( ZoneId.of( "Pacific/Auckland" ) )
.format( DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( new Locale( "en" , "NZ" ) ) )
…also…
LocalDateTime.parse( "2011-10-06 03:35:05".replace( " " , "T" ) )
.atZone( ZoneId.of( "Pacific/Auckland" ) )
java.time
The Question and most Answers use outdated legacy date-time classes from the earliest versions of Java. These old classes have proven to be troublesome and confusing. Avoid them. Instead use the java.time classes.
ISO 8601
Your input string is nearly in standard ISO 8601 format. Just replace the SPACE in the middle with a T
.
String input = "2011-10-06 03:35:05".replace( " " , "T" );
LocalDateTime
Now parse as a LocalDateTime
because the input lacks any information about offset-from-UTC or time zone. A LocalDateTime
has no concept of offset nor time zone, so it does not represent an actual moment on the timeline.
LocalDateTime ldt = LocalDateTime.parse( input );
ZoneOffset
You seem to be saying that from the business context you know the intention of this string is to represent a moment that is 13 hours ahead of UTC. So we instantiate a ZoneOffset
.
ZoneOffset offset = ZoneOffset.ofHours( 13 ); // 13 hours ahead of UTC, in the far east of the globe.
OffsetDateTime
Apply it to get an OffsetDateTime
object. This becomes an actual moment on the timeline.
OffsetDateTime odt = ldt.atOffset( offset);
ZoneId
But then you mention New Zealand. So you had a specific time zone in mind. A time zone is an offset-from-UTC plus a set of rules for handling anomalies such as Daylight Saving Time (DST). So we can specify a ZoneId
to a ZonedDateTime
rather than a mere offset.
Specify a proper time zone name. Never use the 3-4 letter abbreviation such as EST
or IST
as they are not true time zones, not standardized, and not even unique(!). For example, Pacific/Auckland
.
ZoneId z = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime
Apply the ZoneId
.
ZonedDateTime zdt = ldt.atZone( z );
You can easily adjust into another zone for the very same moment on the timeline.
ZoneId zParis = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdtParis = zdt.withZoneSameInstant( zParis ); // Same moment in time, but seen through lens of Paris wall-clock time.
Count from epoch
I strongly recommend against handling date-time values as a count from epoch, such as milliseconds from the start of 1970 UTC. But if you must, create a Instant
from such a number.
Instant instant = Instant.ofEpochMilli( 1_317_816_735_000L );
Then assign a time zone as seen above, if desired, to move away from UTC.
ZoneId z = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime zdt = instant.atZone( z );
Your value of 1_317_816_735_000L
is:
2011-10-05T12:12:15Z
(Wed, 05 Oct 2011 12:12:15 GMT)
2011-10-06T01:12:15+13:00[Pacific/Auckland]
(Thursday October 06, 2011 01:12:15 in Auckland New Zealand).
Generate strings
To generate a string in standard ISO 8601 format, simply call toString
. Note that ZonedDateTime
wisely extends the standard format by appending the name of the time zone in square brackets.
String output = zdt.toString();
For other formats, search Stack Overflow for DateTimeFormatter
class. Already covered many times.
Specify a FormatStyle
and a Locale
.
Locale l = new Locale( "en" , "NZ" );
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( l );
String output = zdt.format( f );
Note that time zone has nothing to do with locale. You can have a Europe/Paris
date-time displayed in Japanese language & cultural norms, or a Asia/Kolkata
date-time displayed in Portuguese language and Brazil cultural norms.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old date-time classes such as java.util.Date
, .Calendar
, & java.text.SimpleDateFormat
.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.
1317816735000L
is the wrong timestamp for2011-10-06 03:35:05 GMT
. Otherwise your approach is correct. – augurarjava.util.Date
,java.util.Calendar
, andjava.text.SimpleDateFormat
are now legacy, supplanted by the java.time classes built into Java 8 and later. See Tutorial by Oracle. – Basil Bourque