SCORM 2004时间格式 - 正则表达式?

时间:2009-08-20 16:24:17

标签: regex time scorm

我正在为LMS构建SCORM 2004 javascript API,SCORM 2004要求之一是传递给它的时间间隔必须遵循以下格式。有谁知道这个正则表达式是什么?我试图围绕它,但无济于事。注意:P必须始终是第一个字符。

  

P [YY] [MM] [日] [T [HH] [nm]的[S [.S] S]]   其中:

     
      
  • y:年数(整数,> = 0,不受限制)
  •   
  • m:月数(整数,> = 0,不受限制)
  •   
  • d:天数(整数,> = 0,不受限制)
  •   
  • h:小时数(整数,> = 0,不受限制)
  •   
  • n:分钟数(整数,> = 0,不受限制)
  •   
  • s:秒数或秒数的分数(实数或整数,> = 0,不是   限制)。如果使用几分之一秒,则SCORM会进一步将字符串限制为   最多2位数(例如34.45 - 有效,34.45454545 - 无效)。
  •   
  • 如果是,则出现字符文字指示符P,Y,M,D,T,H,M和S.   存在相应的非零值。
  •   
  • 应支持零填充值。零填充不会改变   由一组字符表示的数字的整数值。对于   例如,PT05H相当于PT5H和PT000005H。
  •   
     

示例 -

     
      
  • P1Y3M2DT3H表示1年,3个月,2天和3的时间段   小时
  •   
  • PT3H5M表示3小时5分钟的时间段   

非常感谢任何帮助。

谢谢!

更新

我添加了一些必须保留的额外标准 -

  
      
  • 指示符P应存在
  •   
  • 如果是年,月,日,小时,分钟或秒的值   零,值和对应   字符文字指定可能是   省略,但至少有一个字符   字面指示符和值应该是   除指定人外还有礼物   P
  •   
  • 如果所有时间成分(小时,   不使用分钟和秒钟。一个   零值可以与任何一个一起使用   时间成分(例如,PT0S)
  •   

8 个答案:

答案 0 :(得分:5)

这是我使用的正则表达式;

^P(?=\w*\d)(?:\d+Y|Y)?(?:\d+M|M)?(?:\d+D|D)?(?:T(?:\d+H|H)?(?:\d+M|M)?(?:\d+(?:\­.\d{1,2})?S|S)?)?$ 

答案 1 :(得分:1)

使用[0-9]匹配任何数字。 +匹配一次或多次重复。 ?匹配0或1次重​​复。 ()分组并提取输出。

P(([0-9]+Y)?([0-9]+M)?([0-9]+D)?)(T([0-9]+H)?([0-9]+M)?([0-9.]+S)?)?

import re

>>> p = re.compile('P(([0-9]+Y)?([0-9]+M)?([0-9]+D)?)(T([0-9]+H)?([0-9]+M)?([0-9.]+S)?)?')

>>> p.match('P1Y3M2DT3H').groups()
('1Y3M2D', '1Y', '3M', '2D', 'T3H', '3H', None, None)

>>> p.match('P3M2DT3H').groups()
('3M2D', None, '3M', '2D', 'T3H', '3H', None, None)

>>> p.match('PT3H5M').groups()
('', None, None, None, 'T3H5M', '3H', '5M', None)

>>> p.match('P1Y3M4D').groups()
('1Y3M4D', '1Y', '3M', '4D', None, None, None, None)

答案 2 :(得分:1)

JavaScript不支持/x(自由间距或评论模式),因此请在使用前删除此正则表达式中的空格。

/^P(?=.)
 (?:\d+Y)?
 (?:\d+M)?
 (?:\d+D)?
 (?:T(?=.)
    (?:\d+H)?
    (?:\d+M)?
    (?:\d+
       (?:\.\d{1,2})?
    )?
 )?$/i

每个(?=.)前瞻声明在比赛中该点至少有一个角色。这意味着以下组中的至少一个(即,P之后的Y,M,D或T组,以及T之后的H,M或S组)必须匹配,即使它们都是可选的。这满足了更新规范中第二个增加的要求。

答案 3 :(得分:1)

也许它是语义,但SCORM规范的这一部分可以解释为即使没有提供值也允许文字:

  

字符文字指示符P,   如果,则出现Y,M,D,T,H,M和S.   相应的非零值是   本。

“将出现”意味着如果存在相应的数字,则必须存在文字;如果存在相应的数字,它不会说“仅出现”。

我修改了Alan的正则表达式以处理这种可能性(谢谢,Alan):

^P(?:\d+Y|Y)?(?:\d+M|M)?(?:\d+D|D)?(?:T(?:\d+H|H)?(?:\d+M|M)?(?:\d+(?:\.\d{1,2})?S|S)?)?$

到目前为止,我发现的唯一错误是未能标记未指定数值的字符串,例如'PTS'。根据规范的最小值是“P”,后跟单个值和随附的名称,例如P1Y(= 1年)或PT0S(= 1秒):

  

至少一个字符文字   应有指示符和价值   除了指示符P

必须有一种方法可以为这个正则表达式添加一个数值检查,但我的正则表达式并不强大。 :)

答案 4 :(得分:1)

对于它的价值,我已经采用了与Cold Fusion一起使用的已接受答案。我以为有些人可能觉得它很有用,所以我想我会发布它。如上所述,CF轰炸了上面的秒实现,所以我修改了它。我不确定这是否意味着它是上述示例中的一般RegEx错误,或者CF和JS是否有不同的RegEx实现。无论如何,这是CF RegEx,附有评论(因为,你知道,否则正则表达式完全是胡言乱语):

<cfset regex = "(?x) ## allow for multi-line expression, including comments (oh, glorious comments)
            ^ ## ensure that this expression occurs at the start of the string
            P ## the first character must be a P
            (\d+Y|Y)? ## year (the ? indicates 0 or 1 times)
            (\d+M|M)? ## month
            (\d+D|D)? ## day
            (?:T ## T delineates between day and time information
            (\d+H|H)? ## hour
            (\d+M|M)? ## minute
            (\d+(?:\.\d{1,2})?S|S)? ## seconds and milliseconds.  The inner ?: ensure that the sub-sub-expression isn't returned as a separate thing
            )? ## closes 'T' subexpression
            $ ## ensure that this expression occurs at the end of the string.  In conjunction with leading ^, this ensures that the string has no extraenous characters">

之后,你可以像这样对你的字符串运行它:

<cfset result = reFind(regex,mystring,1,true)>

返回一个子表达式数组,您可以迭代它们以获得谨慎的部分:

<cfloop from=1 to=#arrayLen(result.len)# index=i>
    <cfif result.len[i] GT 0>
    #mid(mystring, result.pos[i], result.len[i])#<br>
    </cfif>
</cfloop>

答案 5 :(得分:0)

我们的SCORM Engine实现使用了与上述类似的正则表达式的组合,并且一些基本的JavaScript逻辑确实进行了进一步的验证。

答案 6 :(得分:0)

我正在使用这个表达式:

^P(\d+Y)?(\d+M)?(\d+D)?(T(((\d+H)(\d+M)?(\d+(\.\d{1,2})?S)?)|((\d+M)(\d+(\.\d{1,2})?S)?)|((\d+(\.\d{1,2})?S))))?$

此表达式与“PYMDT0H”之类的值不匹配:指定符号必须与数字匹配。

答案 7 :(得分:0)

基于之前接受的答案,我已经为PCRE制作了这个捕获正则表达式(PHP,ruby,Ecmascript 2018,...):https://regex101.com/r/KfMs1I/6

^P (?=\w*\d) (?:(?<years>\d+)Y|Y)? (?:(?<month>\d+)M|M)? (?:(?<days>\d+)D|D)? (?: T (?:(?<hours>\d+)H|H)? (?:(?<minutes>\d+)M|M)? (?: (?<seconds> \d+ (?: \. \d{1,2} )? )S | S )? )?$

不幸的是我在当前的JS中找不到如何做同样的事情,因为在没有命名组的情况下无法以可靠的方式访问可选组。