Valid_date function

1 visualizzazione (ultimi 30 giorni)
Denise Gobbo
Denise Gobbo il 18 Mag 2020
Commentato: Rik il 22 Set 2021
I am having some troubles with the logical operators in "day". What could I do to solve it?
function valid = valid_date(year, month, day)
if ~isinteger(year)
if ~isinteger(month)
if ~isinteger(day)
if ~isscalar(year)
if ~isscalar(month)
if ~isscalar(day)
valid = false;
elseif month == 2
if ((rem(year,4)== 0) && (rem(year,100) ~= 0)) || (rem(year,400)==0)
(1 <= day) && (day <= 28);
valid = true;
else
(1 <= day) && (day <= 29);
valid = true;
end
elseif month == 1 || 3 || 5 || 7 || 8 || 10 || 12
(1 <= day)&(day <= 31);
valid = true;
elseif month == 4 || 6 || 9 || 11
1 <= day <= 30;
valid = true;
else
valid = false;
end
end
end
end
end
end
end
  4 Commenti
the cyclist
the cyclist il 18 Mag 2020
Personal preference, perhaps, but I actually like keeping the indenting of the isinteger if statements. To my mind, they are a logical grouping and easier to interpret as that group if they appear at the same level if indentation. Similarly, I usually write
for x = 1:10
for y = 1:10
% do something in x-y space
end
end
because x and y are "on equal footing" as spatial coordinates.
Of course, the point is moot because I'm pretty certain that all those if statements are the not the logic that OP is intending to implement.
Adam Danz
Adam Danz il 18 Mag 2020
Modificato: Adam Danz il 18 Mag 2020
Thanks for sharing that perspective, @the cyclist . I can see how that grouping can be helpful when the conditional statements are fully nested. If there are additional lines of code outside of the nested structure, I bet it would become difficult to read, though.
eg
for x = 1:10
for y = 1:10
for z = 1:10
% do something in x-y-z space
end
% some code here
end
% some code here
end

Accedi per commentare.

Risposte (6)

Thyagharajan K K
Thyagharajan K K il 2 Giu 2020
valid = valid_date(2019, 12, 1)
function valid = valid_date(year,month,day)
%check if either year, month, day is not a scalar
if ~isscalar(year) || ~isscalar(month) || ~isscalar(day)
valid =false
return
end
%check if either year, month, day is 0 or negative. check if month is >12
if year<=0 || month>12 || month <=0 ||day<=0
valid =false
return
end
A = [1 3 5 7 8 10 12]; %months with 31 days
B = [4 6 9 11]; %months with 30days
month_31d = sum(ismember(A,month));
%ismember() returns a logical array where element found will be marked as 1 & other positions will be 0
%so only one element in this logical array will be 1 and other elements will be 0 if month falls in this
%month_31d category. Hence sum will be 1 i.e month_31d will be true.
month_30d = sum(ismember(B,month)); %same as above to check whether month falls in the category month_30d
%check for leap year
if rem(year,400)==0
leap_year = true;
elseif rem(year,4)==0 && rem(year,100) ~=0
leap_year =true;
else
leap_year = false;
end
%Check the days for the conditions 28,29,30,31
if month_31d && day>31
valid = false;
elseif month_30d && day>30
valid = false;
elseif (leap_year && month==2 && day>29)||(~leap_year&&month==2&&day>28)
valid = false;
else
valid =true;
end
end
  1 Commento
Walter Roberson
Walter Roberson il 21 Mar 2021
Needs improvement.
try valid_date(nan,nan,nan), catch ME; disp(ME.message); end
ans = logical
1
try valid_date(1234.56,1,7), catch ME; disp(ME.message); end
ans = logical
1
try valid_date(1234,1.23,7), catch ME; disp(ME.message); end
ans = logical
1
try valid_date(1234,1,7.89), catch ME; disp(ME.message); end
ans = logical
1
try valid_date(2021,2,7+3i), catch ME; disp(ME.message); end
ans = logical
1
try valid_date(inf,2,29), catch ME; disp(ME.message); end
ans = logical
0
function valid = valid_date(year,month,day)
%check if either year, month, day is not a scalar
if ~isscalar(year) || ~isscalar(month) || ~isscalar(day)
valid =false
return
end
%check if either year, month, day is 0 or negative. check if month is >12
if year<=0 || month>12 || month <=0 ||day<=0
valid =false
return
end
A = [1 3 5 7 8 10 12]; %months with 31 days
B = [4 6 9 11]; %months with 30days
month_31d = sum(ismember(A,month));
%ismember() returns a logical array where element found will be marked as 1 & other positions will be 0
%so only one element in this logical array will be 1 and other elements will be 0 if month falls in this
%month_31d category. Hence sum will be 1 i.e month_31d will be true.
month_30d = sum(ismember(B,month)); %same as above to check whether month falls in the category month_30d
%check for leap year
if rem(year,400)==0
leap_year = true;
elseif rem(year,4)==0 && rem(year,100) ~=0
leap_year =true;
else
leap_year = false;
end
%Check the days for the conditions 28,29,30,31
if month_31d && day>31
valid = false;
elseif month_30d && day>30
valid = false;
elseif (leap_year && month==2 && day>29)||(~leap_year&&month==2&&day>28)
valid = false;
else
valid =true;
end
end

Accedi per commentare.


the cyclist
the cyclist il 18 Mag 2020
Modificato: the cyclist il 18 Mag 2020
This syntax
1 <= day <= 30
does not check if day is between 1 and 30. You need to do that as two separate checks:
(1 <= day) & (day <= 30);
as you did in the other sections.
Also, for this chain of if statements:
if ~isinteger(year)
if ~isinteger(month)
if ~isinteger(day)
if ~isscalar(year)
if ~isscalar(month)
if ~isscalar(day)
I think you probably actually want a single if statement:
if ~isinteger(year) || ~isinteger(month) || ~isinteger(day) ... and so on
valid = false
end
The way your code is written, if year is an integer, then your function will simply exit, never having evaluated the output variable valid.

Adam Danz
Adam Danz il 18 Mag 2020
"I am having some troubles with the logical operators in "day"."
That doesn't give us enough background infomation to know what the problem is. Does that mean you're getting an error? The wrong value? The wrong class? An empty output? Is it causing your compute to explode? etc. We can help you more quickly if you tell us what the problem is.
That being said, there are lots of problems with this code and the the problems I immediately see have nothing to do with the 'day' variable.
For example, let's say Year is an interger but Month is not. Read through your code and estimate what would happen. Hint: no output at all.
If you want to return a value of false when the inputs aren't in the correct format,
if ~isinteger(year) || ~isinteger(month) || . . . || ~isscalar(month)
valid = false;
else
% [main part of your code]
end
If you want to determine if the month is 1,3,5,7,8,10 or 12,
if ismember(month, [1 3 5. . .]);
If you want to define values based on differet sets of months,
switch month
case 2
% your code
case {1 3 5 . . .}
% your code
case {4 6 9 . . .}
% your code
otherwise
error('Month did not meet any of the case requrements.')
end

Himanshi Singh
Himanshi Singh il 6 Set 2020
function valid = valid_date (year, month, date)
if ~(isscalar(year) && isscalar(month) && isscalar(date))
valid=false;
elseif year ~= fix(year) || year<1
valid=false;
elseif month ~= fix(month) || month<1 || month>12
valid=false;
elseif date ~= fix(date) || date<1 || date>31
valid=false;
elseif (month == 4 || month == 6 || month == 9 || month == 11) && date>30
valid = false;
elseif month == 2 && ((year/4 ~= fix(year/4) || (year/100 == fix(year/100) && year/400 ~= fix(year/400))) || date>29)&&date>28
valid = false;
else
valid = true;
end
  2 Commenti
Rik
Rik il 6 Set 2020
Why did you post a complete solution to a homework question without any explanation? Now your answer is only useful for people wanting to cheat.
Walter Roberson
Walter Roberson il 21 Mar 2021
Better than some, but could still use improvement.
try valid_date(nan,nan,nan), catch ME; disp(ME.message); end
ans = logical
0
try valid_date(1234.56,1,7), catch ME; disp(ME.message); end
ans = logical
0
try valid_date(1234,1.23,7), catch ME; disp(ME.message); end
ans = logical
0
try valid_date(1234,1,7.89), catch ME; disp(ME.message); end
ans = logical
0
try valid_date(2021,2,7+3i), catch ME; disp(ME.message); end
ans = logical
1
try valid_date(inf,2,29), catch ME; disp(ME.message); end
ans = logical
1
function valid = valid_date (year, month, date)
if ~(isscalar(year) && isscalar(month) && isscalar(date))
valid=false;
elseif year ~= fix(year) || year<1
valid=false;
elseif month ~= fix(month) || month<1 || month>12
valid=false;
elseif date ~= fix(date) || date<1 || date>31
valid=false;
elseif (month == 4 || month == 6 || month == 9 || month == 11) && date>30
valid = false;
elseif month == 2 && ((year/4 ~= fix(year/4) || (year/100 == fix(year/100) && year/400 ~= fix(year/400))) || date>29)&&date>28
valid = false;
else
valid = true;
end
end

Accedi per commentare.


Ahmed Saleh
Ahmed Saleh il 21 Mar 2021
Modificato: Ahmed Saleh il 21 Mar 2021
function valid = valid_date(year,month,day)
y= year;
m=month;
d=day;
days_1=[31 28 31 30 31 30 31 31 30 31 30 31];
if (fix(y/4)==(y/4) && fix(y/100)~=(y/100)) || (fix(y/4)==(y/4) && fix(y/100)==(y/100) && fix(y/400)==(y/400))
days_1(2)=29;
end
if ~isscalar(y) || ~isscalar(m) || ~isscalar(d)
valid= false;
return
elseif y<=0 || m<=0 || d<=0 || m>12 || d>31
valid = false;
return
elseif days_1(m)<d
valid=false;
return
else
valid=true;
end
  4 Commenti
Walter Roberson
Walter Roberson il 21 Mar 2021
Rik, please leave this one, as my unit tests are instructive.
Rik
Rik il 21 Mar 2021
@Walter Roberson I agree, and have consequently remove the flag.

Accedi per commentare.


Kabir Puri
Kabir Puri il 22 Set 2021
% this is my answer
function valid = valid_date(year, month, day);
if day<=0 || month <=0 || ~isscalar(year) ||~isscalar(month)||~isscalar(day)||mod(day,1)~=0 ||mod(month,1)~=0||mod(year,1)~=0;
valid = false;
elseif month>12;
valid = false;
elseif (month==1 || month==3|| month==5||month==7||month==8||month==10||month==12)&& day>31;
valid = false;
elseif (month==4||month==6||month==9||month==11)&&day>30;
valid = false;
elseif (month == 2 && ((mod(year,4)==0 && mod(year,100)~=0)||(mod(year,400)==0)) ) && day>29
valid =false;
elseif month== 2 && ~((mod(year,4)==0 && mod(year,100)~=0)||(mod(year,400)==0)) && day>28;
valid= false;
else;
valid =true;
end;
  1 Commento
Rik
Rik il 22 Set 2021
I added an extra end to your function, but after that it passes almost all the unit tests by Walter (you only missed the complex-valued input) and you missed my addition (different datatype).
So now only the question remains why you decided to post this solution to a homework question?
try valid_date(nan,nan,nan), catch ME; disp(ME.message); end
ans = logical
0
try valid_date(1234.56,1,7), catch ME; disp(ME.message); end
ans = logical
0
try valid_date(1234,1.23,7), catch ME; disp(ME.message); end
ans = logical
0
try valid_date(1234,1,7.89), catch ME; disp(ME.message); end
ans = logical
0
try valid_date(2021,2,7+3i), catch ME; disp(ME.message); end
Arguments must be real.
try valid_date(inf,2,29), catch ME; disp(ME.message); end
ans = logical
0
try valid_date(struct,2,28), catch ME; disp(ME.message); end
Undefined function 'mod' for input arguments of type 'struct'.
function valid = valid_date(year, month, day);
if day<=0 || month <=0 || ~isscalar(year) ||~isscalar(month)||~isscalar(day)||mod(day,1)~=0 ||mod(month,1)~=0||mod(year,1)~=0;
valid = false;
elseif month>12
valid = false;
elseif (month==1 || month==3|| month==5||month==7||month==8||month==10||month==12)&& day>31
valid = false;
elseif (month==4||month==6||month==9||month==11)&&day>30
valid = false;
elseif (month == 2 && ((mod(year,4)==0 && mod(year,100)~=0)||(mod(year,400)==0)) ) && day>29
valid =false;
elseif month== 2 && ~((mod(year,4)==0 && mod(year,100)~=0)||(mod(year,400)==0)) && day>28
valid= false;
else
valid =true;
end
end

Accedi per commentare.

Categorie

Scopri di più su Dates and Time in Help Center e File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by