是的,另一个正则表达式问题。不客气;-P
这是我第一次在C#中编写自己的正则表达式进行简单的字符串验证。我想我已经开始工作,但作为一个学习练习,我想知道它是否可以改进以及我是否犯过任何错误。
字符串看起来都像这样:
T20160307.0001
规则:
这是我的正则表达式(fiddle):
^(?I)[T] 20 [0-9] {2} [0-1] [0-9] [0-3] [0-9]。\ d {4} $
^
断言字符串的开头。(?i)[T]
检查我们是否有字母T,不区分大小写。20
YYYY从20开始(我将在2100年前去世,所以我不在乎任何事情:-P)[0-9]{2}
YYYY第二部分的0到99之间的任何数字。[0-1][0-9]
0或1表示月初,0-9表示月份的第二部分。[0-3][0-9]
0-3为第一天的部分,0-9为第二部分。.
完全停止。\d{4}
4个数字字符。$
断言字符串结尾。我已经看到的一个陷阱是日期验证。 2016 - 1935年(第19个月的第35天)被视为有效。我已阅读some / other / posts关于实现这一点,我认为这与数字范围匹配,但我无法理解格式。
我会接受一个简单解决日期问题的答案,如果有人会对ELI5如何运作有所帮助,但其他改进将是一个值得欢迎的奖励。
编辑为了避免进一步混淆,我应该声明我知道DateTime.TryParse等。如上所述,我正在利用这个作为学习正则表达式的机会,并认为这是一个很好的起点。对于任何浪费时间的人都很抱歉,我应该在原帖中说清楚。
答案 0 :(得分:4)
你可以做的事情是:
\d
字符类(因为您只需要ascii数字)[0-1]
,您可以撰写[01]
T
放入字符类中
[Tt]
代替T
^(?i)T20[0-9]{2}[01][0-9][0-3][0-9]\.[0-9]{4}$
或
^[Tt]20[0-9]{2}[01][0-9][0-3][0-9]\.[0-9]{4}$
其他的事情:你真的需要添加额外的日期检查,因为你无法真正测试日期格式是否正确? (想一想闰年)为什么不呢:
^(?i)T(20[0-9]{6})\.[0-9]{4}$
如果您想知道日期是否真的存在,请捕获它并使用DateTime.TryParse
方法对其进行测试。
答案 1 :(得分:3)
为什么使用正则表达式只需使用DateTime.TryParseExact方法。我会这样实现它,并对其他字符进行额外检查:
bool IsCorrectFormat(string input)
{
//14 is a magic number for the length of the expected format
if (input.Length == 14 && input.StartsWith("T", StringComparison.OrdinalIgnoreCase))
{
DateTime dt;
if (DateTime.TryParseExact(input.Substring(1), "yyyyMMdd.ffff", CultureInfo.InvariantCulture, DateTimeStyles.None, out dt))
{
return true;
}
}
return false;
}
我不知道格式是否正确但你总是可以从1到6子串获得yyyyMMdd
然后检查最后5个字符的小数点和数字。
编辑:如果必须使用正则表达式
我过去曾使用过这个正则表达式。请注意,它不会检查闰年
@"^(((0[1-9]{1}|[1-2][0-9]{1}|3[01]{1})(0[13578]{1}|1[12]{1}))" //For a 31 day month
+ @"|"
+ @"((0[1-9]{1}|[1-2][0-9]{1}|30)(0[469]{1}|11))" //For a 30 day month
+ @"|"
+ @"((0[1-9]{1}|1[0-9]{1}|2[0-8]{1})(02)))" //For a 28 day month(feb)
+ @"([0-9]{4})$"; //For the year
答案 2 :(得分:1)
如上所述,我将此作为学习正则表达式的机会,并认为这是一个很好的起点。
使用正则表达式验证日期肯定不是一件容易的事情,特别是考虑到闰年所涉及的复杂规则。但这是有可能的。
如果以YYYYMMdd格式输入有效日期,则以下表达式将匹配:
(?=\p{IsBasicLatin}{8}) # ensures \d matches only 0-9
(?!0000)\d{4} # year any 4-digit year, except 00
(?:0[1-9]\d|1[012]) # month 01-12
(?:
# day logic for leap years
(?:
(!00)[012]\d # Days 01-29 (we exclude 2/29 later)
| (?<!02)30 # Day 30 valid for all months except Feb
| (?<=0[13578]|1[02])31 # Day 31 valid for some months
)
# Non-Leap-year logic. Do not allow 2/29 if the provided year
# is not a leap year.
(?<!
(?:
[13579] # years ending with odd number are not leap years
| [02468][26]|[13579][048] # years not divisible by 4
# are not leap years (02, 06, 10, ...)
| (?:[02468][\d-[048]]|[13579][\d-[26]])00 # years divisible by
# 100 are not leap years,
# unless divisible by 400
)0229)
)
与RegexOptions.IgnorePatternWhitespace
汇编。您可以使用^T~\.\d{4}$
匹配示例中的完整字符串,将~
替换为上述表达式。