Matlab :: Change Day, Month Year of serial date number - matlab

I want to change the Day, Month and Year of a serial date number in matlab
e.g.: 7.367985930307407e+05
gives me 13-Apr-2017 14:13:57.
I need: 01-Jan-2017 14:13:57
I get the serial date number from a simulink model, where is a matlab emb. code block with:
function t = sysTime
coder.extrinsic('now');
t=0;
t = now
end
Anyone can help? Read the matlab datenum and now docu but I still couldnt figure it out :(

You can use a datetime object to alter specific portions of the date
d = 7.367985930307407e+05;
dt = datetime(datevec(d));
dt.Month = 1;
dt.Day = 1;
% 01-Jan-2017 14:13:57
% And if you need the serial date number back:
result = datenum(dt);

In your function sysTime, the output is set to now, which gives you the current time as returned by your system. Try the following instead:
function t = sysTime
coder.extrinsic('now');
t=0;
t=datenum(2017,1,1) + rem(now,1);
end
Matlab date numbers are numbers of type double that represent the number of days since a reference date. Thus, the number before the decimal point gives you a date, the nubers after the decimal point give you the time of day.
With the datenum function you can get the date number for your desired date and add the fractional part of the system time to get what you want. In the long run it would probably be better to parameterize your reference date in the matlab block.

Related

How to generate a date-time array in MATLAB?

How do I generate this 480x1 array of date-times in Matlab?
1982-01-01
1982-02-01
1982-03-01
1982-03-01
1982-04-01
.
.
.
2015-12-01
This is made easy with the datetime function (introduced in R2014b) and following the documentation to Generate Sequence of Dates and Time.
% MATLAB 2019a
t1 = datetime(1982,1,1);
t2 = datetime(2015,12,1);
t = t1:t2;
t = t(:); % Force column
Alternatively, you can specify the number of linearly-spaced points between two dates using the linspace command.
t_alt = linspace(t1,t2,480).';
You can convert to the y-M-d format you specified with datetime as well.
t_format = datetime(t,'Format','y-M-d')
References:
1. Dates and Time (in MATLAB)
2. Represent Dates and Times in MATLAB
3. Set Date and Time Display Format
4. Generate Sequence of Dates and Time

In MATLAB How to calculate a time between two dates with a custom format?

I have two dates with bellow format and want to calculate the time between these times:
t1=datestr(clock,'dd-mm-yyyy HH:MM:SS:FFF');
t2=datestr(clock,'dd-mm-yyyy HH:MM:SS:FFF');
My output should be in this format:
(YY:MM:DD:HH:MM:SS:FFF)
as an example
(0:0:1:2:3:44:25:330)
You can first convert the t1 and t2 char arrays to numeric format
using datenum() function then you can calculate the difference between
the calculated numeric dates back to the required format using
datestr() function.
The code illustrating the procedure is given below.
% storing the two times
t1=datestr(clock,'dd-mm-yyyy HH:MM:SS:FFF')
t2=datestr(clock,'dd-mm-yyyy HH:MM:SS:FFF')
% convertine the stored times to numeric format
% using datenum()
numeric_t1 = datenum(t1, 'dd-mm-yyyy HH:MM:SS:FFF');
numeric_t2 = datenum(t2, 'dd-mm-yyyy HH:MM:SS:FFF');
% calculating the time difference
time_diff = datestr((numeric_t2 - numeric_t1), 'yy:mm:dd:HH:MM:SS:FFF')
Command Window Output

Function for extracting the smallest value from data set [MATLAB]

I have already made a function which extracts all temeperatures from a data-set for a certain time for a given month and year.
Which looks like: exctractperiod(data, year, month, time)
This will as previously said extract all temperatures for a particular month at a time say 1400.
I now want to find a minimum temperature for a certain month say january across many years. For example if I look at the month january between the year 1997 and 2006. Now I want the lowest registered temperatue for Janauary between 1997-2006.
My progress so far is the code below:
function [algo] = getMiniserieone(data, startYear, endYear, time)
v = zeros(12,2);
for month = 1:12
for year = startYear:1:endYear
p = extractperiodtwo(data, year, month, time);
q = min(p);
v(month,1) = v(month,1) + q;
v(month,2) = v(month,2) + 1;
algo = v(12,2);
end
end
end
I do however get the error message:
Unable to perform assignment because the size of the left side is
1-by-1 and the size of the right
side is 0-by-1.
When calling the function in the command window:
>> getMiniserieone(data, 1996, 2006, 1400)
Error in getMiniserieone (line 12)
v(month,1) = v(month,1) + q;
But I have not been able remedy this.
My intention with the program above is to lets say for the years between 1996-2006 for a particular time extract the lowest temperature for all months between January and December. Meaning that between the years 1996-2006 for january for a certain time, say 1300, I want the lowest temperature for that month at that time. Then store it in my vector v column 1, column 2 will then denote the month.
My question is how I can fix this, i'm not really sure what the error message means? Does it maybe mean that q is not a single element value?
I hope the information given was ample enough to understand the problem, if not feel free to ask.
As requested, the code for extractPeriod()
function [mdata] = extractperiodtwo(data, year, month, time)
x = year*100 +month;
k = find( floor(TEMPUF(:,1)/100) == x & (data(:,2)==time));
mdata = data(k,3);
end
So there's two issues that you're running into. The first is the case when your extractperiodtwo() function doesn't find a value it returns a empty vector. You may write a check into the loop that reports that no data was found for a given entry and handles the error. I recommend a try-catch block (which I implement in the code below). The second issue has to do with how you're storing the minimum for each iteration.
Here is my solution:
function [algo] = getMiniserieone(data, startYear, endYear, time)
%initialize output
algo = [zeros(12,1), (1:12)']; %col1 = min(temps), col2 = month
% loop through months
yearsToTest = startYear:1:endYear;
for month = 1:12
%initialize a year storage, i.e. on the first iteration
% this will be january minimum temps from startYear:endYear,
% on iteration 2, it will be all february temps from startYear:endYear
% and so on until it completes month == 12.
lowTempsOverYears = nan(1,length(yearsToTest));
for yearNum = 1:length(yearsToTest)
%edit: forgot to paste this line, sorry.
year = yearsToTest(yearNum);
p = extractperiodtwo(data, year, month, time);
q = min(p);
try
%try appending the min
lowTempsOverYears(yearNum) = q;
catch
fprintf(2, ...
'\nNo data found for month=%d, year=%d.\n Skipping...\n', ...
month, ...
year);
continue
end
end
% inner loop is over, now we need the minimum of mins for the month
algo(month, 1) = min(lowTempsOverYears,[],'omitnan');
end
end
So what i've done is added a second vector, lowTempsOverYears that tracks the min(p) for each month over the startYear:endYear interval. Then I get the minimum of that and store it in the corresponding row of the month, in the output variable. I initialize lowTempsOverYears with nan() because it allows me to later take the min() with the 'omitnan' flag set to true, effectively ignoring any nan that appear in the vector.
Alternatively
You could capture all the temps over the years and months in a matrix and then perform the statistic of your choice. For example, the inside of your function could be:
function algo = getMiniserieone(data, startYear, endYear, time)
algo = [zeros(12,1), (1:12)'];
yearsToTest = startYear:1:endYear;
% create local storage of values as matrix
v = nan(12,length(yearsToTest));
%loop
for month = 1:12
for yearNum = 1:length(yearsToTest)
% current year to gather data from
year = yearsToTest(yearNum);
% p could be scalar, vector, empty
p = extractperiodtwo(data, year, month, time);
% q is scalar or empty
q = min(p);
try
%try inserting the min temp
v(month,yearNum) = q;
catch
fprintf(2,'\nNo data at month=%d, year=%d.\n Skipping...\n', ...
month, year ...
);
continue
end
end
end
% now all data is stored in a matrix perform statistic
algo(:,1) = min(v, [], 2, 'omitnan');
end

Importing Excel Data with Dates and Values and Plotting Time Series in Matlab

I would like to plot a time series in Matlab of a data set I have in Excel.
The Excel file looks as follows:
Data: | Value:
2005-04-01 | 5.20
2006-12-02 | 3.12
...
How could I load this into Matlab and plot the time series of it?
There's 2 easy way of plotting dates, but I'll give you the script to read from the xls file first.
% Read from Excel
[N,T] = xlsread( filepath );
You then need to extract/convert the dates as follows. Dates are the 1st column of the text.
d = datetime( T(:,1) );
Then you can plot the variables as follows
figure;
plot( d, N(:,1) );
A sample plot is here
Alternatively, you can use datenum instead of datetime if you want the date as an integer instead of a datetime object using the following line.
d = datenum( T(:,1) );
use xlsread to load in data as string, now converting the date and values can be done in a number of ways, the most strait forward way for your dates is perhaps using the str2num which allows you to read in the N th character as a number, for example:
string = "2005-04-01|5.20"
year = str2num(string(1:4))
month = str2num(string(6:7)) //%where the number is the N th character in string, and has to be numerical or the str2num will return error
//%Note that this method does not read non-numerical strings, in your case "-" "|" will not be read.
I believe this is one of the faster methods, since it mainly involve a type conversion on a standard format of data. Any other suggestions?
PS: in your time series plot, I would suggest converting your dates into a long number, i.e. 20050401, 20061202, etc; which would be most efficient. (you can do this by years*1000+months*100+days.

adding timestamp to real time data log matlab

I'm trying to find a way to timestamp a string value received from a USB port in real time - every 0.5 s - and save it into a file.
So far I'm using the 'record' function to save the string value, but I haven't been able to add the timestamp to it. Reading through the questions, found someone had used the 'now' funciton, but they do not describe the way to do it. The string value I'm using as example to produce the code is the following:
1 Recording on 12-Feb-2015 at 15:57:13.940. Binary data in little endian format.
2 < 34 ascii values.
Timestamp,4.5,5.5,6.5,7.5,8.5,...
3 < 34 ascii values.
Timestamp,4.5,5.5,6.5,7.5,8.5,...
4 < 34 ascii values.
Timestamp,4.5,5.5,6.5,7.5,8.5,..."
and the code that so far I have developed is the following:
%// start code
delete(instrfind);
s = serial('COM5');
set(s,'BaudRate',57600);
set(s,'terminator','CR');
%// Open Serial COM Port
fopen(s);
%// start save file
s.RecordDetail = 'verbose';
s.RecordName = datestr(now,30)
record(s,'on')
%// start time
tic;
hold on;
count = 1;
t = 0;
keepLooping = true;
while keepLooping
time(count)=toc;
count = count +1;
out = fscanf(s);
fprintf(s,'%s','RS232?')
out1 = strsplit(out,',');
s.UserData = count;
p(count) = str2double(out1(2));
k(count) = str2double(out1(3));
g(count) = str2double(out1(4));
h(count) = str2double(out1(5));
%// plotting of the variables continues from this point.
I guess that the problem is that you get some system time making no sense. For a comprehensive time stamp you can do following:
datestr(datetime,'yyyy-mmm-dd HH:MM:SS:FFF')
You get the time as a char vector using the datetime function for the time and the datestr function for the format and casting. Since you seem to have done some programming before I think that you will be able to google this later to find the format you want to use. That may differ country by country I guess.
Please comment if this is not what you want. Good Luck!