function labels = datestr(D,dateform,pivotyear)
%DATESTR String representation of date.
%   DATESTR(D,DATEFORM) converts a serial data number D (as returned by
%   DATENUM) into a date string.  The string is formatted according to the
%   format number or string DATEFORM (see table below).  By default,
%   DATEFORM is 1, 16, or 0 depending on whether D contains dates, times
%   or both. Date strings with 2 character years are interpreted to be
%   within the 100 years centered around the current year.
%
%   DATESTR(D,DATEFORM,PIVOTYEAR) uses the specified pivot year as the
%   starting year of the 100-year range in which a two-character year
%   resides.  The default pivot year is the current year minus 50 years.
%   DATEFORM = -1 uses the default format.
%
%   DATEFORM number   DATEFORM string         Example
%      0             'dd-mmm-yyyy HH:MM:SS'   01-Mar-1995 15:45:17 
%      1             'dd-mmm-yyyy'            01-Mar-1995  
%      2             'mm/dd/yy'               03/01/95     
%      3             'mmm'                    Mar          
%      4             'm'                      M            
%      5             'mm'                     3            
%      6             'mm/dd'                  03/01        
%      7             'dd'                     1            
%      8             'ddd'                    Wed          
%      9             'd'                      W            
%     10             'yyyy'                   1995         
%     11             'yy'                     95           
%     12             'mmmyy'                  Mar95        
%     13             'HH:MM:SS'               15:45:17     
%     14             'HH:MM:SS PM'             3:45:17 PM  
%     15             'HH:MM'                  15:45        
%     16             'HH:MM PM'                3:45 PM     
%     17             'QQ-YY'                  Q1-96        
%     18             'QQ'                     Q1           
%
%   See also DATE, DATENUM, DATEVEC.

%   Copyright (c) 1984-98 by The MathWorks, Inc.
%   $Revision: 1.20 $  $Date: 1998/08/12 13:30:37 $

if nargin < 2, dateform = -1; end
if nargin < 1, error('Not enough input arguments.'); end

if isstr(dateform), % Determine dateformat from string.
  switch dateform
  case 'dd-mmm-yyyy HH:MM:SS', dateform = 0;
  case 'dd-mmm-yyyy', dateform = 1;
  case 'mm/dd/yy', dateform = 2;
  case 'mmm', dateform = 3;
  case 'm', dateform = 4;
  case 'mm', dateform = 5;
  case 'mm/dd', dateform = 6;
  case 'dd', dateform = 7;
  case 'ddd', dateform = 8;
  case 'd', dateform = 9;
  case 'yyyy', dateform = 10;
  case 'yy', dateform = 11;
  case 'mmmyy', dateform = 12;
  case 'HH:MM:SS', dateform = 13;
  case 'HH:MM:SS PM', dateform = 14;
  case 'HH:MM', dateform = 15;
  case 'HH:MM PM', dateform = 16;
  case 'QQ-YY', dateform = 17;
  case 'QQ', dateform = 18;
  otherwise
    error(sprintf('Unknown date format: %s',dateform))
  end
end

if ceil(dateform) < -1 | ceil(dateform) > 18
  error('Please use a date format between 0 and 18.');
end
if isstr(D), 
  if nargin==3
     D = datenum(D,pivotyear); 
  else
     D = datenum(D); 
  end
end

labels = [];
D = D(:);

% To guarantee that the day, month, and year strings have the
% the same number of characters after the integer to string 
% conversion, add 100 to the day and month numbers and 10000 to
% the year numbers for proper padding.  This also allows for
% padding numbers with zeros.  For example, the first day of a 
% given month will be printed as 01 instead of 1.  The labels
% are converted into one long concatenated string by sprintf.
% Reshape matrix so each column is a single value plus the 
% appropriate padding number.  Transpose so each row is now this
% single value and the needed columns can be extracted.

n = length(D);

% Determine automatic behavior.  If all the times are zero, display
% using date only.  If all dates are all zero display time only.
% Otherwise display both time and date.
if dateform == -1,
  if all(floor(D)==D),
    dateform = 1;
  elseif all(floor(D)==0)
    dateform = 16;
  else
    dateform = 0;
  end
end

% Round input based on output format
if dateform == 15 | dateform == 16 % truncate to nearest minute
  DV = dvcore(floor(1440*D(:))*60);
else % round to nearest second
  DV = dvcore(round(86400*D(:)));
end

mths = ['Jan';'Feb';'Mar';'Apr';'May';'Jun';'Jul';
        'Aug';'Sep';'Oct';'Nov';'Dec'];

% Build day of month matrix
ds = reshape(sprintf('%.0f',DV(:,3)+100),3,n)';

% Build quarter number matrix
qnum = reshape(floor((DV(:,2)-1)/3)+1,size(D)); % Get quarter number DV
qs = reshape(sprintf('%.0f',qnum+10),2,n)';

% Build month number matrix
mnum = reshape(DV(:,2),size(D)); % Get month number DV
mstring = mths(DV(:,2),:); % Get month string from DV
ms = reshape(sprintf('%.0f',mnum+100),3,n)';

% Build 4 and 2 digit year matrix
neg = find(DV(:,1) < 0);
msign = '-';
yrs = reshape(sprintf('%0.f',abs(DV(:,1))+10000),5,n)';
ys = yrs(:,2:5); ys(neg,1) = msign*ones(length(neg),1);
ys2 = yrs(:,4:5);ys2(neg,1)= msign*ones(length(neg),1);

% Build hour matrix
hs = reshape(sprintf('%.0f',DV(:,4)+100),3,n)';

% Build minute and rounded minute matrix
mins = reshape(sprintf('%.0f',DV(:,5)+100),3,n)';
mins2 = reshape(sprintf('%.0f',round(DV(:,5)+DV(:,6)/60)+100),3,n)';

% Build second matrix
ss = reshape(sprintf('%.0f',DV(:,6)+100),3,n)';

if dateform == 0  % Day-Month-Year hour:minute (01-Mar-1995 03:45)
  delim1 = setstr(ones(n,1)*'-');
  delim2 = setstr(ones(n,1)*' ');
  delim3 = setstr(ones(n,1)*':');
  labels = [ds(:,2:3),delim1,mstring,delim1,ys,delim2,...
            hs(:,2:3),delim3,mins(:,2:3),delim3,ss(:,2:3)];
elseif dateform == 1  % Day-Month-Year (01-Mar-1995)
  delim = setstr(ones(n,1)*'-');
  labels = [ds(:,2:3),delim,mstring,delim,ys];

elseif dateform == 2 % Month/Day/Year (03/01/1995)
  delim = setstr(ones(n,1)*'/');
  labels = [ms(:,2:3),delim,ds(:,2:3),delim,ys2];

elseif dateform == 3 % 3 letter month (Mar)
  labels = mstring;

elseif dateform == 4 % 1 letter month (M)
  labels = mstring(:,1);

elseif dateform == 5 % month (number)
  labels = reshape(sprintf('%2.0f',mnum),2,length(mnum))';

elseif dateform == 6 % Month/Day (03/01)
  delim = setstr(ones(n,1)*'/');
  labels = [ms(:,2:3),delim,ds(:,2:3)];

elseif dateform == 7 % Day of month (01)
  labels = ds(:,2:3);

elseif dateform == 8 % 3 letter day of week (Wed)
  [d,s] = weekday(D);
  labels = s;

elseif dateform == 9 % 1 letter day of week (W)
  [d,s] = weekday(D);
  labels = s(:,1);

elseif dateform == 10 % 4 digit year (1995)
  labels = ys;

elseif dateform == 11 % 2 digit year (95)
  labels = ys2;

elseif dateform == 12 % Month year (Mar95)
  labels = [mstring,ys2];

elseif dateform == 13 % hour:minute:second (24 hour clock)
  delim = setstr(ones(n,1)*':');
  labels = [hs(:,2:3),delim,mins(:,2:3),delim,ss(:,2:3)];

elseif dateform == 14 % hour:minute:second AM or PM
  delim = setstr(ones(n,1)*':');
  medpad = setstr(ones(n,1)*' AM');
  nhs = str2double(hs);
  i = find(nhs >= 112);
  medpad(i,:) = setstr(ones(length(i),1)*' PM');
  i = find(nhs > 112);
  nhs(i) = nhs(i) - 12;
  i = find(nhs == 100);
  nhs(i) = nhs(i) + 12;
  hs = reshape(sprintf('%.0f',nhs),3,n)';
  i = find(nhs >= 101 & nhs <= 109);
  hs(i,2) = setstr(' '*ones(length(i),1));
  labels = [hs(:,2:3),delim,mins(:,2:3),delim,ss(:,2:3),medpad];

elseif dateform == 15 % hour:minute (24 hour clock)
  delim = setstr(ones(n,1)*':');
  labels = [hs(:,2:3),delim,mins2(:,2:3)];

elseif dateform == 16 % hour:minute AM or PM
  delim = setstr(ones(n,1)*':');
  medpad = setstr(ones(n,1)*' AM');
  nhs = str2double(hs);
  i = find(nhs >= 112);
  medpad(i,:) = setstr(ones(length(i),1)*' PM');
  i = find(nhs > 112);
  nhs(i) = nhs(i) - 12;
  i = find(nhs == 100);
  nhs(i) = nhs(i) + 12;
  hs = reshape(sprintf('%.0f',nhs),3,n)';
  i = find(nhs >= 101 & nhs <= 109);
  hs(i,2) = setstr(' '*ones(length(i),1));
  labels = [hs(:,2:3),delim,mins2(:,2:3),medpad];
elseif dateform == 17 % quarter-year
  delim = setstr(ones(n,1)*'-');
  labels = [setstr(ones(n,1)*'Q'),qs(:,2),delim,ys2];
elseif dateform == 18 % quarter
  delim = setstr(ones(n,1)*'-');
  labels = [setstr(ones(n,1)*'Q'),qs(:,2)];
end
