From: <car...@us...> - 2012-04-17 14:04:40
|
Revision: 10264 http://octave.svn.sourceforge.net/octave/?rev=10264&view=rev Author: carandraug Date: 2012-04-17 14:04:28 +0000 (Tue, 17 Apr 2012) Log Message: ----------- financial/time: moved the rest of time package into financial. Time package is now a dummy package, transitional, only listing the financial package as dependency. Updated NEWS file of both packages and deprecated datesplit. Modified Paths: -------------- trunk/octave-forge/main/financial/DESCRIPTION trunk/octave-forge/main/time/DESCRIPTION trunk/octave-forge/main/time/NEWS Added Paths: ----------- trunk/octave-forge/main/financial/INDEX trunk/octave-forge/main/financial/NEWS trunk/octave-forge/main/financial/inst/datesplit.m trunk/octave-forge/main/financial/inst/easter.m Removed Paths: ------------- trunk/octave-forge/main/time/inst/datesplit.m trunk/octave-forge/main/time/inst/easter.m Modified: trunk/octave-forge/main/financial/DESCRIPTION =================================================================== --- trunk/octave-forge/main/financial/DESCRIPTION 2012-04-17 13:33:51 UTC (rev 10263) +++ trunk/octave-forge/main/financial/DESCRIPTION 2012-04-17 14:04:28 UTC (rev 10264) @@ -2,11 +2,11 @@ Version: 0.3.2 Date: 2008-08-17 Author: Bill Denney <bi...@de...>, Kurt Hornik <Kur...@wu...> -Maintainer: Octave Community +Maintainer: Octave-Forge community <oct...@li...> Title: Financial -Description: Financial manipulation and plotting functions -Categories: Financial -Depends: octave (>= 3.0.0), time (>= 1.0.5), miscellaneous (>= 1.0.6) -Autoload: yes +Description: Financial manipulation, plotting functions and additional + date manipulation tools. +Depends: octave (>= 3.0.1), miscellaneous (>= 1.0.6) +Autoload: no License: GPL version 3 and GPL version 2 or later Url: http://octave.sf.net Added: trunk/octave-forge/main/financial/INDEX =================================================================== --- trunk/octave-forge/main/financial/INDEX (rev 0) +++ trunk/octave-forge/main/financial/INDEX 2012-04-17 14:04:28 UTC (rev 10264) @@ -0,0 +1,61 @@ +financial >> Financial +Financial + cfconv + cfdur + corr2cov + cov2corr + effrr + fetch + fvl + fv + google + hhigh + irr + llow + mirr + movavg + negvolidx + nomrr + nper + npv + onbalvol + pmt + posvolidx + pvl + pv + rate + rsindex + taxedrr + vol + yahoo +Plot + bolling + dateaxis + highlow + pointfig +Time + busdate + busdays + datefind + datesplit + day + daysact + easter + eomdate + fbusdate + holidays + hour + isbusday + lbusdate + lweekdate + m2xdate + minute + month + months + nweekdate + second + thirdwednesday + today + x2mdate + yeardays + year Added: trunk/octave-forge/main/financial/NEWS =================================================================== --- trunk/octave-forge/main/financial/NEWS (rev 0) +++ trunk/octave-forge/main/financial/NEWS 2012-04-17 14:04:28 UTC (rev 10264) @@ -0,0 +1,37 @@ +Summary of important user-visible changes for financial 0.4.0: +------------------------------------------------------------------- + + ** The following functions are new at financial 0.4.0: + + cfconv cfdur corr2cov cov2corr + + ** The following functions have been imported from the time package + which has been removed (it is now simply a dummy package that + lists the financial package as its single dependency): + + busdate busdays datefind datesplit + day daysact easter eomdate + fbusdate holidays hour isbusday + lbusdate lweekdate m2xdate minute + month months nweekdate second + thirdwednesday today x2mdate year + yeardays + + ** The following functions were made private (`fetch' should be used + directly instead): + + __fetch_google__ __fetch_yahoo__ + + ** The function `datesplit' (just imported from the time package) has + been deprecated in favour of `datevec' from Octave-core. + + ** The functions `rate' and `irr' should now be compatible with new + releases of octave. + + ** The function `fetch' should now work properly when using google + finnance to adapt to the UTF-8 file received. + + ** The function `dateaxis' should no longer enter in debug mode at the + end of its call. + + ** Package is no longer automatically loaded. Copied: trunk/octave-forge/main/financial/inst/datesplit.m (from rev 10262, trunk/octave-forge/main/time/inst/datesplit.m) =================================================================== --- trunk/octave-forge/main/financial/inst/datesplit.m (rev 0) +++ trunk/octave-forge/main/financial/inst/datesplit.m 2012-04-17 14:04:28 UTC (rev 10264) @@ -0,0 +1,492 @@ +## Copyright (C) 2001 Bill Denney <bi...@de...> +## +## 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 <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {Y =} datesplit(date, P) +## @deftypefnx {Function File} {[Y,M,D,h,m,s] =} datesplit(date, P) +## Split a date string into the Year, Month, Day, hour, minute, and +## second. This routine tries to be as forgiving as possible to the +## date input while requiring that the date is not ambiguous. +## +## Anywhere possible where it would not be ambiguous, efforts were made +## to make times possible with seconds and AM/PM as optional. Also, +## along the same lines, where possible, commas were allowed with +## spaces, and the year/month/day separators were allowed as period (.), +## slash (/), and dash (-). Not all format possibilities are shown in +## the following table, but a date like @code{dd-mmm-yyyy HH:MM:SS} is +## parsed just as well as @code{d/mmm.yyyy, ,H:MM, AM}. +## +## Supported @code{date} formats include (the same as datestr): +## @multitable @columnfractions 0.1 0.45 0.45 +## @item @strong{Code} @tab @strong{Format} @tab @strong{Example} +## @item 0 @tab dd-mmm-yyyy HH:MM:SS @tab 07-Sep-2000 15:38:09 +## @item 1 @tab dd-mmm-yyyy @tab 07-Sep-2000 +## @item 2 @tab mm/dd/yy @tab 09/07/00 +## @item 3 @tab mmm @tab Sep +## @item 6 @tab mm/dd @tab 09/13 +## @item 10 @tab yyyy @tab 2000 +## @item 12 @tab mmmyy @tab Sep00 +## @item 13 @tab HH:MM:SS @tab 15:38:09 +## @item 14 @tab HH:MM:SS PM @tab 03:38:09 PM +## @item 15 @tab HH:MM @tab 15:38 +## @item 16 @tab HH:MM PM @tab 03:38 PM +## @item 17 @tab QQ-YY @tab Q3-00 +## @item 19 @tab dd/mm @tab 13/03 +## @item 20 @tab dd/mm/yy @tab 13/03/95 +## @item 21 @tab mmm.dd.yyyy HH:MM:SS @tab Mar.03.1962 13:53:06 +## @item 22 @tab mmm.dd.yyyy @tab Mar.03.1962 +## @item 23 @tab mm/dd/yyyy @tab 03/13/1962 +## @item 24 @tab dd/mm/yyyy @tab 12/03/1962 +## @item 25 @tab yy/mm/dd @tab 95/03/13 +## @item 26 @tab yyyy/mm/dd @tab 1995/03/13 +## @item 27 @tab QQ-YYYY @tab Q4-2132 +## @item 28 @tab mmmyyyy @tab Mar2047 +## @item 29 @tab yyyymmdd @tab 20470313 +## @item 30 @tab yyyymmddTHHMMSS @tab 20470313T132603 +## @item 31 @tab yyyy-mm-dd HH:MM:SS @tab 1047-03-13 13:26:03 +## @end multitable +## +## The parameter @code{P} is needed to convert date strings with 2 digit +## years into dates with 4 digit years. 2 digit years are assumed to be +## between @code{P} and @code{P+99}. If @code{P} is not given then the +## current year - 50 is used, so that dates are centered on the present. +## For birthdates, you would want @code{P} to be current year - 99. For +## appointments, you would want @code{P} to be current year. +## +## This function makes no strong attempt to verify the accuracy of the +## numbers that it returns in that it doesn't (currently) check to see +## that you're not trying to use the date Feb 30. When applicable, it +## tries to make your input work, though. It will try to determine if +## you're using the date "03/13/95" that the date is "March 13, 1995", +## but if there is doubt, datesplit will return an error instead of +## trying to guess the wrong value. +## +## @seealso{date,clock,now,datestr,datenum,calendar,weekday} +## @end deftypefn + +## TODO: +## * Some formats are ambiguous. Allow the user to specify the format +## to remove ambiguity. +## * Validate the dates. +## * Possible bug (after dates are validated): There are times where +## the year is assumed, Feb 29 may be a valid date, but with the +## assumed year, it may become invalid. +## * Internationalize. Not all months use the English system. +## * Vectorize. That requires vectorization of regexp though... + +function [y, m, d, h, mi, s] = datesplit(ds, P) + + persistent warned = false; + if (! warned) + warned = true; + warning ("Octave:deprecated-function", + "`datesplit' has been deprecated in favor of `datevec' from Octave core. This function will be removed from future versions of the `financial' package"); + endif + + if nargin < 2 + P = []; + endif + + today = datevec(now); + + if (isempty(P)) + P = today(1)-50; + endif + + global __month_names = ["Jan";"Feb";"Mar";"Apr";"May";"Jun";... + "Jul";"Aug";"Sep";"Oct";"Nov";"Dec"]; + global __day_names = ["Sun";"Mon";"Tue";"Wed";"Thu";"Fri";"Sat"]; + global __time_names = ["AM";"PM"]; + + if (iscellstr(ds)) + ds = ds{1}; + endif + ds = tolower(deblank(ds)); + + if (nargin < 1) + error("datesplit: no input arguments"); + elseif (nargin == 1) + fmt = []; + endif + %% we have to determine the format, this could be error prone + + ## format 0 dd-mmm-yyyy HH:MM:SS e.g. 07-Sep-2000 15:38:09 + [match, d, m, y, h, mi, s, ap] = \ + of_regexp("^(3[01]|[0-2]?[0-9])[-./]([a-z]{3})[-./]([0-9]{4})[, ]+(2[0-3]|[01]?[0-9]):([0-5][0-9])(:[0-5][0-9]|)[, ]*([ap]m|)$", ds); + + ## format 21 mmm.dd.yyyy HH:MM:SS e.g. Mar.03.1962 13:53:06 + if (isempty(match)) + [match, m, d, y, h, mi, s, ap] = \ + of_regexp("^([a-z]{3})[-./](3[01]|[0-2]?[0-9])[-./]([0-9]{4})[, ]+(2[0-3]|[01]?[0-9]):([0-5][0-9])(:[0-5][0-9]|)[, ]*([ap]m|)$", ds); + endif + + ## format 31 yyyy-mm-dd HH:MM:SS e.g. 2004-03-13 13:26:03 + if (isempty(match)) + [match, y, m, d, h, mi, s, ap] = \ + of_regexp("^([0-9]{4})[-./](1[012]|0?[0-9])[-./](3[01]|[0-2]?[0-9])[, ]+(2[0-3]|[01]?[0-9]):([0-5][0-9])(:[0-5][0-9]|)[, ]*([ap]m|)$", ds); + endif + + ## format 30 yyyymmddTHHMMSS e.g. 20470313T132603 + if (isempty(match)) + [match, y, m, d, h, mi, s] = \ + of_regexp("^([0-9]{4})(1[012]|0[0-9])(3[01]|[012][0-9])t(2[0-3]|[01][0-9])([0-5][0-9])([0-5][0-9])$", ds); + ap = "NA"; + endif + + ## format 13 HH:MM:SS e.g. 15:38:09 + ## format 14 HH:MM:SS PM e.g. 03:38:09 PM + ## format 15 HH:MM e.g. 15:38 + ## format 16 HH:MM PM e.g. 03:38 PM + if (isempty(match)) + [match, h, mi, s, ap] = \ + of_regexp("^(2[0-3]|[01]?[0-9]):([0-5][0-9])(:[0-5][0-9]|)[, ]*([ap]m|)$", ds); + + if (! isempty(match)) + %% assume that it is as of today + y = today(1); + m = today(2); + d = today(3); + endif + endif + + ## format 1 dd-mmm-yyyy e.g. 07-Sep-2000 + if (isempty(match)) + [match, d, m, y] = \ + of_regexp("^(3[01]|[012]?[0-9])[-./]([a-z]{3})[-./]([0-9]{4})$", ds); + + if (! isempty(match)) + %% assume the beginning of the day + h = 0; + mi = 0; + s = 0; + ap = "NA"; + endif + endif + + ## format 22 mmm.dd.yyyy e.g. Mar.03.1962 + if (isempty(match)) + [match, m, d, y] = \ + of_regexp("^([a-z]{3})[-./](3[01]|[012]?[0-9])[-./]([0-9]{4})$", ds); + + if (! isempty(match)) + %% assume the beginning of the day + h = 0; + mi = 0; + s = 0; + ap = "NA"; + endif + endif + + ## format 2 mm/dd/yy e.g. 09/07/00 + ## format 23 mm/dd/yyyy e.g. 03/13/1962 + ## format 20 dd/mm/yy e.g. 13/03/95 + ## format 24 dd/mm/yyyy e.g. 12/03/1962 + ## format 25 yy/mm/dd e.g. 95/03/13 + ## format 26 yyyy/mm/dd e.g. 1995/03/13 + if (isempty(match)) + [match, d, m, y] = \ + of_regexp("^([0-9]{1,2}|[0-9]{4})[-./](3[01]|[012]?[0-9])[-./]([0-9]{1,2}|[0-9]{4})$", ds); + + if (! isempty(match)) + %% we have to determine if the date is unambiguous + d = str2num(d); + m = str2num(m); + y = str2num(y); + + if ((y == 0) || (y > 31)) + %% we've got the year correct + if ((m > 12) && (d < 13)) + %% we're operating on mm/dd/yyyy + tmp = m; + m = d; + d = tmp; + elseif ((m < 13) && (d > 12)) + %% it's fine + else + %% it's ambiguous + error(["datesplit: ambiguous date " ds]); + endif + elseif ((d == 0) || (d > 31)) + %% the day and the year need to be switched + tmp = y; + y = d; + d = tmp; + else + %% it's ambiguous + error(["datesplit: ambiguous date " ds]); + endif + + %% assume the beginning of the day + h = 0; + mi = 0; + s = 0; + ap = "NA"; + endif + + endif + + ## format 29 yyyymmdd e.g. 20470313 + if (isempty(match)) + [match, y, m, d] = \ + of_regexp("^([0-9]{4})(1[012]|0?[0-9])(3[01]|[012][0-9])$", ds); + %% I've never seen a date that has the year first that was not + %% yyyy/mm/dd, so I'm going to assume that it's unambiguous. + + if (! isempty(match)) + %% assume the beginning of the day + h = 0; + mi = 0; + s = 0; + ap = "NA"; + endif + endif + + ## format 17 QQ-YY e.g. Q3-00 + ## format 27 QQ-YYYY e.g. Q4-2132 + if (isempty(match)) + [match, q, y] = \ + of_regexp("^q([1-4])[-./]([0-9]{2}|[0-9]{4})$", ds); + if (! isempty(match)) + %% Assume that it's the end of the quarter + q = str2num(q); + m = 3*q; + dayopts = [31 30 30 31]; + d = dayopts(q); + + %% assume the end of the day + h = 23; + mi = 59; + s = 59; + ap = "NA"; + endif + endif + + ## format 28 mmmyyyy e.g. Mar2047 + ## format 12 mmmyy e.g. Sep00 + if (isempty(match)) + [match, m, y] = \ + of_regexp("^([a-z]{3})([0-9]{2}|[0-9]{4})$", ds); + if (! isempty(match)) + %% assume the beginning of the month + d = 1; + h = 0; + mi = 0; + s = 0; + ap = "NA"; + endif + endif + + ## format 6 mm/dd e.g. 09/07 + ## format 19 dd/mm e.g. 13/03 + if (isempty(match)) + [match, m, d] = \ + of_regexp("^(3[01]|[012]?[0-9])[-./](3[01]|[012][0-9])$", ds); + + if (! isempty(match)) + m = str2num(m); + d = str2num(d); + + %% we have to determine if the date is unambiguous + if ((m > 12) && (d < 13)) + %% we're operating on mm/dd/yyyy + tmp = m; + m = d; + d = tmp; + elseif ((m < 13) && (d > 12)) + %% it's fine + else + %% it's ambiguous + error(["datesplit: ambiguous date " ds]); + endif + %% assume this year and the beginning of the day + y = today(1); + h = 0; + mi = 0; + s = 0; + ap = "NA"; + endif + endif + + ## format 10 yyyy e.g. 2000 + if (isempty(match)) + [match, y] = of_regexp("^([0-9]{4})$", ds); + + if (! isempty(match)) + %% assume the beginning of the year + m = 1; + d = 1; + h = 0; + mi = 0; + s = 0; + ap = "NA"; + endif + endif + + ## format 3 mmm e.g. Sep + if (isempty(match)) + m = strmatch(ds, tolower(__month_names)); + + if (! isempty(m)) + match = 1; + %% assuming the beginning of the month, this year + y = today(1); + d = 1; + h = 0; + mi = 0; + s = 0; + ap = "NA"; + endif + endif + + ## format 8 ddd e.g. Thu + %% People shouldn't use this function for something like this + + if (isempty(match)) + %% you mean I did all that work, and you still didn't use a valid + %% date? Darn you! + error(["datesplit: Unknown date format " ds]); + endif + + if (! isempty(match)) + if isempty(s) + s = 0; + elseif (ischar(s) && (1 == findstr(s,":"))) + s = s(2:3); + endif + if isempty(ap) + ap = "NA"; + endif + endif + + %% start converting the date from characters to numbers + if (ischar(y)) + y = str2num(y); + if (isempty(y)) + error(["datesplit: Invalid year specification " y]); + endif + endif + %% Handle Y2K issues... + if (y < 100) + y = y + 1900; + if (y < P) + y = y + 100; + endif + endif + + if (ischar(m)) + m_num = str2num(m); + if (isempty(m_num)) + m = strmatch(m, tolower(__month_names)); + else + m = m_num; + endif + if (isempty(m)) + error(["datesplit: Invalid month specification"]); + endif + endif + + if (ischar(d)) + d = str2num(d); + if (isempty(d)) + error(["datesplit: Invalid day specification " d]); + endif + endif + + if (ischar(h)) + h = str2num(h); + if (isempty(h)) + error(["datesplit: Invalid hour specification " h]); + elseif ((ap(2) == "M") && (h > 12)) + error(["datesplit: Invalid hour specification, AM or PM specified but" + "hour is greater than 12."]); + endif + + if (strcmpi(ap, "PM") && (h < 12)) + h = h + 12; + elseif (strcmpi(ap, "AM") && (h == 12)) + h = 0; + endif + endif + + if (ischar(mi)) + mi = str2num(mi); + if (isempty(mi) || (mi > 59)) + error(["datesplit: Invalid minute specification " mi]); + endif + endif + + if (ischar(s)) + s = str2num(s); + if (isempty(s) || (s > 59)) + error(["datesplit: Invalid second specification " s]); + endif + endif + + if (nargout <= 1) + y = [y, m, d, h, mi, s]; + endif + +endfunction + +# wrapper around Octave's regexp +# compatible with octave-forge's regexp + +function varargout = of_regexp(pattern,string) + [S, E, TE, M, T, NM] = regexp(string,pattern); + varargout{1} = S; + + # return sub-strings if match + if (S) + for i=2:nargout + varargout{i} = T{1}{i-1}; + end + else + for i=2:nargout + varargout{i} = []; + end + end +endfunction + + +%!shared nowvec +%! nowvec=datevec(now); % Some tests could fail around midnight! +%!assert (datevec("07-Sep-2000 15:38:09"),[2000,9,7,15,38,9]); +%!assert (datevec("07-Sep-2000"),[2000,9,7,0,0,0]); +%!assert (datevec("1 Jan 2000"),[2000,1,1,0,0,0]); +%!assert (datevec("Sep00"),[2000,9,1,0,0,0]); +%!assert (datevec("15:38:09"),[nowvec(1:3),15,38,9]); +%!assert (datevec("03:38:09 PM"),[nowvec(1:3),15,38,9]); +%!assert (datevec("15:38"),[nowvec(1:3),15,38,0]); +%!assert (datevec("3:38 PM"),[nowvec(1:3),15,38,0]); +%!assert (datevec("03/13/1962"),[1962,3,13,0,0,0]); + +## Ambiguous +%!#assert (datevec("09/07/00"),[2000,9,7,0,0,0]); +%!#assert (datevec("09/13"),[nowvec(1),9,13,0,0,0]); + +## Not supported in octave version of datevec +%!#assert (datevec("Sep"),[nowvec(1),9,1,0,0,0]); +%!#assert (datevec("Q3-00"),[2000,9,30,23,59,59]); +%!#assert (datevec("Q4-2132"),[2132,12,31,23,59,59]); + +## This should be a standard string (without or without the time) +%!assert (datevec("Mar.03.1962 13:53:06","mmm.dd.yyyy HH:MM:SS"),[1962,3,3,13,53,6]); + +## No longer a predefined string to parse the date in octave version +%!assert (datevec("1995/03/13","yyyy/mm/dd"),[1995,3,13,0,0,0]); +%!assert (datevec("Mar2047","mmmyyyy"),[2047,3,1,0,0,0]); +%!assert (datevec("20470313","yyyymmdd"),[2047,3,13,0,0,0]); +%!assert (datevec("20470313T132603","yyyymmddTHHMMSS"),[2047,3,13,13,26,3]); +%!assert (datevec("1047-03-13 13:26:03","yyyy-mm-dd HH:MM:SS"),[1047,3,13,13,26,3]); Copied: trunk/octave-forge/main/financial/inst/easter.m (from rev 10262, trunk/octave-forge/main/time/inst/easter.m) =================================================================== --- trunk/octave-forge/main/financial/inst/easter.m (rev 0) +++ trunk/octave-forge/main/financial/inst/easter.m 2012-04-17 14:04:28 UTC (rev 10264) @@ -0,0 +1,69 @@ +## Copyright (C) 2008 Bill Denney <bi...@de...> +## +## 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 <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {[m, d] =} easter (y) +## @deftypefnx {Function File} {datenum =} easter (y) +## +## Return the month (@var{m}) and day (@var{d}) of Easter in the +## Gregorial calendar on a given year or years. +## +## @seealso{holidays} +## @end deftypefn + +function varargout = easter (y) + + ## This uses the Meesus/Jones/Butcher Gregorian algorithm as described + ## on http://en.wikipedia.org/wiki/Computus#Algorithms + a = mod (y, 19); + b = floor (y/100); + c = mod (y, 100); + d = floor (b/4); + e = mod (b, 4); + f = floor ((b + 8)/25); + g = floor ((b - f + 1)/3); + h = mod ((19*a+b-d-g+15), 30); + i = floor (c/4); + k = mod (c, 4); + L = mod ((32 + 2*e + 2*i - h - k), 7); + m = floor ((a + 11*h + 22*L)/451); + mon = floor ((h + L - 7*m + 114)/31); + day = 1 + mod ((h + L - 7*m + 114), 31); + + if nargout == 2 + varargout = {mon(:), day(:)}; + else + varargout{1} = reshape (datenum (y(:), mon(:), day(:)), size (y)); + end + +endfunction + +## Tests +## Validate that it calculates the correct date for a decade +%!assert(easter(1990), datenum(1990, 4, 15)) +%!assert(easter(1991), datenum(1991, 3, 31)) +%!assert(easter(1992), datenum(1992, 4, 19)) +%!assert(easter(1993), datenum(1993, 4, 11)) +%!assert(easter(1994), datenum(1994, 4, 3)) +%!assert(easter(1995), datenum(1995, 4, 16)) +%!assert(easter(1996), datenum(1996, 4, 7)) +%!assert(easter(1997), datenum(1997, 3, 30)) +%!assert(easter(1998), datenum(1998, 4, 12)) +%!assert(easter(1999), datenum(1999, 4, 4)) +## Validate vector and matrix inputs +%!assert(easter([2000 2001]), [datenum(2000, 4, 23) datenum(2001, 4, 15)]) +%!assert(easter([2002;2003]), [datenum(2002, 3, 31);datenum(2003, 4, 20)]) +%!assert(easter([2004 2005;2006 2007;2008 2009]), [datenum(2004, 4, 11) datenum(2005, 3, 27);datenum(2006, 4, 16) datenum(2007, 4, 8);datenum(2008, 3, 23) datenum(2009, 4, 12)]) +%!assert(easter([2002;2003]), [datenum(2002, 3, 31);datenum(2003, 4, 20)]) Modified: trunk/octave-forge/main/time/DESCRIPTION =================================================================== --- trunk/octave-forge/main/time/DESCRIPTION 2012-04-17 13:33:51 UTC (rev 10263) +++ trunk/octave-forge/main/time/DESCRIPTION 2012-04-17 14:04:28 UTC (rev 10264) @@ -4,9 +4,10 @@ Author: Bill Denney <bi...@de...> Maintainer: Octave-Forge community <oct...@li...> Title: Time and Dates -Description: Additional date manipulation tools. +Description: Additional date manipulation tools. This a dummy package + as transition for the financial package. Categories: Time -Depends: octave (>= 3.0.1) +Depends: financial (>= 0.4.0) Autoload: no License: GPLv3+ Url: http://octave.sf.net Modified: trunk/octave-forge/main/time/NEWS =================================================================== --- trunk/octave-forge/main/time/NEWS 2012-04-17 13:33:51 UTC (rev 10263) +++ trunk/octave-forge/main/time/NEWS 2012-04-17 14:04:28 UTC (rev 10264) @@ -1,5 +1,13 @@ Summary of important user-visible changes for time 2.0.0: ------------------------------------------------------------------- + ** VERY IMPORTANT: the time package has been removed. All its functions + have been moved to the financial package (23 of its 25 functions are + part of Matlab's financial toolbox). To avoid transition problems, this + new release is merely a dummy package with no functions, and dependent + on the new version of the financial package. + + ** The function `datesplit' (now part of the financial package) has been + deprecated in favour of `datevec' from Octave-core. + ** Package is no longer automatically loaded. - Deleted: trunk/octave-forge/main/time/inst/datesplit.m =================================================================== --- trunk/octave-forge/main/time/inst/datesplit.m 2012-04-17 13:33:51 UTC (rev 10263) +++ trunk/octave-forge/main/time/inst/datesplit.m 2012-04-17 14:04:28 UTC (rev 10264) @@ -1,485 +0,0 @@ -## Copyright (C) 2001 Bill Denney <bi...@de...> -## -## 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 <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {Y =} datesplit(date, P) -## @deftypefnx {Function File} {[Y,M,D,h,m,s] =} datesplit(date, P) -## Split a date string into the Year, Month, Day, hour, minute, and -## second. This routine tries to be as forgiving as possible to the -## date input while requiring that the date is not ambiguous. -## -## Anywhere possible where it would not be ambiguous, efforts were made -## to make times possible with seconds and AM/PM as optional. Also, -## along the same lines, where possible, commas were allowed with -## spaces, and the year/month/day separators were allowed as period (.), -## slash (/), and dash (-). Not all format possibilities are shown in -## the following table, but a date like @code{dd-mmm-yyyy HH:MM:SS} is -## parsed just as well as @code{d/mmm.yyyy, ,H:MM, AM}. -## -## Supported @code{date} formats include (the same as datestr): -## @multitable @columnfractions 0.1 0.45 0.45 -## @item @strong{Code} @tab @strong{Format} @tab @strong{Example} -## @item 0 @tab dd-mmm-yyyy HH:MM:SS @tab 07-Sep-2000 15:38:09 -## @item 1 @tab dd-mmm-yyyy @tab 07-Sep-2000 -## @item 2 @tab mm/dd/yy @tab 09/07/00 -## @item 3 @tab mmm @tab Sep -## @item 6 @tab mm/dd @tab 09/13 -## @item 10 @tab yyyy @tab 2000 -## @item 12 @tab mmmyy @tab Sep00 -## @item 13 @tab HH:MM:SS @tab 15:38:09 -## @item 14 @tab HH:MM:SS PM @tab 03:38:09 PM -## @item 15 @tab HH:MM @tab 15:38 -## @item 16 @tab HH:MM PM @tab 03:38 PM -## @item 17 @tab QQ-YY @tab Q3-00 -## @item 19 @tab dd/mm @tab 13/03 -## @item 20 @tab dd/mm/yy @tab 13/03/95 -## @item 21 @tab mmm.dd.yyyy HH:MM:SS @tab Mar.03.1962 13:53:06 -## @item 22 @tab mmm.dd.yyyy @tab Mar.03.1962 -## @item 23 @tab mm/dd/yyyy @tab 03/13/1962 -## @item 24 @tab dd/mm/yyyy @tab 12/03/1962 -## @item 25 @tab yy/mm/dd @tab 95/03/13 -## @item 26 @tab yyyy/mm/dd @tab 1995/03/13 -## @item 27 @tab QQ-YYYY @tab Q4-2132 -## @item 28 @tab mmmyyyy @tab Mar2047 -## @item 29 @tab yyyymmdd @tab 20470313 -## @item 30 @tab yyyymmddTHHMMSS @tab 20470313T132603 -## @item 31 @tab yyyy-mm-dd HH:MM:SS @tab 1047-03-13 13:26:03 -## @end multitable -## -## The parameter @code{P} is needed to convert date strings with 2 digit -## years into dates with 4 digit years. 2 digit years are assumed to be -## between @code{P} and @code{P+99}. If @code{P} is not given then the -## current year - 50 is used, so that dates are centered on the present. -## For birthdates, you would want @code{P} to be current year - 99. For -## appointments, you would want @code{P} to be current year. -## -## This function makes no strong attempt to verify the accuracy of the -## numbers that it returns in that it doesn't (currently) check to see -## that you're not trying to use the date Feb 30. When applicable, it -## tries to make your input work, though. It will try to determine if -## you're using the date "03/13/95" that the date is "March 13, 1995", -## but if there is doubt, datesplit will return an error instead of -## trying to guess the wrong value. -## -## @seealso{date,clock,now,datestr,datenum,calendar,weekday} -## @end deftypefn - -## TODO: -## * Some formats are ambiguous. Allow the user to specify the format -## to remove ambiguity. -## * Validate the dates. -## * Possible bug (after dates are validated): There are times where -## the year is assumed, Feb 29 may be a valid date, but with the -## assumed year, it may become invalid. -## * Internationalize. Not all months use the English system. -## * Vectorize. That requires vectorization of regexp though... - -function [y, m, d, h, mi, s] = datesplit(ds, P) - - if nargin < 2 - P = []; - endif - - today = datevec(now); - - if (isempty(P)) - P = today(1)-50; - endif - - global __month_names = ["Jan";"Feb";"Mar";"Apr";"May";"Jun";... - "Jul";"Aug";"Sep";"Oct";"Nov";"Dec"]; - global __day_names = ["Sun";"Mon";"Tue";"Wed";"Thu";"Fri";"Sat"]; - global __time_names = ["AM";"PM"]; - - if (iscellstr(ds)) - ds = ds{1}; - endif - ds = tolower(deblank(ds)); - - if (nargin < 1) - error("datesplit: no input arguments"); - elseif (nargin == 1) - fmt = []; - endif - %% we have to determine the format, this could be error prone - - ## format 0 dd-mmm-yyyy HH:MM:SS e.g. 07-Sep-2000 15:38:09 - [match, d, m, y, h, mi, s, ap] = \ - of_regexp("^(3[01]|[0-2]?[0-9])[-./]([a-z]{3})[-./]([0-9]{4})[, ]+(2[0-3]|[01]?[0-9]):([0-5][0-9])(:[0-5][0-9]|)[, ]*([ap]m|)$", ds); - - ## format 21 mmm.dd.yyyy HH:MM:SS e.g. Mar.03.1962 13:53:06 - if (isempty(match)) - [match, m, d, y, h, mi, s, ap] = \ - of_regexp("^([a-z]{3})[-./](3[01]|[0-2]?[0-9])[-./]([0-9]{4})[, ]+(2[0-3]|[01]?[0-9]):([0-5][0-9])(:[0-5][0-9]|)[, ]*([ap]m|)$", ds); - endif - - ## format 31 yyyy-mm-dd HH:MM:SS e.g. 2004-03-13 13:26:03 - if (isempty(match)) - [match, y, m, d, h, mi, s, ap] = \ - of_regexp("^([0-9]{4})[-./](1[012]|0?[0-9])[-./](3[01]|[0-2]?[0-9])[, ]+(2[0-3]|[01]?[0-9]):([0-5][0-9])(:[0-5][0-9]|)[, ]*([ap]m|)$", ds); - endif - - ## format 30 yyyymmddTHHMMSS e.g. 20470313T132603 - if (isempty(match)) - [match, y, m, d, h, mi, s] = \ - of_regexp("^([0-9]{4})(1[012]|0[0-9])(3[01]|[012][0-9])t(2[0-3]|[01][0-9])([0-5][0-9])([0-5][0-9])$", ds); - ap = "NA"; - endif - - ## format 13 HH:MM:SS e.g. 15:38:09 - ## format 14 HH:MM:SS PM e.g. 03:38:09 PM - ## format 15 HH:MM e.g. 15:38 - ## format 16 HH:MM PM e.g. 03:38 PM - if (isempty(match)) - [match, h, mi, s, ap] = \ - of_regexp("^(2[0-3]|[01]?[0-9]):([0-5][0-9])(:[0-5][0-9]|)[, ]*([ap]m|)$", ds); - - if (! isempty(match)) - %% assume that it is as of today - y = today(1); - m = today(2); - d = today(3); - endif - endif - - ## format 1 dd-mmm-yyyy e.g. 07-Sep-2000 - if (isempty(match)) - [match, d, m, y] = \ - of_regexp("^(3[01]|[012]?[0-9])[-./]([a-z]{3})[-./]([0-9]{4})$", ds); - - if (! isempty(match)) - %% assume the beginning of the day - h = 0; - mi = 0; - s = 0; - ap = "NA"; - endif - endif - - ## format 22 mmm.dd.yyyy e.g. Mar.03.1962 - if (isempty(match)) - [match, m, d, y] = \ - of_regexp("^([a-z]{3})[-./](3[01]|[012]?[0-9])[-./]([0-9]{4})$", ds); - - if (! isempty(match)) - %% assume the beginning of the day - h = 0; - mi = 0; - s = 0; - ap = "NA"; - endif - endif - - ## format 2 mm/dd/yy e.g. 09/07/00 - ## format 23 mm/dd/yyyy e.g. 03/13/1962 - ## format 20 dd/mm/yy e.g. 13/03/95 - ## format 24 dd/mm/yyyy e.g. 12/03/1962 - ## format 25 yy/mm/dd e.g. 95/03/13 - ## format 26 yyyy/mm/dd e.g. 1995/03/13 - if (isempty(match)) - [match, d, m, y] = \ - of_regexp("^([0-9]{1,2}|[0-9]{4})[-./](3[01]|[012]?[0-9])[-./]([0-9]{1,2}|[0-9]{4})$", ds); - - if (! isempty(match)) - %% we have to determine if the date is unambiguous - d = str2num(d); - m = str2num(m); - y = str2num(y); - - if ((y == 0) || (y > 31)) - %% we've got the year correct - if ((m > 12) && (d < 13)) - %% we're operating on mm/dd/yyyy - tmp = m; - m = d; - d = tmp; - elseif ((m < 13) && (d > 12)) - %% it's fine - else - %% it's ambiguous - error(["datesplit: ambiguous date " ds]); - endif - elseif ((d == 0) || (d > 31)) - %% the day and the year need to be switched - tmp = y; - y = d; - d = tmp; - else - %% it's ambiguous - error(["datesplit: ambiguous date " ds]); - endif - - %% assume the beginning of the day - h = 0; - mi = 0; - s = 0; - ap = "NA"; - endif - - endif - - ## format 29 yyyymmdd e.g. 20470313 - if (isempty(match)) - [match, y, m, d] = \ - of_regexp("^([0-9]{4})(1[012]|0?[0-9])(3[01]|[012][0-9])$", ds); - %% I've never seen a date that has the year first that was not - %% yyyy/mm/dd, so I'm going to assume that it's unambiguous. - - if (! isempty(match)) - %% assume the beginning of the day - h = 0; - mi = 0; - s = 0; - ap = "NA"; - endif - endif - - ## format 17 QQ-YY e.g. Q3-00 - ## format 27 QQ-YYYY e.g. Q4-2132 - if (isempty(match)) - [match, q, y] = \ - of_regexp("^q([1-4])[-./]([0-9]{2}|[0-9]{4})$", ds); - if (! isempty(match)) - %% Assume that it's the end of the quarter - q = str2num(q); - m = 3*q; - dayopts = [31 30 30 31]; - d = dayopts(q); - - %% assume the end of the day - h = 23; - mi = 59; - s = 59; - ap = "NA"; - endif - endif - - ## format 28 mmmyyyy e.g. Mar2047 - ## format 12 mmmyy e.g. Sep00 - if (isempty(match)) - [match, m, y] = \ - of_regexp("^([a-z]{3})([0-9]{2}|[0-9]{4})$", ds); - if (! isempty(match)) - %% assume the beginning of the month - d = 1; - h = 0; - mi = 0; - s = 0; - ap = "NA"; - endif - endif - - ## format 6 mm/dd e.g. 09/07 - ## format 19 dd/mm e.g. 13/03 - if (isempty(match)) - [match, m, d] = \ - of_regexp("^(3[01]|[012]?[0-9])[-./](3[01]|[012][0-9])$", ds); - - if (! isempty(match)) - m = str2num(m); - d = str2num(d); - - %% we have to determine if the date is unambiguous - if ((m > 12) && (d < 13)) - %% we're operating on mm/dd/yyyy - tmp = m; - m = d; - d = tmp; - elseif ((m < 13) && (d > 12)) - %% it's fine - else - %% it's ambiguous - error(["datesplit: ambiguous date " ds]); - endif - %% assume this year and the beginning of the day - y = today(1); - h = 0; - mi = 0; - s = 0; - ap = "NA"; - endif - endif - - ## format 10 yyyy e.g. 2000 - if (isempty(match)) - [match, y] = of_regexp("^([0-9]{4})$", ds); - - if (! isempty(match)) - %% assume the beginning of the year - m = 1; - d = 1; - h = 0; - mi = 0; - s = 0; - ap = "NA"; - endif - endif - - ## format 3 mmm e.g. Sep - if (isempty(match)) - m = strmatch(ds, tolower(__month_names)); - - if (! isempty(m)) - match = 1; - %% assuming the beginning of the month, this year - y = today(1); - d = 1; - h = 0; - mi = 0; - s = 0; - ap = "NA"; - endif - endif - - ## format 8 ddd e.g. Thu - %% People shouldn't use this function for something like this - - if (isempty(match)) - %% you mean I did all that work, and you still didn't use a valid - %% date? Darn you! - error(["datesplit: Unknown date format " ds]); - endif - - if (! isempty(match)) - if isempty(s) - s = 0; - elseif (ischar(s) && (1 == findstr(s,":"))) - s = s(2:3); - endif - if isempty(ap) - ap = "NA"; - endif - endif - - %% start converting the date from characters to numbers - if (ischar(y)) - y = str2num(y); - if (isempty(y)) - error(["datesplit: Invalid year specification " y]); - endif - endif - %% Handle Y2K issues... - if (y < 100) - y = y + 1900; - if (y < P) - y = y + 100; - endif - endif - - if (ischar(m)) - m_num = str2num(m); - if (isempty(m_num)) - m = strmatch(m, tolower(__month_names)); - else - m = m_num; - endif - if (isempty(m)) - error(["datesplit: Invalid month specification"]); - endif - endif - - if (ischar(d)) - d = str2num(d); - if (isempty(d)) - error(["datesplit: Invalid day specification " d]); - endif - endif - - if (ischar(h)) - h = str2num(h); - if (isempty(h)) - error(["datesplit: Invalid hour specification " h]); - elseif ((ap(2) == "M") && (h > 12)) - error(["datesplit: Invalid hour specification, AM or PM specified but" - "hour is greater than 12."]); - endif - - if (strcmpi(ap, "PM") && (h < 12)) - h = h + 12; - elseif (strcmpi(ap, "AM") && (h == 12)) - h = 0; - endif - endif - - if (ischar(mi)) - mi = str2num(mi); - if (isempty(mi) || (mi > 59)) - error(["datesplit: Invalid minute specification " mi]); - endif - endif - - if (ischar(s)) - s = str2num(s); - if (isempty(s) || (s > 59)) - error(["datesplit: Invalid second specification " s]); - endif - endif - - if (nargout <= 1) - y = [y, m, d, h, mi, s]; - endif - -endfunction - -# wrapper around Octave's regexp -# compatible with octave-forge's regexp - -function varargout = of_regexp(pattern,string) - [S, E, TE, M, T, NM] = regexp(string,pattern); - varargout{1} = S; - - # return sub-strings if match - if (S) - for i=2:nargout - varargout{i} = T{1}{i-1}; - end - else - for i=2:nargout - varargout{i} = []; - end - end -endfunction - - -%!shared nowvec -%! nowvec=datevec(now); % Some tests could fail around midnight! -%!assert (datevec("07-Sep-2000 15:38:09"),[2000,9,7,15,38,9]); -%!assert (datevec("07-Sep-2000"),[2000,9,7,0,0,0]); -%!assert (datevec("1 Jan 2000"),[2000,1,1,0,0,0]); -%!assert (datevec("Sep00"),[2000,9,1,0,0,0]); -%!assert (datevec("15:38:09"),[nowvec(1:3),15,38,9]); -%!assert (datevec("03:38:09 PM"),[nowvec(1:3),15,38,9]); -%!assert (datevec("15:38"),[nowvec(1:3),15,38,0]); -%!assert (datevec("3:38 PM"),[nowvec(1:3),15,38,0]); -%!assert (datevec("03/13/1962"),[1962,3,13,0,0,0]); - -## Ambiguous -%!#assert (datevec("09/07/00"),[2000,9,7,0,0,0]); -%!#assert (datevec("09/13"),[nowvec(1),9,13,0,0,0]); - -## Not supported in octave version of datevec -%!#assert (datevec("Sep"),[nowvec(1),9,1,0,0,0]); -%!#assert (datevec("Q3-00"),[2000,9,30,23,59,59]); -%!#assert (datevec("Q4-2132"),[2132,12,31,23,59,59]); - -## This should be a standard string (without or without the time) -%!assert (datevec("Mar.03.1962 13:53:06","mmm.dd.yyyy HH:MM:SS"),[1962,3,3,13,53,6]); - -## No longer a predefined string to parse the date in octave version -%!assert (datevec("1995/03/13","yyyy/mm/dd"),[1995,3,13,0,0,0]); -%!assert (datevec("Mar2047","mmmyyyy"),[2047,3,1,0,0,0]); -%!assert (datevec("20470313","yyyymmdd"),[2047,3,13,0,0,0]); -%!assert (datevec("20470313T132603","yyyymmddTHHMMSS"),[2047,3,13,13,26,3]); -%!assert (datevec("1047-03-13 13:26:03","yyyy-mm-dd HH:MM:SS"),[1047,3,13,13,26,3]); Deleted: trunk/octave-forge/main/time/inst/easter.m =================================================================== --- trunk/octave-forge/main/time/inst/easter.m 2012-04-17 13:33:51 UTC (rev 10263) +++ trunk/octave-forge/main/time/inst/easter.m 2012-04-17 14:04:28 UTC (rev 10264) @@ -1,69 +0,0 @@ -## Copyright (C) 2008 Bill Denney <bi...@de...> -## -## 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 <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[m, d] =} easter (y) -## @deftypefnx {Function File} {datenum =} easter (y) -## -## Return the month (@var{m}) and day (@var{d}) of Easter in the -## Gregorial calendar on a given year or years. -## -## @seealso{holidays} -## @end deftypefn - -function varargout = easter (y) - - ## This uses the Meesus/Jones/Butcher Gregorian algorithm as described - ## on http://en.wikipedia.org/wiki/Computus#Algorithms - a = mod (y, 19); - b = floor (y/100); - c = mod (y, 100); - d = floor (b/4); - e = mod (b, 4); - f = floor ((b + 8)/25); - g = floor ((b - f + 1)/3); - h = mod ((19*a+b-d-g+15), 30); - i = floor (c/4); - k = mod (c, 4); - L = mod ((32 + 2*e + 2*i - h - k), 7); - m = floor ((a + 11*h + 22*L)/451); - mon = floor ((h + L - 7*m + 114)/31); - day = 1 + mod ((h + L - 7*m + 114), 31); - - if nargout == 2 - varargout = {mon(:), day(:)}; - else - varargout{1} = reshape (datenum (y(:), mon(:), day(:)), size (y)); - end - -endfunction - -## Tests -## Validate that it calculates the correct date for a decade -%!assert(easter(1990), datenum(1990, 4, 15)) -%!assert(easter(1991), datenum(1991, 3, 31)) -%!assert(easter(1992), datenum(1992, 4, 19)) -%!assert(easter(1993), datenum(1993, 4, 11)) -%!assert(easter(1994), datenum(1994, 4, 3)) -%!assert(easter(1995), datenum(1995, 4, 16)) -%!assert(easter(1996), datenum(1996, 4, 7)) -%!assert(easter(1997), datenum(1997, 3, 30)) -%!assert(easter(1998), datenum(1998, 4, 12)) -%!assert(easter(1999), datenum(1999, 4, 4)) -## Validate vector and matrix inputs -%!assert(easter([2000 2001]), [datenum(2000, 4, 23) datenum(2001, 4, 15)]) -%!assert(easter([2002;2003]), [datenum(2002, 3, 31);datenum(2003, 4, 20)]) -%!assert(easter([2004 2005;2006 2007;2008 2009]), [datenum(2004, 4, 11) datenum(2005, 3, 27);datenum(2006, 4, 16) datenum(2007, 4, 8);datenum(2008, 3, 23) datenum(2009, 4, 12)]) -%!assert(easter([2002;2003]), [datenum(2002, 3, 31);datenum(2003, 4, 20)]) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |