我试图解析的一些事情是:
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 :(得分:1)
验证应该在正则表达式之外进行,因为它不是基于语义,而是基于我们对时间的理解。 虽然我们可以在正则表达式中做到这一点,但它会使模式非常混乱。
模式的基本形式应该是这样,简单直接:
\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));
编辑:我们有一种奇怪的方式来记下时间:下午1点= 13点,下午2点= 14点,... 11点= 23点,下午12点!= 24点(但= = 12点)。而且,上面的例子没有考虑到这一点。
所以这里有一个修复:
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));
结果:
8点00分00秒
12时10分00秒
17:45:00
14时24分00秒
00:10:00
17:45:00
答案 1 :(得分:1)
如果您想使用原始问题中所述的时刻,您可以:
您可以moment.updateLocale
使用meridiemParse
指定isPM
和['ha', 'h a', 'h.mma']
。
然后,您可以使用docs指定所需的每种格式(示例中为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>
&#13;
{{1}}&#13;
答案 2 :(得分: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
PS。您已将其标记为c#
,因此我认为后台是可以的。 (还有momentjs
标签让我不确定。)
答案 3 :(得分:0)