diff --git a/src/@dates/dates.m b/src/@dates/dates.m index ea1a60444100c80920ca5c9769b0deabcc4aae67..6694253e7dcad0664b90657399b0c60fa2fa38d1 100644 --- a/src/@dates/dates.m +++ b/src/@dates/dates.m @@ -1,60 +1,13 @@ -function dd = dates(varargin) % --*-- Unitary tests --*-- +classdef dates<handle -%@info: -%! @deftypefn {Function File} {@var{dd} =} dates (@var{a},@var{b},...) -%! @anchor{dates} -%! @sp 1 -%! Constructor for the Dynare dates class (unordered sequence of dates). -%! @sp 2 -%! @strong{Inputs} -%! @sp 1 -%! @table @ @var -%! @item a -%! String, date. -%! @item b -%! @end table -%! @sp 2 -%! @strong{Outputs} -%! @sp 1 -%! @table @ @var -%! @item dd -%! Dynare dates object. -%! @end table -%! @sp 1 -%! @strong{Properties} -%! @sp 1 -%! The constructor defines the following properties: -%! @sp 1 -%! @table @ @var -%! @item ndate -%! Scalar integer, the number of dates. -%! @item freq -%! Scalar integer, the frequency of the time series. @var{freq} is equal to 1 if data are on a yearly basis or if -%! frequency is unspecified. @var{freq} is equal to 4 if data are on a quaterly basis. @var{freq} is equal to -%! 12 if data are on a monthly basis. @var{freq} is equal to 52 if data are on a weekly basis. -%! @item time -%! Array of integers (nobs*2). The first column defines the years associated to each date. The second column, -%! depending on the frequency, indicates the week, month or quarter numbers. For yearly data or unspecified frequency -%! the second column is filled by ones. -%! @end table -%! @sp 2 -%! @strong{This function is called by:} -%! @sp 2 -%! @strong{This function calls:} -%! -%! @end deftypefn -%@eod: - -% Copyright (C) 2011-2014 Dynare Team -% -% This file is part of Dynare. +% Copyright (C) 2014 Dynare Team % -% Dynare is free software: you can redistribute it and/or modify +% This code 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. % -% Dynare is distributed in the hope that it will be useful, +% Dynare dates submodule 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. @@ -62,107 +15,109 @@ function dd = dates(varargin) % --*-- Unitary tests --*-- % You should have received a copy of the GNU General Public License % along with Dynare. If not, see <http://www.gnu.org/licenses/>. -% Initialization. -if nargin>0 && ischar(varargin{1}) && isequal(varargin{1},'initialize') - dd = struct('ndat', 0, 'freq', NaN(0), 'time', NaN(0,2)); - dd = class(dd,'dates'); - assignin('base','emptydatesobject',dd); - return -end - -dd = evalin('base','emptydatesobject'); - -if isequal(nargin, 0) - % Return an empty dates obect - return -end - -if all(cellfun(@isdates, varargin)) - % Concatenates dates in a dates object. - dd = horzcat(varargin{:}); - return -end - -if all(cellfun(@isstringdate,varargin)) - % Concatenates dates in a dates object. - tmp = cellfun(@string2date,varargin); - if all([tmp.freq]-tmp(1).freq==0) - dd.freq = tmp(1).freq; - else - error('dates::dates: Wrong calling sequence of the constructor! All dates must have common frequency.') - end - dd.ndat = length(tmp); - dd.time = transpose(reshape([tmp.time],2,dd.ndat)); - return -end - -if isequal(nargin,1) && isfreq(varargin{1}) - % Instantiate an empty dates object (only set frequency) - if ischar(varargin{1}) - dd.freq = string2freq(varargin{1}); - else - dd.freq = varargin{1}; - end - return -end - -if isequal(nargin,3) && isfreq(varargin{1}) - if ischar(varargin{1}) - dd.freq = string2freq(varargin{1}); - else - dd.freq = varargin{1}; + properties + ndat = []; % Number of dates (integer scalar) + freq = []; % Frequency (integer scalar) + time = []; % Array (ndat rows and two columns) end - if (isnumeric(varargin{2}) && isvector(varargin{2}) && all(isint(varargin{2}))) - if isnumeric(varargin{3}) && isvector(varargin{3}) && all(isint(varargin{3})) - if all(varargin{3}>=1) && all(varargin{3}<=dd.freq) - dd.time = [varargin{2}(:), varargin{3}(:)]; - dd.ndat = size(dd.time,1); - else - error(sprintf('dates::dates: Wrong calling sequence of the constructor! Third input must contain integers between 1 and %i.',dd.freq)) + + methods + function o = dates(varargin) + if ~nargin + % Returns empty dates object. + o.ndat = 0; + o.freq = NaN(0); + o.time = NaN(0,2); + return end - else - error('dates::dates: Wrong calling sequence of the constructor! Third input must be a vector of integers.') - end - else - error('dates::dates: Wrong calling sequence of the constructor! Second input must be a vector of integers.') - end - return -end - -if isequal(nargin,2) && isfreq(varargin{1}) - if ischar(varargin{1}) - dd.freq = string2freq(varargin{1}); - else - dd.freq = varargin{1}; - end - if isequal(dd.freq, 1) - if (isnumeric(varargin{2}) && isvector(varargin{2}) && isint(varargin{2})) - dd.time = [varargin{2}, ones(length(varargin{2}),1)]; - dd.ndat = size(dd.time,1); - return - else - error('dates::dates: Wrong calling sequence of the constructor! Second input must be a vector of integers.') - end - else - if isequal(size(varargin{2},2), 2) - if all(isint(varargin{2}(:,1))) && all(isint(varargin{2}(:,1))) - if all(varargin{2}(:,2)>=1) && all(varargin{2}(:,2)<=dd.freq) - dd.time = [varargin{2}(:,1), varargin{2}(:,2)]; - dd.ndat = size(dd.time,1); + if all(cellfun(@isdates, varargin)) + % Concatenates dates objects in a dates object. + o = horzcat(varargin{:}); + return + end + if all(cellfun(@isstringdate,varargin)) + % Concatenates dates in a dates object. + tmp = cellfun(@string2date,varargin); + if all([tmp.freq]-tmp(1).freq==0) + o.freq = tmp(1).freq; else - error(sprintf('dates::dates: Wrong calling sequence of the constructor! Second column of the last input must contain integers between 1 and %i.',dd.freq)) + error('dates:ArgCheck', 'All dates passed as inputs must have the same frequency!') end - else - error('dates::dates: Wrong calling sequence! Second input argument must be an array of integers.') + o.ndat = length(tmp); + o.time = transpose(reshape([tmp.time],2,o.ndat)); + return end - else - error('dates::dates: Wrong calling sequence!') - end - end - return -end + if isequal(nargin,1) && isfreq(varargin{1}) + % Instantiate an empty dates object (only set frequency) + o = dates(); + if ischar(varargin{1}) + o.freq = string2freq(varargin{1}); + else + o.freq = varargin{1}; + end + return + end + if isequal(nargin,3) && isfreq(varargin{1}) + o = dates(); + if ischar(varargin{1}) + o.freq = string2freq(varargin{1}); + else + o.freq = varargin{1}; + end + if (isnumeric(varargin{2}) && isvector(varargin{2}) && all(isint(varargin{2}))) + if isnumeric(varargin{3}) && isvector(varargin{3}) && all(isint(varargin{3})) + if all(varargin{3}>=1) && all(varargin{3}<=o.freq) + o.time = [varargin{2}(:), varargin{3}(:)]; + o.ndat = size(o.time,1); + else + error('dates:ArgCheck','Third input must contain integers between 1 and %i.', o.freq) + end + else + error('dates:ArgCheck','Third input must be a vector of integers.') + end + else + error('dates:ArgCheck','Second input must be a vector of integers.') + end + return + end + if isequal(nargin,2) && isfreq(varargin{1}) + o = dates(); + if ischar(varargin{1}) + o.freq = string2freq(varargin{1}); + else + o.freq = varargin{1}; + end + if isequal(o.freq, 1) + if (isnumeric(varargin{2}) && isvector(varargin{2}) && isint(varargin{2})) + o.time = [varargin{2}, ones(length(varargin{2}),1)]; + o.ndat = size(o.time,1); + return + else + error('dates:ArgCheck','Second input must be a vector of integers.') + end + else + if isequal(size(varargin{2},2), 2) + if all(isint(varargin{2}(:,1))) && all(isint(varargin{2}(:,1))) + if all(varargin{2}(:,2)>=1) && all(varargin{2}(:,2)<=o.freq) + o.time = [varargin{2}(:,1), varargin{2}(:,2)]; + o.ndat = size(o.time,1); + else + error('dates:ArgCheck','Second column of the last input must contain integers between 1 and %i.',o.freq) + end + else + error('dates:ArgCheck','Second input argument must be an array of integers.') + end + else + error('dates:ArgCheck','Wrong calling sequence!') + end + end + return + end + error('dates:ArgCheck','You should first read the manual!') + end % dates constructor. + end % methods +end % classdef -error('dates::dates: Wrong calling sequence!') %@test:1 %$ % Define some dates diff --git a/src/initialize_dates_toolbox.m b/src/initialize_dates_toolbox.m index c9928979caedc7920c27a001286decb66b999598..e51c79ce84d3a8abee42d809a3f4b5657b878b0e 100644 --- a/src/initialize_dates_toolbox.m +++ b/src/initialize_dates_toolbox.m @@ -6,9 +6,6 @@ addpath([dates_src_root '/utilities/is']) addpath([dates_src_root '/utilities/op']) addpath([dates_src_root '/utilities/convert']) -% Add empty dates object in the base workspace -dates('initialize'); - % Add missing routines if dynare is not in the path if ~exist('isint','file') addpath([dates_src_root '/utilities/missing/isint'])