Subtract months from a given date in Matlab - matlab

I need to subtract 21 months from a given date.
My solution as given below only takes me to the first month of the given year :(
[a,b,c]= datevec(date);
b= b-21;
datestr(datenum(a,b,c)) %--> 11-Jan-2011 (WRONG).
I want the answer to be 11-June-2009.

Go via date numbers rather than date vectors and use addtodate:
>> d = datenum(date);
>> e = addtodate(d, -21, 'month');
>> datestr(e)
ans =
11-Jun-2009

Related

How to convert datetimes to days of the year?

Suppose DT is a vector of type datetime. How can I get their days of the year?
This is an approximation, but I can't find the right function:
month(DT) * 30 + day(DT)
You can use the Matlab's day function with a vector of datetime elements (see the doc)
t = [datetime('yesterday');datetime('today');datetime('tomorrow')]; % vector of datetime
day( t, 'dayofyear')
that will give the Day-of-year number, from 1 to 365 or 366, depending on the year.
ans =
334
335
336
You can use datetime and between as follows:
d = datetime; %Read current time (just for the example).
jan_1st = datetime(d.Year, 1, 1); %Create datetime object of January fist in year of d.
day_in_year = between(jan_1st, d, 'Days'); %Get day in year.
The result is a calendarDuration object: 334d.
For converting to scalar, use split:
day_in_year = split(day_in_year, 'Days') + 1; % Add one in case the first day of the year is day 1 and not 0
Applying the solution on a vector of datetime may require a for loop due to the usage of datetime(d.Year, 1, 1).

Why do 4 days in the output of datetime() correspond to 1 month and 4 days with datestr() in Matlab?

I am running into the following problem in Matlab 2019a.
>> datestr(datetime('20190927','InputFormat','yyyyMMdd')-datetime('20190923','InputFormat','yyyyMMdd'),'yyyymmdd')
ans =
'00000104'
Why is the answer 1 month 4 days? Shouldn't it be zero month 4 days?
EDIT:
I realize that arithmetic on datetime arrays create duration arrays. But I don't know how to set format of duration arrays after doing arithmetic on datetime arrays or how to retrieve the duration data in a format free way.
Datetime arithmetic is what I need. So I am asking the question so I can do datetime arithmetic without issue.
d = datetime('20190927','InputFormat','yyyyMMdd')-datetime('20190923','InputFormat','yyyyMMdd')
returns:
d =
duration
96:00:00
That is, 96 hours. Converting this to a date string results in January 4th. If you start counting hours from midnight on the year 0, 96 hours later you end up on January 4th. There's no 0th month.
What you can do is this:
d = duration(d,'Format','dd:hh:mm:ss')
which returns:
d =
duration
04:00:00:00
You can also do:
d = days(d)
which returns:
d =
4

How to move a date conversion to the end of the end of the Quarter?

I'm trying to convert a date in matlab to the end of the quarter after getting data in the quarterly format.
For a date in the format Year-Quarter
>> date1='2014Q1';
>> datetime(date1,'InputFormat','yyyyQQ','Format','MM/dd/yyyy')
ans =
01/01/2014
I would like to make this output 3/31/2014 as that would be the date at the end of the quarter.
Simply create a datetime object for the second quarter of the year, then go back one day in time by subtracting one day from the beginning of the second quarter so you get the end of the first quarter. In that case, your date should become '2014Q2' to denote the second quarter of the year.
>> date1 = '2014Q2'; %// Change - note Q2, not Q1
>> datetime(date1,'InputFormat','yyyyQQ','Format','MM/dd/yyyy') - days(1)
ans =
03/31/2014
The function days gives you a datetimeobject that's the equivalent of 1 day, and so subtracting this from your datetime object that starts in the second quarter will give you the end of the first quarter.

Daily values to Monthly Means for Multiple Years Matlab

I have observed daily data that I need to compare to generated Monthly data so I need to get a mean of each month over the thirty year period.
My observed data set is currently in 365x31 with rows being each day (no leap years!) and the extra column being the month number (1-12).
the problem I am having is that I can only seem to get a script to get the mean of all years. ie. I cannot figure how to get the script to do it for each column separately. Example of the data is below:
1 12 14
1 -15 10
2 13 3
2 2 37
...all the way to 12 for 365 rows
SO: to recap, I need to get the mean of [12; -15; 13; 2] then [14; 10; 3; 37] and so on.
I have been trying to use the unique() function to loop through which works for getting the number rows to average but incorrect means. Now I need it to do each month(28-31 rows) and column individually. Result should be a 12x30 matrix. I feel like I am missing something SIMPLE. Code:
u = unique(m); %get unique values of m (months) ie) 1-12
for i=1:length(u)
month(i) = mean(obatm(u(i), (2:31)); % the average for each month of each year
end
Appreciate any ideas! Thanks!
You can simply filter the rows for each month and then apply mean, like so:
month = zeros(12, size(obatm, 2));
for k = 1:12
month(k, :) = mean(obatm(obatm(:, 1) == k, :));
end
EDIT:
If you want something fancy, you can also do this:
cols = size(obatm, 2) - 1;
subs = bsxfun(#plus, obatm(:, 1), (0:12:12 * (cols - 1)));
vals = obatm(:, 2:end);
month = reshape(accumarray(subs(:), vals(:), [12 * cols, 1], #mean), 12, cols)
Look, Ma, no loops!

Converting to matlab time

I have strings of the format '15:10:21' for time, and I also know the date, which is in the format 2011-08-05.
What's the best way to obtain matlab time (in days since 1900) out of this data?
Use datenum:
>> num = datenum('2011-08-05 15:10:21')
num =
7.3472e+05
>> datestr(num)
ans =
05-Aug-2011 15:10:21
The "matlab time" is actually days since the 0th of January, in the year 0:
>> datestr(0)
ans =
00-Jan-0000