Info
This question is locked. Reopen it to edit or answer.
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.
    20 views (last 30 days)
  
       Show older comments
    
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
Accepted Answer
  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
 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
 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
More Answers (14)
  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
 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
      
      
 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))
compare to
sum(mod([-3.2,4.2,5],1))
  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
1 Comment
  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
0 Comments
  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 !!
1 Comment
  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
0 Comments
  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
0 Comments
  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
0 Comments
  Erikc Anderson Cortez Benites
 on 3 Apr 2022
        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
0 Comments
  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
0 Comments
  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
0 Comments
  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
      
      
 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
 on 25 Jul 2022
				Thanks for pointing that out. I'll definitely revisit the relative priority of the two short-circuit logic operators
  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
 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
      
      
 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.
  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.
0 Comments
This question is locked.
See Also
Categories
				Find more on Data Type Identification in Help Center and File Exchange
			
	Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
























