java - 使用年份和不同的亚秒位数解析 LocalDateTime
问题描述
我有使用年和年(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"
等等
我想以尽可能普遍的方式做到这一点,所以理想情况下我不会检查每种可能性。
一种解决方案是让输出格式字符串有九个亚秒数字,然后填充输入字符串,但问题是检查是否应该填充它以及填充多少变得非常笨重。我希望它能够处理各种各样的字符串,并且只需通过向正则表达式映射添加更多条目而不是在其他地方添加复杂性和特殊情况来进行扩展。
也许我不能在这里得到我想要的一切,但如果你能想到一个解决方案,我会很乐意。谢谢!
解决方案
您可以使用 anew DateTimeFormatterBuilder()
来构建一个灵活的方法,使用该方法以秒的可变分数DateTimeFormatter
解析s 。String
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);
这是使用问题中的 s 的示例String
:
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
推荐阅读
- mysql - SELECT JOIN 与条件 (OR) 交叉
- r - 对行中的单元格进行排序以匹配 R 中的相应列标题
- javascript - 有一种方法可以在 v3 中重新获取 fullcalendar 吗?
- asp.net-core - 异常时 Serilog 更改日志级别
- php - Symfony4 上的 Gandi + SwiftMailer
- xml - 存在 xmlns 属性时如何使用 XSLT?
- c - 在 mac os x 上是否有 clang 识别的常量?
- android - 移动网络提供商阻止对 api 的 volley 请求
- reactjs - 如何在“react app 2”中设置 SCSS 文件(ViewEncapsulated 方式),如 Angular 组件特定的 SCSS?
- vue.js - 是否可以在 vueJS 中将数据从插槽组件传递到父级?