RadoslavIvanov
RadoslavIvanov

Reputation: 3

Datetime() returns wrong values

I am trying to plot in matlab using values for the x-axis from a datetime array.
Example of one value: '2016-06-03T13:37:20.315Z'
At first the values are saved into a struct array from where I try to copy them into a separate array. I do it with the following code:

 timestamp=[];
 for j=1:length(data)
   timestamp = getfield(data,{j},'timestamp');
   timestamp{j}=(datetime);
end  

But when I take a look at the array it seems like all the values are one date, which is not even in the "data" struct array.
Example:

timestamp{1} = '14-Dec-2018 00:31:05';  
timestamp{10} = '14-Dec-2018 00:31:05';   
timestamp{19} = '14-Dec-2018 00:31:05'; 

My first thoughts were that it is probably because of the input format so I tried

timestamp{j}=(datetime(timestamp,'InputFormat','uuuu-MM-dd''T''HH:mmXXX','TimeZone','UTC'));  

But I got a message: "Error using datetime (line 635) Unable to convert '2016-06-03T13:37:20.315Z' to datetime using the format 'uuuu-MM-dd'T'HH:mmXXX'."

Any ideas?

Upvotes: 0

Views: 475

Answers (2)

Wolfie
Wolfie

Reputation: 30046

Your indexing and type conversion are just a bit confusing, see my comments...

% Your code:
timestamp=[];                                     
for i=1:length(data)                              % Your loop variable is "i"
    % You override the entire "timestamp" array here, with element "j" not "i" of "data"
    % You also don't need to use getfield here
    timestamp = getfield(data,{j},'timestamp');  
    % You override element "j" (again, not "i") with the CURRENT datetime.
    % This line doesn't do any type conversion, "datetime" with no arguments is now!
    % Also you're using curly braces for indexing, which isn't right for a datetime array
    timestamp{j}=(datetime);
end 

You can correct this as follows:

timestamp = NaT(1,length(data)); % pre-allocate the output to "not a time" array
for ii = 1:length(data)
    t = getfield( data, {ii}, 'timestamp' );
    t( t == 'T' | t == 'Z' ) = []; % remove T and Z, they will break datetime
    timestamp( ii ) = datetime( t, 'InputFormat', 'yyyy-MM-ddHH:mm:ss.SSS' );
end

Output:

timestamp = 
 1×2 datetime array
 03-Jun-2016 13:37:20   03-Jun-2016 13:37:21

(Created using your example string, and the same string with one second added).


That's how to correct your code, here's how I would do it:

timestamp = regexprep( {data.timestamp}, '[TZ]', '' );
timestamp = datetime( timestamp, 'InputFormat', 'yyyy-MM-ddHH:mm:ss.SSS' );   

Upvotes: 0

Anjan
Anjan

Reputation: 364

There are numerous errors in your code. They are summarized below.

  1. You are looping to get the data stored in a field in the given structure. Whereas you can directly get all the data stored within a particular field in a struct just using the getfield() function.
  2. In the loop you are just using the datetime function simply to populate the timestamp variable. As a result each time when datetime is called it returns the current time, hence populating the array with the same value at each position.
  3. You can not directly convert a date char array having TimeZone offset directly to datetime format. You need to remove the offsets first with strrep() command.

Solutions to the problem

  1. You should use getfield function to access the timestamp char array from the data struct altogether in a single line without using loops.

-

  1. You should remove the offset fields(T and Z) first from the date char array and

-

  1. Finally, you should convert the edited datetime strings back to the datetime type using required format to be used in plot.

The code illustrating the procedure is given below.

% suppose we have a struct named data 
% with a field known as timestamp holding the
% different datetime char arrays of particular 
% TimeZone offsets
data.timestamp = {'2016-06-03T13:37:20.315Z', '2016-07-10T17:45:20.200Z', ...
                '2016-07-09T13:37:21.305Z', '2016-11-10T01:30:20.320Z'};

% now getting the timestamp field elements in a variable using getfield()
% command
timestamp = getfield(data, 'timestamp')

% now removing each offsets chars(T and Z) from each datetime strings
edited_timestamp = strrep(timestamp, 'T', ' '); % removing T
edited_timestamp = strrep(edited_timestamp, 'Z', '') % removing Z

% finally, convert the edited_timestamp back to datetime type using the
% required format to use in plot
timestamp_datetime = datetime(edited_timestamp, 'Format', 'yyyy-MM-dd HH:mm:ss.SSS')

% ------------------------------------------------------
% now you can do the plotting here using timestamp_datetime
% ------------------------------------------------------
% e.g., plot(timestamp_datetime, [1:4])

OUTPUT

enter image description here

enter image description here

Upvotes: 1

Related Questions