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 提供。