有些事情我試圖解析是:正則表達式人類可讀的時間 - 下午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$
有些事情我試圖解析是:正則表達式人類可讀的時間 - 下午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$
驗證應正則表達式的外部進行,因爲它不是基於語義的,而是在我們的理解的時間。 雖然我們可以在正則表達式中這樣做,但它會使模式變得非常混亂。
模式的基本形式應該是這樣的,簡單而直接:
\d{1,2}(\.\d{1,2})? ?([a|p]m|noon)
但是,我們必須添加一些命名組隔離的時間不同的部分:
(?<hours>\d{1,2})
(?<minutes>\d{1,2})
(?<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
您的正則表達式也匹配上午9時9分,下午39,9時,中午99.99和下午59.6時,這些都不是有效的時間值。 –
您編輯的正則表達式仍然匹配9.99(上午9點匹配),90.66中午(匹配中午6點),0.7上午(匹配整個字符串)和其他無效時間。 –
謝謝 - 我會試一試,讓你知道我該怎麼去 - 輸入數據被認爲是正確的,我使用reges來知道在句子中有多少次發生時間,並將它們提取到一個時間跨度對象。 – GMan
如果你想使用momentjs,你在原來的問題,你可以說:
解析您可以使用moment.updateLocale
,指定meridiemParse
和isPM
,如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>
我希望這所有這一切:)這是你自己嘗試的稍微修改。
(?<![\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
標籤,這使我不確定。)
謝謝 - momentjs標籤是看看是否有方法使用片刻庫來解析人類可讀的時間。 – GMan
我認爲這個正則表達式解析了[\ d] {1,2}上的所有情況(\。[\ d] {1,2})?\ s ?(am | pm | noon)' –
你應該刪除你的最後一段,這個段落使問題變得無關緊要,而是要求正則表達式的幫助。 –
@CaioOliveira:您的努力也將匹配上午9點,下午39.9點和中午99,99點,這些時間都不是有效時間。 –