我得到了一些用戶輸入的日期時間格式字串,并且需要檢查java.time我可以決議該格式資料的時間(在合理范圍內,我現在只支持更簡單的情況)。
類似于這張表的內容:
| 輸入格式 | 預期答案 |
|---|---|
yyyy-MM |
java.time.YearMonth |
MM/dd/yyyy |
java.time.LocalDate |
yyyy:DD |
java.time.LocalDate (由于年份資料) |
HH:mm:ss |
java.time.LocalTime |
dd MM yyyy hh:mm:ssV |
java.time.ZonedDateTime |
請記住,日期格式和日期都是由用戶輸入的,因此這些輸入格式只是示例,它們顯然可以包含文字(但不是可選部分,這是一種解脫)。
到目前為止,我只能想出這個ifs 的龍卷風作為解決方案:
private static final ZonedDateTime ZDT = ZonedDateTime.of(1990, 10, 26, 14, 40, 59, 123456, ZoneId.of("Europe/Oslo"));
...
String formatted = externalFormatter.format(ZDT);
Class<?> type;
TemporalAccessor parsed = externalFormatter.parse(formatted);
if (parsed.isSupported(YEAR)) {
if (parsed.isSupported(MONTH_OF_YEAR)) {
if (parsed.query(TemporalQueries.localDate()) != null) {
if (parsed.query(TemporalQueries.localTime()) != null) {
if (parsed.query(TemporalQueries.zone()) != null) {
type = ZonedDateTime.class;
}
else if (parsed.query(TemporalQueries.offset()) != null) {
type = OffsetDateTime.class;
}
else {
type = LocalDateTime.class;
}
}
else {
type = LocalDate.class;
}
}
else {
type = YearMonth.class;
}
}
else {
type = Year.class;
}
}
else if (parsed.query(TemporalQueries.localTime()) != null) {
if (parsed.query(TemporalQueries.offset()) != null) {
type = OffsetTime.class;
}
else {
type = LocalTime.class;
}
}
當然,必須有一些更好的方法,至少稍微好一點?我不會限制自己只使用java.time,我也可以使用 Joda-Time 庫(盡管它在技術上處于遺留狀態),并且SimpleDateFormat如果有這樣的選項,我不會拒絕使用 的更簡單的代碼。
uj5u.com熱心網友回復:
DateTimeFormatter::parseBest()
我相信你的話:
請記住,日期格式和日期均由用戶輸入,...
所以我假設我可以同時使用格式模式和輸入的日期字串來查看我能做些什么。DateTimeFormatter::parseBest()是我們需要的方法。
public static TemporalAccessor parse(String formatPattern, String toBeParsed) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(formatPattern, Locale.ROOT);
return formatter.parseBest(toBeParsed, ZonedDateTime::from,
LocalDate::from, LocalTime::from, YearMonth::from);
}
為了演示上述方法的威力,我使用了以下輔助方法:
public static void demo(String formatPattern, String toBeParsed) {
TemporalAccessor result = parse(formatPattern, toBeParsed);
System.out.format("%-21s %s%n", formatPattern, result.getClass().getName());
}
讓我們用你的例子來稱呼它:
demo("yyyy-MM", "2017-11");
demo("MM/dd/yyyy", "10/21/2023");
demo("yyyy:DD", "2021:303");
demo("HH:mm:ss", "23:34:45");
demo("dd MM yyyy HH:mm:ssVV", "05 09 2023 14:01:55Europe/Oslo");
我更正了最后一個格式模式字串中的幾個錯誤。輸出是:
yyyy-MM java.time.YearMonth MM/dd/yyyy java.time.LocalDate yyyy:DD java.time.LocalDate HH:mm:ss java.time.LocalTime dd MM yyyy HH:mm:ssVV java.time.ZonedDateTime
在TemporalQuery引數串列中,parseBest()必須將包含最多資訊的類放在首位。或者你更喜歡哪些課程,但我假設你想要盡可能多的資訊。parseBest()使用第一個有效的查詢。所以把ZonedDateTime第一和Year,Month并且DayOfWeek如果你打算支持任何過去三年的最后一次。
請記住決定您想要的語言環境。
只有格式模式字串
如果您應該在沒有決議字串的情況下使用技巧,那么它的復雜程度還不錯。首先使用您從格式模式字串構造的格式化程式格式化一些內容ZonedDateTime。然后用于parseBest()決議生成的字串。您必須使用ZonedDateTime它,因為它是唯一保存格式模式字串中可能存在的每個欄位的類,因此對于其他一些類,格式可能會中斷。另一方面,進入格式化字串的資訊受模式限制,因此在大多數情況下您將無法決議ZonedDateTime回傳。這正是我們想要的:parseBest()將告訴我們可以決議為哪個類。
public static Class<? extends TemporalAccessor> getParseableType(String formatPattern) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(formatPattern, Locale.ROOT);
String example = ZonedDateTime.now(ZoneId.systemDefault()).format(formatter);
TemporalAccessor parseableTemporalAccessor = formatter.parseBest(example, ZonedDateTime::from,
LocalDate::from, LocalTime::from, YearMonth::from);
return parseableTemporalAccessor.getClass();
}
檔案鏈接
parseBest?(CharSequence text, TemporalQuery<?>... queries)
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/347853.html
