我的資料使用年份和年份(1-365/366) 加上一天中的時間,例如2018-338T14:02:57.47583,而不是年-月-日。
我正在嘗試撰寫一個輸入時間戳的函式,它通過一堆正則運算式運行它,并回傳一個模式,我可以用它來通過 LocalDateTime.parse 決議該時間戳。我有一個功能可以做到這一點,除了一個問題。
public static String getInputFormat(String rawFirst) {
String first = rawFirst.replaceAll("[^-.:/ a-zA-Z0-9]", "");
ImmutableMap<String, String> regexFormatMap = new ImmutableMap.Builder<String, String>()
.put("(-)?[0-9]{4}(Z?)", "YYYY")
.put("(-)?[0-9]{4}-((00[1-9])|(0[1-9][0-9])|([1-2][0-9][0-9])|(3(([0-5][0-9])|(6[0-6]))))(T)(([0-1][0-9])|(2[0-3])):[0-5][0-9](Z?)", "yyyy-DDD'T'HH:mm")
.put("(-)?[0-9]{4}-((00[1-9])|(0[1-9][0-9])|([1-2][0-9][0-9])|(3(([0-5][0-9])|(6[0-6]))))(T)(([0-1][0-9])|(2[0-3])):[0-5][0-9]:(([0-5][0-9])|60)(\\.([0-9]{1,6}))?(Z?)", "yyyy-DDD'T'HH:mm:ss.SSSSS")
.put("(-)?[0-9]{4}-((00[1-9])|(0[1-9][0-9])|([1-2][0-9][0-9])|(3(([0-5][0-9])|(6[0-6]))))(T)(([0-1][0-9])|(2[0-4]))(Z?)", "yyyy-DDD'T'HH")
.put("(-)?[0-9]{4}-((00[1-9])|(0[1-9][0-9])|([1-2][0-9][0-9])|(3(([0-5][0-9])|(6[0-6]))))(T)24((:00)|(:00:00))?(Z?)", "yyyy-DDD'T'HH:mm:ss")
.put("(-)?[0-9]{4}-((00[1-9])|(0[1-9][0-9])|([1-2][0-9][0-9])|(3(([0-5][0-9])|(6[0-6]))))(T)24:00:00(\\.([0]{1,6}))(Z?)", "yyyy-DDD'T'HH:mm:ss")
.put("(-)?[0-9]{4}-((00[1-9])|(0[1-9][0-9])|([1-2][0-9][0-9])|(3(([0-5][0-9])|(6[0-6]))))(Z?)", "yyyy-DDD")
.build();
for (String regex : regexFormatMap.keySet()) {
System.out.println(first.matches(regex) ": " first " fits " regex);
if (first.matches(regex)) {
System.out.println("Returning pattern " regexFormatMap.get(regex));
return regexFormatMap.get(regex);
}
}
System.out.println("did not match pattern, returning default pattern used with test data, eventually this should just fail.");
return "yyyy-DDD'T'HH:mm:ss.SSSSS";
}
我不知道如何處理任意數量的亞秒數字,即,
"2018-338T14:02:57.47583""2018-338T14:02:57.475835""2018-338T14:02:57.4758352""2018-338T14:02:57.47583529"
等等。
我想以盡可能一般的方式執行此操作,因此理想情況下我不會檢查每種可能性。
一種解決方案是讓輸出格式字串有九個亞秒數字,然后填充輸入字串,但問題是檢查我是否應該填充它以及填充多少變得非常笨拙。我希望它可以處理各種各樣的字串,并且可以通過向正則運算式映射添加更多條目而不是在其他地方添加復雜性和特殊情況來擴展。
也許我不能在這里得到我想要的一切,但如果你能想到一個解決方案,我會很樂意的。謝謝!
uj5u.com熱心網友回復:
對于此要求,您可以使用u-D'T'H:m:s[.[SSSSSSSSS][SSSSSSSS][SSSSSSS][SSSSSS][SSSSS][SSSS][SSS][SS][S]]作為DateTimeFormatter允許在方括號內指定可選模式的模式,而不是使用復雜且容易出錯的 RegEx 解決方案。
演示:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(
"u-D'T'H:m:s[.[SSSSSSSSS][SSSSSSSS][SSSSSSS][SSSSSS][SSSSS][SSSS][SSS][SS][S]]", Locale.ENGLISH);
// Test
Stream.of(
"2018-338T14:02:57.47583",
"2018-338T14:02:57.475835",
"2018-338T14:02:57.4758352",
"2018-338T14:02:57.47583529"
).forEach(s -> System.out.println(LocalDateTime.parse(s, dtf)));
}
}
輸出:
2018-12-04T14:02:57.475830
2018-12-04T14:02:57.475835
2018-12-04T14:02:57.475835200
2018-12-04T14:02:57.475835290
ONLINE DEMO
從Trail: Date Time 中了解有關現代日期時間 API * 的更多資訊。檢查此答案和此答案以了解如何將API 與 JDBC結合使用。java.time
* 如果您正在為 Android 專案作業并且您的 Android API 級別仍然不符合 Java-8,請檢查通過 desugaring 可用的 Java 8 API。請注意,Android 8.0 Oreo 已提供對java.time.
uj5u.com熱心網友回復:
您可以使用 anew DateTimeFormatterBuilder()來構建一個靈活的DateTimeFormatter,它String使用方法 以可變的秒數來決議s appendFraction(TemporalField, int, int, boolean)。
例如像這樣,我使用了 5 納秒到 8 秒(這可能不是最好的主意,但它可以處理您String的所有示例):
DateTimeFormatter ldtVarFracSecFormatter =
new DateTimeFormatterBuilder()
.appendPattern("uuuu-DDD'T'HH:mm:ss")
.appendFraction(ChronoField.NANO_OF_SECOND, 5, 8, true)
.toFormatter(Locale.ENGLISH);
這是使用String您問題中的s的示例:
public static void main(String[] args) throws IOException {
String a = "2018-338T14:02:57.47583";
String b = "2018-338T14:02:57.475835";
String c = "2018-338T14:02:57.4758352";
String d = "2018-338T14:02:57.47583529";
DateTimeFormatter ldtVarFracSecFormatter =
new DateTimeFormatterBuilder()
.appendPattern("uuuu-DDD'T'HH:mm:ss")
.appendFraction(ChronoField.NANO_OF_SECOND, 5, 8, true)
.toFormatter(Locale.ENGLISH);
LocalDateTime aLdt = LocalDateTime.parse(a, ldtVarFracSecFormatter);
LocalDateTime bLdt = LocalDateTime.parse(b, ldtVarFracSecFormatter);
LocalDateTime cLdt = LocalDateTime.parse(c, ldtVarFracSecFormatter);
LocalDateTime dLdt = LocalDateTime.parse(d, ldtVarFracSecFormatter);
System.out.println(aLdt);
System.out.println(bLdt);
System.out.println(cLdt);
System.out.println(dLdt);
}
輸出是(隱式使用LocalDateTime.toString()):
2018-12-04T14:02:57.475830
2018-12-04T14:02:57.475835
2018-12-04T14:02:57.475835200
2018-12-04T14:02:57.475835290
uj5u.com熱心網友回復:
我不確定你的真正目標是什么。如果重點是決議這些字串,請不要使用任何模式。從已經內置的格式化程式構建格式化程式:
private static final DateTimeFormatter PARSER = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_ORDINAL_DATE)
.appendLiteral('T')
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.toFormatter(Locale.ROOT);
這將決議您的所有示例字串:
String[] timestampStrings = {
"2018-338T14:02:57.47583",
"2018-338T14:02:57.475835",
"2018-338T14:02:57.4758352",
"2018-338T14:02:57.47583529"
};
for (String tss : timestampStrings) {
LocalDateTime ldt = LocalDateTime.parse(tss, PARSER);
System.out.format("%-26s -> %s%n", tss, ldt);
}
輸出:
2018-338T14:02:57.47583 -> 2018-12-04T14:02:57.475830 2018-338T14:02:57.475835 -> 2018-12-04T14:02:57.475835 2018-338T14:02:57.4758352 -> 2018-12-04T14:02:57.475835200 2018-338T14:02:57.47583529 -> 2018-12-04T14:02:57.475835290
不要被LocalDateTIme.toString()總是以 3 位小數列印組(如果秒上有小數)并根據需要填充尾隨零這一事實感到困惑。數字,列印的時間確實與您的字串一致。
序數日期的 ISO 8601 格式(例如2018-3382018 年的第 338 天)并不經常使用,但 java.time 包含一個格式化程式。常用DateTimeFormatter.ISO_LOCAL_TIME的秒數接受 0 到 9 位小數,該范圍足以容納所有時間戳字串。
如果由于某種原因我還不明白你確實想要一個模式,Arvind Kumar Avinash 的答案會給你一個。
顯然和這里的其他人一樣,我正在使用并推薦 java.time,現代 Java 日期和時間 API。
關聯
Oracle 教程:解釋如何使用 java.time 的日期時間。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/350657.html
