XQuery/Net 工作日
外观
< XQuery
为了计算许多文档的“有效”年龄,您需要计算它们在各个阶段的实际工作天数。这意味着您需要计算工作日,但不包括周末。您甚至可以排除节假日,以便生成一致的陈旧报告。
由于 NetWorkingDays 是许多系统共用的计算,因此使用 XQuery 模块来存放逻辑是合理的。
module namespace fxx = "http://xquery.wikibooks.org/fxx";
declare function fxx:net-working-days-n($s as xs:date, $f as xs:date, $dates as xs:date*, $total as xs:integer) as xs:integer {
if ($s= $f)
then $total
else if (fxx:weekday($s) and not($s = $dates))
then fxx:net-working-days-n($s + xs:dayTimeDuration('P1D'), $f, $dates,$total + 1)
else fxx:net-working-days-n($s + xs:dayTimeDuration('P1D'), $f, $dates,$total )
};
declare function fxx:net-working-days($s as xs:date, $f as xs:date) as xs:integer {
(: this function returns one less than the number returned from Excel NETWORKDAY :
networkdays($d,$d) should be 0 but it is 1.
networkdays and workday should be inverses and they are not
common practice seems to be to subtract one anyway.
:)
(: assumes $s <= $f :)
fxx:net-working-days-n($s,$f, (), 0)
};
declare function fxx:net-working-days($s as xs:date,$f as xs:date, $dates as xs:date*) as xs:integer {
fxx:net-working-days-n($s,$f, $dates, 0)
};
此计算的核心是一个 NetWorkingDays 算法,它接受两个日期作为参数。
xquery version "1.0";
import module namespace fxx = "http://xquery.wikibook.org/fxx" at "net-working-days.xq";
(: Test driver for Net Working Days
: tags to generate documentation using xqdoc.org scripts at http://www.xqdoc.org/qs_exist.html
:
: @return XHTML table for next "caldays" days from now including working days calculations from today
: @input-parameter: caldays - an integer number of calendar days in the future from now
:
:)
let $cal-days := xs:integer(request:get-parameter("caldays", "30"))
let $now := xs:date(substring(current-date(),1,10))
return
<html>
<body>
<h1>Days from {$now}</h1>
<p>Today is a {fxx:day-of-week-name-en(xs:date(substring(current-date(),1,10)))}</p>
<p>Format: net-working-days.xq?cal-days=50</p>
<table border="1">
<thead>
<tr>
<th>Cal Days</th>
<th>Future Date</th>
<th>Day of Week</th>
<th>Net Working Days</th>
</tr>
</thead>
{
for $i in (0 to $cal-days)
let $d := $now + xs:dayTimeDuration(concat('P',$i,'D'))
let $dow := fxx:day-of-week($d)
return
<tr>
<td align="center">{$i}</td>
<td align="center">{$d}</td>
<td align="center">{fxx:day-of-week-name-en(xs:date(substring($d,1,10)))}</td>
<td align="center">{fxx:net-working-days(xs:date(substring(current-date(),1,10)),$d)}</td>
</tr>
}
</table>
<br/>
<a href="index.xhtml">Back to Unit Testing Main Menu</a>
<br/>
<a href="../../index.xhtml">Back to CRV Main Menu</a>
</body>
</html>
递归函数有效,但速度很慢。它必须对两个日期之间的每个日期调用自身一次。另一种方法是计算每个星期部分的结束天数,计算周数并乘以 5。
代码??
该内容最初由 Chris Wallace 提供。