是否有一个等效于oracle add_months()的XQuery

时间:2019-06-12 12:06:07

标签: sql xquery

Oracle(SQL)函数add_months()将月份添加到日期中,但是如果日期在每月的最后一天,则也要考虑在内。 2019-02-28的YYYY-MM-DD将在2019-05-31中产生add_months(3)

https://www.oracletutorial.com/oracle-date-functions/oracle-add_months/

我要将相同的功能移植到xquery,并且我已经了解了functx:add-months(date, int)functx:last-day-of-month(date)

我想我可以在2种功能之外实现自己的功能,但是这里有一个更大的算法在工作,所以我更喜欢已经通过测试和工作的方式提供的功能以及可靠的官方功能...

长话短说,这是已经在我不知道的函数库中伪造的,还是我必须自己做??

2 个答案:

答案 0 :(得分:1)

“ +”运算符允许您将yearMonthDuration添加到日期。例如

xs:date('2019-02-28') + xs:yearMonthDuration('P3M')

我不知道语义是否与Oracle SQL函数完全相同。它们在https://www.w3.org/TR/xpath-functions-31/#func-add-dayTimeDuration-to-date

处给出

LATER

Oracle函数似乎对月份的最后一天进行特殊处理,因此在月份的最后一天加上或减去月份会得出不同月份的最后一天。

W3C算法(通过引用https://www.w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes定义)做了不同的工作:它会调整(年,月,日)的年和月数字,如果结果天超出了范围,结果月份,将其固定到该月的最后一天。

您应该能够使用用户定义的函数重现Oracle函数的行为。这可能会调用几个辅助函数:

function d:is-last-day-of-month($date as xs:date) as xs:boolean {
  month-from-date($date) != month-from-date($date + xs:dayTimeDuration('P1D')
}

function d:last-date-in-month($date as xs:date) as xs:date {
  if (d:is-last-day-of-month($date))
  then $date
  else d:last-date-in-month($date + xs:dayTimeDuration('P1D'))
}

function d:add-months($date as xs:date, $months as xs:integer) {
  if (d:is-last-day-of-month($date))
  then d:last-date-in-month($date + $months * xs:dayTimeDuration('P1M'))
  else $date + $months * xs:dayTimeDuration('P1M')
}

答案 1 :(得分:0)

好吧,我想用下面的自定义函数(现在在算法中使用它)代替了官方的xquery-> functx:add-months(date,int)

declare function local:addMonths($input as xs:date?, $amount as xs:integer?)
as xs:date?
{
  let $outputN := functx:add-months($input,$amount)
  let $outputLD := functx:last-day-of-month(functx:add-months($input,$amount))
  return if($input = functx:last-day-of-month($input)) then $outputLD else $outputN
};

需要更多的测试,因为这些修改背后的整个算法要困难得多,但是第一次运行看起来不错

整个算法的目的是通过移动日期(例如)来更改.xml中的日期属性。 date =“ 2018-11-28”(通常)未来3个月

日期应该相对于来源保持不变,这意味着将“ 2018-11-28” 向前移动3个月会导致:

“ 2019-02-26” (每月最后一天的前2天!)