當你這樣做:
dateFormat.setTimeZone(TimeZone.getDefault());
然後解析String
,你說的格式:「我會給你在這個時區的日期和時間的字符串」。如您使用TimeZone.getDefault()
,它將使用JVM的默認時區。所以,第一件事就是告訴格式化使用UTC在解析時:
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// use UTC to parse
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
....
date = dateFormat.parse(dateString);
我與dateString
測試等於2017-08-01 10:00:00
。因此,date
將等於2017-08-01 10:00:00 UTC
。當您用System.out.println
打印日期時,它會調用toString()
並將其轉換爲JVM的默認時區。
在我使用的JVM,默認的時區爲America/Sao_Paulo
,所以當我把這個:
System.out.println(date);
它打印:
週二8月1日07:00:00 BRT 2017年
因爲在8月1日,上午10時在UTC相當於在聖保羅7 AM。 這將導致根據您的JVM默認時區更改。
如果你想打印日期,但日期和時間等同於另一個時區(UTC相比其他),你需要用不同的時區設定的另一格式:
DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// use my default timezone to format (America/Sao_Paulo)
dateFormat2.setTimeZone(TimeZone.getDefault());
formattedDate = dateFormat2.format(date);
這將打印:
2017年8月1日07:00:00
而不是默認的時區,你可以使用任何你想要的時區(我使用America/New_York
爲例):
DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// use New York timezone
dateFormat2.setTimeZone(TimeZone.getTimeZone("America/New_York"));
formattedDate = dateFormat2.format(date);
這將轉換的日期/時間到紐約的時區:
2017年8月1日06:00:00
如果您想要在UTC中打印日期/時間,則不需要創建另一個格式化程序,只需使用第一個格式程序(因爲它已設置爲UTC)。
JVM的默認時區can be changed without notice, even at runtime,所以最好使用特定的一個,而不是隻用getDefault()
的。
傾向於使用IANA timezones names(總是格式爲Region/City
,如America/Sao_Paulo
或Europe/Berlin
)。 避免使用3字母縮寫(如CST
或),因爲它們是ambiguous and not standard。
通過調用TimeZone.getAvailableIDs()
,您可以獲得可用時區列表(並選擇最適合您系統的時區)。
新的日期/時間API
老班(Date
,Calendar
和SimpleDateFormat
)有lots of problems和design issues,他們正在被新的API取代。
在Android中,您可以使用ThreeTen Backport,它是Java 8新日期/時間類的一個很好的後端。要使其工作,您還需要ThreeTenABP(更多關於如何使用它here)。
該API使用起來要容易得多。首先創建一個org.threeten.bp.format.DateTimeFormatter
並將輸入String
解析爲org.threeten.bp.LocalDateTime
。
然後將其轉換爲UTC(創建org.threeten.bp.ZonedDateTime
),然後到你想要的時區,並使用其他格式以進行輸出:
// date/time with optional milliseconds
DateTimeFormatter parser = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[.SSS]");
// parse to LocalDateTime
LocalDateTime dt = LocalDateTime.parse(dateString, parser);
// convert to UTC
ZonedDateTime z = dt.atZone(ZoneOffset.UTC);
// convert to another timezone
z = z.withZoneSameInstant(ZoneId.of("America/New_York"));
// format it
// date/time without milliseconds
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(fmt.format(z));
您還可以使用使用ZoneId.systemDefault()
默認的時區,並使用ZoneId.getAvailableZoneIds()
獲得所有可用時區。
如果你想要UTC的日期/時間,你可以跳過withZoneSameInstant()
。
要將其轉換爲java.util.Date
,你可以使用org.threeten.bp.DateTimeUtils
類:
// convert ZonedDateTime to java.util.Date
Date d = DateTimeUtils.toDate(z.toInstant());
能否請您提供一些輸入和輸出(預期VS你在說什麼)? – 2017-09-01 12:25:50
您的'dateFormat'解析輸入爲本地TZ可以嗎? – yegodm
在你的日期格式模式中,你不知道什麼時區會傳遞給你的方法。所以字符串被解析,因爲它已經在默認的時區。 – Damian0o