2013-05-13 149 views
1

我想創建一個程序來解析一個字符串中有意義的日期和時間。我希望能夠給以下幾種輸入,並創建一個日期/時間對象:從字符串解析日期/時間?

5 o'clock 
5 p.m. 
5 a.m. 
5 
530 
530 a.m. 
530 p.m. 
Tuesday at [insert any above string here] 
the 30th at [same as above] 
May 12th at [same as above] 
today at [same as above] 
tomorrow at [same as above] 

不包含日/日期可以假設今天是任何字符串,任何時間沒有上午/下午指定可以被認爲是在上午9點到下午8點59分之間發生。 我很快就意識到什麼亂七八糟的在寫代碼的這一部分後成爲:

private void createEvent(String phrase) { 
    int hour; 
    int day = 0; 
    String dayOfWeek = ""; 

    if (phrase.contains("o'clock")) { 
     hour = Integer.parseInt(phrase.substring(phrase.indexOf("o'clock")-3, phrase.indexOf("o'clock")-1).trim()); 
     out.write(""+hour); 
    } 

    if (phrase.contains("tomorrow")) 
     day = (Calendar.DAY_OF_WEEK % 7)+1; 

    if (phrase.contains("sunday") || day == 1) { 
     dayOfWeek = "Sunday"; day = 1; } 
    else if (phrase.contains("monday") || day == 2) { 
     dayOfWeek = "Monday"; day = 2; } 
    else if (phrase.contains("tuesday") || day == 3) { 
     dayOfWeek = "Tuesday"; day = 3; } 
    else if (phrase.contains("wednesday") || day == 4) { 
     dayOfWeek = "Wednesday"; day = 4; } 
    else if (phrase.contains("thursday") || day == 5) { 
     dayOfWeek = "Thursday"; day = 5; } 
    else if (phrase.contains("friday") || day == 6) { 
     dayOfWeek = "Friday"; day = 6; } 
    else if (phrase.contains("saturday") || day == 7) { 
     dayOfWeek = "Saturday"; day = 7; } 
    else { 
     dayOfWeek = "Today"; day = 0; }  
} 

任何人都可以提供一些方向?

+1

我會專注於每個案件seperatly,也許創建一個簡單的'格式化工具'的基本目的。將它們全部添加到中央'FormatFactory'中。這將允許您根據需要增加可能的格式化器數量(或者在需要時排除一些格式器) – MadProgrammer 2013-05-13 05:42:24

+0

您的字符串中可能還有其他什麼?整個字符串是否與時間有關,還是可能包含其他信息?例如:「我會在五點鐘在車站接你」 – GHC 2013-05-13 05:45:23

回答

3

你可以使用日期格式

String now = new Date().toString(); 
SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy"); 
Date date = format.parse(now); 

也許你可以建立提前幾個格式,然後比較分析的日期。

檢查教程這裏:http://www.xyzws.com/Javafaq/how-to-use-simpledateformat-class-formating-parsing-date-and-time/142

+0

不會解析「a.m.」或「下午」。 「明天」呢? – MadProgrammer 2013-05-13 06:00:26

+0

如果字符串格式沒有限制,編寫代碼來處理所有情況是不可能的。如果你想解析用戶輸入的所有內容,它將成爲關於自然語言處理的一個問題... – ltebean 2013-05-13 06:09:20

+0

然後說盡可能多的 – MadProgrammer 2013-05-13 06:15:28

2

下打破你的問題轉化爲可管理的塊...

我會通過提供這,因爲你需要,你可以添加新的格式化的手段開始。

我也試着找到重用現有的代碼。時間對於你的問題是一個非常一致的方面。

這將導致我提供某種形式的統一格式工廠的概念(使管理更容易),但個性化需求分解成更小的可管理的塊

import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.Calendar; 
import java.util.Date; 
import java.util.List; 

public class CustomDateFormatter { 

    public static void main(String[] args) { 
     new CustomDateFormatter(); 
    } 

    public CustomDateFormatter() { 

     String values[] = new String[]{ 
      "5 o'clock", 
      "5 p.m.", 
      "5 a.m.", 
      "5", 
      "530", 
      "530 a.m.", 
      "530 p.m.",}; 

     for (String value : values) { 
      System.out.println(value + " = " + CustomFormatFactory.format(value)); 
     } 
    } 

    public static class CustomFormatFactory { 

     private static List<CustomFormat> formatters = new ArrayList<>(); 

     public static Date format(String value) { 
      Date date = null; 
      for (CustomFormat format : formatters) { 
       if (format.canFormat(value)) { 
        date = format.format(value); 
        if (date != null) { 
         break; 
        } 
       } 
      } 
      return date; 
     } 

     protected static boolean formatTime(String value, Calendar cal) { 
      boolean formatted = false; 
      if (Character.isDigit(value.charAt(0))) { 
       formatted = true; 
       StringBuilder timePart = new StringBuilder(4); 
       int index = 0; 
       while (index < value.length() && Character.isDigit(value.charAt(index))) { 
        timePart.append(value.charAt(index)); 
        index++; 
       } 

       int hour = 0; 
       int min = 0; 
       if (timePart.length() < 3) { 
        hour = Integer.parseInt(timePart.toString()); 
       } else { 
        hour = Integer.parseInt(timePart.substring(0, timePart.length() - 2)); 
        min = Integer.parseInt(timePart.substring(timePart.length() - 2, 3)); 
       } 

       cal.set(Calendar.HOUR_OF_DAY, hour); 
       cal.set(Calendar.MINUTE, min); 
       cal.set(Calendar.MILLISECOND, 0); 

       String sufix = value.substring(timePart.length()).trim(); 
       if ("p.m.".equalsIgnoreCase(sufix) || "pm".equalsIgnoreCase(sufix)) { 
        cal.add(Calendar.HOUR, 12); 
       } 
      } 
      return formatted; 
     } 

     static { 
      formatters.add(new SimpleTimeFormat()); 
     } 
    } 

    public static interface CustomFormat { 

     public boolean canFormat(String value); 

     public Date format(String value); 
    } 

    public static class SimpleTimeFormat implements CustomFormat { 

     @Override 
     public boolean canFormat(String value) { 
      return format(value) != null; 
     } 

     @Override 
     public Date format(String value) { 
      Date date = null; 
      Calendar cal = Calendar.getInstance(); 
      if (CustomFormatFactory.formatTime(value, cal)) { 
       date = cal.getTime(); 
      } 
      return date; 
     } 
    } 
} 

對於擴展的日期格式,我會提取日期部分,根據日期生成Calendar,將時間分區提取爲單獨的String,並使用CustomFormatFactory.formatTime方法來格式化時間,從而使您不必每次重新編碼它。

同樣,日期格式化器可以在內部簡單地擁有一個時間格式化器的實例,或者您可以將工廠設置爲具有多個格式方法,一個需要時間值並通過可用時間格式化器循環......這會是我個人的選擇;)