I declared Calendar
and SimpleDateFormat
like this:
calendar = Calendar.getInstance(TimeZone.getTimeZone("Malaysia"));
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MMMMM.dd hh:mm aaa");
or:
calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+08:00"));
Then I call this:
sdf.format(calendar.getTime());
but result is not in correct time zone (+8 hours). What could be the problem?
tl;dr
Avoid legacy classes
The Question and other Answers use troublesome old date-time classes that are now legacy, supplanted by the java.time classes.
java.time
The modern approach uses java.time classes. Forget all about the terribly confusing
Calendar
class.Current moment
First get the current moment in UTC. The
Instant
class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).Time zone
Adjust into another time zone.
Specify a proper time zone name in the format of
continent/region
, such asAmerica/Montreal
,Africa/Casablanca
, orPacific/Auckland
. Never use the 3-4 letter pseudo-zones such asEST
orIST
as they are not true time zones, not standardized, and not even unique(!).Apply the
ZoneId
to instantiate aZonedDateTime
object. Both theZonedDateTime
andInstant
represent the same moment, the very same point on the timeline, but is viewed through a different wall-clock time.Offset
If you had only an offset-from-UTC such as
+08:00
rather than a known time zone, you would useZoneOffset
to get aOffsetDateTime
instead of aZoneId
&ZonedDateTime
. But a time zone is always preferable to a mere offset. A zone is a history of offsets used by the people of particular region.Strings
To generate a string in standard ISO 8601 format, call
toString
method.The
ZonedDateTime
class wisely extends the standard by appending the time zone name in square brackets.Localize to the user’s preferences. To localize, specify:
FormatStyle
to determine how long or abbreviated should the string be.Locale
to determine (a) the human language for translation of name of day, name of month, and such, and (b) the cultural norms deciding issues of abbreviation, capitalization, punctuation, separators, and such.Locale l = Locale.CANADA_FRENCH ; DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( l ); String output = zdt.format( f );
Dump to console.
See this code run live at IdeOne.com. Note that IdeOne.com overrides any
Locale
setting to always useLocale.US
.About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as
java.util.Date
,Calendar
, &SimpleDateFormat
.The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
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.Unless you are going to perform Date/Time related calculations, there is no point in instantiating Calendar with given TimeZone. After calling Calendar's
getTime()
method, you will receiveDate
object, which is timezone-less either way (GMT based, actually).What you need to do, is to set
TimeZone
for formatter instead. And also do not bother with passing your own format, there is a built-in already:This prints something like
10 Mei 2011 2:30:05 AM
, which I believe is your desired result.The
TimeZone.getTimeZone()
call is incorrect. You have to pass a the correct identifier.EDIT -- You can try to getAvailableIDs() and iterate through them to make sure you have the correct id.
Time zone id should be set as
Asia/Kuala_Lumpur
.Date.toString()
always returns time string using default time zone. But your default time zone is different.If you've read the javadoc of TimeZone carefully, the way to use getTimeZone is: TimeZone.getTimeZone("GMT-8") or TimeZone.getTimeZone("GMT+8")