MATLAB Answers

0

How to turn a column of seconds into the datetime-type?

Asked by Heidi Mäkitalo on 2 Jul 2019
Latest activity Edited by Stephen Cobeldick on 4 Jul 2019
I have a table that looks like this:
TIME_s SD1_SPEED_MEASURED_1_rpm SD2_SPEED_MEASURED_1_rpm SD3_SPEED_MEASURED_1_rpm SD4_SPEED_MEASURED_1_rpm SD1_MOTOR_SPEED_rpm SD2_MOTOR_SPEED_rpm SD3_MOTOR_SPEED_rpm SD4_MOTOR_SPEED_rpm SD1_MOTOR_TORQUE_pct SD2_MOTOR_TORQUE_pct SD3_MOTOR_TORQUE_pct SD4_MOTOR_TORQUE_pct SD1_TORQUE_REF_B_pct SD2_TORQUE_REF_B_pct SD3_TORQUE_REF_B_pct SD4_TORQUE_REF_B_pct
______ ________________________ ________________________ ________________________ ________________________ ___________________ ___________________ ___________________ ___________________ ____________________ ____________________ ____________________ ____________________ ____________________ ____________________ ____________________ ____________________
242.2 -66.174 -69.167 -77.607 -74.388 -66.369 -69.19 -77.367 -73.986 -2.6341 -0.046144 0.34017 -0.7492 -1.97 -2.3501 -2.3501 -2.3501
242.18 -66.174 -69.167 -77.607 -74.388 -66.369 -69.19 -77.367 -73.986 -2.6341 -0.046144 0.34017 -0.7492 -1.97 -2.3501 -2.3501 -2.3501
242.16 -68.547 -72.838 -79.49 -77.035 -68.078 -72.151 -78.954 -75.901 -2.8352 -0.24927 -1.2125 -4.7041 -1.97 -1.97 -2.3501 -2.3501
242.14 -68.547 -72.838 -79.49 -77.035 -68.078 -72.151 -78.954 -75.901 -2.8352 -0.24927 -1.2125 -4.7041 -1.97 -1.97 -2.3501 -2.3501
242.12 -71.372 -75.556 -80.754 -79.204 -70.49 -74.884 -80.715 -78.217 -3.1016 -3.7407 -1.6364 -2.9571 -1.97 -1.97 -1.97 -1.97
...
0 0 0 0 0 0 0 0
Where the leftmost column records the time that has passed since the beginning of the recording in seconds. In a separate variable, I have stored the starting time of the recording in the datetime-type. In this example, the time is this:
zinterval =
datetime
18-Feb-2018 15:11:11
Now, is there any way to turn the value 0 in the column of seconds into the starting time, and then have all the following seconds be times in the datetime-type following the starting time?

  0 Comments

Sign in to comment.

Products


Release

R2012b

4 Answers

Answer by Stephen Cobeldick on 2 Jul 2019
Edited by Stephen Cobeldick on 2 Jul 2019
 Accepted Answer

The simple MATLAB solution using datetime and duration classes (no outdated datevec):
T.TIME_S = zinterval + seconds(T.TIME_s)
Note that using the variable name "TIME_s" is then a bit misleading (better would be "TIME" or something similar) and I would recommend avoiding overwriting your raw data. Here is a full working example:
>> T = array2table([242.2;242.18;242.16;242.14;242.12;0],'VariableNames',{'TIME_s'})
T =
TIME_s
______
242.2
242.18
242.16
242.14
242.12
0
>> zinterval = datetime('18-Feb-2018 15:11:11')
zinterval =
18-Feb-2018 15:11:11
>> T.TIME = zinterval + seconds(T.TIME_s)
T =
TIME_s TIME
______ ____________________
242.2 18-Feb-2018 15:15:13
242.18 18-Feb-2018 15:15:13
242.16 18-Feb-2018 15:15:13
242.14 18-Feb-2018 15:15:13
242.12 18-Feb-2018 15:15:13
0 18-Feb-2018 15:11:11

  4 Comments

Show 1 older comment
@Heidi Mäkitalo: make sure that you do not have a variable named seconds, otherwise you will get exactly that error (because you shadow the seconds function with the variable):
>> seconds = [1,2,3]; % do NOT name any variable SECONDS!
>> seconds(T.TIME_s) % tries to use non-integers as indices into SECONDS.
Subscript indices must either be real positive integers or logicals.
Once you clear your workspace of that unfortunately named variable, the example will work.
Oh haha yes that's exactly it, now it works! If using datevec really does affect the precision of the data, I suppose I should do it this way instead.
"If using datevec really does affect the precision of the data, I suppose I should do it this way instead."
According to the datetime documentation: "datetime values have flexible display formats up to nanosecond precision", which you would definitely lose when converting to datenum or datevec and back again. Even if you do not need that much precision, a good rule of thumb is to only perform data-type conversions when required... and in this case, the conversion is not required!

Sign in to comment.


Answer by Rik
on 2 Jul 2019
Edited by Rik
on 2 Jul 2019

The rowfun function should be usefull here. You can convert seconds to datetime with t = datetime(Y,M,D,H,MI,S) (set the rest of the inputs to 0).
Edit:
This shows how little I work with the table format. I massively over-complicated it when trying to flesh out my answer:
clc
tab=table([250 200 150 100]',[-66 -55 -44 -33]','VariableNames',{'TIME_s','SD1_SPEED_MEASURED_1_rpm'});
zinterval = datetime(2018,02,18,15,11,11);
FieldName='TIME_s';
pos=find(ismember(tab.Properties.VariableNames,{FieldName}));
tab.(FieldName)=rowfun(@(t) add_my_date(t,zinterval),tab,...
'InputVariables',FieldName,'OutputFormat','uniform');
disp(tab)
function t=add_my_date(t,t0)
t=datenum(0,0,0,0,0,t);
t0=datenum(t0);
t=datetime(t+t0,'ConvertFrom','datenum');
end

  1 Comment

Sign in to comment.


Answer by Alex Mcaulley on 2 Jul 2019
Edited by Alex Mcaulley on 2 Jul 2019

Being T your table:
[Y,M,D,H,MN,S] = datevec(zinterval);
T.TIME_S = datetime(Y,M,D,H,MN,S + T.TIME_S);

  3 Comments

Thank you, it works perfectly!! :--)
Note that multiple data-type conversions are not required (with accompanying loss of precision and meta-data from the datetime object).
Multiple intermediate variables are also not required.
It is not required to use outdated datevec with datetime/duration data.
See the other answers for simpler solutions without loss of precision.
EDIT: according to the MATLAB documentation, both seconds and datetime were introduced in R2014b.
Thanks Stephen for the comment. I am not very familiar with datetime data and I don't have seconds function in my Matlab release ;)
EDIT: Yes, I posted it without those functions (R2012b)

Sign in to comment.


Answer by Steven Lord
on 2 Jul 2019

There's no need to split the current date and time into parts to solve this. Let's make a reference datetime.
N = datetime('now')
Here's a vector of random seconds data.
TIME_s = cumsum([0; 10*rand(9, 1)])
Combine them. The call to seconds is necessary. If you add a datetime and a raw number, MATLAB treats the raw number as a number of days. If you'd wanted to add multiples of a different time unit (like minutes) see the "Create Date and Time Arrays" section on this documentation page.
timeFromReference = N + seconds(TIME_s)
Let's display the result with three fractional seconds in the Format so you can see the change more clearly.
timeFromReference.Format = 'dd-MMM-uuuu HH:mm:ss.SSS'
You can perform these operations on a "free" datetime array and/or array of seconds, or you can perform these same operations on arrays stored in a table array.

  1 Comment

Sign in to comment.