2016-09-29 140 views
0

有些事情我試圖解析是:正則表達式人類可讀的時間 - 下午5點,5.30點,中午12點

8am, 12.10pm, 5.45pm 
8am, 11.30am 
12noon 
12 noon 
8 am 
7 pm. 

我有沒有照顧中午以下 - 但它不捕獲以上所有情況。

^([0-9]|0[0-9]|1[0-9]|2[0-3]).[0-5][0-9][a|p]m$ 
+0

我認爲這個正則表達式解析了[\ d] {1,2}上的所有情況(\。[\ d] {1,2})?\ s ?(am | pm | noon)' –

+0

你應該刪除你的最後一段,這個段落使問題變得無關緊要,而是要求正則表達式的幫助。 –

+0

@CaioOliveira:您的努力也將匹配上午9點,下午39.9點和中午99,99點,這些時間都不是有效時間。 –

回答

1

驗證應正則表達式的外部進行,因爲它不是基於語義的,而是在我們的理解的時間。 雖然我們可以在正則表達式中這樣做,但它會使模式變得非常混亂。

模式的基本形式應該是這樣的,簡單而直接:

\d{1,2}(\.\d{1,2})? ?([a|p]m|noon) 

但是,我們必須添加一些命名組隔離的時間不同的部分:

  1. 時間:(?<hours>\d{1,2})
  2. 分鐘:(?<minutes>\d{1,2})
  3. 期:(?<period>[ap]m|noon)

結合所有togather:@"(?<hours>\d{1,2})(\.(?<minutes>\d{1,2}))? ?(?<period>[ap]m|noon)"


下面的代碼捕獲,看起來像一個人類可讀的時間,只是那些在你的例子發現,並解析成字符串的一部分一個TimeSpan對象:

var times = Regex.Matches(input, @"(?<hours>\d{1,2})(\.(?<minutes>\d{1,2}))? ?(?<period>[ap]m|noon)") 
    .Cast<Match>() 
    // parse parts of time 
    .Select(m => new 
    { 
     Hours = int.Parse(m.Groups["hours"].Value), 
     Minutes = m.Groups["minutes"].Success ? int.Parse(m.Groups["minutes"].Value) : 0, 
     IsAfternoon = Regex.IsMatch(m.Groups["period"].Value, "pm|noon"), 
    }) 
    // filter out invalid time 
    .Where(x => x.Hours <= 12 && x.Minutes <= 59) 
    // convert 
    .Select(x => new TimeSpan((x.Hours + (x.IsAfternoon ? 12 : 0)) % 24, x.Minutes, 0)); 

編輯:我們有一個奇怪的寫下時間的方式:1pm = 13:00,2pm = 14:00,... 11pm = 23:00,12pm!= 24:00(但= 12:00)。而且,上面的例子沒有考慮到這一點。

所以這裏的修復:

var input = @" Monday 8am, 12.10pm, 5.45pm, 14:24||8:0|0:10|17:45"; 
var results = Regex.Matches(input, @"(?<hours>\d{1,2})([\.:](?<minutes>\d{2}))?(?<period>[ap]m|noon)?") 
    .Cast<Match>() 
    .Where(m => m.Groups["minutes"].Success || m.Groups["period"].Success) 
    .Select(m => new 
    { 
     Hours = int.Parse(m.Groups["hours"].Value), 
     Minutes = m.Groups["minutes"].Success ? int.Parse(m.Groups["minutes"].Value) : 0, 
     IsAfternoon = m.Groups["period"].Success ? Regex.IsMatch(m.Groups["period"].Value, "pm|noon") : (bool?)null 
    }) 
    .Dump() 
    .Where(x => (x.IsAfternoon != null ? x.Hours <= 12 : x.Hours < 24) && x.Minutes <= 59) 
    .Select(x => new TimeSpan(
     x.Hours == 12 && x.IsAfternoon == true 
      ? 12 
      : x.Hours + (x.IsAfternoon == true ? 12 : 0), 
     x.Minutes, 
     0)); 

結果:

08:00:00
12時10分00秒
17:45:00
十四時24分00秒
00:10:00
17:45:00

+0

這實際上就是我之後的 - 我不知道如何整合Regex和C#解析。它仍然沒有正確解析以下內容 - 特別是晚上12點10分解析爲00:10。除此之外,它工作正常。週一早上8點,12點10分,5點。45 pm||8:0|0:10|17:45 – GMan

+0

@GMan查看我的編輯 – Xiaoy312

+0

謝謝Xiaoy312的作品! – GMan

0
(1[0-2]|[0-9])(\.[0-5]?[0-9])?\s?([a|p]m|noon) 

證明:https://regex101.com/r/9yu6l6/2

編輯:返工基於邊緣的情況下

+0

您的正則表達式也匹配上午9時9分,下午39,9時,中午99.99和下午59.6時,這些都不是有效的時間值。 –

+0

您編輯的正則表達式仍然匹配9.99(上午9點匹配),90.66中午(匹配中午6點),0.7上午(匹配整個字符串)和其他無效時間。 –

+0

謝謝 - 我會試一試,讓你知道我該怎麼去 - 輸入數據被認爲是正確的,我使用reges來知道在句子中有多少次發生時間,並將它們提取到一個時間跨度對象。 – GMan

1

如果你想使用momentjs,你在原來的問題,你可以說:

  • 定製您的語言環境來解析「中午」像點
  • 使用時刻兼容多種格式

解析您可以使用moment.updateLocale,指定meridiemParseisPM,如docs中所述。

然後您可以使用moment parsing with multiple format指定您需要的每種格式(在您的示例中爲['ha', 'h a', 'h.mma'])。

這裏的問題給出的輸入工作示例:

moment.updateLocale('en', { 
 
    meridiemParse : /[ap]\.?m?\.?|noon/i, 
 
    isPM : function (input) { 
 
    input = (input + '').toLowerCase(); 
 
    return input[0] === 'p' || input === 'noon'; 
 
    } 
 
}); 
 

 
var arr = ['8am', '12.10pm', '5.45pm', '11.30am', '12noon', '12 noon', '8 am', '7 pm.']; 
 

 
for(var i=0; i<arr.length; i++){ 
 
    var m = moment(arr[i], ['ha', 'h a', 'h.mma'], true); 
 
    console.log(m.format('HH:mm'), arr[i]); 
 
}
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.1/moment.min.js"></script>

1

我希望這所有這一切:)這是你自己嘗試的稍微修改。

(?<![\d.])        # Mustn't be preceeded by a digit or . 
    (?: 
     12\s*noon      # just 12 noon 
    |  
     (?:[0-9]|0[0-9]|1[0-2])   # 12 hour clock 
     (?:\.[0-5][0-9])?    # optional minutes 
     \s*(?:[ap]m)     # mandatory am/pm 
    | 
     (?:[0-9]|0[0-9]|1[0-9]|2[0-3]) # 24 hour clock 
     (?:\.[0-5][0-9])?    # optional minutes 
    ) 
(?![\d.]|[ap]m)       # Correct ending 

Check it out here at regex101

PS。您已將其標記爲c#,因此我認爲後視可以。 (還有momentjs標籤,這使我不確定。)

+0

謝謝 - momentjs標籤是看看是否有方法使用片刻庫來解析人類可讀的時間。 – GMan

相關問題