time | Calls | line |
---|
| | 1 | function dtstr = cnv2icudf(formatstr,escaping)
|
| | 2 | % CNV2ICUDF maps date format tokens to ICU date format tokens
|
| | 3 | % ICUFORMAT = CNV2ICUDF(MLFORMAT) transforms a date/time format that uses
|
| | 4 | % DATESTR's format tokens into one that uses the ICU format tokens. MLFORMAT
|
| | 5 | % is a char vector containing a user specified format as described below.
|
| | 6 | % ICUFORMAT is a char vector containing the transformed format. Characters in
|
| | 7 | % MLFORMAT not listed in Note 1 are "escaped" with single quotes in ICUFORMAT.
|
| | 8 | %
|
| | 9 | % ICUFORMAT = CNV2ICUDF(MLFORMAT,FALSE) does not escape invalid characters.
|
| | 10 | % This is useful only for use by FORMATDATE.
|
| | 11 | %
|
| | 12 | % The format specifier allows free-style date/time format using the following
|
| | 13 | % tokens:
|
| | 14 | % dddd => day is formatted as full name of weekday
|
| | 15 | % ddd => day is formatted as abbreviated name of weekday
|
| | 16 | % dd => day is formatted as two digit day of month
|
| | 17 | % d => day is formatted as first letter of name of weekday
|
| | 18 | % mmmm => month is formatted as full of name of month
|
| | 19 | % mmm => month is formatted as three letter abbreviation of name of month
|
| | 20 | % mm => month is formatted as two digit month of year
|
| | 21 | % m => month is formatted as one or two digit month of year
|
| | 22 | % yyyy => year is formatted as four digit year
|
| | 23 | % yy => year is formatted as two digit year
|
| | 24 | % QQ => quarter is formatted as 'Q' and one digit quarter of year
|
| | 25 | % HH => hour is formatted as two digit hour of the day
|
| | 26 | % MM => minute is formatted as two digit minute of the hour
|
| | 27 | % SS => second is formatted as two digit second of the minute
|
| | 28 | % FFF => millisecond is formatted as three digit ms of the second
|
| | 29 | % PM or PM => day period is formatted as 'AM' or 'PM'
|
| | 30 | % MLFORMAT may contain separators and other delimiters. At most one of
|
| | 31 | % the year tokens, is allowed; similarly for the month tokens or the day
|
| | 32 | % name tokens (although both day number and day name are allowed). The
|
| | 33 | % quarter token is only allowed with one of the year tokens.
|
| | 34 | %
|
| | 35 | %
|
| | 36 | %------------------------------------------------------------------------------
|
| | 37 |
|
| | 38 | % Copyright 2002-2019 The MathWorks, Inc.
|
| | 39 |
|
< 0.001 | 50 | 40 | dtstr = formatstr;
|
< 0.001 | 50 | 41 | if nargin == 1
|
< 0.001 | 20 | 42 | escaping = true;
|
< 0.001 | 50 | 43 | end
|
| | 44 | % Replace AM/PM with 'a' to avoid confusion with months and minutes.
|
0.001 | 50 | 45 | showAmPm = [strfind(lower(dtstr), 'am'), strfind(lower(dtstr), 'pm')];
|
< 0.001 | 50 | 46 | wrtAmPm = numel(showAmPm);
|
< 0.001 | 50 | 47 | if wrtAmPm > 0
|
| | 48 | if wrtAmPm > 1
|
| | 49 | error(message('MATLAB:formatdate:ampmFormat', formatstr));
|
| | 50 | end
|
| | 51 | dtstr(showAmPm) = []; % delete the 'a' or the 'p'
|
| | 52 | dtstr(showAmPm) = 'a'; % overwrite the 'm'
|
< 0.001 | 50 | 53 | end
|
| | 54 |
|
| | 55 | % Day, millisecond, hour, quarter, second, and year are case insensitive, standardize them.
|
< 0.001 | 50 | 56 | dtstr = strrep(dtstr, 'd', 'D'); % some of which ultimately become 'd', some 'e'
|
< 0.001 | 50 | 57 | dtstr = strrep(dtstr, 'f', 'F'); % which ultimately becomes 'S'
|
< 0.001 | 50 | 58 | dtstr = strrep(dtstr, 'h', 'H'); % which MAY ultimately become 'h', if AM/PM is present
|
< 0.001 | 50 | 59 | dtstr = strrep(dtstr, 'q', 'Q');
|
< 0.001 | 50 | 60 | dtstr = strrep(dtstr, 'S', 's');
|
< 0.001 | 50 | 61 | dtstr = strrep(dtstr, 'Y', 'y');
|
| | 62 |
|
| | 63 | % Swap 'm' and 'M' to output 'M' for month and 'm' for minute.
|
< 0.001 | 50 | 64 | minuteLocs = strfind(dtstr,'M');
|
< 0.001 | 50 | 65 | dtstr = strrep(dtstr,'m','M');
|
< 0.001 | 50 | 66 | dtstr(minuteLocs) = 'm';
|
| | 67 |
|
| | 68 | % Escape unused characters.
|
< 0.001 | 50 | 69 | if escaping
|
0.001 | 20 | 70 | dtstr = regexprep(dtstr,'((?=[A-Za-z])([^amsyDFHMQ]))*','''$1''');
|
< 0.001 | 50 | 71 | end
|
| | 72 |
|
< 0.001 | 50 | 73 | showYr = strfind(dtstr,'y'); wrtYr = numel(showYr);
|
< 0.001 | 50 | 74 | showMo = strfind(dtstr,'M'); wrtMo = numel(showMo);
|
< 0.001 | 50 | 75 | showDay = strfind(dtstr,'D'); wrtDay = numel(showDay);
|
< 0.001 | 50 | 76 | showHr = strfind(dtstr,'H'); wrtHr = numel(showHr);
|
< 0.001 | 50 | 77 | showMin = strfind(dtstr,'m'); wrtMin = numel(showMin);
|
< 0.001 | 50 | 78 | showSec = strfind(dtstr,'s'); wrtSec = numel(showSec);
|
< 0.001 | 50 | 79 | showMsec = strfind(dtstr,'F'); wrtMsec = numel(showMsec);
|
< 0.001 | 50 | 80 | showQrt = strfind(dtstr,'Q'); wrtQrt = numel(showQrt);
|
| | 81 |
|
| | 82 | % Format date
|
< 0.001 | 50 | 83 | if wrtYr > 0
|
< 0.001 | 50 | 84 | if (wrtYr ~= 4 && wrtYr ~= 2) || showYr(end) - showYr(1) >= wrtYr
|
| | 85 | error(message('MATLAB:formatdate:yearFormat', formatstr));
|
< 0.001 | 50 | 86 | end
|
< 0.001 | 50 | 87 | end
|
< 0.001 | 50 | 88 | if wrtQrt > 0
|
| | 89 | if wrtQrt ~= 2 || showQrt(2) - showQrt(1) > 1
|
| | 90 | error(message('MATLAB:formatdate:quarterFormat', formatstr));
|
| | 91 | end
|
| | 92 | if any([wrtMo, wrtDay, wrtAmPm, wrtHr, wrtMin, wrtSec, wrtMsec] > 0)
|
| | 93 | error(message('MATLAB:formatdate:quarterFormatMismatch',formatstr));
|
| | 94 | end
|
| | 95 | dtstr = strrep(dtstr, 'QQ', 'QQQ'); % output exactly 'QQQ' for quarter
|
< 0.001 | 50 | 96 | end
|
< 0.001 | 50 | 97 | if wrtMo > 0
|
< 0.001 | 50 | 98 | if wrtMo > 4 || showMo(end) - showMo(1) >= wrtMo
|
| | 99 | error(message('MATLAB:formatdate:monthFormat', formatstr));
|
< 0.001 | 50 | 100 | end
|
< 0.001 | 50 | 101 | end
|
< 0.001 | 50 | 102 | if wrtDay > 0
|
| | 103 | % 'D' is special in that it ultimately maps to _two_ tokens, one of which is
|
| | 104 | % a literal char. Ultimately the day name token will be 'e', but that can be
|
| | 105 | % confused with 'e' intended as a literal. d/D have been standardized to
|
| | 106 | % 'D', so recognize day name vs. day number fields and temporarily
|
| | 107 | % distinguish between them using case. d/D are non-literal chars, so we're
|
| | 108 | % not stepping on anything.
|
< 0.001 | 50 | 109 | dtstr = strrep(dtstr, 'DDDDDD', 'DDDDdd'); % split into day name/number pieces
|
< 0.001 | 50 | 110 | dtstr = strrep(dtstr, 'DDDDD', 'DDDdd'); % split into day name/number pieces
|
| | 111 | % The above two strreps match _all_ 'DDDDDD' or 'DDDDD' ovelapping substrings,
|
| | 112 | % so seven or more contiguous D's become something illegal caught below. One to
|
| | 113 | % four contiguous D's are left alone, to be handled next.
|
| | 114 | % Leave 'DDDD' as is
|
| | 115 | % Leave 'DDD' as is
|
0.002 | 50 | 116 | dtstr = regexprep(dtstr,'(?<!D)(DD)(?!D)','dd'); % 'DD'->'dd', leaving DDDD and DDD alone
|
0.001 | 50 | 117 | dtstr = regexprep(dtstr,'(?<!D)(D)(?!D)','DDDDD'); % 'D'->'DDDDD', leaving DDDD and DDD alone
|
< 0.001 | 50 | 118 | showNday = strfind(dtstr,'d'); wrtNday = numel(showNday);
|
< 0.001 | 50 | 119 | if wrtNday > 0
|
< 0.001 | 50 | 120 | if wrtNday ~= 2 || showNday(2) - showNday(1) ~= 1
|
| | 121 | error(message('MATLAB:formatdate:dayFormat', formatstr));
|
< 0.001 | 50 | 122 | end
|
< 0.001 | 50 | 123 | end
|
< 0.001 | 50 | 124 | if escaping
|
| | 125 | % Find D's to validate the format, and only then replace 'D' with 'e'.
|
< 0.001 | 20 | 126 | showWday = strfind(dtstr,'D'); wrtWday = numel(showWday);
|
< 0.001 | 20 | 127 | dtstr = strrep(dtstr,'D','e'); % now replace 'D' with 'e'
|
< 0.001 | 30 | 128 | else
|
| | 129 | % Preserve existing behavior: formatDate (and therefore datestr) is the
|
| | 130 | % one caller who doesn't want escaped literals, and it expects E's. If we're
|
| | 131 | % not escaping, replace 'D' with 'E' before looking for E's, which means that
|
| | 132 | % E's don't work correctly when intended as literals. Also formatdate expects
|
| | 133 | % only one E where there was a single D.
|
< 0.001 | 30 | 134 | dtstr = strrep(dtstr,'DDDDD','D'); % exactly 'DDDDD' -> exactly 'D'
|
< 0.001 | 30 | 135 | dtstr = strrep(dtstr,'D','E'); % all D's -> 'E'
|
< 0.001 | 30 | 136 | showWday = strfind(dtstr,'E'); wrtWday = numel(showWday);
|
< 0.001 | 50 | 137 | end
|
< 0.001 | 50 | 138 | if wrtWday > 0
|
| | 139 | if wrtWday > 5 || showWday(end) - showWday(1) >= wrtWday
|
| | 140 | error(message('MATLAB:formatdate:dayFormat', formatstr));
|
| | 141 | end
|
< 0.001 | 50 | 142 | end
|
< 0.001 | 50 | 143 | end
|
| | 144 |
|
| | 145 | % Format time
|
< 0.001 | 50 | 146 | if wrtHr > 0
|
< 0.001 | 50 | 147 | if wrtHr == 2 && showHr(2) - showHr(1) == 1
|
< 0.001 | 50 | 148 | if wrtAmPm
|
| | 149 | dtstr = strrep(dtstr,'H','h'); % output 12-hour field if am/pm present
|
< 0.001 | 50 | 150 | end
|
| | 151 | else
|
| | 152 | error(message('MATLAB:formatdate:hourFormat', formatstr));
|
< 0.001 | 50 | 153 | end
|
< 0.001 | 50 | 154 | end
|
< 0.001 | 50 | 155 | if wrtMin > 0
|
< 0.001 | 50 | 156 | if wrtMin ~= 2 || showMin(2) - showMin(1) ~= 1
|
| | 157 | error(message('MATLAB:formatdate:minuteFormat', formatstr));
|
< 0.001 | 50 | 158 | end
|
< 0.001 | 50 | 159 | end
|
< 0.001 | 50 | 160 | if wrtSec > 0
|
< 0.001 | 50 | 161 | if wrtSec ~= 2 || showSec(2) - showSec(1) ~= 1
|
| | 162 | error(message('MATLAB:formatdate:secondFormat', formatstr));
|
< 0.001 | 50 | 163 | end
|
< 0.001 | 50 | 164 | end
|
< 0.001 | 50 | 165 | if wrtMsec > 0
|
| | 166 | if wrtMsec ~= 3 || showMsec(3) - showMsec(1) ~= 2
|
| | 167 | error(message('MATLAB:formatdate:millisecondFormat', formatstr));
|
| | 168 | end
|
| | 169 | dtstr = strrep(dtstr, 'F', 'S'); % output 'S' for milliseconds.
|
< 0.001 | 50 | 170 | end
|
Other subfunctions in this file are not included in this listing.