The problem with these 3-letter abbreviations is that they are ambiguous and not standard.
So, MST
is a timezone name that can be applied to lots of different regions, and they might have different DST rules (some might have DST, others might not, and not to mention the historical information - some might had DST in the past and currently don't have anymore, or the opposite).
The old API (java.util.TimeZone
) handled these ambiguities assuming default values for those ambiguous 3-letter names, so MST
was mapped to America/Denver
and this was kept in joda-time - IMO - for compatibility reasons (you can see in the source code - I'm using jodatime 2.7). At least that's what I could understand from the comment:
map.put("MST", "America/Denver"); // JDK 1.1 compatible
And this map is only used in DateTimeZone.forTimeZone(TimeZone)
, a method to convert the old TimeZone
class to jodatime's DateTimeZone
(which, for me, confirms the compatibility reason).
If you want to make sure your code uses the correct timezone, you could do as already told in @Ole V.V.'s comment and use America/Phoenix
instead of MST
. This will remove the ambiguity and make your code more clear about what timezone it's using.
These kind of timezone names (Continent/City
) comes from IANA database and that's the names used by Java's API and Joda time.
Example code:
// create a date/time in UTC
DateTime utc = new DateTime("2017-03-26T10:00:00Z", DateTimeZone.UTC);
System.out.println(utc); // 2017-03-26T10:00:00.000Z
// convert to Arizona timezone
DateTimeZone arizona = DateTimeZone.forID("America/Phoenix");
DateTime arizonaDate = utc.withZone(arizona);
System.out.println(arizonaDate); // 2017-03-26T03:00:00.000-07:00
New Java Time API
If possible, I suggest you to use the new Date/Time API (if migrating from Joda-time to this new API is not possible, desconsider the rest of this answer; but if you want to migrate it, just go on).
The problem with joda is because in joda's website it says: Note that Joda-Time is considered to be a largely "finished" project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).
If you're using Java 8, consider using the new java.time API. It's easier, less bugged and less error-prone than the old APIs.
If you're using Java <= 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it here).
The code below works for both.
The only difference is the package names (in Java 8 is java.time
and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp
), but the classes and methods names are the same.
In the new API, it's possible to map MST
to the timezone you want, using a custom Map
:
// custom map with timezone names
Map<String, String> map = new HashMap<>();
// map "MST" to Arizona's timezone
map.put("MST", "America/Phoenix");
// create timezone
ZoneId arizona = ZoneId.of("MST", map);
// datetime in UTC
ZonedDateTime utc = ZonedDateTime.parse("2017-03-26T10:00:00Z");
System.out.println(utc); // 2017-03-26T10:00Z
// convert to Arizona timezone
ZonedDateTime arizonaDate = utc.withZoneSameInstant(arizona);
System.out.println(arizonaDate); // 2017-03-26T03:00-07:00[America/Phoenix]
Of course the ideal is to use ZoneId.of("America/Phoenix")
, but if it's not possible and you must use MST
, the custom map is a good alternative.
Also note that the new API prints the timezone name between []
. If you want to change it, you can use the DateTimeFormatter
class. You can either use a built-in formatter (check javadoc for more info), or make your own:
// use built-in formatter
DateTimeFormatter fmt = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
System.out.println(fmt.format(arizonaDate)); // 2017-03-26T03:00:00-07:00
// use custom format
fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
System.out.println(fmt.format(arizonaDate)); // 2017-03-26T03:00:00.000-07:00