Perl 格式化日期

Perl 格式化日期,perl,Perl,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 th

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.
您将如何着手解决此问题,将日期格式化为2012年4月9日

我知道日期可能不明确,即12112可以是12/1/12或1/21/12,但假设是尽可能最小的月份。

安装日期::Calc

关于ubuntu libdate calc perl


这应该能够读取所有这些日期(除了4912、499 2012、409 2012),然后以通用格式输出它们

这实际上是正则表达式擅长的事情;做出一个假设,继续前进,然后在必要时回溯以获得一场成功的比赛

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格式,用于获取值并以特定方式格式化它们;我想你的问题是关于如何解析你已经给出的任何格式的日期?不,不做模块就不做。“11113”是11-1-2013还是1-11-2013?什么日期是代码> 12212 < /代码>?那么你有几个问题要考虑。code>11111111是明确的,因此8s
111
,但是您想如何处理介于
'1'x 4
'1'x 7
之间的字符串?我对Perl还是很陌生,所以您能对您的代码做些什么评论吗?我不知道
s括号
在做什么,也不知道
\A
\z
xe
%02u/%02u
在做什么;还有其他问题吗?很好的解决方案!但是,我猜我必须检查年份是否为,例如,开始时添加
04
20
,然后用字符串重新连接它?您最初说的是“将日期格式化为04/09/12”,但可以。。。