Xpath 中的循环时间

Round time in Xpath

在 XPath 中舍入时间和日期时间的最简单和正确的方法是什么?

例如,如何定义一个函数 local:round-time-to-minutes 使得下面的测试用例:

let $t1 := xs:time( "12:58:37" )
let $t2 := local:round-time-to-minutes( $t1 )
return format-time( $t2, '[H01]:[m01]:[s01]' )

将 return "12:59:00"。 不确定在“23:59:31”的情况下什么更好——return“00:00:00”或引发动态错误。

和处理日期时间的类似函数local:round-datetime-to-minutes? (它没有像上面这样的边缘情况)

让这些函数使用 "round half towards positive infinity" 规则,其中一半是 30.0 秒。

这是@michael.hor257k 提出的解决方案在 XQuery 中的样子:

declare variable $ONE_MIN := xs:dayTimeDuration("PT1M");
declare variable $MIDNIGHT := xs:time("00:00:00");

declare function local:round-time-to-minutes($time) {
  $MIDNIGHT + round(($time - $MIDNIGHT) div $ONE_MIN) * $ONE_MIN
};

另一种解决方案是从给定的日期时间中减去秒数,如果秒数不小于 30,则增加一分钟(60 秒)。

为了将秒数转换为持续时间,我们将其乘以 1S 持续时间(实际上,编译器可以消除此操作)。

declare function local:round-time-to-minutes ( $time as xs:time ) {
  let $s := seconds-from-time( $time )
  return $time - xs:dayTimeDuration('PT1S') * ( $s - 60 * ($s idiv 30) )
};

declare function local:round-dateTime-to-minutes ( $dt as xs:dateTime ) {
  let $s := seconds-from-dateTime( $dt )
  return $dt - xs:dayTimeDuration('PT1S') * ( $s - 60 * ($s idiv 30) )
};

此解决方案对于 xs:timexs:dateTime 类型的情况是统一的。