1

What is the simplest and correct way to round the time and dateTime in XPath?

For example, how to define a function local:round-time-to-minutes in such way that the following test-case:

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

will return "12:59:00". Don't sure what is better in case of "23:59:31" — to return "00:00:00" or to raise a dynamic error.

And similar function local:round-datetime-to-minutes to handle dateTime? (it doesn't have such edge case as above)

Let these functions use "round half towards positive infinity" rule, where half is 30.0 seconds.

ruvim
  • 7,151
  • 2
  • 27
  • 36
  • I would convert the time to number of minutes since midnight, round that and convert the result back to time. Same with dateTime - see: https://stackoverflow.com/questions/38604414/finding-the-difference-between-two-datetimes-in-xslt – michael.hor257k Nov 15 '18 at 13:20

2 Answers2

2

This is how the solution proposed by @michael.hor257k would look in 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
};
Leo Wörteler
  • 4,191
  • 13
  • 10
0

Another solution is to subtract the number of second from the given dateTime and add one minute (60 seconds) if the number of seconds is not less than 30.

To convert a number of seconds into duration we multiple it on 1S duration (actually, this operation can be eliminated by a compiler).

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) )
};

This solution is uniform for the cases of xs:time and xs:dateTime types.

ruvim
  • 7,151
  • 2
  • 27
  • 36