matlab 转换为只有小数秒的日期时间数组?

ua4mk5z4  于 2023-10-23  发布在  Matlab
关注(0)|答案(4)|浏览(140)

我有一个包含日期格式字符串的单元格数组,我想将整个数组转换为日期时间数组。问题是有些字符串包含小数秒(精度不同),而有些则不包含,如下所示:

my_date_strings{1} = '2022-01-15T14:04:58.23Z'  ;
my_date_strings{2} = '2022-01-15T14:19:28Z'     ;
my_date_strings{3} = '2022-01-08T09:43:24.702Z' ;
my_datetime = datetime(my_date_strings, 'InputFormat','yyyy-MM-dd''T''HH:mm:ss.SS''Z''' );

如何指定日期时间的输入格式,使其能够处理这两种类型?(理想情况下,我希望忽略每个元素上的小数秒,但是可以使用输入格式说明符吗?).

piv4azn7

piv4azn71#

Regexp很难。erase使用pattern更容易。

>> x = erase(my_date_strings, "." + digitsPattern)
x =
  1×3 cell array
    {'2022-01-15T14:04:58Z'}    {'2022-01-15T14:19:28Z'}    {'2022-01-08T09:43:24Z'}
>> my_datetime = datetime(x, 'InputFormat','yyyy-MM-dd''T''HH:mm:ss''Z''' )
my_datetime = 
  1×3 datetime array
   2022-Jan-15 14:04:58   2022-Jan-15 14:19:28   2022-Jan-08 09:43:24
jv2fixgn

jv2fixgn2#

您可以填充缺少小数秒的字符串,使其以.00结尾,然后格式保持一致。如果你知道my_date_strings的每个元素都以':ss.SSZ'':ssZ'结尾,那么你可以检查小数点后3个字符,如果缺少,用.00Z替换'Z'。这可能看起来像:

my_date_strings{1} = '2022-01-15T14:04:58.23Z';
my_date_strings{2} = '2022-01-15T14:19:28Z';

% Check which dates have the decimal point 3 characters from the end
hasMS = cellfun( @(x) x(end-3) == '.', my_date_strings );
% For those where it's missing, add it in
my_date_strings( ~hasMS ) = strrep( my_date_strings( ~hasMS ), 'Z', '.00Z' );

% Do a consistent conversion
my_datetime = datetime(my_date_strings, 'InputFormat','yyyy-MM-dd''T''HH:mm:ss.SS''Z''' );

如果小数点后的位数可以变化,那么你需要稍微复杂一些的东西。您可以将“填充”定义为'.000Z',并计算出每个日期字符串需要多少个填充字符。然后在末端粘上那么多填充物。我认为最清晰的方法是在一个小循环中,注意到在您定义的格式中,一个“完整的”3位小数的日期字符串有24个字符:

ms = '.000Z';
n = 24 - cellfun( @numel, my_date_strings );
for ii = 1:numel(my_date_strings)
    my_date_strings{ii} = [my_date_strings{ii}(1:end-1), ms(end-n(ii):end)];
end

my_datetime = datetime(my_date_strings, 'InputFormat','yyyy-MM-dd''T''HH:mm:ss.SS''Z''' );
rsl1atfo

rsl1atfo3#

下面是另一种方法,基于使用非常简单的正则表达式将字符串拆分为相关部分。这对小数点的数量没有限制。
1.使用regexp匹配每个字符串中包含一个或多个除'-''T'':''Z'之外的字符的部分。对于每个字符串,这将产生6个子字符串,对应于年,月,日,小时,分钟和秒,后者将包含小数部分,如果它存在的话。由于regexp的工作方式,结果是单元阵列的单元阵列。
1.使用vertcatcomma-separated列表转换为二维非嵌套单元数组。现在每一行都引用一个原始字符串,每一列都是它的6个子字符串之一。
1.使用str2double将每个子字符串转换为数字。这给出了6列的数字矩阵。
1.使用num2cell将矩阵分成6列的单元数组。
1.将逗号分隔的6列列表作为输入传递给datetime,以生成所需的输出。

my_date_strings{1} = '2022-01-15T14:04:58.23Z' ;
my_date_strings{2} = '2022-01-15T14:19:28Z'    ;
my_date_strings{3} = '2022-01-08T09:43:24.702Z';
str = regexp(my_date_strings, '[^-T:Z]+', 'match'); % step 1
str = vertcat(str{:});                              % step 2
num = str2double(str);                              % step 3
num = num2cell(num, 1);                             % step 4
my_datetime = datetime(num{:});                     % step 5

请注意,尽管默认显示方法不指示秒的分数,

>> my_datetime
my_datetime = 
  3×1 datetime array
   15-Jan-2022 14:04:58
   15-Jan-2022 14:19:28
   08-Jan-2022 09:43:24

他们确实在那里:

>> second(my_datetime)
ans =
   58.2300
   28.0000
   24.7020
mo49yndu

mo49yndu4#

使用textscan保留小数秒:

s = textscan([my_date_strings{:}], repmat('%f%*c', 1, 6));
my_datetime = datetime(s{:});

相关问题