function dat = str2dat(string,varargin)
% str2dat  Convert strings to IRIS serial date numbers.
%
% Syntax
% =======
%
%     DAT = str2dat(S,...)
%
% Input arguments
% ================
%
% * `S` [ char | cellstr ] - Strings representing dates.
%
% Output arguments
% =================
%
% * `DAT` [ numeric ] - IRIS serial date numbers.
%
% Options
% ========
%
% * `'freq='` [ `1` | `2` | `4` | `6` | `12` | *empty* ] - Enforce
% frequency.
%
% See help on [`dat2str`](dates/dat2str) for other options available.
%
% Description
% ============
%
% Example
% ========
%
%
%     d = str2dat('04-2010','dateformat','MM-YYYY');
%     dat2str(d)
%     ans =
%        '2010M04'
%
%     d = str2dat('04-2010','dateformat','MM-YYYY','freq',4);
%     dat2str(d)
%     ans =
%        '2010Q2'
%

% -IRIS Toolbox.
% -Copyright (c) 2007-2012 Jaromir Benes.

opt = passvalopt('dates.str2dat',varargin{:});

% If the following options are empty numerics, the default setting from
% irisconfig is used.
config = irisget();
if isequal(opt.dateformat,'config')
    opt.dateformat = config.dateformat;
end
if isequal(opt.freqletters,'config')
    opt.freqletters = config.freqletters;
end
if isequal(opt.months,'config')
    opt.months = config.months;
end

%**************************************************************************

longmonthlist = sprintf('%s|',opt.months{:});
longmonthlist(end) = '';
tmp = regexp(opt.months,'\w{1,3}','match','once');
shortmonthlist = sprintf('%s|',tmp{:});
shortmonthlist(end) = '';
romanlist = 'xii|xi|x|ix|viii|vii|vi|v|iv|iii|ii|i|iv|v|x';
offset = config.highcharcode;

if ischar(string)
    string = {string};
end

if isempty(string)
    dat = nan(size(string));
    return
end

pattern = dopattern();
tokens = regexpi(string,pattern,'names','once');
[year,per,freq] = xxparsedates(tokens,opt);
dat = datcode(freq,year,per);

% Try indeterminate frequency.
index = find(isnan(dat(:).'));
for i = index
    aux = round(str2double(string{i}));
    if ~isempty(aux)
        dat(i) = aux;
    end
end


%***********************************************************************
    function x = dopattern()
        x = upper(opt.dateformat);
        x = regexprep(x,'[\.\+\{\}\(\)]','\\$0');
        x = regexprep(x,'(?<!%)\*','.*?');
        x = regexprep(x,'(?<!%)\?','.');
        subs = { ...
            '(?<!%)YYYY','(?<longyear>\\d{4})'; ...
            '(?<!%)YY','(?<shortyear>\\d{2})'; ...
            '(?<!%)Y','(?<longyear>\\d{0,4})'; ...
            '(?<!%)PP','(?<longperiod>\\d{2})'; ...
            '(?<!%)P','(?<shortperiod>\\d*)'; ...
            '(?<!%)F',sprintf('(?<freqletter>[%s])',opt.freqletters); ...
            '(?<!%)MMMM',['(?<month>',longmonthlist,')']; ...
            '(?<!%)MMM',['(?<month>',shortmonthlist,')']; ...
            '(?<!%)MM','(?<numericmonth>\\d{1,2})'; ...
            '(?<!%)M','(?<numericmonth>\\d+)'; ...
            '(?<!%)Q',['(?<romanmonth>',romanlist,')']; ...
            '(?<!%)R',['(?<romanperiod>',romanlist,')']; ...
            '(?<!%)I','(?<indeterminate>\\d+)'; ...
            };
        for i = 1 : size(subs,1)
            x = regexprep(x,subs{i,1},char(offset+i));
        end
        for i = 1 : size(subs,1)
            x = regexprep(x,char(offset+i),subs{i,2});
        end
        x = regexprep(x,'%([YFPMQRI])','$1');
    end
% dopattern().

end

% Subfunctions.

%**************************************************************************
function [year,per,freq] = xxparsedates(tokens,options)
[thisyear,ans] = datevec(now());
thiscentury = 100*floor(thisyear/100);
freqvec = [1,2,4,6,12];
freq = nan(size(tokens));
% Set period to 1 by default so that e.g. YPF is correctly matched with
% 2000Y.
per = ones(size(tokens));
year = nan(size(tokens));
for i = 1 : length(tokens)
    if length(tokens{i}) ~= 1
        continue
    end
    if isfield(tokens{i},'indeterminate') ...
            && ~isempty(tokens{i}.indeterminate)
        freq(i) = 0;
        per(i) = str2num(tokens{i}.indeterminate);
        continue
    end
    if ~isempty(options.freq) && ( ...
            (isfield(tokens{i},'longmonth') && ~isempty(tokens{i}.longmonth)) ...
            || (isfield(tokens{i},'shortmonth') && ~isempty(tokens{i}.shortmonth)) ...
            || (isfield(tokens{i},'numericmonth') && ~isempty(tokens{i}.numericmonth)) )
        freq(i) = 12;
    end
    if isfield(tokens{i},'freqletter') && ~isempty(tokens{i}.freqletter)
        freqi = freqvec(upper(options.freqletters) == upper(tokens{i}.freqletter));
        if ~isempty(freqi)
            freq(i) = freqi;
        end
    end
    try %#ok<*TRYNC>
        yeari = str2double(tokens{i}.shortyear);
        yeari = yeari + thiscentury;
        if yeari - thisyear > 20
            yeari = yeari - 100;
        elseif yeari - thisyear <= -80
            yeari = yeari + 100;
        end
        year(i) = yeari;
    end
    try
        yeari = str2double(tokens{i}.longyear);
        if ~isempty(yeari)
            year(i) = yeari;
        end
    end
    try
        per(i) = str2double(tokens{i}.shortperiod);
    end
    try
        per(i) = str2double(tokens{i}.longperiod);
    end
    try
        per(i) = xxroman2num(tokens{i}.romanperiod);
    end
    month = NaN;
    try
        month = xxroman2num(tokens{i}.romanmonth);
    end
    try
        month = str2double(tokens{i}.numericmonth);
    end
    try
        index = strncmpi(tokens{i}.month,options.months,length(tokens{i}.month));
        if any(index)
            month = find(index,1);
        end
    end
    if ~isnumeric(month) || length(month) ~= 1 || isinf(month)
        month = NaN;
    end
    if ~isempty(options.freq)
        freq(i) = options.freq;
    end
    if ~isnan(month)
        if ~isnan(freq(i)) && freq(i) ~= 12
            per(i) = month2per(month,freq(i));
        else
            per(i) = month;
            freq(i) = 12;
        end
    end
    % Disregard periods for annul dates. This is now also consistent with
    % the YY function.
    if freq(i) == 1
        per(i) = 1;
    end
end
% Try to guess freq by the highest period found in all the dates passed
% in.
if all(isnan(freq))
    maxper = max(per(~isnan(per)));
    if ~isempty(maxper)
        index = find(maxper <= freqvec,1,'first');
        if ~isempty(index)
            freq(:) = freqvec(index);
        end
    end
end
end
% xxparsedates().

%**************************************************************************
function per = xxroman2num(romanper)
per = 1;
list = {'i','ii','iii','iv','v','vi','vii','viii','ix','x','xi','xii'};
index = strcmpi(romanper,list);
if any(index)
    per = find(index,1);
end
end
% xxroman2num().