捕获下一行的正则表达式 Date/Time YYYY/MM/DD HH:mm 或 YYYY/M/D H:m
Regex to Capture next line Date/Time YYYY/MM/DD HH:mm or YYYY/M/D H:m
我想捕捉日期格式 - yyyy/mm/dd hh:mm
[^\n\r]*[\r\n]+([12]\d{3}/(0[1-9]|1[0-2])/(0[1-9]|[12]\d|3[01]))**
上面的表达式捕获下一行到当天,但我也想包括时间部分,并且还想捕获月份、日期和时间的个位数,而不是必须输入两位数。
例如。用户可以输入 2017/5/2 9:5
或 2017/05/02 09:05
需要有关捕获个位数月和日以及时间部分的帮助。
要使数字可选,只需使用 the ?
quantifier。
假设您使用 classes Pattern
和 Matcher
来自 java.util.regex
包,您的代码将是这样的(另请注意在 Java 中你必须转义反斜杠 ,因此模式 \d
必须写成 \d
):
String input = "2017/5/2 9:5";
Pattern pattern = Pattern.compile("(\d{4})/(0?[1-9]|1[0-2])/(0?[1-9]|[12]\d|3[01]) ([01]?\d|2[0-3]):([0-5]?\d)");
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
String year = matcher.group(1);
String month = matcher.group(2);
String day = matcher.group(3);
String hour = matcher.group(4);
String minute = matcher.group(5);
}
对于月份和日期,我只是在零之后添加了一个 ?
,使其成为可选的。
这个小时,我做了:
[01]?
:可选零或一,后接任意数字(\d
),或
2[0-3]
:数字 2,后跟 0、1、2 或 3(因此小时数从 20 到 23)
会议纪要:
[0-5]?
: 0到5的可选数字
- 后跟任意数字 (
\d
)
这也适用于输入为零的情况,例如 "2017/05/02 09:05"
。您可以选择将 String
值转换为 int
,使用 Integer.parseInt(matcher.group(1))
.
为什么不使用 date/time API?
上面的代码不会检查所有有效日期的情况,例如一个月中的天数(包括闰年的二月)。尽管可以使用正则表达式来完成,但它会非常复杂且难以维护,IMO 最好为此使用适当的 API(只是闰年验证是 a very complex expression by itself) .
如果您编写此代码只是为了学习目的,那很好。但是对于实际的业务应用程序,最好使用 date/time API(regex 很棒,但并不总是最好的工具)。
如果您正在使用 Java 8,请考虑使用 new java.time
API. It's easier, less bugged and less error-prone than the old APIs.
如果您使用 Java 6 或 7,您可以使用 ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, you'll also need the ThreeTenABP (more on how to use it here).
下面的代码适用于两者。
唯一的区别是包名称(在 Java 8 中是 java.time
,在 ThreeTen Backport(或 Android 的 ThreeTenABP)中是 org.threeten.bp
),但是 classes和方法名称相同。
首先,您可以使用 DateTimeFormatter
and parse the input to a LocalDateTime
(代表日期和时间的 class,与您的输入数据完美匹配)。然后你使用这个 class 来获取你想要的字段:
String input = "2017/5/2 9:5";
// pattern with optional zero for month, day, hour and minute
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy/M/d H:m")
// use strict mode to validate dates like Feb 29th
.withResolverStyle(ResolverStyle.STRICT);
LocalDateTime dt = LocalDateTime.parse(input, fmt);
int year = dt.getYear();
int month = dt.getMonthValue();
int day = dt.getDayOfMonth();
int hour = dt.getHour();
int minute = dt.getMinute();
这也适用于 "2017/05/02 09:05"
。这也有检查无效值的优点(如月份 > 12,或闰年的 Feb 29th 等)。
如果不使用严格模式,non-leap年2月29日日调整为2月28日日 (这是 smart resolver style, which is the default 的行为)。
Check the javadoc 对于 DateTimeFormatter
接受的所有可用模式。
这里是...
\d{4}\/([1-9]{1}|0[1-9]|1[0-2])\/([1-9]{1}|[0-2]{1}[1-9]{1}|3[0-1])\s+([0-9]{1}|[0-1]{1}[0-9]{1}|2[0-4]):([0-9]{1}|[0-5]{1}[0-9]{1})\s+
这似乎让人不知所措,所以这里是表达式的演练。
此表达式不仅会查找日期和时间,还会忽略不切实际的日期时间,例如 2001/44/44 或 2344/44444/999。它仅检查有效的日期时间。无效的日期时间将是 ignored.Also 它不仅会检查行首的日期时间,还会检查字符串中的任何位置,无论字符串是单行还是多行。
说明
第 4 位数字将是年份....
\d{4}
后跟'/'...
\d{4}\/
现在,月份可以是个位数,例如 1-9
\d{4}\/( [1-9]{1} )
或两位数01、02、03、09(这里记住如果月份以0开头,那么它的第二位数字不能大于9。)
\d{4}\/( [1-9]{1} | 0[1-9]{1} )
或 10、11、12 但不能大于 12。
\d{4}\/( [1-9]{1} | 0[1-9]{1} | 1[0-2]{1} )
后跟一个“/”
\d{4}\/( [1-9]{1} | 0[1-9]{1} | 1[0-2]{1} ) \/
现在有天了,可以是个位数1-9
\d{4}\/( [1-9]{1} | 0[1-9]{1} | 1[0-2]{1} ) \/( [1-9]{1} )
或两位数 01、02、03、09、19、29。
\d{4}\/( [1-9]{1} | 0[1-9]{1} | 1[0-2]{1} ) \/( [1-9]{1} | [0-2]{1}[1-9]{1} )
或者它可以是 30 或 31,但不能大于它。
\d{4}\/( [1-9]{1} | 0[1-9]{1} | 1[0-2]{1} ) \/( [1-9]{1} | [0-2]{1}[1-9]{1} | 3[0-1] )
现在日期部分已经完成。日期和时间之间有些 space。
\d{4}\/( [1-9]{1} | 0[1-9]{1} | 1[0-2]{1} ) \/( [1-9]{1} | [0-2]{1}[1-9]{1} | 3[0-1] ) \s+
现在让我们关注时间部分。
假设时间基于 24 小时格式。
小时可以是单个数字,如 0、1、2、9
( [0-9]{1} )
或两位数,如 01、02、09、11、19
( [0-9]{1} | [0-1]{1}[0-9]{1} )
或 20、21、22、23、24 但不大于 24。
( [0-9]{1} | [0-1]{1}[0-9]{1} | 2[0-4]{1} )
后跟“:”
( [0-9]{1} | [0-1]{1}[0-9]{1} | 2[0-4]{1} ) :
分钟可以是个位数,例如 0、1、2、9...
( [0-9]{1} | [0-1]{1}[0-9]{1} | 2[0-4]{1} ) : ( [0-9]{1} )
或两位数,如 01、02、03、23、44、59(不是 60)。
( [0-9]{1} | [0-1]{1}[0-9]{1} | 2[0-4]{1} ) : ( [0-9]{1} | [0-5]{1}[0-9]{1} )
其次是一些 space
( [0-9]{1} | [0-1]{1}[0-9]{1} | 2[0-4]{1} ) : ( [0-9]{1} | [0-5]{1}[0-9]{1} )
\s+
现在结合您的日期正则表达式和时间正则表达式,您将得到
\d{4}\/([1-9]{1}|0[1-9]|1[0-2])\/([1-9]{1}|[0-2]{1}[1-9]{1}|3[0-1])\s+([0-9]{1}|[0-1]{1}[0-9]{1}|2[0-4]):([0-9]{1}|[0-5]{1}[0-9]{1})\s+
注意:在解释过程中,为了更好的可读性,我在正则表达式中添加了额外的space。
我想捕捉日期格式 - yyyy/mm/dd hh:mm
[^\n\r]*[\r\n]+([12]\d{3}/(0[1-9]|1[0-2])/(0[1-9]|[12]\d|3[01]))**
上面的表达式捕获下一行到当天,但我也想包括时间部分,并且还想捕获月份、日期和时间的个位数,而不是必须输入两位数。
例如。用户可以输入 2017/5/2 9:5
或 2017/05/02 09:05
需要有关捕获个位数月和日以及时间部分的帮助。
要使数字可选,只需使用 the ?
quantifier。
假设您使用 classes Pattern
和 Matcher
来自 java.util.regex
包,您的代码将是这样的(另请注意在 Java 中你必须转义反斜杠 ,因此模式 \d
必须写成 \d
):
String input = "2017/5/2 9:5";
Pattern pattern = Pattern.compile("(\d{4})/(0?[1-9]|1[0-2])/(0?[1-9]|[12]\d|3[01]) ([01]?\d|2[0-3]):([0-5]?\d)");
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
String year = matcher.group(1);
String month = matcher.group(2);
String day = matcher.group(3);
String hour = matcher.group(4);
String minute = matcher.group(5);
}
对于月份和日期,我只是在零之后添加了一个 ?
,使其成为可选的。
这个小时,我做了:
[01]?
:可选零或一,后接任意数字(\d
),或2[0-3]
:数字 2,后跟 0、1、2 或 3(因此小时数从 20 到 23)
会议纪要:
[0-5]?
: 0到5的可选数字- 后跟任意数字 (
\d
)
这也适用于输入为零的情况,例如 "2017/05/02 09:05"
。您可以选择将 String
值转换为 int
,使用 Integer.parseInt(matcher.group(1))
.
为什么不使用 date/time API?
上面的代码不会检查所有有效日期的情况,例如一个月中的天数(包括闰年的二月)。尽管可以使用正则表达式来完成,但它会非常复杂且难以维护,IMO 最好为此使用适当的 API(只是闰年验证是 a very complex expression by itself) .
如果您编写此代码只是为了学习目的,那很好。但是对于实际的业务应用程序,最好使用 date/time API(regex 很棒,但并不总是最好的工具)。
如果您正在使用 Java 8,请考虑使用 new java.time
API. It's easier, less bugged and less error-prone than the old APIs.
如果您使用 Java 6 或 7,您可以使用 ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, you'll also need the ThreeTenABP (more on how to use it here).
下面的代码适用于两者。
唯一的区别是包名称(在 Java 8 中是 java.time
,在 ThreeTen Backport(或 Android 的 ThreeTenABP)中是 org.threeten.bp
),但是 classes和方法名称相同。
首先,您可以使用 DateTimeFormatter
and parse the input to a LocalDateTime
(代表日期和时间的 class,与您的输入数据完美匹配)。然后你使用这个 class 来获取你想要的字段:
String input = "2017/5/2 9:5";
// pattern with optional zero for month, day, hour and minute
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy/M/d H:m")
// use strict mode to validate dates like Feb 29th
.withResolverStyle(ResolverStyle.STRICT);
LocalDateTime dt = LocalDateTime.parse(input, fmt);
int year = dt.getYear();
int month = dt.getMonthValue();
int day = dt.getDayOfMonth();
int hour = dt.getHour();
int minute = dt.getMinute();
这也适用于 "2017/05/02 09:05"
。这也有检查无效值的优点(如月份 > 12,或闰年的 Feb 29th 等)。
如果不使用严格模式,non-leap年2月29日日调整为2月28日日 (这是 smart resolver style, which is the default 的行为)。
Check the javadoc 对于 DateTimeFormatter
接受的所有可用模式。
这里是...
\d{4}\/([1-9]{1}|0[1-9]|1[0-2])\/([1-9]{1}|[0-2]{1}[1-9]{1}|3[0-1])\s+([0-9]{1}|[0-1]{1}[0-9]{1}|2[0-4]):([0-9]{1}|[0-5]{1}[0-9]{1})\s+
这似乎让人不知所措,所以这里是表达式的演练。 此表达式不仅会查找日期和时间,还会忽略不切实际的日期时间,例如 2001/44/44 或 2344/44444/999。它仅检查有效的日期时间。无效的日期时间将是 ignored.Also 它不仅会检查行首的日期时间,还会检查字符串中的任何位置,无论字符串是单行还是多行。
说明
第 4 位数字将是年份....
\d{4}
后跟'/'...
\d{4}\/
现在,月份可以是个位数,例如 1-9
\d{4}\/( [1-9]{1} )
或两位数01、02、03、09(这里记住如果月份以0开头,那么它的第二位数字不能大于9。)
\d{4}\/( [1-9]{1} | 0[1-9]{1} )
或 10、11、12 但不能大于 12。
\d{4}\/( [1-9]{1} | 0[1-9]{1} | 1[0-2]{1} )
后跟一个“/”
\d{4}\/( [1-9]{1} | 0[1-9]{1} | 1[0-2]{1} ) \/
现在有天了,可以是个位数1-9
\d{4}\/( [1-9]{1} | 0[1-9]{1} | 1[0-2]{1} ) \/( [1-9]{1} )
或两位数 01、02、03、09、19、29。
\d{4}\/( [1-9]{1} | 0[1-9]{1} | 1[0-2]{1} ) \/( [1-9]{1} | [0-2]{1}[1-9]{1} )
或者它可以是 30 或 31,但不能大于它。
\d{4}\/( [1-9]{1} | 0[1-9]{1} | 1[0-2]{1} ) \/( [1-9]{1} | [0-2]{1}[1-9]{1} | 3[0-1] )
现在日期部分已经完成。日期和时间之间有些 space。
\d{4}\/( [1-9]{1} | 0[1-9]{1} | 1[0-2]{1} ) \/( [1-9]{1} | [0-2]{1}[1-9]{1} | 3[0-1] ) \s+
现在让我们关注时间部分。 假设时间基于 24 小时格式。 小时可以是单个数字,如 0、1、2、9
( [0-9]{1} )
或两位数,如 01、02、09、11、19
( [0-9]{1} | [0-1]{1}[0-9]{1} )
或 20、21、22、23、24 但不大于 24。
( [0-9]{1} | [0-1]{1}[0-9]{1} | 2[0-4]{1} )
后跟“:”
( [0-9]{1} | [0-1]{1}[0-9]{1} | 2[0-4]{1} ) :
分钟可以是个位数,例如 0、1、2、9...
( [0-9]{1} | [0-1]{1}[0-9]{1} | 2[0-4]{1} ) : ( [0-9]{1} )
或两位数,如 01、02、03、23、44、59(不是 60)。
( [0-9]{1} | [0-1]{1}[0-9]{1} | 2[0-4]{1} ) : ( [0-9]{1} | [0-5]{1}[0-9]{1} )
其次是一些 space
( [0-9]{1} | [0-1]{1}[0-9]{1} | 2[0-4]{1} ) : ( [0-9]{1} | [0-5]{1}[0-9]{1} )
\s+
现在结合您的日期正则表达式和时间正则表达式,您将得到
\d{4}\/([1-9]{1}|0[1-9]|1[0-2])\/([1-9]{1}|[0-2]{1}[1-9]{1}|3[0-1])\s+([0-9]{1}|[0-1]{1}[0-9]{1}|2[0-4]):([0-9]{1}|[0-5]{1}[0-9]{1})\s+
注意:在解释过程中,为了更好的可读性,我在正则表达式中添加了额外的space。