2013-05-08 45 views
8

Trong một String được như thế nàyLàm thế nào để thay thế một giữ chỗ trong một String với một Pattern SimpleDateFormat

".../uploads/${customer}/${dateTime('yyyyMMdd')}/report.pdf" 

tôi cần phải thay thế một customeryyyyMMdd dấu thời gian.

Để thay thế trình giữ chỗ customer, tôi có thể sử dụng số StrSubstitutor từ Apache Commons. Nhưng làm thế nào để thay thế SimpleDateFormat? Chúng tôi đang chạy trong một môi trường mùa xuân, vì vậy có lẽ Spring EL là một lựa chọn?

Đánh dấu cho trình giữ chỗ không cố định, sẽ ổn nếu thư viện khác cần thay đổi cú pháp.

này kiểm tra nhỏ cho thấy vấn đề:

SimpleDateFormat   formatter = new SimpleDateFormat("yyyyMMdd"); 

String      template = ".../uploads/${customer}/${dateTime('yyyyMMdd')}/report.pdf"; 

@Test 
public void shouldResolvePlaceholder() 
{ 
    final Map<String, String> model = new HashMap<String, String>(); 
    model.put("customer", "Mr. Foobar"); 

    final String filledTemplate = StrSubstitutor.replace(this.template, model); 

    assertEquals(".../uploads/Mr. Foobar/" + this.formatter.format(new Date()) + "/report.pdf", filledTemplate); 
} 
+1

là phần ngày luôn là thư mục cuối cùng trong cấu trúc thư mục của bạn? –

+0

Không, trong một số báo cáo khác là ở giữa. Hoặc trong tên tệp. Đây chỉ là một ví dụ. – d0x

Trả lời

24

Tại sao bạn không sử dụng MessageFormat để thay thế?

String result = MessageFormat.format(".../uploads/{0}/{1,date,yyyyMMdd}/report.pdf", customer, date); 

Hoặc với String.format

String result = String.format(".../uploads/%1$s/%2$tY%2$tm%2$td/report.pdf", customer, date); 
+0

Tôi thích họ với các biến được đặt tên. Bởi vì String đến từ một mô-đun khác. Họ không biết tôi sử dụng cái gì. Với 'MessageFormat' tôi cần giao tiếp Index 0 = customer, 1 = current date, 2 = .... hm .... – d0x

+0

Không phải là định dạng chi tiết triển khai? Làm thế nào nó "tiếp xúc" với khách hàng của bạn? Nó không chỉ là một cuộc gọi phương thức với các thông số đã gõ? – NilsH

8

Như NilsH gợi ý MessageFormat là thật sự tốt đẹp cho mục đích này. Để có các biến tên bạn có thể ẩn đằng sau MessageFormat lớp học của bạn:

public class FormattedStrSubstitutor { 
    public static String formatReplace(Object source, Map<String, String> valueMap) { 
     for (Map.Entry<String, String> entry : valueMap.entrySet()) { 
      String val = entry.getValue(); 
      if (isPlaceholder(val)) { 
       val = getPlaceholderValue(val); 
       String newValue = reformat(val); 

       entry.setValue(newValue); 
      } 
     } 

     return new StrSubstitutor(valueMap).replace(source); 
    } 

    private static boolean isPlaceholder(String isPlaceholder) { 
     return isPlaceholder.startsWith("${"); 
    } 

    private static String getPlaceholderValue(String val) { 
     return val.substring(2, val.length()-1); 
    } 

    private static String reformat(String format) { 
     String result = MessageFormat.format("{0,date," + format + "}", new Date()); 

     return result; 
    } 
} 

Và bạn phải điều chỉnh testcase của bạn:

SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd"); 

String template = ".../uploads/${customer}/${dateTime}/report.pdf"; 

@Test 
public void shouldResolvePlaceholder() { 
    final Map<String, String> model = new HashMap<String, String>(); 
    model.put("customer", "Mr. Foobar"); 
    model.put("dateTime", "${yyyyMMdd}"); 

    final String filledTemplate = FormattedStrSubstitutor.formatReplace(this.template, 
     model); 

    assertEquals(".../uploads/Mr. Foobar/" + this.formatter.format(new Date()) 
     + "/report.pdf", filledTemplate); 
} 

Tôi đã gỡ bỏ Generics và thay thế những với String. Ngoài ra, isPlaceholdergetPlaceholderValue được mã hóa cứng và mong đợi cú pháp $ {value}.

Nhưng đây chỉ là ý tưởng để giải quyết vấn đề của bạn. Để thực hiện việc này, bạn có thể sử dụng các phương thức từ StrSubstitutor (chỉ cần sử dụng hoặc thực hiện FormattedStrSubstitutor extends StrSubstitutor).

Ngoài ra, bạn có thể sử dụng ví dụ $ d {value} để định dạng ngày và $ foo {value} để định dạng foo.

CẬP NHẬT

Không thể ngủ mà không có giải pháp đầy đủ. Bạn có thể thêm phương pháp này để FormattedStrSubstitutor lớp:

public static String replace(Object source, 
     Map<String, String> valueMap) { 

    String staticResolved = new StrSubstitutor(valueMap).replace(source); 

    Pattern p = Pattern.compile("(\\$\\{date)(.*?)(\\})"); 
    Matcher m = p.matcher(staticResolved); 

    String dynamicResolved = staticResolved; 
    while (m.find()) { 
     String result = MessageFormat.format("{0,date" + m.group(2) + "}", 
       new Date()); 

     dynamicResolved = dynamicResolved.replace(m.group(), result); 
    } 

    return dynamicResolved; 
} 

testcase của bạn giống như trong câu hỏi của bạn (thay đổi nhỏ trong placeholder):

SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd"); 

String template = ".../uploads/${customer}/${date,yyyyMMdd}/report.pdf"; 

@Test 
public void shouldResolvePlaceholder() { 
    final Map<String, String> model = new HashMap<String, String>(); 
    model.put("customer", "Mr. Foobar"); 

    final String filledTemplate = FormattedStrSubstitutor.replace(this.template, 
      model); 

    assertEquals(
      ".../uploads/Mr. Foobar/" + this.formatter.format(new Date()) 
        + "/report.pdf", filledTemplate); 
} 

Cùng hạn chế như trước đây; không có generics và sửa tiền tố và hậu tố cho trình giữ chỗ.

Các vấn đề liên quan