的parse
method expects a String
in a specific format,像2007-12-03T10:15:30+01:00[Europe/Paris]
。由於您的輸入格式不同,您需要一個DateTimeFormatter
。
需要注意的一個細節是API使用IANA timezones names(始終格式爲Continent/City
,如America/Sao_Paulo
或Europe/Berlin
)。 避免使用3字母縮寫(如CST
或),因爲它們是ambiguous and not standard。
該API會對特定ID進行一些例外處理,併爲它們提供一些默認值。對於PDT
,它默認爲America/Los_Angeles
。
另一個細節是,在下面的例子中我在圖案中使用小寫hh
:該格式具有AM/PM指示,所以我認爲hh
是正確的模式,如its value is from 1 to 12(共用值時,有在AM/PM指示符)。
如果您使用大寫HH
,它允許從0到23的值(和它的不常見的帶AM/PM使用),並如果輸入包含像07:00 PM
一個小時它會拋出異常。
因此,代碼將是這樣的:
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm a (zzz)");
ZonedDateTime z = ZonedDateTime.parse("06/24/2017 07:00 AM (PDT)", fmt);
System.out.println(z);
輸出是:
2017-06-24T07:00-07:00[America/Los_Angeles]
但並不是所有的3個字母的時區的名稱將由API的認可,並會拋出異常。
無論如何,還有其他時區也在光動力療法(如America/Vancouver
) - 你可以通過調用ZoneId.getAvailableZoneIds()
得到所有的列表。如果你想使用一個不同的時區爲默認值,你可以創建一組優選區,並建立一個格式化這一套:
Set<ZoneId> preferredZones = new HashSet<>();
// set America/Vancouver as preferred zone
preferredZones.add(ZoneId.of("America/Vancouver"));
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// pattern
.appendPattern("MM/dd/yyyy hh:mm a (")
// append timezone with set of prefered zones
.appendZoneText(TextStyle.SHORT, preferredZones)
// finish the pattern
.appendPattern(")")
// create formatter
.toFormatter();
System.out.println(ZonedDateTime.parse("06/24/2017 07:00 AM (PDT)", fmt));
的API將使用的首選區域設置(在這種情況下,America/Vancouver
)而不是默認的(America/Los_Angeles
)。輸出將是:
2017-06-24T07:00-07:00[America/Vancouver]
其中輸入String
的來自目前尚不清楚。如果你無法控制他們的格式,那麼你別無選擇:他們需要這樣解析。然後,你可以使用withZoneSameInstant
方法將其轉換爲另一個時區:
// parse the input string
ZonedDateTime z = ZonedDateTime.parse("06/24/2017 07:00 AM (PDT)", fmt);
// convert to another timezone
ZonedDateTime other = z.withZoneSameInstant(ZoneId.of("America/Sao_Paulo")); // 2017-06-24T11:00-03:00[America/Sao_Paulo]
的other
值將是2017-06-24T11:00-03:00[America/Sao_Paulo]
。
但如果你能控制輸出,它總是更好(IMO)在內部與UTC(java.time.Instant
)工作,並轉換成顯示給用戶,只有當一些時區:
// convert ZonedDateTime to instant
ZonedDateTime z = // parse input
// convert to UTC (Instant is always in UTC)
Instant instant = z.toInstant();
// internally work with instant (as it's always in UTC)
// convert instant to some timezone only when necessary (like displaying to users)
ZonedDateTime converted = instant.atZone(ZoneId.of("Europe/London"));
「您是否同意我應該使用ZonedDateTime?」:取決於要實現的功能。如果目標是從運行代碼的語言環境獲取java.util.Date,那麼使用java.text.SimpleDateFormat可能會更好。 –
當您可以使用現代日期和時間API(其中'ZonedDateTime'屬於)時,您不會希望獲得'java.util.Date'。你一定要避免'SimpleDateFormat'。 @AxelRichter –