If I do the following:
t1 = now;
pause(2);
t2 = now;
How do I calculate the difference between t2 and t1 in seconds?
dt = t2 - t1
When using 'now', your statement
dt = t2 - t1
returns the difference in number of days. To get it to seconds, simply multiply by 24*3600:
dt_s = 24 * 3600 * (t2 - t1)
However, if you just want to measure elapsed time I would recommend using tic/toc instead
tic
pause(2);
dt = toc;
Jakob L is right with simply multiplying by 24 * 3600.
In case you work a lot with dates and times consider using the datetime() function instead.
Your code would look like this:
t1 = datetime()
pause(2)
t2 = datetime()
dt = t2 - t1 % will give you this duration 00:00:02
dt is now of type duration. You can use the function seconds() to get the number of seconds
sec = seconds(dt) % will give you something like 2.01 seconds (round it in case you want integer seconds)
Related
I have an array of Epoch times that include fractional (nanoseconds). I have reviewed Converting Epoch to Date in Matlab but still cannot seem to convert to the correct date. I must be missing something simple.
Example data:
1548348497.191261
I am using the code in the link above.
time_unix_nanos = 1548348497.191261;
millis = round(time_unix_nanos);
nanos = time_unix_nanos - 1e6 * millis;
time_matlab = round(864e5 * (millis - datenum('1970', 'yyyy')));
s = [datestr(time_matlab, 'yyyy-mm-dd hh:mm:ss.FFF;), num2str(nanos)];
fprintf('s: = %f\n',s);
Two desired outputs
Full date format: yyyy-mm-dd HH:mm:ss.SSS
Just time format: HH:mm:ss.SSS
Thanks in advance!
It seems you've mistaken the conversion of unixtime to matlab time with matlab time to unixtime.
time_unix_nanos = 1548348497.191261;
millis = round(time_unix_nanos / 1e6); % You had also a /1e6 missing here
nanos = time_unix_nanos - 1e6 * millis;
% The following line converts unix time to matlab time. The line you used was doing the opposite
time_matlab = datenum('1970', 'yyyy') + millis / 864e5;
% First desired date format
s1 = [datestr(time_matlab, 'yyyymmdd HH:MM:SS.FFF;'), num2str(nanos)]
% Second desired date format
s2 = [datestr(time_matlab, 'HH:MM:SS.FFF;'), num2str(nanos)]
gives
>> s1
'19700101 00:00:01.548;348497.1913'
>> s2
'00:00:01.548;348497.1913'
For simple test models, I commonly a syntax similar to:
// Assuming the start time is 0 and stop time is 1
x = xMin + (xMax - xMin) * time;
y = f(x);
To be correct no matter the simulation setup, I would like to use:
x = xMin + (xMax - xMin) * (time - startTime) / (stopTime - startTime);
y = f(x);
However, I am unsure how I can reference the values defined in the Simulation Setup / General form.
I have tried simply referencing StartTime, startTime, starttime, timestart, timeStart, etc. with no success.
I understand that it is possible to set StartTime and StopTime using an annotation, but those values are only set the first time a model is opened and so may not truly reflect a simulation's start time and stop time.
It is currently not possible to access the stop-time of a simulation inside Dymola to use in the model, but you can get the start-time as follows:
parameter Real startTime(fixed=false);
initial equation
startTime=time;
Note that if you use Simulation>Continue>Continue the startTime will not be updated, but continue with its original value.
Not perfect, but you could provide the information from outside:
Add the start- and stop-time as parameters to your model
parameter Modelica.SIunits.Time stopTime = 0;
parameter Modelica.SIunits.Time startTime = 1;
and use a function to perform the simulations
function sim
input Modelica.SIunits.Time startTime = 1;
input Modelica.SIunits.Time stopTime = 2;
algorithm
DymolaCommands.SimulatorAPI.simulateExtendedModel(
"model-name", startTime, stopTime,
initialNames={"startTime", "stopTime"},
initialValues={startTime, stopTime});
end sim;
I'm trying to convert an array of milliseconds and its respective data. However I want to do so in hours and minutes.
Millis = [60000 120000 180000 240000....]
Power = [ 12 14 12 13 14 ...]
I've set it up so the data records every minute, hence the 60000 millis (= 1 minimte). I am trying to plot time on the x axis and power on the y. I would like to have the x axis displayed in hours and minutes with each respective power data corresponding to its respective time.
I've tried this
for i=2:length(Millis)
Conv2Min(i) = Millis(i) / 60000;
Time(i) = startTime + Conv2Min(i);
if (Time(i-1) > Time(i) + 60)
Time(i) + 100;
end
end
s = num2str(Time);
This in attempt to turn the milliseconds into hours starting at 08:00 and once 60 minutes have past going to 09:00, the problem is plotting this. I get a gap between 08:59 and 09:00. I also cannot maintain the 0=initial 0.
In this scenario it is preferable to work with datenum values and then use datetick to set the format of the tick labels of your plot to 'HH:MM'.
Let's suppose that you started taking measurements at t_1 = [HH_1, MM_1] and stopped taking measurements at t_2 = [HH_2, MM_2].
A cool trick to generate the array of datenum values is to use the following expression:
time_datenums = HH_1/24 + MM_1/1440 : 1/1440 : HH_2/24 + MM_2/1440;
Explanation:
We are creating a regularly-spaced vector time_datenums = A:B:C using the colon (:) operator, where A is the starting datenum value, B is the increment between datenum values and C is the ending datenum value.
Since your measurements have been taken every minute (60000 milliseconds), then the increment between datenum values should be of 1 minute too. As a day has 24 hours, that makes 1440 minutes a day, so use B = 1/1440 as the increment between vector elements, to get 1 minute increments.
For A and C we simply need to divide the hour digits by 24 and the minute digits by 1440 and sum them up like this:
A = HH_1/24 + MM_1/1440
C = HH_2/24 + MM_2/1440
So for example, if t_1 = [08, 00], then A = 08/24 + 00/1440. As simple as that.
Notice that this procedure doesn't use the datenum function at all, and still, it manages to generate a valid array of datenum values only taking into consideration the time of the datenum, without needing to bother about the date of the datenum. You can learn more about this here and here.
Going back to your original problem, let's have a look at the code:
time_millisec = 0:60000:9e6; % Time array in milliseconds.
power = 10*rand(size(time_millisec)); % Random power data.
% Elapsed time in milliseconds.
elapsed_millisec = time_millisec(end) - time_millisec(1);
% Integer part of elapsed hours.
elapsed_hours_int = fix(elapsed_millisec/(1000*60*60));
% Fractional part of elapsed hours.
elapsed_hours_frac = (elapsed_millisec/(1000*60*60)) - elapsed_hours_int;
t_1 = [08, 00]; % Start time 08:00
t_2 = [t_1(1) + elapsed_hours_int, t_1(2) + elapsed_hours_frac*60]; % Compute End time.
HH_1 = t_1(1); % Hour digits of t_1
MM_1 = t_1(2); % Minute digits of t_1
HH_2 = t_2(1); % Hour digits of t_2
MM_2 = t_2(2); % Minute digits of t_2
time_datenums = HH_1/24+MM_1/1440:1/1440:HH_2/24+MM_2/1440; % Array of datenums.
plot(time_datenums, power); % Plot data.
datetick('x', 'HH:MM'); % Set 'HH:MM' datetick format for the x axis.
This is the output:
I would use datenums:
Millis = [60000 120000 180000 240000 360000];
Power = [ 12 14 12 13 14 ];
d = [2017 05 01 08 00 00]; %starting point (y,m,d,h,m,s)
d = repmat(d,[length(Millis),1]);
d(:,6)=Millis/1000; %add them as seconds
D=datenum(d); %convert to datenums
plot(D,Power) %plot
datetick('x','HH:MM') %set the x-axis to datenums with HH:MM as format
an even shorter approach would be: (thanks to codeaviator for the idea)
Millis = [60000 120000 180000 240000 360000];
Power = [ 12 14 12 13 14 ];
D = 8/24+Millis/86400000; %24h / day, 86400000ms / day
plot(D,Power) %plot
datetick('x','HH:MM') %set the x-axis to datenums with HH:MM as format
I guess, there is an easier way using datetick and datenum, but I couldn't figure it out. This should solve your problem for now:
Millis=6e4:6e4:6e6;
power=randi([5 15],1,numel(Millis));
hours=floor(Millis/(6e4*60))+8; minutes=mod(Millis,(6e4*60))/6e4; % Calculate the hours and minutes of your Millisecond vector.
plot(Millis,power)
xlabels=arrayfun(#(x,y) sprintf('%d:%d',x,y),hours,minutes,'UniformOutput',0); % Create time-strings of the format HH:MM for your XTickLabels
tickDist=10; % define how often you want your XTicks (e.g. 1 if you want the ticks every minute)
set(gca,'XTick',Millis(tickDist:tickDist:end),'XTickLabel',xlabels(tickDist:tickDist:end))
I need to use etime to calculate how many seconds a computation takes. I thought about something like this:
t1 = datetime('now');
% Do some computation
t2 = datetime('now');
temp = etime(t2, t1)
But I am getting this error message:
Error using etime(line 40), Index exceeds matrix dimensions.
What's wrong with it?
The inputs to etime are expected to be vectors that are the same format as the output of clock and not datetime objects.
t1 = clock;
t2 = clock;
elapsed = etime(t2, t1)
It is likely easier to surround your code with tic and toc which will automatically compute the elapsed time.
tmr = tic;
% do stuff
elapsed = toc(tmr);
That being said, if you want an accurate measurement of execution time, it is far better to use timeit.
I would like to convert an elapsed number of seconds into HH:MM:SS format. Is there a built-in function for this, or do I have to write my own?
datestr is probably the function you are looking for. Express your time interval as a decimal fraction of a day, for example:
>> datestr(0.25, 'HH:MM:SS.FFF')
ans =
06:00:00.000
That is, one quarter of a day is 6 hours. If you want to transform intervals longer than a day this way you'll have to adjust the second argument, which formats the function's output, for example:
>> datestr(2.256789741, 'DD:HH:MM:SS.FFF')
ans =
02:06:09:46.634
The first argument to datestr could also be either a date vector or a date string rather than a date serial number. This should get you started, if you have problems ask another question or edit this one.
--
To convert a time in seconds using datestr, divide the value by 24*60*60.
Sample:
t1 = toc;
timeString = datestr(t1/(24*60*60), 'DD:HH:MM:SS.FFF');
I don't know a built-in function. However, there is a SEC2HMS on Matlab's File Exchange. Basically, it boils down to something like
function [hours, mins, secs] = sec2hms(t)
hours = floor(t / 3600);
t = t - hours * 3600;
mins = floor(t / 60);
secs = t - mins * 60;
end
If you also want to have it formatted, use a printf:
function hms = sec2hms(t)
hours = floor(t / 3600);
t = t - hours * 3600;
mins = floor(t / 60);
secs = t - mins * 60;
hms = sprintf('%02d:%02d:%05.2f\n', hours, mins, secs);
end
sec2hms(69.9904)
ans =
00:01:09.99
If you want to get the hours, minutes and seconds as doubles consider the following line of code:
seconds = 5000;
hms = fix(mod(seconds, [0, 3600, 60]) ./ [3600, 60, 1])
hms =
1 23 20
This line of code is more than 100 times faster than using the built-in datestr funciton.
nIterations = 10000;
tic
for i = 1:nIterations
hms = fix(mod(seconds, [0, 3600, 60])./[3600, 60, 1]);
end
sprintf('%f ms\r', toc / nIterations * 1000)
gives 0.001934 ms.
tic
for i = 1:nIterations
datestr(seconds/24/3600, 'HH:MM:SS');
end
sprintf('%f ms\r', toc / nIterations * 1000)
gives 0.209402 ms.
If you want from original second input, just convert it to a fraction of the day:
datestr(25/24/3600, 'DD-HH:MM:SS')
ans =
00-00:00:25
Just gives it for 25 seconds (as from tic/toc)