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.

128 views (last 30 days)
Hi Folks,
I have tried and ended up in errors. For example(valid_date(2018, 4, 1) failed,The last day of every month
Variable valid has an incorrect value. valid_date(2000, 1, 31) failed..., Random leap years
Variable valid has an incorrect value. valid_date(1624, 2, 29) failed..., Random dates
Variable valid has an incorrect value. valid_date(1433, 6, 28) failed...)
Kindly point out the errors I have made!
function valid = valid_date(year,month,day)
if (nargin==3)
if (fix(valid_date)&&isscalar(valid_date))
if((rem(year,4)==0||rem(year,400)==0) && rem(year,100)~=0)
if((month==1||3||5||7||9||11) && 0<day<32)
valid=true;
elseif(month==2 && 0<day<30)
valid=true;
elseif((month==4||6||8||10||12) && 0<day<31)
valid=true;
else
valid=false;
end
else
if((month==1||3||5||7||9||11) && 0<day<32)
valid=true;
elseif((month==4||6||8||10||12) && 0<day<31)
valid=true;
elseif(month==2 && 0<day<29)
valid=true;
else
valid=false;
end
end
else
valid=false;
end
else
valid=false;
end
  4 Comments
Rakeshwar Elango
Rakeshwar Elango on 28 Jun 2019
Thank you Stephen and Guillaume as the newly invented statement of me didn't through any error so I was wandering wheather where it went wrong. Thank you for your suggesion!

Sign in to comment.

Accepted Answer

James Tursa
James Tursa on 27 Jun 2019
Looks like you are taking the same class as Rahul. Rather than repeat my answer here, I will simply direct you to the link:
  3 Comments
Karina Medina Barzola
Karina Medina Barzola on 8 Jun 2021
function valid = valid_date(year,month,day)
if (isscalar(year)&&isscalar(month)&&isscalar(day))&&(isinteger(year/4) || ~isinteger(year/4)) && ((month == 1) || (month == 3) || (month == 5) || (month == 7) || (month == 8) || (month == 10) || (month == 12)) && (day>0 && day<=31)
valid = true;
elseif (isscalar(year)&&isscalar(month)&&isscalar(day))&&(isinteger(year/4) || ~isinteger(year/4)) && ((month == 4) || (month == 6) || (month == 9) || (month == 11)) && (day>0 && day<=30)
valid = true;
elseif (isscalar(year)&&isscalar(month)&&isscalar(day))&&mod(year, 400) == 0 && month == 2 && (day>0 && day<=29)
valid = true;
elseif (isscalar(year)&&isscalar(month)&&isscalar(day))&&mod(year, 4) == 0 && mod(year, 100) ~= 0 && month == 2 && (day>0 && day<=29)
valid = true;
elseif (isscalar(year)&&isscalar(month)&&isscalar(day))&&~(mod(year, 400) == 0) && month == 2 && (day>0 && day<=28)
valid = true;
elseif (isscalar(year)&&isscalar(month)&&isscalar(day))&&~(mod(year, 4) == 0 && mod(year, 100) ~= 0) && month == 2 && (day>0 && day<=28)
valid = true;
else
valid = false;
end
Divyanshu Gupta
Divyanshu Gupta on 3 Jul 2022
Hello I tried floowing code but its not working can anyone tell why?
function valid = valid_date(year,month,day)
if isinteger(year) && year>0 && isinteger(month) && month==1||month==3||month==5||month==7||month==8||month==10||month==12 && day < 32 && isinteger(day) && day>0
valid = true;
elseif isinteger(year) && year>0 && isinteger(month) && month==4||month==6||month==9||month==11 && day <31 && isinteger(day) && day>0
valid = true;
elseif isinteger(year) && year>0 && isinteger(year/4) && isinteger(year/400) && isinteger(month) && month == 2 && isinteger(day) && day>0 && day < 30
valid = true;
elseif isinteger(year) && year>0 && ~isinteger(year/4) && isinteger(month) && month == 2 && isinteger(day) && day>0 && day < 29
valid = true;
else
valid = false;
end

Sign in to comment.

More Answers (14)

Martín Avalos Postigo
Martín Avalos Postigo on 28 Jun 2021
function valid = valid_date(year,month,day)
if sum(rem([year,month,day],1))==0 && sum([year,month,day]>0)==3
if ismember(month,[1,3,5,7,8,10,12]) && day<32
valid=true;
elseif ismember(month,[4,6,9,11]) && day<31
valid=true;
elseif month==2 && ismember(sum(rem(year,[4,100,400])==0),[1,3]) && day<30
valid=true;
elseif month==2 && ismember(sum(rem(year,[4,100,400])==0),[0,2]) && day<29
valid=true;
else
valid=false;
end
else
valid=false;
end
  3 Comments
Alexandar
Alexandar on 29 Jun 2022
Can you please explain what
sum(rem([year,month,day],1))==0
does? Is it trying to say if there is a remainder of 1 then it is false?
Walter Roberson
Walter Roberson on 4 Aug 2022
rem() of something with 1 is 0 if the item is integer, and is non-zero if the item has a fraction. So the rem([year,month,day],1) is creating a vector of fractions (possibly 0) for year, month, day. Those fractions are summed, and the sum is compared to 0. The hypothesis is that if the fractions are all 0 then the sum of fractions are 0, and if any of the fractions are non-zero, then the sum of the fractions would be non-zero.
However, the code has a bug:
sum(rem([-3.2,4.2,5],1))
ans = 0
compare to
sum(mod([-3.2,4.2,5],1))
ans = 1

Sign in to comment.


Jatan Shah
Jatan Shah on 5 Aug 2021
Edited: Walter Roberson on 4 Aug 2022
function valid = valid_date (year, month, day)
if nargin<3
valid = false;
elseif ~isscalar(year) || year<1 || year~=fix(year)
valid = false;
elseif ~isscalar(month) || month<1 || month~=fix(month) || month>12
valid = false;
elseif ~isscalar(day) || 1>day || day~=fix(day) || day>31
valid = false;
elseif (month==4 || month==6 || month==9 || month==11) && day>30
valid = false;
elseif month==2 && day>29
valid = false;
elseif month==2 && day>28 && (year/4) ~= fix(year/4)
valid = false;
elseif (year/100)==fix(year/100) && (year/400)~=fix(year/400)
valid = false;
else
valid = true;
end

Abhinav Gadge
Abhinav Gadge on 31 Jul 2022
Edited: Abhinav Gadge on 31 Jul 2022
%works correctly for all cases
function valid=valid_date(y,m,d)
days=[31,28,31,30,31,30,31,31,30,31,30,31]
if (mod(y,4)==0 & mod(y,100) ~=0) | mod(y,400)==0
days(2)=29
end
if (isscalar(y) & isscalar(m) & isscalar(d)) & y>1 & (m>=1 & m<=12) & (d>=1 & d<=days(m))
valid=true
else
valid=false
end
end

VIGNESH B S
VIGNESH B S on 13 Oct 2021
Edited: DGM on 21 Feb 2023
function [valid] = valid_date(year,month,day)
Entered = 0;
if isscalar(year) == 0
valid = logical(0);
Entered = 1;
elseif isscalar(month) == 0
valid = logical(0);
Entered = 1;
elseif isscalar(day) == 0
valid = logical(0);
Entered = 1;
end
if year <= 0
valid = logical(0);
Entered = 1;
elseif month <= 0
valid = logical(0);
Entered = 1;
elseif day <= 0
valid = logical(0);
Entered = 1;
end
leap_year = 0;
if(mod(year,4) == 0)
leap_year = 1;
if mod(year,100) == 0
if mod(year,400) == 0
leap_year = 1;
else
leap_year = 0;
end
end
end
if [leap_year,month,day] == [0,2,29]
valid = logical(0);
Entered = 1;
end
if [leap_year,month,day] == [1,2,29]
valid = logical(1);
end
if month == 1
if day >= 32
valid = (0>1);
Entered = 1;
end
elseif month == 10
if day >= 32
valid = (0>1);
Entered = 1;
end
elseif month == 8
if day >= 32
valid = (0>1);
Entered = 1;
end
elseif month == 7
if day >= 32
valid = (0>1);
Entered = 1;
end
elseif month == 5
if day >= 32
valid = (0>1);
Entered = 1;
end
elseif month == 3
if day >= 32
valid = (0>1);
Entered = 1;
end
elseif month == 12
if day >= 32
valid = (0>1);
Entered = 1;
end
elseif month == 4
if day >= 31
valid = logical(0);
Entered = 1;
end
elseif month == 9
if day >= 31
valid = logical(0);
Entered = 1;
end
elseif month == 6
if day >= 31
valid = logical(0);
Entered = 1;
end
elseif month == 11
if day >= 31
valid = logical(0);
Entered = 1;
end
end
if month == 2
if day >= 30
Entered = 1;
valid = logical(0);
end
end
if month >= 13
Entered = 1;
valid = logical(0);
end
if Entered == 0
valid = logical(1);
end
end
%A HELL LINES OF CODES!!!!!!! BUT IT WORKED OUT !!

S HARIPRAKASH
S HARIPRAKASH on 25 Aug 2021
valid date or not
function valid=valid_date(year,month,day)
%check whether the given input is scalar positive integer or not
%1<=day<=31
%1<=month<=12
if((~isscalar(year))||(~isscalar(month))||(~isscalar(day))||(year<=0)||(month<=0)||(day<=0)||(month>12)||(day>31)||(~(year==fix(year)))||(~(month==fix(month)))||(~(day==fix(day))))
valid=false;
return
end
%february has 29 days in leap year and 28 days in non leap year
if (month==2)
if((mod(year,4)==0 && mod(year,100)~=0)||(mod(year,400)==0))
if day<30
valid=true;
return
else
valid=false;
return
end
else
if day<29
valid=true;return
else
valid=false;return
end
end
%check whether the number of given days is within the limit of days that particular month has.
else
month_days=[31,28,31,30,31,30,31,31,30,31,30,31];
if day<=month_days(month)
valid=true;
return
else
valid=false;
return
end
end
end

Fazal Hussain
Fazal Hussain on 19 Jan 2022
Edited: DGM on 21 Feb 2023
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

Erikc Anderson Cortez Benites
function valid = valid_date(year, month, day)
if isscalar(year) && isscalar(month) && isscalar(day)
if month < 1 || month > 12
valid = false;
else
if month == 2 && isleapyear(year)
valid = day <= 29 && day>0 ;
elseif sum(month == [1,3,5,7,8,10,12])
valid = day <= 31 && day>0;
else
valid = day <= 30 && day>0;
end
end
else
valid = false;
end
function re = isleapyear(year)
if mod(year,400) == 0
re = 1;
elseif (mod(year,4) == 0) && (mod(year,100)) ~= 0
re = 1;
else
re = 0;
end

Ravleen Kaur
Ravleen Kaur on 19 May 2022
function valid = valid_date(year,month,day)
if (isscalar(year) && (year>=1) && year==fix(year)) && (isscalar(month) && ((1<=month)&&(month<=12)) && (month==fix(month))) && (isscalar(day) && ((1<=day)) && (day==fix(day)))
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) && day<32
valid = true;
elseif ( month == 4 || month == 6 || month == 7 || month == 9 || month == 11) && day<31
valid = true;
else
valid = false;
end
if (month == 2)
if day<29
valid = true; return
elseif day<30 && rem(year,4)==0 && rem(year,100)~=0 || rem(year,400)==0
valid = true; return
else
valid = false; return
end
end
else
valid = false; return
end

David Goh
David Goh on 20 Jun 2022
function valid = valid_date(year,month,day)
if isscalar(year) == 1 && isscalar(month) == 1 && isscalar(day) == 1 && year > 0 && month > 0 && day > 0
if month <= 12
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)
if day <= 31
valid = true;
else
valid = false;
end
elseif month == 2
if (rem(year,4)==0 || rem(year,400)==0) && (rem(year,400)~=100 && rem(year,400)~=200 && rem(year,400)~=300)
if day <= 29
valid = true;
else
valid = false;
end
else
if day <= 28
valid = true;
else
valid = false;
end
end
else
if day <= 30
valid = true;
else
valid = false;
end
end
else
valid = false;
end
else
valid = false;
end

Muhammad
Muhammad on 25 Jul 2022
function valid =valid_date(year,month,day)
if isscalar(year)&&isscalar(month)&&isscalar(day)&& (isinteger((year/4)==0) || ~isinteger((year/400==0))) && ((month==1) || (month==3) || (month==5) || (month==7) ||(month==8) || (month==10 )|| (month==12 )) && (day>=1 && day<=31)
valid=true;
elseif isscalar(year)&&isscalar(month)&&isscalar(day)&& (isinteger((year/4)==0) || ~isinteger((year/400==0))) && ((month==4) || (month==6) || (month==9) || (month==11))&&(day>=1 && day<=30)
valid=true;
elseif isscalar(year)&&isscalar(month)&&isscalar(day)&& (mod(year,4)==0)&& mod(year,100)~=0 && month==2 && (day>=1 && day<=29)
valid=true;
elseif isscalar(year)&&isscalar(month)&&isscalar(day)&& (mod(year,400)==0) && (month==2) && (day>=1 && day<=29)
valid=true;
elseif isscalar(year)&&isscalar(month)&&isscalar(day)&& (mod(year,400)~=0) && month==2 &&(day>=1 && day<=28)
valid=true;
elseif isscalar(year)&&isscalar(month)&&isscalar(day)&& (mod(year,4)~=0) && month==2 &&(day>=1 && day<=28)
valid=true;
else
valid=false;
end
  2 Comments
Walter Roberson
Walter Roberson on 25 Jul 2022
It is not efficient to keep checking isscalar()
I think you should check the documentation about the relative priority of the two short-circuit logic operators. I do not recommend chaining them together without using () to make the interpretation clear to people reading the code
Muhammad
Muhammad on 25 Jul 2022
Thanks for pointing that out. I'll definitely revisit the relative priority of the two short-circuit logic operators

Sign in to comment.


ARYA
ARYA on 18 Oct 2022
function valid= valid_date(year,month,day)
flag=0;
if(month<=0||month>12||day<=0||day>31)
flag=0;
else
if(month==4||month==6||month==9||month==11)
if day<=30
flag=1;
else
flag=0;
end
elseif month==2
if (mod(year,4)==0&&mod(year,100)~=0)||(mod(year,400)==0)&& day<=29
flag=1;
elseif (day<=28)
flag=1;
else
flag=0;
end
else
if day<=31
flag=1;
else
flag=0;
end
end
end
if(~isscalar(year)||~isscalar(month)||~isscalar(day))
flag=0;
end
if(flag==0)
valid=false;
else
valid=true;
end

Paul
Paul on 17 May 2023
Edited: DGM on 23 Aug 2023
function valid = valid_date(y,m,d);
if ~isscalar(y)||~isscalar(m)||~isscalar(d)||y~=fix(y)||m~=fix(m)||d~=fix(d);
valid = false;
else
if y > 0 && (m == 12 || m == 1 || m == 3 || m == 5|| m == 7 || m == 8 || m == 10) && d >= 1 && d <= 31;
valid = true;
elseif (m== 4 || m == 6 || m ==9 || m == 11) && d >=1 && d <= 30;
valid = true;
elseif m==2 && d>=1 && d<=28;
valid = true;
elseif ((mod(y,4)==0 && mod(y,100)~=0)||mod(y,400)==0) && m==2 && d>=1 && d<=29;
valid = true;
else
valid = false;
end
end
end
  1 Comment
DGM
DGM on 23 Aug 2023
This fails for negative years. When you have a control structure with a single output and you have multiple cases where the output is identical, that's a good sign that you need to simplify things. Similarly, see how many times you're checking that d>=1.
I can't fault you too much, since your example is at least relatively compact already, but it still squarely fits the theme of giant tangled salads of undocumented inline logic in nested control structures. It's easy to miss certain cases when you can't really even read the logic or understand how it's responding to the inputs. You can make it easier on yourself if you use logical variables to describe the aspects of the input, and then simply calculate the output based on a logical combination of those variables. That way you can easily see whether things are being evaluated correctly.

Sign in to comment.


DGM
DGM on 23 Aug 2023
Edited: DGM on 23 Aug 2023
Instead of a giant undocumented salad of inline logic, use logical variables to clearly describe the input conditions as they pertain to the relevant concepts.
function valid = valid_date(y,m,d)
% VALID = VALID_DATE(Y,M,D)
% Synopsis goes here blah blah blah
% basic input validation
scalarinput = isscalar(y) && isscalar(m) && isscalar(d);
integerinput = ~mod(y,1) && ~mod(m,1) && ~mod(d,1);
nonsenseinput = y<1 || m<1 || m>12 || d<1 || d>31;
acceptableinput = scalarinput && integerinput && ~nonsenseinput;
% three classes of month length
isleapyear = ~mod(y,4) && (mod(y,100) || ~mod(y,400));
validmonthA = ismember(m,[1 3 5 7 8 10 12]) && d<=31;
validmonthB = ismember(m,[4 6 9 11]) && d<=30;
validmonthC = m==2 && d<=(28 + isleapyear); % implicit casting of logicals to numeric!
% assemble the output based on those conditions
valid = acceptableinput && (validmonthA || validmonthB || validmonthC)
end
The variable names are self-explanatory, and tell you exactly what's being tested on each line. At a glance, you know that the output is only true when the given inputs are scalar, integer, within sensible ranges, and together describe one of three classes of month (31 days, 30 days, and February).
This example leans heavily on implicit casting behaviors in MATLAB. The use of comparision or negation operators will make sure the numeric output of mod() is always logical. Similarly, adding a logical to a numeric value treats the logical as either zero or one.
Could this be made more efficient using an if-else structure? Yes, though for scalar inputs, I doubt that the benefit of early returns are even measurable. The reason I did it this way is simply for emphasis.
Did I miss something? I don't know. I'm not the one taking the online course.

Aramis
Aramis on 5 Feb 2024
The best answer
function valid = valid_date(year,month,day)
if not(isscalar(year))|| not(isscalar(month)) || not(isscalar(day))|| min([year month day]) <1 || month>12 || day>31 || nargin<3
valid = false;
elseif month == 2
if mod(year,4) == 0 && not(mod(year,100) == 0) || mod(year,400) == 0
valid = day<30;
else
valid = day<29;
end
elseif max(month == [4 6 9 11])
valid = day<31;
else
valid = true;
end
end

Community Treasure Hunt

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

Start Hunting!