2012年4月9日可以用以下任何方式编写:
4912
4/9/12
4-9-12
4 9 12
04-9-12
04-09-12
4 9 2012
4 09 2012
(I think you get the point)
对于那些不理解的人,规则是:
1. Dates may or may not have ` `, `-` or `/` between them
2. The year can be written as 2 digits (assumed to be dates in the range of [2000, 2099] inclusive) or 4 digits
3. One digit month/days may or may not have leading zeroes.
你如何解决问题,将日期格式化为04/09/12?
我知道日期可能不明确,即12112可能是12/1/12或1/21/12,但假设可能是最小的月份。
答案 0 :(得分:2)
这实际上是正则表达式擅长的东西;做出一个假设,继续前进,然后在必要时进行回溯以获得成功的匹配。
s{
\A
( 1[0-2] | 0?[1-9] )
[-/ ]?
( 3[01] | [12][0-9] | 0?[1-9] )
[-/ ]?
( (?: [0-9]{2} ){1,2} )
\z
}
{
sprintf '%02u/%02u/%04u', $1, $2, ( length $3 == 4 ? $3 : 2000+$3 )
}xe;
目前的范围检查虽然不是由月份的价值决定,但应该足以从模棱两可的案例中选出一个好的约会(有好的约会)。
请注意,首先尝试两位数的月份和日期非常重要;否则111111变为1-1-1111,而不是大概是11-11-11。但这意味着11111将更喜欢11-1-11,而不是1-11-11。
如果需要进行有效的月检查,则应在重新格式化后执行。
注意:
s{}{}
是使用花括号代替/来分隔正则表达式的部分以避免必须转义/的替换,并且还因为使用成对分隔符允许打开和关闭模式和替换部分,对我来说很好看。
\A
匹配匹配字符串的开头; \z
匹配结尾。 ^
和$
通常用于此,但在某些情况下可能会略有不同的含义;我更喜欢这些因为它们总是只意味着一件事。
最后的x标志表示这是一个扩展的正则表达式,可以有额外的空格或被忽略的注释,因此它更具可读性。 (字符类中的空格不会被忽略。)e标志表示替换部分不是字符串,而是要执行的代码。
'%02u/%02u/%02u'
是一种printf格式,用于获取值并以特定方式格式化它们;见http://perldoc.perl.org/functions/sprintf.html。
答案 1 :(得分:1)
安装Date :: Calc
在ubuntu libdate-calc-perl
上这应该能够读取所有这些日期(2012年4月9日,2012年4月9日除外),然后以通用格式输出