How to convert datetimes to days of the year? - matlab

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).

Related

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

Cumulative sum computation from hourly rainfall data MATLAB

I have a hourly rainfall timeseries from 1970 to 2003. I want to calculate:
n-hour values, n = 2,3,6,12,24 & 48 hr. 24-hr rainfall data can be calculated by accumulating 24 consecutive 1-hr data.
Similarly, 48-hr rainfall can be calculated by adding 2-day rainfall values.
From n-hr timeseries, I want to calculate maximum rainfall value for each year.
Likewise, I can compute for other accumulation periods. However, I need suggestions for calculation of annual maximum rainfall value from n-hrly data (aggregated time series), which can be calculated from maximum value of yearly n-hourly rainfall information. For example, from 1970 to 2003, I want to extract 34 annual maxima values correspond to 2,...24 hrs and 19 annual maxima values for 48-hr. Please find sample dataset here:
https://docs.google.com/document/d/1e8g54c6KDw8lwdQ53xi0Bs9fJmasTqbIk2n4LbKA-gM/edit
The frist, second, third & fourth column indicates year, month, day & values respectively.
I tried this code:
ny_p = []; Ann_Max = [];grp_pr = [];
for yr = 1970:1975
i = yr - 1969;
matched = ismember(Precip_Final(:,1), yr, 'rows');
grp_pr = Precip_Final(matched,4); % extracting hourly value of the same year
[nrow,ncol] = size(grp_pr);
for row = 6:nrow % to get 6~ hourly sum
p_new = sum(grp_pr(row-5:row));
ny_p(end+1) = p_new;
end
Max_p = max(ny_p);
Ann_Max = [Ann_Max;Max_p];
clear matched; clear grp_pr; clear i; clear Max_p;
end
I edited my code. Now the problem is: in the matrix ny_p, the earlier years' value also getting stored while running. I want to get an array of maximum n-hrly value of each year in the matrix Ann_Max.

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.

Generating consistent arrays of datenums

Whenever I need to plot data vs time I generate the corresponding array of datenums so I can visualize a timeline on the plot by calling datetick.
Let's suppose I need all the datenums with a 1 minute interval between hours h_1 and h_2. This is how would I generate my array of datenums vd:
h_1 = [01 00]; % 01:00 AM
h_2 = [17 00]; % 17:00 PM
HH_1 = h_1(1); % Hour digits of h_1
MM_1 = h_1(2); % Minute digits of h_1
HH_2 = h_2(1); % Hour digits of h_2
MM_2 = h_2(2); % Minute digits of h_2
% Vector of 01:00 - 17:30 with 1 minute increments (24 hours a day, 1440 minutes a day)
vd = HH_1/24+MM_1/1440:1/1440:HH_2/24+MM_2/1440;
I learnt this technique reading this answer.
On the other hand, whenever I wish to generate a single datenum, I use the datenum function like this:
d = datenum('14:20','HH:MM');
Since 14:20 is comprised between the interval 01:00 - 17:30, its datenum should be too! Unfortunately this is not working as expected, since the number assigned to d is radically different to those values contained in vd. I think I might be missing something, probably something to do with setting up a reference date or similar.
So what would be the appropriate way to generate datenums consistently?
The reason is that the datenum function gives you a number of days from January 0, 0000.
So when calling
d = datenum('14:20','HH:MM');
you get a number about 735965, while the numbers in your vd array are between 0 and 1. In order to substruct the days between January 0, 0000 and today you can write
d = datenum('14:20','HH:MM') - datenum('00:00','HH:MM');
Then your code will look like
h_1 = [01 00]; % 01:00 AM
h_2 = [17 00]; % 17:00 PM
HH_1 = h_1(1); % Hour digits of h_1
MM_1 = h_1(2); % Minute digits of h_1
HH_2 = h_2(1); % Hour digits of h_2
MM_2 = h_2(2); % Minute digits of h_2
vd = HH_1/24 + MM_1/1440 : 1/1440 : HH_2/24+MM_2/1440;
d = datenum('14:20','HH:MM') - datenum('00:00','HH:MM');
display(d);
display(vd(801));
And the result:
d = 0.5972
ans = 0.5972

Subtract months from a given date in 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