X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?p=CreaPhase.git;a=blobdiff_plain;f=octave_packages%2Ffinancial-0.4.0%2Fnweekdate.m;fp=octave_packages%2Ffinancial-0.4.0%2Fnweekdate.m;h=28b86ed367b8a912640af950dd1f3cd8c8367dde;hp=0000000000000000000000000000000000000000;hb=f5f7a74bd8a4900f0b797da6783be80e11a68d86;hpb=1705066eceaaea976f010f669ce8e972f3734b05 diff --git a/octave_packages/financial-0.4.0/nweekdate.m b/octave_packages/financial-0.4.0/nweekdate.m new file mode 100644 index 0000000..28b86ed --- /dev/null +++ b/octave_packages/financial-0.4.0/nweekdate.m @@ -0,0 +1,152 @@ +## Copyright (C) 2008 Bill Denney +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {last =} nweekdate (n, weekday, year, month, nextday) +## +## Returns the @var{n}th occurrence of @var{weekday} from the +## @var{month} and @var{year}. If the optional @var{nextday} argument +## is given, then the week must also contain @var{nextday}. If @var{n} +## is greater than the number of occurrences of that day in the month, 0 +## is returned. +## +## @seealso{eomdate, lweekdate, weekday} +## @end deftypefn + +function t = nweekdate (varargin) + if nargin < 4 || nargin > 5 + error ("4 or 5 input arguments are required") + elseif nargin == 4 + varargin{5} = 0; + endif + + ## special handling so that most of this code will not need to be + ## duplicated in lweekdate + do_lweekdate = is_lweekdate(varargin{1}); + if do_lweekdate + varargin{1} = 1; + endif + + scale = cellfun (@numel, varargin); + if ~ all (scale == 1 | scale == max(scale)); + error("All inputs must be either scalars or have the same number of elements"); + else + ## make sure that the sizes are the same for any non-scalar inputs + ind = find (scale > 1); + if length(ind) > 1 + for i = 2:length (ind) + if ndims (varargin{ind(1)}) ~= ndims (varargin{ind(i)}) + error("Mismatching dimensions on inputs %d and %d", ind(1), ind(i)); + elseif ~ all (size (varargin{ind(1)}) == size (varargin{ind(i)})) + error("The sizes of inputs %d and %d do not match", ind(1), ind(i)); + endif + endfor + endif + endif + + if max(scale) > 1 + t = zeros (size (varargin{ind(1)})); + for i = 1:numel (varargin{ind(1)}) + args = cell(5,1); + for j = 1:5 + if isscalar (varargin{j}) + args{j} = varargin{j}; + else + args{j} = varargin{j}(i); + endif + endfor + if do_lweekdate + args{1} = "lweekdate"; + end + t(i) = nweekdate (args{:}); + endfor + else + ## Do the real work. + n = varargin{1}; + wd = varargin{2}; + y = varargin{3}; + mon = varargin{4}; + nextday = varargin{5}; + + ## Find the day of the week for the last day of the mon. + doml = eomday (y, mon); + dowl = weekday (datenum (y, mon, doml)); + ## Make sure that the day is in the weeks for the last then the + ## first week. + if (wd < nextday) || (dowl < wd) + ## adjust the last day + adjust = 7; + else + adjust = 0; + endif + dom = sort((doml - dowl + wd - adjust):-7:1); + if nextday && (dom(1) <= wd - nextday) + # adjust the first day + dom(1) = []; + endif + if do_lweekdate + t = datenum (y, mon, dom(end)); + elseif n > length(dom) + t = 0; + else + t = datenum (y, mon, dom(n)); + end + endif + +endfunction + +function v = is_lweekdate(v) + if ischar(v) + if strcmp (v, "lweekdate") + v = true(); + else + error("Invalid input for n") + endif + else + v = false(); + endif +endfunction + +# Tests for all calling options +# Find the first Wednesday in Jan 2008 +%!assert(nweekdate(1, 4, 2008, 1), datenum(2008, 1, 2)) +# Find the second Wednesday in Jan 2008 +%!assert(nweekdate(2, 4, 2008, 1), datenum(2008, 1, 9)) +# Find the third Wednesday in Jan 2008 +%!assert(nweekdate(3, 4, 2008, 1), datenum(2008, 1, 16)) +# Find the fourth Wednesday in Jan 2008 +%!assert(nweekdate(4, 4, 2008, 1), datenum(2008, 1, 23)) +# Find the fifth Wednesday in Jan 2008 +%!assert(nweekdate(5, 4, 2008, 1), datenum(2008, 1, 30)) +# Find the sixth Wednesday in Jan 2008, it doesn't exist, so return 0 +%!assert(nweekdate(6, 4, 2008, 1), 0) +# Find the fifth Friday in Jan 2008, it doesn't exist, so return 0 +%!assert(nweekdate(5, 6, 2008, 1), 0) +# Find the first Wednesday in Jan 2008 in the same week as a Monday +# WARNING: it is unclear from the Matlab docs if this should work or if +# this should be called the second Wednesday in Jan 2008. +%!assert(nweekdate(1, 4, 2008, 1, 2), datenum(2008, 1, 9)) +# Find the fifth Wednesday in Jan 2008 in the same week as a Friday. +# It doesn't exist, so return 0 +%!assert(nweekdate(5, 4, 2008, 1, 6), 0) +# Try vector arguments +%!assert(nweekdate(1:6, 4, 2008, 1, 6), [datenum(2008, 1, 2:7:23), 0, 0]) + +# Try the lweekdate operation of this function: +# Find the last Wednesday in Jan 2008 +%!assert(nweekdate('lweekdate', 4, 2008, 1), datenum(2008, 1, 30)) +# Find the last Wednesday in Jan 2008 with a Friday +%!assert(nweekdate('lweekdate', 4, 2008, 1, 6), datenum(2008, 1, 23)) +