日期格式的字符串,可能有以下格式:
'2008-10-11'
'2009-10-11 23:22'(日期和时间之间是空格)
'2009-10-11 23:22:49'
日期分隔符可以是'-','/','.',但这3种情况下时间分隔符一定是':'
日期也可能是'年月日',但此时时间分隔符可能是':'('2009年01月11日 23:22:23'),也可能是'时分秒'('2009年01月11日 23时22分23秒')不会出现其他情况求验证表达式,并能转化为java.util.Date
'2008-10-11'
'2009-10-11 23:22'(日期和时间之间是空格)
'2009-10-11 23:22:49'
日期分隔符可以是'-','/','.',但这3种情况下时间分隔符一定是':'
日期也可能是'年月日',但此时时间分隔符可能是':'('2009年01月11日 23:22:23'),也可能是'时分秒'('2009年01月11日 23时22分23秒')不会出现其他情况求验证表达式,并能转化为java.util.Date
(\d{4}[-/\.]{1}\d{2}[-/\.]{1}\d{2}(\s{1}\d{2}:\d{2}(:\d{2}){0,1}){0,1})
|
(\d{4}年}\d{2}月\d{2}日(\s{1}\d{2}:\d{2}(:\d{2}){0,1}){0,1})
|
(\d{4}年}\d{2}月\d{2}日(\s{1}\d{2}时\d{2}分(\d{2}秒){0,1}){0,1})分成了三个分支结构,由“|”(意同或)连接。其中对于月份,日期,时,分,秒等数字合理性的判断没写在里面,免得太长,影响阅读理解。
具体数字的范围判断如下,可以逐个按照位置上面的正则里
月 0{1}/d{1}|10|11|12
日 [0-2]{1}/d{1}|30|31
时 [0-1]{1}/d{1}|20|21|22|23
分 [0-5]{1}/d{1}
秒 [0-5]{1}/d{1}
不要把简单的事情复杂化~
写出来的话,正则表达式字符长度将会超过 400 个字符。建议使用正则表达式验证基本的数据格式,至于数据的合法性应采用代码逻辑进行验证。
原来在 CSDN 的 blog 里写的,带有行内嵌注释: 1. import java.util.regex.Matcher;
2. import java.util.regex.Pattern;
3.
4. public class DateRegex {
5.
6. public static void main(String[] args) {
7. String[] str = {
8. "2001-00-00", "2001-01-01", "2001-01-30", "2001-01-31",
9. "2001-01-32", "2001-02-01", "2001-02-27", "2001-02-28",
10. "2004-02-29", "2001-02-29", "2001-02-30", "2001-02-31",
11. "2001-02-32", "2001-03-01", "2001-03-10", "2001-03-29",
12. "2001-03-30", "2001-03-31", "2001-03-32", "2001-04-01",
13. "2001-04-10", "2001-04-29", "2001-04-30", "2001-04-31",
14. "2001-04-32", "2001-05-01", "2001-05-10", "2001-05-29",
15. "2001-05-30", "2001-05-31", "2001-05-32", "2001-06-01",
16. "2001-06-10", "2001-06-29", "2001-06-30", "2001-06-31",
17. "2001-06-32", "2001-07-01", "2001-07-10", "2001-07-29",
18. "2001-07-30", "2001-07-31", "2001-07-32", "2001-08-01",
19. "2001-08-10", "2001-08-29", "2001-08-30", "2001-08-31",
20. "2001-08-32", "2001-09-01", "2001-09-10", "2001-09-29",
21. "2001-09-30", "2001-09-31", "2001-09-32", "2001-10-01",
22. "2001-10-10", "2001-10-29", "2001-10-30", "2001-10-31",
23. "2001-10-32", "2001-11-01", "2001-11-10", "2001-11-29",
24. "2001-11-30", "2001-11-31", "2001-11-32", "2001-12-01",
25. "2001-12-10", "2001-12-29", "2001-12-30", "2001-12-31",
26. "2001-12-32", "2001-13-01", "2001-13-10", "2001-13-29",
27. "2001-13-30", "2001-13-31", "2001-13-32", "245-12-04",
28. "100-02-29" , "200-02-29" , "300-02-29" , "400-02-29",
29. "500-02-29" , "800-02-29" , "900-02-29" , "2008-02-29",
30. "1900-02-29", "2000-02-29", "1-01-01" , "1-02-28",
31. "0-01-01" , "1-12-31" , "351-02-29" , "352-02-29",
32. "353-02-29" , "354-02-29" , "355-02-29" , "356-02-29",
33. "357-02-29" , "358-02-29" , "350-02-29" , "1-02-29",
34. "2-02-29" , "3-02-29" , "4-02-29" , "5-02-29",
35. "6-02-29" , "7-02-29" , "8-02-29" , "9-02-29",
36. "10-02-29" , "11-02-29" , "12-02-29" , "13-02-29",
37. "14-02-29" , "15-02-29" , "16-02-29" , "17-02-29",
38. "18-02-29" , "19-02-29" , "20-02-29" , "21-02-29",
39. "22-02-29" , "23-02-29" , "24-02-29" , "25-02-29",
40. "26-02-29" , "27-02-29" , "28-02-29" , "29-02-29",
41. "0-01-12" , "00-01-12" , "000-01-12" , "0000-01-12",
42. "0028-02-29"
43. };
44.
45. String moreMonth =
46. "(?: \n" +
47. " ## 日期前是大月 \n" +
48. " ## 01 03 05 07 08 \n" +
49. " ## 10 12 月 \n" +
50. " (?<= \n" +
51. " (?: \n" +
52. " 0[13578] \n" +
53. " | \n" +
54. " 1[02] \n" +
55. " ) \n" +
56. " - \n" + // 分隔符
57. " ) \n" +
58. " (?: \n" +
59. " ## 大月的日期 29 \n" +
60. " 29 \n" +
61. " | \n" +
62. " ## 大月的日期 30~31 \n" +
63. " 3[01] \n" +
64. " ) \n" +
65. ") \n";
66.
67. String lesserMonth =
68. "(?: \n" +
69. " ## 日期前是小月 \n" +
70. " ## 04 06 09 11 月 \n" +
71. " (?<= \n" +
72. " (?: \n" +
73. " 0[469] \n" +
74. " | \n" +
75. " 11 \n" +
76. " ) \n" +
77. " - \n" + // 分隔符
78. " ) \n" +
79. " (?: \n" +
80. " ## 小月的日期 29 \n" +
81. " 29 \n" +
82. " | \n" +
83. " ## 小月的日期 30~31 \n" +
84. " 30 \n" +
85. " ) \n" +
86. ") \n";
87.
89. "(?: \n" +
90. " ## 29 号必须满足的条件,闰年 \n" +
91. " (?<= \n" +
92. " (?: \n" +
93. " ## 被 4 整除的年份 \n" +
94. " ## 除去最后两位为 0 的年份 \n" +
95. " ## 最后两位数一定是: \n" +
96. " ## 20 40 60 80 \n" +
97. " ## 04 24 44 64 84 \n" +
98. " ## 08 28 48 68 88 \n" +
99. " ## 12 32 52 72 92 \n" +
100. " ## 16 36 56 76 96 \n" +
101. " (?: \n" +
102. " [0-9]{0,2}(?!0?0) \n" +
103. " (?: \n" +
104. " ## 当尾数为[048]时前面不允是 \n" +
105. " ## [13579]中的任何一个 \n" +
106. " [02468]?(?<![13579])[048] \n" +
107. " | \n" +
108. " [13579][26] \n" +
109. " ) \n" +
110. " ) \n" +
111. " | \n" +
112. " ## 能被 400 整除的年份 \n" +
113. " ## 其头两位数字规定同上 \n" +
114. " (?: \n" +
115. " (?: \n" +
116. " [02468]?[048] \n" +
117. " | \n" +
118. " [13579][26] \n" +
119. " ) \n" +
120. " 00 \n" +
121. " ) \n" +
122. " ) \n" +
123. " -02- \n" + // 02 前后为分隔符
124. " ) \n" +
125. " (?:29) \n" +
126. ") \n";
127.
128. String debugRegex =
129. "(?x: \n" +
130. " ## 年份 0001~9999,并忽略0年 \n" +
131. " (?:[0-9]{1,4}(?<!^0?0?0?0)) \n" +
132. " - \n" + // 分隔符
133. " ## 月份 \n" +
134. " (?: \n" +
135. " 0[1-9] \n" +
136. " | \n" +
137. " 1[0-2] \n" +
138. " ) \n" +
139. " - \n" + // 分隔符
140. " (?: \n" +
141. " ## 每个月都有的公共日期 01~09 \n" +
142. " 0[1-9] \n" +
143. " | \n" +
144. " ## 每个月都有的公共日期 10~19 \n" +
145. " 1[0-9] \n" +
146. " | \n" +
147. " ## 每个月都有的公共日期 20~28 \n" +
148. " 2[0-8] \n" +
149. " | \n" +
150. moreMonth +
151. " | \n" +
152. lesserMonth +
153. " | \n" +
154. feburary +
155. " ) \n" +
156. ")";
157.
158. Pattern pattern = Pattern.compile(debugRegex);
159. Matcher matcher = pattern.matcher("");
160. for(String s : str) {
161. matcher.reset(s);
162. System.out.println(s + " " + matcher.matches());
163. }
164. }
165. }上面那个是带注释用于调试用的,去掉空格、注释和换行后正式用的是这样的:(?:[0-9]{1,4}(?<!^0?0?0?0))-(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8]|(?:(?<=(?:0[13578]|1[02])-)(?:29|3[01]))|(?:(?<=(?:0[469]|11)-)(?:29|30))|(?:(?<=(?:(?:[0-9]{0,2}(?!0?0)(?:[02468]?(?<![13579])[048]|[13579][26]))|(?:(?:[02468]?[048]|[13579][26])00))-02-)(?:29)))这种表达式仅仅适合学习研究之用,仅仅是验证日期的还没带上时间,共有 266 个字符,
因此并不建议用于正式环境之中,用了是跟自己过不过。另外,在下面这个链接中可以找到很多日期和时间的正则表达式(这个站点上面的表达式很多都是用 .net 正则
表达式语法写的,在 Java 中可能不能正常使用):
http://regexlib.com/DisplayPatterns.aspx?cattabindex=4&categoryId=5
这么麻烦啊?难道真的要自己写代码实现,本来想在XML里面配置一下的?
其他的逻辑(日期分隔符可以是'-','/','.',但这3种情况下时间分隔符一定是':' ),带有逻辑的东西正则表达
式都很难实现,就算实现了字符数将非常之多,验证效率也很低,还有可能会存在很多的 bug。由于表达式很长,
而且相似的字符也很多,直接导致测试和修改都会变得极其困难。
但用的多的也就这几个
看看我的总结
http://blog.csdn.net/terryzero/archive/2009/01/05/3716115.aspx
---------------->(\d{4}[-/\.]{1}\d{2}[-/\.]{1}\d{2}(\s{1}\d{2}:\d{2}(:\d{2}){0,1}){0,1})
|
(\d{4}年\d{2}月\d{2}日(\s{1}\d{2}:\d{2}(:\d{2}){0,1}){0,1})
|
(\d{4}年\d{2}月\d{2}日(\s{1}\d{2}时\d{2}分(\d{2}秒){0,1}){0,1})
嗯,Server 端的校验无论如何都得做,但客户端选择到的时间日期的格式固定下来后服务器端可以直接用 DateFormat 解析了。