我如何 trim 一个字符串来解析 java 中带有 SimpleDateFormat 的时间?

How do I trim a string to parse a time with a SimpleDateFormat in java?

我正在尝试输入一个混合字符的字符串,并使用一些代码删除除了与所需的 SimpleDateFormat 匹配的部分以外的所有内容

String wholeString = new String("The time is 7:00.");
String timeOnlyString = CODE TO TRIM STRING;
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
Date timeAsObject = sdf.parse(timeOnlyString);
String timeAsString = sdf.format(timeAsObject);
System.out.println(timeAsString);`

我想要这个代码

07:00

打印在控制台中。

String wholeString = "The time is 7:00.";
Pattern pattern = Pattern.compile("(0?[1-9]|1[0-2]):[0-5][0-9]");
Matcher matcher = pattern.matcher(wholeString);
if(matcher.find()) {
    String timeOnlyString = matcher.group();
    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
    Date timeAsObject = sdf.parse(timeOnlyString);
    String timeAsString = sdf.format(timeAsObject);
    System.out.println(timeAsString);
}

java.time

我建议您使用 java.time,现代 Java 日期和时间 API,作为您的时间工作。

    String wholeString = "The time is 7:00.";
    Matcher m = TIME_PATTERN.matcher(wholeString);
    while (m.find()) {
        String timeOnlyString = m.group();
        try {
            LocalTime timeAsObject
                    = LocalTime.parse(timeOnlyString, TIME_FORMATTER);
            System.out.println("Time found: " + timeAsObject);
        } catch (DateTimeParseException dtpe) {
            System.out.println("Looked a bit like a time but couldn’t be parsed as one: " + timeOnlyString);
        }
    }

我使用了这两个静态声明:

private static final Pattern TIME_PATTERN
        = Pattern.compile("\b\d{1,2}:\d{2}\b");
private static final DateTimeFormatter TIME_FORMATTER
        = DateTimeFormatter.ofPattern("H:mm");

我的代码片段的输出是:

Time found: 07:00

我用于从整个字符串中提取时间的正则表达式匹配 1 或 2 个数字,一个冒号和 2 个数字。它前后需要一个单词边界,所以我们不会碰巧从 987:12354letters1:11moreletters.

中提取时间

用于 DateTimeFormatter 的格式模式字符串只有一个 H 表示一天中的小时。这接受 1 或 2 位数字,因此我们也可以解析 15:00

我认为我们应该考虑到正则表达式可能在字符串中匹配多次,所以我在循环中提取。

我正在解析到 java.time.LocalTime。这个 class 适用于一天中的某个时间(从 00:00 到 23:59:59.999999999),因此比过时的 Date class(后者既不代表日期也不代表一天中的时间,而是不带时区的时间点)。

您可以使用正则表达式 .*?(\d{1,2}:\d{1,2}(?:\:\d{1,2}(?:\.\d{1,9})?)?).* 来匹配整个字符串,并将其替换为组#1 匹配的模式。

regex的说明:

  • .*? :(懒惰地)匹配任何字符任意次数
  • (: 捕获组#1 开始
    • \d{1,2}:\d{1,2} : 一到两位数后跟一到两位数
    • (?: :可选非捕获组的开始
      • \:\d{1,2} : : 后跟一到两位数字(秒)
        • (?: :可选非捕获组的开始
          • \.\d{1,9} : . 后跟一到九位数字(纳秒)
        • )? : 关闭可选的非捕获组
    • )? : 关闭可选的非捕获组
  • ) : 关闭捕获组#1
  • .*:匹配任意字符任意次数

演示:

public class Main {
    public static void main(String[] args) {
        // Test strings
        String[] wholeStringArr = { "The time is 7:00.", "The time is 7:00:05.", "The time is 7:00:05.1.",
                "The time is 7:00:05.123.", "The time is 7:00:05.123456789." };

        for (String wholeString : wholeStringArr) {
            String timeOnlyString = wholeString.replaceAll(".*?(\d{1,2}:\d{1,2}(?:\:\d{1,2}(?:\.\d{1,9})?)?).*",
                    "");
            System.out.println(timeOnlyString);
        }
    }
}

输出:

7:00
7:00:05
7:00:05.1
7:00:05.123
7:00:05.123456789

ONLINE DEMO

java.time

java.util 日期时间 API 及其格式 API、SimpleDateFormat 已过时且容易出错。建议完全停止使用它们并切换到 modern Date-Time API*.

解决方案使用 java.time,现代日期时间 API:

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String wholeString = "The time is 7:00.";
        String timeOnlyString = wholeString.replaceAll(".*?(\d{1,2}:\d{1,2}(?:\:\d{1,2}(?:\.\d{1,9})?)?).*",
                "");

        DateTimeFormatter dtf = DateTimeFormatter
                .ofPattern("H:m[:s[.[SSSSSSSSS][SSSSSSSS][SSSSSSS][SSSSSS][SSSSS][SSSS][SSS][SS][S]", Locale.ENGLISH);
        LocalTime time = LocalTime.parse(timeOnlyString, dtf);
        System.out.println(time);
    }
}

输出:

07:00

ONLINE DEMO

注意方括号中的可选模式。

Trail: Date Time 中了解有关 modern Date-Time API* 的更多信息.


* 无论出于何种原因,如果您必须坚持Java 6 或Java 7,您可以使用ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and