我有关于Java正则表达式的以下问题。
当我使用模式定义正则表达式时:
String pattern = "(\\d{4})\\d{2}\\d{2}";
和输入字符串是"20180808"
,我可以得到group(0)
- 20180808
但
group(1)
- 不匹配
group (2)
- 08
group (3)
- 08
,
我确信正则表达式可以在其他语言中有效,比如Python,C#。
有人可以帮忙吗?感谢您的专家解决方案。
@Test
public void testParseDateStringToMinimumOfTheDate() {
try {
UtilsFactory utilsFactory = UtilsFactory.getInstance();
DateUtils dateUtils = utilsFactory.getInstanceOfDateUtils();
CalendarUtils calendarUtils = utilsFactory.getInstanceOfCalendarUtils();
calendarUtils.parseDateStringToMinimumOfTheDate("20180808");
} catch (Exception e) {
e.printStackTrace();
}
}
public Calendar parseDateStringToMinimumOfTheDate(String dateString_yyyyMMdd) throws Exception {
Calendar cal = null;
String pattern = "(\\d{4})\\d{2}\\d{2}";
try {
cal = getMaxUtcCalendarToday();
List<String> matchStringList = regMatch(dateString_yyyyMMdd, pattern);
for (int i = 0; i < matchStringList.size(); i++) {
}
} catch (Exception e) {
logger.error(getClassName() + ".parseDateStringToBeginningOfTheDate()- dateString_yyyyMMdd="
+ dateString_yyyyMMdd, e);
throw e;
}
return cal;
}
private List<String> regMatch(String sourceString, String patternString) throws Exception {
List<String> matchStrList = null;
Pattern pattern = null;
Matcher matcher = null;
try {
matchStrList = new ArrayList<String>();
pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);
matcher = pattern.matcher(sourceString);
while (matcher.find()) {
matchStrList.add(matcher.group());
}
} catch (Exception e) {
logger.error(
getClassName() + ".regMatch() - sourceString=" + sourceString + ",patternString=" + patternString,
e);
throw e;
}
return matchStrList;
}
Pattern pattern = Pattern.compile("\\d{8}");
String sourceString = "20180808";
Matcher matcher = pattern.matcher(sourceString);
while (matcher.find()) {
LocalDate date = LocalDate.parse(matcher.group(), DateTimeFormatter.BASIC_ISO_DATE);
System.out.println(date);
}
此代码段的输出是预期日期:
2018-08-08
如果您的字符串可能包含的文本多于8位数日期,则使用正则表达式取出这8位数字是正确的。用于日期的正确类是java.time中的LocalDate
,它是现代Java日期和时间API。它是ISO日历系统中的日期,没有时间和没有时区。相比之下,Calendar
代表某些日历系统中带时区的日期和时间。它远远超过你的需要。 Calendar
类也很久了,并且在四年半前被java.time取代,因为它的设计很差。
如果你确实需要一个Calendar
对象用于一些你无法改变或者现在不想改变的遗留API,那么转换如下:
ZoneId zone = ZoneId.of("America/Punta_Arenas");
ZonedDateTime startOfDay = date.atStartOfDay(zone);
Calendar cal = GregorianCalendar.from(startOfDay);
如果没有恰好是America / Punta_Arenas,请替换正确的时区。
您的代码没有任何问题,除了它过于复杂并使用过时的日期和时间类。
String patternString = "(\\d{4})(\\d{2})(\\d{2})";
Pattern pattern = null;
Matcher matcher = null;
try {
pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);
matcher = pattern.matcher(sourceString);
while (matcher.find()) {
System.out.println("group(1): " + matcher.group(1));
System.out.println("group(2): " + matcher.group(2));
System.out.println("group(3): " + matcher.group(3));
}
} catch (Exception e) {
// TODO handle exception
throw e;
}
此代码段的输出是:
group(1): 2018 group(2): 08 group(3): 08
Oracle tutorial: Date Time解释如何使用java.time
。
你的正则表达式没有任何问题(正如你提到的(\d{4})(\d{2})(\d{2})
。你做错了是,你没有正确地抓住被捕获的组。重构你的方法到这个
private static List<String> regMatch(String sourceString, String patternString) {
List<String> matchStrList = new ArrayList<>();
Pattern pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(sourceString);
if(matcher.find()) {
for(int i = 1; i <= matcher.groupCount(); i++) {
matchStrList.add(matcher.group(i));
}
}
return matchStrList;
}
你可能想知道group 0
在哪里。 Patter
API捕获的组通过从左到右计算它们的左括号来编号,第一组始终是整个正则表达式。因此对于String (A)(B(C))
您将获得如下组
Group 0: (A)(B(C))
Group 1: (A)
Group 2: (B(C))
Group 3: (C)
并且groupCount()
方法返回匹配器模式中存在的捕获组的数量。
正如@ haba713在评论中提到的那样,你可能不想只是为了解析Date来做所有这些正则表达式的麻烦。你可以简单地使用SimpleDateFormat
。
SimpleDateFormat formater = new SimpleDateFormat("yyyyMMdd");
System.out.println(formater.parse(dateString));