[英]Parsing with Java 8 DateTimeFormatter and Spanish month names
使用“舊的”,Java 8 之前的SimpleDateFormat
我可以做到:
new java.text.SimpleDateFormat("MMM yyyy", new java.util.Locale("es", "ES")).parse("Mayo 2017")
獲取具有西班牙月份名稱的日期的Date
對象。
如何使用 Java 8 和DateTimeFormatter
實現相同的目標?
我試過:
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale(new Locale("es", "ES")).ofPattern("MMM yyyy").parse("Mayo 2017")
但只得到一個java.time.format.DateTimeParseException
。
可以刪除對ofLocalizedDateTime()
的調用,因為最后你調用ofPattern()
,創建另一個具有完全不同模式的格式化程序(並且ofLocalizedDateTime(FormatStyle.FULL)
返回的模式與僅month year
非常不同,所以這是不是你想要的)。
另一個細節是Mayo
是完整的月份名稱,因此模式必須是MMMM
(有關更多詳細信息, 請查看 javadoc )。 此外,默認情況下DateTimeFormatter
僅接受小寫名稱(至少在我使用西班牙語言環境進行的測試中),因此您必須將格式化程序設置為不區分大小寫。
您可以通過使用java.time.format.DateTimeFormatterBuilder
來做到這java.time.format.DateTimeFormatterBuilder
:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// case insensitive
.parseCaseInsensitive()
// pattern with full month name (MMMM)
.appendPattern("MMMM yyyy")
// set locale
.toFormatter(new Locale("es", "ES"));
// now it works
fmt.parse("Mayo 2017");
或者,您可以直接將其解析為java.time.YearMonth
對象,因為它似乎是這種情況下的最佳選擇(因為輸入只有年和月):
YearMonth ym = YearMonth.parse("Mayo 2017", fmt);
System.out.println(ym); // 2017-05
當輸入沒有所有字段時, SimpleDateFormat
只為它們使用一些默認值。 在這種情況下,輸入只有年和月,因此解析的Date
將等同於解析的月/年,但日將設置為 1,時間設置為午夜(在 JVM 默認時區)。
新 API 對此非常嚴格並且不會創建默認值,除非您告訴它這樣做。 配置它的一種方法是將parseDefaulting
與java.time.temporal.ChronoField
一起使用:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// case insensitive
.parseCaseInsensitive()
// pattern with full month name (MMMM)
.appendPattern("MMMM yyyy")
// default value for day of month
.parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
// default value for hour
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
// default value for minute
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
// set locale
.toFormatter(new Locale("es", "ES"));
有了這個,您可以將其解析為LocalDateTime
並將缺失的字段分配給相應的默認值:
LocalDateTime dt = LocalDateTime.parse("Mayo 2017", fmt);
System.out.println(dt); // 2017-05-01T00:00
如果您需要獲取與SimpleDateFormat
創建的具有相同值的java.util.Date
,您可以將此LocalDateTime
轉換為 JVM 默認時區,然后將其轉換為Date
:
Date javaUtilDate = Date.from(dt.atZone(ZoneId.systemDefault()).toInstant());
請注意,我必須明確使用 JVM 默認時區 ( ZoneId.systemDefault()
),它是SimpleDateFormat
隱式使用的。
另一種選擇是手動設置YearMonth
值中的值:
// in this case, the formatter doesn't need the default values
YearMonth ym = YearMonth.parse("Mayo 2017", fmt);
ZonedDateTime z = ym
// set day of month to 1
.atDay(1)
// midnight at JVM default timezone
.atStartOfDay(ZoneId.systemDefault());
Date javaUtilDate = date.from(z.toInstant());
默認時區可以在沒有通知的情況下更改,即使在運行時也是如此,因此最好始終明確您正在使用哪個時區。
API 使用IANA 時區名稱(始終采用Region/City
格式,例如America/New_York
或Europe/Berlin
),因此您可以調用ZoneId.of("America/New_York")
例如。 避免使用 3 個字母的縮寫(如CST
或PST
),因為它們含糊不清且不標准。
您可以通過調用ZoneId.getAvailableZoneIds()
獲取可用時區列表(並選擇最適合您系統的時區ZoneId.getAvailableZoneIds()
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.