How to write a function to determine if a date entered is valid

I am to Write a function called valid_date that takes three positive integer scalar inputs year, month, day. If these three represent a valid date, return a logical true, otherwise false. The name of the output argument is valid. If any of the inputs is not a positive integer scalar, return false as well. Here is the code i have tried but keeps returning true for all dates, I have editted it a lot and now i just need a fresh eye to point out what i am doing wrong:
NB: I am not to use any built in MatLab function.
function valid = valid_date (year, month, date)
if (nargin==3)
valid=true;
elseif (isinteger(year)) && year>0 && (isscalar(year))
valid=true;
elseif (isinteger(month))&& month>0 && month <=12 && (isscalar(month))
valid=true;
elseif (isinteger(date)) && date > 0 && (isscalar(date))
valid=true;
elseif (month==1||month==3||month==5||month==7||month==8||month==10||month==12)&& date<=31
valid=true;
elseif date <=30
valid=true;
elseif (isinteger(year/4)) && month == 2 && (~(isinteger(year/100))||(isinteger(year/400))) && date <= 29
valid=true;
else
valid = false;
end

9 Kommentare

isinteger() and isscalar() are built-in functions.
Also, you can't just say it's valid after checking the year alone or the number of inputs. You have to check the months and days also.
so do i need to take out all the "valid = true" lines?
"so do i need to take out all the "valid = true" lines?"
No, you need to revise your logic. For example, the very first thing your function does is check if three inputs were provided:
function valid = valid_date (year, month, date)
if (nargin==3)
valid=true;
elseif ...
...
end
and if there are three inputs then you set valid=true and exit the function. So I could provide any three inputs and your function would set valid=true ... is that what your assignment required?
You can arrange the code as a cascade of rejections, each step declaring that valid is false if conditions were not met. Then at the very end when all possible rejections had been processed, anything left over must be valid.
Okay, I get now. I will find a way to cascade it as rejections and see how it goes. Thank you Walter. Stephen, that's not what I want, I will try and work on it!
Hello Walter, I tried doing that and everything returns false now.
Here is the code
function valid = valid_date (year, month, date)
if (nargin~=3)
valid=false;
elseif ~(isinteger(year)) && year>0 && (isscalar(year))
valid=false;
elseif ~(isinteger(month))&& month>0 && month <=12 && (isscalar(month))
valid=false;
elseif ~(isinteger(date)) && date > 0 && (isscalar(date))
valid=false;
elseif ~(month==1||month==3||month==5||month==7||month==8||month==10||month==12)&& date<=31
valid=false;
elseif ~(date <=30)
valid=false;
elseif ~(isinteger(year/4)) && month == 2 && (~(isinteger(year/100))||(isinteger(year/400))) && date <= 29
valid=false;
else
valid = true;
end
TF = isinteger(A) returns logical 1 (true) if A is an array of integer type. Otherwise, it returns logical 0 (false).
Not integer value, integer type
so what can i use in place of isinteger
Stephen23
Stephen23 am 31 Dez. 2019
Bearbeitet: Stephen23 am 31 Dez. 2019
"so what can i use in place of isinteger"
Take a look at this answer you were given six hours ago:
Does it use isinteger? (hint: no)
What does it use? (hint: mod)
Also read my comment following that answer.

Melden Sie sich an, um zu kommentieren.

Antworten (4)

function isvalid = valid_date(y, m, d)
% Check if the inputs are valid
% Check that they are scalars
if ~(isscalar(y) && isscalar(m) && isscalar(d))
isvalid = false;
% Check that inputs are positive
elseif ~all([y, m, d] > 0)
isvalid = false;
% Check that inputs are integers (not the data type)
elseif any(rem([y, m, d], 1))
isvalid = false;
% Check that m and d are below the max possible
elseif (m > 12) || (d > 31)
isvalid = false;
% The inputs could be a valid date, let's see if they actually are
else
% Vector of the number of days for each month
daysInMonth = [31 28 31 30 31 30 31 31 30 31 30 31];
% If leap year, change days in Feb
if isequal(rem(y, 4), 0) && (~isequal(rem(y, 100), 0) || isequal(rem(y, 400), 0))
daysInMonth(2) = 29;
end
maxDay = daysInMonth(m);
if d > maxDay
isvalid = false;
else
isvalid = true;
end
end
end
function valid = valid_date(year,month,day)
if nargin ~=3
valid=false;
elseif ((~isscalar(year))||(mod(year,1)~=0)||year<=0)
valid=false;
elseif ((~isscalar(month))||(mod(month,1)~=0)||month<=0||month>12)
valid=false;
elseif ((~isscalar(day))||(mod(day,1)~=0)||day<=0)
valid=false;
elseif (any(month==[1,3,5,7,8,10,12]) && day>31)
valid=false;
elseif (any(month==[4,6,9,11]) && day>30)
valid=false;
else
valid=true;
if (rem(year,4)==0 && month==2 && day<=29)
valid=true;
if (rem(year,100)==0)
valid=false;
if rem(year,400)==0
valid=true;
return
end
end
elseif month==2 && day>28
valid=false;
end
end
end

4 Kommentare

this is the final code.
if (rem(year,4)==0 && month==2 && day<=29)
valid=true;
if (rem(year,100)==0)
valid=false;
No, that would declare (for example) February 15 1900 to be invalid. rem(year,4) would be 0, month would be 2, day <= 29 would be true, so you would set valid true, but then you test rem(year,100)=0 which would be true so you would set valid = false. Then rem(year,400) would not be 0 so you would leave valid false. Then since you found true on the year/month/day test you would not execute the elseif so valid will still be false. Then you would return, with valid still false.
function valid = valid_date_2(year,month,day)
if nargin ~=3
valid=false;
elseif ((~isscalar(year))||(mod(year,1)~=0)||year<=0)
valid=false;
elseif ((~isscalar(month))||(mod(month,1)~=0)||month<=0||month>12)
valid=false;
elseif ((~isscalar(day))||(mod(day,1)~=0)||day<=0)
valid=false;
elseif (any(month==[1,3,5,7,8,10,12]) && day>31)
valid=false;
elseif (any(month==[4,6,9,11]) && day>30)
valid=false;
else
valid=true;
if (rem(year,4)==0 && month==2 && day<=29)
valid=true;
if ((rem(year,100)==0)&& day>28)
valid=false;
if (rem(year,400)==0 && day<=29)
valid=true;
return
end
end
elseif month==2 && day>28
valid=false;
end
is this the correct one?

Melden Sie sich an, um zu kommentieren.

Hi,
You can try the following function and see if it works for you:
function valid = valid_date(year, month, date)
if(nargin ~= 3)
valid = false;
elseif (~(mod(year,1)==0) || (year<0) || ~isscalar(year))
valid = false;
elseif (~(mod(month,1)==0) || (month<=0) || (month>12) || ~isscalar(month))
valid = false;
elseif (~(mod(date,1)==0) || (date<=0) || ~isscalar(date))
valid = false;
elseif( (month==1||month==3||month==5||month==7||month==8||month==10||month==12)&& date>31 )
valid = false;
elseif ((month==4||month==6||month==9||month==11) && date>30)
valid = false;
elseif(~leapyear(year) && month==2 && date>28)
valid=false;
elseif(leapyear(year) && month==2 && date>29)
valid=false;
else
valid = true;
end

6 Kommentare

This answer has a few bugs in it, for example, the order of these arguments:
(~(mod(year,1)==0) || (year<0) || ~isscalar(year)
means that if year is non-scalar the code will throw an error (as inputs to the short-circuiting || must be scalar). The solution is to read the || documentation and check isscalar first, then the code will work as specified by the assignment:
~isscalar(year) || ...
The function leapyear is in the Aerospace Toolbox, which is unlikely to be available to most MATLAB users.
Rather than this obfuscation
~(mod(year,1)==0)
prefer the simpler
mod(year,1)~=0
Rather than repeating code:
month==1||month==3||month==5||month==7||month==8||month==10||month==12
just use basic MATLAB vector operations:
any(month==[1:2:7,8:2:12])
Hello, I have worke on it and i am not supposed to use any date function already in matlab, but the leap year still gives me errors for some inputs.
This is my function
function valid = valid_date(year, month, date)
if(nargin ~= 3)
valid = false;
elseif ((~isscalar(year)||(mod(year,1)~=0) || year<0))
valid = false;
elseif ((~isscalar(month))||(mod(month,1)~=0) || (month<=0) || (month>12))
valid = false;
elseif ((~isscalar(date))||(mod(date,1)~=0) || (date<=0))
valid = false;
elseif(any(month==[1:2:7,8:2:12])&& date>31)
valid = false;
elseif (any(month==[4,6,9,11]) && date>30)
valid = false;
elseif(mod(year,4)~=0 && month==2 && date>28)
valid=false;
elseif((mod(year,4)==0) && (mod(year,400)==0 && mod(year,100)==0) && month==2 && date>29)
valid=false;
else
valid = true;
end
it still recognizes 1900 as a leap year
Nice work. Your code is developing nicely.
Leap years are a bit fiddly. One simple approach would be to calculate the date limit number based on the year (i.e. not have a hard-coded 28 or 29), e.g. replace your two leapyear elseif conditions/statements with something like this:
elseif month==2 && date>(28+(mod(year,400)==0 || (mod(year,100)~=0 && mod(year,4)==0)))
Thanks a lot. That was really a nice way to work around it.
This is the final code and everything worked.
function valid = valid_date(year, month, date)
if(nargin ~= 3)
valid = false;
elseif ((~isscalar(year)||(mod(year,1)~=0) || year<0))
valid = false;
elseif ((~isscalar(month))||(mod(month,1)~=0) || (month<=0) || (month>12))
valid = false;
elseif ((~isscalar(date))||(mod(date,1)~=0) || (date<=0))
valid = false;
elseif(any(month==[1:2:7,8:2:12])&& date>31)
valid = false;
elseif (any(month==[4,6,9,11]) && date>30)
valid = false;
elseif month==2 && date>(28+(mod(year,400)==0 || (mod(year,100)~=0 && mod(year,4)==0)))
valid=false;
else
valid = true;
end
Thanks a lot once again.
Code doesn't work
Anil Muradiya which code are you finding is failing, and what inputs are you finding that it is failing on?

Melden Sie sich an, um zu kommentieren.

Sravani Kurma
Sravani Kurma am 17 Jul. 2020
Bearbeitet: Sravani Kurma am 17 Jul. 2020
function valid=valid_date(year,month,date)
if nargin == 3;
if ~isscalar(year) || year<1|| year~=fix(year)||~isscalar(month) || month<1|| month~=fix(month)||~isscalar(date) || date<1|| date~=fix(date);
valid=false;
else
if ((year/100)~=fix(year/100)&&(year/4)==fix(year/4))||((year/400)==fix(year/400));
%leap yr
valid=mmm(month,date);
else
%non leap year
valid=sss(month,date);
end
end
end
function valid=mmm(month,date)
m30=[4,6,9,11];
m31=[1,3,5,7,8,10,12];
m29=2;
m28=2;
if max((month==m31)')==1
valid=(date>=1)&&date<=31;
elseif max(( month==m30)')==1
valid=(date>=1)&&date<=30;
elseif max((month==m29)')==1
valid=(date>=1)&&date<=29;
else
valid=false;
end
function valid=sss(month,date)
m30=[4,6,9,11];
m31=[1,3,5,7,8,10,12];
m29=2;
m28=2;
if max((month==m31)')==1
valid=(date>=1)&&date<=31;
elseif max(( month==m30)')==1
valid=(date>=1)&&date<=30;
elseif max((month==m28)')==1
valid=(date>=1)&&date<=28;
else
valid=false;
end

Kategorien

Gefragt:

am 28 Dez. 2019

Kommentiert:

am 17 Jul. 2020

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by