111111 end
112112 end
113113 elseif strcmp(type , ' isodatetime' )
114- addpath(fullfile(fileparts(which(' NwbFile' )), ' external_packages' , ' datenum8601' ));
115- assert(ischar(val ) || iscellstr(val ) || isdatetime(val ) || ...
116- (iscell(val ) && all(cellfun(' isclass' , val , ' datetime' ))), errid , errmsg );
114+ assert(ischar(val )...
115+ || iscellstr(val )...
116+ || isdatetime(val ) ...
117+ || (iscell(val ) && all(cellfun(' isclass' , val , ' datetime' ))),...
118+ errid , errmsg );
117119 if ischar(val ) || iscellstr(val )
118120 if ischar(val )
119121 val = {val };
120122 end
121123
122124 datevals = cell(size(val ));
123- % one of:
124- % +-hh:mm
125- % +-hhmm
126- % +-hh
127- % Z
128- tzre_pattern = ' (?:[+-]\d{2}(?::?\d{2})?|Z)$' ;
129125 for i = 1 : length(val )
130- dnum = datenum8601(val{i });
131-
132- tzre_match = regexp(val{i }, tzre_pattern , ' once' );
133- if isempty(tzre_match )
134- tz = ' local' ;
135- else
136- tz = val{i }(tzre_match : end );
137- if strcmp(tz , ' Z' )
138- tz = ' UTC' ;
139- end
140- end
141- datevals{i } = ...
142- datetime(dnum(1 ), ' TimeZone' , tz , ' ConvertFrom' , ' datenum' );
126+ datevals{i } = datetime8601(val{i });
143127 end
144128 val = datevals ;
145129 end
148132 val = {val };
149133 end
150134
151- for i= 1 : length(val )
135+ for i = 1 : length(val )
152136 if isempty(val{i }.TimeZone)
153137 val{i }.TimeZone = ' local' ;
154138 end
187171 val = truval ;
188172 end
189173end
174+ end
175+
176+ function date_time = datetime8601(datestr )
177+ addpath(fullfile(fileparts(which(' NwbFile' )), ' external_packages' , ' datenum8601' ));
178+ [~ , ~ , format ] = datenum8601(datestr );
179+ format = format{1 };
180+ has_delimiters = format(1 ) == ' *' ;
181+ if has_delimiters
182+ format = format(2 : end );
183+ end
184+
185+ assert(strncmp(format , ' ymd' , 3 ),...
186+ ' MatNWB:Types:Util:CheckDType:DateTime:Unsupported8601' ,...
187+ ' non-ymd formats not supported.' );
188+ separator = format(4 );
189+ if separator ~= ' '
190+ % non-space digits will error when specifying import format
191+ separator = [' '' ' separator ' '' ' ];
192+ end
193+
194+ has_fractional_sec = isstrprop(format(8 : end ), ' digit' );
195+ if has_fractional_sec
196+ seconds_precision = str2double(format(8 : end ));
197+ if seconds_precision > 9
198+ warning(' MatNWB:Types:Util:CheckDType:DateTime:LossySeconds' ,...
199+ [' Potential loss of time data detected. MATLAB fractional seconds ' ...
200+ ' precision is limited to 1 ns. Extra precision will be truncated.' ]);
201+ end
202+ end
203+ day_segments = {' yyyy' , ' MM' , ' dd' };
204+ time_segments = {' HH' , ' mm' , ' ss' };
205+
206+ if has_delimiters
207+ day_delimiter = ' -' ;
208+ time_delimiter = ' :' ;
209+ else
210+ day_delimiter = ' ' ;
211+ time_delimiter = ' ' ;
212+ end
213+
214+ day_format = strjoin(day_segments , day_delimiter );
215+ time_format = strjoin(time_segments , time_delimiter );
216+ format = [day_format separator time_format ];
217+ if has_fractional_sec
218+ format = sprintf(' %s .%s ' , format , repmat(' S' , 1 , seconds_precision ));
219+ end
220+
221+ [datestr , timezone ] = derive_timezone(datestr );
222+ date_time = datetime(datestr ,...
223+ ' InputFormat' , format ,...
224+ ' TimeZone' , timezone );
225+ end
226+
227+ function [datestr , timezone ] = derive_timezone(datestr )
228+ % one of:
229+ % +-hh:mm
230+ % +-hhmm
231+ % +-hh
232+ % Z
233+ tzre_pattern = ' (?:[+-]\d{2}(?::?\d{2})?|Z)$' ;
234+ tzre_match = regexp(datestr , tzre_pattern , ' once' );
235+ if isempty(tzre_match )
236+ timezone = ' local' ;
237+ else
238+ timezone = datestr(tzre_match : end );
239+ if strcmp(timezone , ' Z' )
240+ timezone = ' UTC' ;
241+ end
242+ datestr = datestr(1 : (tzre_match - 1 ));
243+ end
190244end
0 commit comments