簡體   English   中英

在Java中的列表中拆分字符串以匹配日期格式

[英]Splitting a String to match date format in a List in Java

我有一個要寫入CSV文件的字符串列表。 列表元素具有這樣的字符串,

List<String> list1 = new ArrayList<String>();
list1.add("one, Aug 21, 2018 11:08:51 PDT, last");
list1.add("two, newlast, Aug 22, 2018 11:08:52 PDT");

但是問題是當我寫入CSV文件時, "Aug 21""2018 11:08:51"被分成不同的列。

我需要像"Aug 21, 2018 11:08:51 PDT"

另外,索引可能會更改,因此不確定8月21日是否總是在列表中的同一位置。

我嘗試了下面的代碼來解決此問題,它正在工作。 但是有什么更好的方法來解決這個問題(而不是拆分為數組並進行迭代)

list1.forEach(s -> {
        String s1[] = s.split(",");
        for(int i=0; i<s1.length; i++) {
            if(isValidMonthDate(s1[i])==true) {
                if(s1[i+1]!=null && !s1[i+1].isEmpty()) {
                    if(isValidYearTime(s1[i+1])) {
                        s1[i] = s1[i].trim();
                        System.out.println("\""+ s1[i] +","+s1[i+1]+"\""); //i will concatenate this string and write to csv
                    }
                }
            }
        }
    });
}

public static boolean isValidMonthDate(String inDate) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("MMM dd");       dateFormat.setLenient(false);
    try {
        dateFormat.parse(inDate.trim());
    } catch (ParseException pe) {
        return false;
    }
    return true;
}

public static boolean isValidYearTime(String inDate) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy HH:mm:ss zzz");        
            dateFormat.setLenient(false);
    try {
        dateFormat.parse(inDate.trim());
    } catch (ParseException pe) {
        return false;
    }
    return true;
}

我能夠得到輸出,

"Aug 21, 2018 11:08:51 PDT"
"Aug 22, 2018 11:08:52 PDT"

有沒有更好的方法來實現此目的而無需拆分為數組並對其進行迭代。

您可以利用普通的日期解析器嘗試使用解析位置在每個索引處進行解析,並查看成功的地方。

如今,當我嘗試忽略舊的日期api時,下面是一個帶有新示例的簡單演示:

public static void main(String[] args) {
    List<String> inputs = Arrays.asList(
        "Aug 21, 2018 11:08:51 PDT",
        "one, Aug 21, 2018 11:08:51 PDT, last",
        "two, newlast, Aug 22, 2018 11:08:52 PDT"
        );
    String formatPattern = "MMM dd, yyyy HH:mm:ss zzz";
    DateTimeFormatter pattern = DateTimeFormatter.ofPattern(formatPattern, Locale.US);

    for(String input : inputs) {
        System.out.println("Processing " + input);

        int[] matchStartEnd = null;
        TemporalAccessor temp = null;

        // check all possible offsets i in the input string
        for(int i = 0, n = input.length() - formatPattern.length(); i <= n; i++) {
            try {
                ParsePosition pt = new ParsePosition(i);
                temp = pattern.parse(input, pt); 
                matchStartEnd = new int[] { i, pt.getIndex() };
                break;
            }
            catch(DateTimeParseException e) {
                // ignore this
            }
        }
        if(matchStartEnd != null) {
            System.out.println("  Found match at indexes " + matchStartEnd[0] + " to " + matchStartEnd[1]);
            System.out.println("  temporal accessor is " + temp);
        }
        else {
            System.out.println("  No match");
        }
    }
}

輸出時,將日期放在引號中。 這就是CSV逃脫它們的方式。

要解析您的輸入,請使用正則表達式。 這將讀取每個日期或單詞,並使用逗號分隔符

(\w{3} \d{1,2}, \d{4})|(\w+),?

您可以使用更多的括號來詳細說明您的日期。 如果第一個表達式匹配,則為日期。 我將其留給OP來訂購最終的CSV。

這里是用於POC的Java正則表達式。 我知道問題是Java,但是REGEX是相同的。

 // read word or date followed by comma const rx = /(\\w{3} \\d{1,2}, \\d{4})|(\\w+),?/g const input = ['one, Aug 2, 1999, two', 'three, four, Aug 3, 2000', 'Aug 3, 2010, five, six'] let csv2 = '' input.forEach(it => { let parts = [] let m2 = rx.exec(it) while (m2) { parts.push(m2[1] || m2[2]) m2 = rx.exec(it) } csv2 += parts.map(it => '"' + it + '"').join(',') + '\\n' }) console.log(csv2) 

我建議您使用正則表達式提取日期:

^(.*?)(\w{3} \d{1,2}, \d{4} \d{2}:\d{2}:\d{2} PDT)(.*?)$

然后使用Stream::map提取日期並嘗試解析它。 不要忘記將null值過濾掉,因為它們沒有通過解析。

SimpleDateFormat sdf = new SimpleDateFormat("MMM dd, yyyy HH:mm:ss Z", Locale.ENGLISH);
list1.stream()
     .map(s -> { 
         try {
             return sdf.parse(s.replaceAll("^(.*?)(\\w{3} \\d{1,2}, \\d{4} \\d{2}:\\d{2}:\\d{2} PDT)(.*?)$", "$2")));
         } catch (ParseException e) {} return null; })
     .filter(Objects::nonNull)
     .forEach(System.out::println);

我建議您將try-catch和Regex提取文件包裝到單獨的方法中。

static SimpleDateFormat sdf = new SimpleDateFormat("MMM dd, yyyy HH:mm:ss Z", Locale.ENGLISH);

static Date validate(String date) {
    String s = date.replaceAll("^(.*?)(\\w{3} \\d{1,2}, \\d{4} \\d{2}:\\d{2}:\\d{2} PDT)(.*?)$", "$2");
    try {
        return sdf.parse(s);
    } catch (ParseException e) { }
    return null;
}

...大大簡化了Stream:

list1.stream()
     .map(Main::validate)
     .filter(Objects::nonNull)
     .forEach(System.out::println);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM