A code which computes which is the nth day of the year - matlab

I want to write a matlab code to get which day is the first day of year and also get n and display which is the nth day of that year.
And also i don't know why it can not compare a(for example sat) and w(i)
(W=[sat,sun,....,fri]
Please help me I really can't make it work!
This is what I have done so far:
First=input('sat,sun,...,fri');
day=('a number between 1and 365');
day=mod(day,7);
w=[sat,sun,....,fri];
for i=1:7
if first==w(i)
disp(mod(i+day,7))
end
end

Note the syntax in the code below. I noticed you had quite a lot of errors in your syntax. Also, I recommend you use datenumand datestr as in the code below. Run help datenum and help datestr to get more information about the functions.
% User selects a year as a double
year = input('Select a year: ');
% the first day of that year as a value
date = datenum([num2str(year),'-01-01']);
% Get the name of the first day and diplay it
first = datestr(date,'dddd');
disp(['The first day of ', num2str(year), ' was a ', first])
% get nth day from user
day = input('Choose a number between 1 and 365: ');
% Add this value to the value of 1st jan on the selected year
newDate = date + day-1;
% Turn this date into a string and display it
nth = datestr(newDate,'dddd-dd-mmmm');
disp(['Day ', num2str(day),' of ', num2str(year), ' was ', nth])

Related

How to get the first business day in a new month after the weekend?

How can I in a smart way get the first business day of a month after the weekend?
To get the first business day of the month (given dateInput), we can do:
firstBusdayMonth = fbusdate(year(dateInput),month(dateInput));
As an example, for November, using the above function will return Thursday November 1 as the first business day. However, the first business day of the month after the first weekend is Monday November 5. How can I get this latter date?
Notes:
The weekend does not have to be in the same month.
If the Monday is not a working day, then I would like it to return the next business day
This function will do the trick. Here is the logic:
Create a datetime array for all days in the given month.
Get the day numbers.
Create a logical array, true from the first Monday onwards (so after the first weekend, accounting for the last day of the previous month being a Sunday).
Create another logical array using isbusday to exclude Mondays which aren't working days.
Finding the first day number where these two logical arrays are true, therefore the first business day after the weekend.
Code:
function d = fbusdateAferWE( y, m )
% Inputs: y = year, m = month
% Outputs: day of the month, first business day after weekend
% Create array of days for the given month
dates = datetime( y, m, 1 ):days(1):datetime( y, m, eomday( y, m ) );
% Get the weekday numbers to find first Monday, 1 = Sunday
dayNum = weekday( dates );
% Create the logical array to determine days from first Monday
afterFirstWeekend = ( cumsum(dayNum==2) > 0 ).';
% Get first day which is afterFirstWeekend and a business day.
d = find( afterFirstWeekend & isbusday( dates ), 1 );
end
You could probably speed this up (although it will be pretty rapid already) by not looking at the whole month, but say just 2 weeks. I used eomday to get the last day of the month, which means I don't have to make assumptions about a low number of holiday days in the first week or anything.
Edit: Working with datenum speeds it up by half (C/O JohnAndrews):
function d = fbusdateAferWE( y, m )
% Inputs: y = year, m = month
% Outputs: day of the month, first business day after weekend
% Create array of days for (first 2 weeks of) the given month
dates = datenum(datetime(y,m,1)):datenum(datetime(y,m,eomday(y,m)))-14;
% Get the weekday numbers to find first Monday, 1 = Sunday
dayNum = weekday( dates );
% Create the logical array to determine days from first Monday
afterFirstWeekend = ( cumsum(dayNum==2) > 0 ).';
% Get first day which is afterFirstWeekend and a business day.
d = find( afterFirstWeekend & isbusday( dates ), 1 );
end
I would add something like this after your statement:
[DayNumber, DayName] = weekday(firstBusdayMonth);
if DayNumber > 2
day = 10 - DayNumber;
else
This works because 'weekday' will return a number between 1 (Sunday) and 7 (Saturday).
The fbusdate() function will never return a 1 or 7, so we can ignore those cases.
If weekday(fbusdate()) == 2, the first is on a Monday and the firstBusdayMonth variable doesn't need to be changed.
If weekday(firstBusdayMonth) returns between 2 and 6, we need to skip to the next week, so we subtract the weekday value from 10 to find the next Monday.
It might not be the most elegant solution, but should work.

How to find the first business date of a week in MATLAB?

We can use fbusdate to get the first business day of a month:
Date = fbusdate(Year, Month);
However, how do we get the first business day of a week?
As an example, during the week that I'm posting this, Monday 09/07/2017 was a holiday in the US:
isbusday(736942) % = 0
How do I determine that the first business day for this week would be the next day 736943?
I'm not aware of a builtin function that returns the first working day of a week, but you can obtain it by requesting the next working day after Sunday:
busdate(736941); % 736941 = Sunday 09/03/2017
Your desired fbusdateweek function can be done in one line using just the function weekday to get the first Sunday of the week then busdate to get the next business day after that:
dn = 736942; % Date number for any day in a week
Date = busdate(dn-weekday(dn)+1);
Note: busdate uses the function holidays by default to get all holidays and special nontrading days for the New York Stock Exchange. If necessary, you can define an alternate set of holidays for busdate to use as follows:
holidayArray = ...; % Some set of date numbers, vectors, or datetimes
Date = busdate(dn-weekday(dn)+1, 1, holidayArray);
This way you can define a set of localized holidays.
Solved it. Here is a function that is based on the answer of #m7913d:
function Busday = fbusdateweek(date)
% Return the first business day after Sunday
% 'date' is a datenum input
dperiod = date-6:date;
sundays = weekday(dperiod)==1;
sunday = find(sundays==1,1,'first');
datesunday = dperiod(sunday);
% -->
Busday = busdate(datesunday);
end

Create vector of dates by start date and end date

Is it possible to create a vector automatically or progressively with dates. I want to ask the user about the starting date and the final date and I'd to fill a vector with the dates and the ones between both.
so abstractly:
"what is the first date?" '...' firstDate = '...' --> "what is the final date?" '...' finalDate='...'
and following, I'd like to fill in a vector all of the dates between firstDate and finalDate. is this possible in Matlab, and how? Is there a function to use?
You can use linspace after the user input:
%// prompt and user input
prompt1 = 'What is the first date? (yyyy-MM-dd)\n';
prompt2 = 'What is the last date? (yyyy-MM-dd)\n';
startDate = datenum(input(prompt1,'s'),'yyyy-mm-dd')
endDate = datenum(input(prompt2,'s'),'yyyy-mm-dd')
% number of days
numdays = endDate-startDate
% array of dates
alldays = linspace(startDate,endDate,numdays)
DateString = datestr(alldays, 'mm/dd/yyyy')
For the input 1989-07-01 and 1989-07-07 it will return:
DateString =
07/01/1989
07/02/1989
07/03/1989
07/04/1989
07/05/1989
07/07/1989
Dates can be called using datevec, datestr, datenum etc. datenum will be your best bet, since you can then create your vector using
DateVector = datenum(firstDate):datenum(finalDate);
This will create a vector containing dates per day. The way back is to say datestr(DateVector)

Vectorising Date Array Calculations

I simply want to generate a series of dates 1 year apart from today.
I tried this
CurveLength=30;
t=zeros(CurveLength);
t(1)=datestr(today);
x=2:CurveLength-1;
t=addtodate(t(1),x,'year');
I am getting two errors so far?
??? In an assignment A(I) = B, the number of elements in B and
Which I am guessing is related to the fact that the date is a string, but when I modified the string to be the same length as the date dd-mmm-yyyy i.e. 11 letters I still get the same error.
Lsstly I get the error
??? Error using ==> addtodate at 45
Quantity must be a numeric scalar.
Which seems to suggest that the function can't be vectorised? If this is true is there anyway to tell in advance which functions can be vectorised and which can not?
To add n years to a date x, you do this:
y = addtodate(x, n, 'year');
However, addtodate requires the following:
x must be a scalar number, not a string.
n must be a scalar number, not a vector.
Hence the errors you get.
I suggest you use a loop to do this:
CurveLength = 30;
t = zeros(CurveLength, 1);
t(1) = today; % # Whatever today equals to...
for ii = 2:CurveLength
t(ii) = addtodate(t(1), ii - 1, 'year');
end
Now that you have all your date values, you can convert it to strings with:
datestr(t);
And here's a neat one-liner using arrayfun;
datestr(arrayfun(#(n)addtodate(today, n, 'year'), 0:CurveLength))
If you're sequence has a constant known start, you can use datenum in the following way:
t = datenum( startYear:endYear, 1, 1)
This works fine also with months, days, hours etc. as long as the sequence doesn't run into negative numbers (like 1:-1:-10). Then months and days behave in a non-standard way.
Here a solution without a loop (possibly faster):
CurveLength=30;
t=datevec(repmat(now(),CurveLength,1));
x=[0:CurveLength-1]';
t(:,1)=t(:,1)+x;
t=datestr(t)
datevec splits the date into six columns [year, month, day, hour, min, sec]. So if you want to change e.g. the year you can just add or subtract from it.
If you want to change the month just add to t(:,2). You can even add numbers > 12 to the month and it will increase the year and month correctly if you transfer it back to a datenum or datestr.

find mean or median date of event

I have a dataset for which I have extracted the date at which an event occurred. The date is in the format of MMDDYY although MatLab does not show leading zeros so often it's MDDYY.
Is there a method to find the mean or median (I could use either) date? median works fine when there is an odd number of days but for even numbers I believe it is averaging the two middle ones which doesn't produce sensible values. I've been trying to convert the dates to a MatLab format with regexp and put it back together but I haven't gotten it to work. Thanks
dates=[32381 41081 40581 32381 32981 41081 40981 40581];
You can use datenum to convert dates to a serial date number (1 at 01/01/0000, 2 at 02/01/0000, 367 at 01/01/0001, etc.):
strDate='27112011';
numDate = datenum(strDate,'ddmmyyyy')
Any arithmetic operation can then be performed on these date numbers, like taking a mean or median:
mean(numDates)
median(numDates)
The only problem here, is that you don't have your dates in a string type, but as numbers. Luckily datenum also accepts numeric input, but you'll have to give the day, month and year separated in a vector:
numDate = datenum([year month day])
or as rows in a matrix if you have multiple timestamps.
So for your specified example data:
dates=[32381 41081 40581 32381 32981 41081 40981 40581];
years = mod(dates,100);
dates = (dates-years)./100;
days = mod(dates,100);
months = (dates-days)./100;
years = years + 1900; % set the years to the 20th century
numDates = datenum([years(:) months(:) days(:)]);
fprintf('The mean date is %s\n', datestr(mean(numDates)));
fprintf('The median date is %s\n', datestr(median(numDates)));
In this example I converted the resulting mean and median back to a readable date format using datestr, which takes the serial date number as input.
Try this:
dates=[32381 41081 40581 32381 32981 41081 40981 40581];
d=zeros(1,length(dates));
for i=1:length(dates)
d(i)=datenum(num2str(dates(i)),'ddmmyy');
end
m=mean(d);
m_str=datestr(m,'dd.mm.yy')
I hope this info to be useful, regards
Store the dates as YYMMDD, rather than as MMDDYY. This has the useful side effect that the numeric order of the dates is also the chronological order.
Here is the pseudo-code for a function that you could write.
foreach date:
year = date % 100
date = (date - year) / 100
day = date % 100
date = (date - day) / 100
month = date
newdate = year * 100 * 100 + month * 100 + day
end for
Once you have the dates in YYMMDD format, then find the median (numerically), and this is also the median chronologically.
You see above how to present dates as numbers.
I will add no your issue of finding median of the list. The default matlab median function will average the two middle values when there are an even number of values.
But you can do it yourself! Try this:
dates; % is your array of dates in numeric form
sdates = sort(dates);
mediandate = sdates(round((length(sdates)+1)/2));