私は解析しようとしているものは以下のとおりです。私は正午のためのケータリングせずに、次の必要があり正規表現 - 午後5時、5.30午後、正午
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午後、正午
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)
すべてのテーマと連動組み合わせる:@"(?<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));
EDIT:私たちは奇妙なを持っています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));
結果:
午前8時00分00秒
12時10分00秒
午後五時45分00秒
午後02時24分○○秒
00:10:00
17:45:00
(1[0-2]|[0-9])(\.[0-5]?[0-9])?\s?([a|p]m|noon)
証明:https://regex101.com/r/9yu6l6/2
編集:リワークたちの理解の上ではなく、それがセマンティックに基づいていないよう
あなたの正規表現は、午前9時09分、午後39時99分、正午59時、午後59時と一致しますが、いずれも有効な時間値ではありません。 –
編集した正規表現は、9.99 am(午前9時に一致)、90.66正午(正午6時に一致)、0.7 am(文字列全体に一致)、およびその他の無効な時刻に一致します。 –
ありがとう - 私はこれを試してみると、私はどのように行くのかを教えてあげる - 入力データは正しいと思われる、私はregesを使用して、時間の出現回数を知り、 timespanオブジェクト。 – GMan
あなたはあなたができる元の質問で述べたようにmomentjsを使用する場合:
で解析する
moment.updateLocale
をmeridiemParse
とisPM
と指定することができます。 次に、必要なすべての形式(例では['ha', 'h a', 'h.mma']
)を指定してmoment parsing with multiple formatを使用できます。ここで
質問に与えられた入力のための作業例:
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#
とタグ付けしました。したがって、私は裏返しがOKであると仮定します。 (momentjs
タグもあります)
ありがとう - momentjsタグは、人間が読める時間を解析するためにモーメントライブラリを使用する方法があるかどうかを確認することでした。 – GMan
この正規表現は '[\ d] {1,2}(\。[\ d] {1,2})の上のすべてのケースを解析すると思いますか?\ s ?(am | pm | noon) ' –
最後の段落を削除して、トピックをオフトピックにして、正規表現のヘルプを求めてください。 –
@CaioOliveira:あなたの努力は、午前9時9分、午後39時9分、正午99,99時間に一致しますが、いずれも有効な時間はありません。 –