Checking if a Date is Valid in MATLAB - matlab

So as to not mislead anyone, this is a HW problem that I am attempting to complete and need a little help with. The problem itself is pretty self-explanatory. I have to write a function where I input a string 'Month Day, Year' and have it tell me whether or not it's valid (true or false statements). I have it working for almost everything, except now it doesn't seem to recognize my constraints for possible days.
function[valid] = isValidDate(str)
[date, year] = strtok(str, ','); %Should give me the date and year
[~, year2] = strtok(year, ' ');
[month, day] = strtok(date, ' '); %Should give me month and the day
day = round(day);
if length(date) < 6
valid = false;
elseif month(1) == upper(month(1))
valid = true;
elseif length(date) >= 12
valid = false;
end
if year2 >= 0
valid = true;
else
valid = false;
end
leapyear = mod(year, 400) == 0 | (mod(year, 4) == 0 ~= mod(year, 100) == 0);
switch month
case {'September','April','June','November'}
day <= 30;
valid = true;
case {'February'}
if leapyear
day <= 29;
valid = true;
else
day <= 28;
valid = true;
end
case {'January', 'March', 'May', 'July', 'August', 'October', 'December'}
days <= 31;
valid = true;
otherwise
valid = false;
end
end
So basically
valid4 = isValidDate('December 29.9, -1005.7')
valid = false
Note: There will be no suffix after the day. My only issue now is that my function doesn't realize my constraints on days. it likes to think 'February 30, 2014' is possible

Code
function[valid] = isValidDate(str)
[date1, year1] = strtok(str, ','); %Should give me the date and year
[month1, day1] = strtok(date1, ' '); %Should give me month and the day
%// 1. Take care of bad month strings
all_months = {'January', 'February','March', 'April', 'May','June',...
'July', 'August', 'September','October','November' 'December'} ;
if ~ismember(cellstr(month1),all_months)
valid = false;
return;
end
%// 2. Take care of negative or fraction days
day1 = day1(isstrprop(day1,'digit')); %// Take care of suffixes after day string
num_day = str2double(day1);
if round(num_day)~=num_day || num_day<1
valid = false;
return;
end
%// 3. Take care of fraction or negative years
num_year = str2double(strtok(year1,','));
if round(num_year)~=num_year || num_year<0
valid = false;
return;
end
lpyr =mod(num_year, 400) == 0 | (mod(num_year, 4) == 0 ~= mod(num_year, 100) == 0);
switch month1
case {'September','April','June','November'}
if num_day > 30
valid = false;
return;
end
case {'February'}
if (lpyr && num_day > 29) | (~lpyr && num_day > 28)
valid = false;
return;
end
case {'January', 'March', 'May', 'July', 'August', 'October', 'December'}
if num_day > 31;
valid = false;
return;
end
end
valid = true; %// We made it through!
return;
If you would prefer a compact code -
function valid = isValidDate(str)
[date1, year1] = strtok(str, ','); %Should give me the date and year
[month1, day1] = strtok(date1, ' '); %Should give me month and the day
%// 1. Take care of bad month strings
all_months = {'January', 'February','March', 'April', 'May','June',...
'July', 'August', 'September','October','November' 'December'} ;
valid_month = ismember(cellstr(month1),all_months);
%// 2. Take care of negative or fraction days
day1 = day1(isstrprop(day1,'digit')); %// Take care of suffixes after day string
num_day = str2double(day1);
valid_day = round(num_day)==num_day && num_day>=1;
%// 3. Take care of fraction or negative years
num_year = str2double(strtok(year1,','));
valid_year = round(num_year)==num_year && num_year>=0;
%// 4. Take care of valid days based on leap year and days in a month limits
lpyr = mod(num_year, 400) == 0 | (mod(num_year, 4) == 0 ~= mod(num_year, 100) == 0);
valid_leapyear = true;
switch month1
case {'September','April','June','November'}
valid_leapyear = num_day<=30;
case {'February'}
valid_leapyear = ~((lpyr && num_day>29) || (~lpyr && num_day>28));
case {'January', 'March', 'May', 'July', 'August', 'October', 'December'}
valid_leapyear = num_day<=31;
end
valid = valid_year & valid_month & valid_day & valid_leapyear;
return;

I made some simple function, using the java interface in matlab. Hope it will be useful.
function [valid] = isValidDate(dateStr)
valid = true;
dateFormat = java.text.SimpleDateFormat('MMM dd, yyyy');
dateFormat.setLenient(false);
try
dateFormat.parse(dateStr);
valid = true;
catch err
valid = false;
end
end
Example:
isValidDate('December 21, 1934'); % gives 1
isValidDate('December 29.9, -1005.7'); % gives 0

Related

Test for scalar function inputs is failing

Despite using isscalar, isinteger... the result after running is still true, I still had this test which is incorrect and in relation with Scalar values.
My program:
function valid = valid_date(year, month, day)
[y1 y2] = size(year);
[m1 m2] = size(month);
[d1 d2] = size(day);
if (mod(year,4)==0 && mod(year,100)~=0) || mod(year,400)==0
is_leap_year = 1;
else
is_leap_year = 0;
end
if ~(y1==y2==d1==d2==m1==m2==1)
valid = false;
elseif any(month == [1, 3, 5, 7, 8, 10, 12])
valid = (day >0 && day <= 31)
elseif any(month == [4, 6, 9, 11])
valid = day >0 && day <= 30;
elseif month == 2 && is_leap_year == 1
valid = (day >0 && day <=29);
elseif month == 2 && is_leap_year == 0
valid = (day >0 && day <=28);
else
valid = false;
end
end
The result after submitting my program, all tests are passed except the one related to scalar values:
Why did my program fail on the non-scalar test?
The way you're checking for scalars is really not well defined.
~(y1==y2==d1==d2==m1==m2==1)
This chained equivalence check is not the same as checking if all of your variables are equal to 1, consider the following counter-example:
1==0==0==1 % Output: 1
In this case none of your comparison variables should be 0, so you might skirt this issue, but it's still best to avoid it. You're also contending with floating point comparisons which are prone to issues.
You should use isscalar, you say you tried it but didn't show how. Something like this should work:
function valid = valid_date(year, month, day)
if ~( isscalar(year) && isscalar(month) && isscalar(day) )
valid = false;
return
end
% ... other code now we know inputs are scalar
end
Thank you so much #Wolfie. The problem is solved.
I used what you told me about and put it at the beginning of my function.
I show you guys the code, in case you had the same error:
function valid = valid_date(year, month, day)
if ~(isscalar(year) && isscalar(month) && isscalar(day))
valid = false;
return
end
if ((mod(year,4)==0 && mod(year,100)~=0) || mod(year,400)==0)
is_leap_year = 1;
else
is_leap_year = 0;
end
if any(month == [1, 3, 5, 7, 8, 10, 12])
valid = (day >0 && day <= 31);
elseif any(month == [4, 6, 9, 11])
valid = day >0 && day <= 30;
elseif (month == 2 && is_leap_year == 1)
valid = (day >0 && day <=29);
elseif (month == 2 && is_leap_year == 0)
valid = (day >0 && day <=28);
else
valid = false;
end
end
Yaaay all the tests are passed lhamdullah!

Getting two outputs instead of one in Matlab

The question here was to find if the date provided is a valid one or not without using native Matlab date functions. I was hoping if someone can point out my mistake here. I'm also getting the "Output argument valid (and maybe others) not assigned during call to valid_date" error in Matlab learning tool when I submit it.
function valid = valid_date(year,month,day)
if nargin~=3
valid = false;
elseif ~isscalar(year)||year<1||year~=fix(year)
valid = false;
return
elseif ~isscalar(month)||month<1||month~=fix(month)
valid = false;
return
elseif ~isscalar(day)||day<1||day~=fix(day)
valid = false;
return
elseif month>12 || day > 31
valid = false;
end
if ((mod(year,4)==0 && mod(year,100)~=0) || mod(year,400)==0)
leapdata=1;
else
leapdata=0;
end
%the below if statements are used to define the months. Some months have
%31 days and others have 30 days, while February has only 28 days and 29 on
%leap years. this is checked in the below code.
% I feel the below code is where the error is.
if ismember (month, [1 3 5 7 8 10 12])
ismember (day, (1:31))
return
elseif ismember( month, [4 6 9 11])
ismember (day, (1:30))
return
end
if month == 2
if leapdata==1
ismember (day, (1:29))
return
elseif leapdata==0
ismember (day, (1:28))
return
else
valid = false;
end
end
When returning at the end of a Matlab function, the value of the variable valid is sent as an output. In the lines below the four comments, you need to assign the variable to true or false inside of the if statements. For example:
if ismember(month, [1 3 5 7 8 10 12])
valid = ismember(day, (1:31))
return
elseif ismember(month, [4 6 9 11])
valid = ismember(day, (1:30))
return
end
if month == 2
if leapdata == 1
valid = ismember(day, (1:29))
return
elseif leapdata == 0
valid = ismember(day, (1:28))
return
else
valid = false;
end
end

Function that take date and return the statement of the validation of the date

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. Note that every year that is exactly divisible by 4 is a leap year, except for years that are exactly divisible by 100. However, years that are exactly divisible by 400 are also leap years. For example, the year 1900 was not leap year, but the year 2000 was. Note that your solution must not contain any of the date related built-in MATLAB functions.
samples:
valid = valid_date(2018,4,1)
valid = valid_date(2018,4,31)
The outputs are :
valid =
logical
1
valid =
logical
0
Here is a partial solution:
function valid= valid_date(year,month,date)
if nargin~=3
valid=false;
elseif ~isscalar(year) | ~isscalar(month) | ~isscalar(date)
valid=false;
elseif year<1 || month<1 || date<1
valid=false;
elseif year~=fix(year) || month~=fix(month) || date~=fix(date)
valid=false;
elseif month>12 || date>31
valid=false;
elseif month==2
if (rem(year,400)==0 || (rem(year,4)==0 && rem(year,100)~=0)) && date<30
valid=true;
elseif (rem(year,400)~=0 || (rem(year,4)~=0 && rem(year,100)==0)) && date<29
valid=true;
else
valid=false;
end
else
days = [31 29 31 30 31 30 31 31 30 31 30 31];
totaldays = days(month);
if date>totaldays
valid=false;
else
valid=true;
end
end
end
My solution is:
function out= valid_date(y,m,d)
if mod(y,4)==0
if mod (y,100)==0
if mod(y,400)==0
leap =true;
else
leap=false;
end
else
leap =true;
end
else
leap= false;
end
if y>0 &m>0&d>0 &y==fix(y)&m==fix(m)&d==fix(d)&m<=12 &isscalar(y)&isscalar(m)& isscalar(d)
if (m==1 | m==3|m==5|m==7 |m==8 |m==10 |m==12)&d <=31
out=true;
elseif d<=30
if m==2
if leap==true & d<=29
out =true;
elseif leap==false &d<=28
out=true;
else
out=false;
end
else
out=true;
end
else
out =false;
end
else
out= false;
end

Leap years not working in Date and Time program in Dlang

I haven't been programming very long, so I'm practicing some logic exercises in dlang. Any ideas on what I've done wrong here. When I get to a leap year, my program just keeps looping on the WHILE.
import std.stdio;
void main()
{
bool dead;
string thing;
int phew = 5; //days
int tahr = 1; //months
int tron; //monthsDate
string[7] days = ["Sunday", "Monday", "Tuesday", "Wednesday","Thursday", "Friday", "Saturday"];
int date = 28;
string[12] months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
int year = 1996;
int hours = 11;
int mins = 28;
string ampm = "pm";
bool ly;
int leap = 1996;
int cen = 996;
//writeln("This program is incomplete. Obviously.");
write("Press Enter to Continue.");
readf("%s\n",&thing);
while(!dead)
{
while(hours <= 12)
{
while(mins <= 59)
{
if(mins < 10)
write(date," ",months[tahr],", ",year,". ",days[phew],". ",hours,":0",mins,ampm,": ");
else
write(date," ",months[tahr],", ",year,". ",days[phew],". ",hours,":",mins,ampm,": ");
readf("%s\n",&thing);
mins++;
}
hours++;
if(hours == 12 && ampm == "am")
{
ampm = "pm";
}
else if (hours == 12 && ampm == "pm")
{
ampm = "am";
phew++;
date++;
if(phew > 6)
phew = 0;
if((date == 29 || date == 30) && tahr == 1)
{
while(leap <= year) //this assuming time travel doesn't work
{ //reminder: add time travel
if (leap == year)
{
ly = true;
break;
}
leap+=4;
ly = false;
}
if(!ly || date == 30)
{
date = 31;
leap-=4;
}
}
if(!ly || date == 30)
{
date = 31;
leap-=4;
}
}
if(date == 31 && (tahr == 1 || tahr == 3 || tahr == 5 || tahr == 8 || tahr == 10))
{
date = 1;
tahr++;
}
else if (tahr == 11 && date == 32)
{
tahr = 0;
date = 1;
year++;
cen++;
if(cen == 1000)
{
writeln("Happy Millennium!");
cen = 0;
}
else
writeln("Happy New Year!");
}
else if(date == 32 && (tahr == 0 || tahr == 2 || tahr == 4 || tahr == 6 || tahr == 7 || tahr == 9))
{
date = 1;
tahr++;
}
}
if(hours == 13)
{
hours = 1;
}
mins = 0;
}
}
}
The important part is this:
if((date == 29 || date == 30) && tahr == 1)
{
while(leap <= year) //this assuming time travel doesn't work
{ //reminder: add time travel
if (leap == year)///
{
ly = true;
break;
}
leap+=4;
ly = false;
}
if(!ly || date == 30)
{
date = 31;
leap=-4;
}
}
So, I figured out the issue almost immediately after posting. Basically, I wrote =+ instead of +=. Very simple mistake. That's what I get for typing too fast. So, I've fixed up the code now, if you have any other suggestions, make sure to put them in the comments. Thanks.
Decided to print out leap into the terminal, and I figured out my issue. Leap was continuously equal to 4, because I wrote =+ instead of +=. It was just a case of clicking the wrong button first. That's what I get for typing fast. The program works now, as far as I know. Feel free to correct me on anything else you may notice.
I haven't read it in depth, but I recommend you add lots of debug writelns.
Particularly just inside the block you're THINKING should get run:
if((date == 29 || date == 30) && tahr == 1) {
writefln("Handling leap years...");
while(leap <= year) //this assuming time travel doesn't work
{ //reminder: add time travel
writefln("In loop, Leap <= year? %s", leap <= year);
This will allow you to debug more what is actually happening when your program is run.

how to get the range date in vb6

i have 2 date picker
Dim pday, eitday, otherday, tpenalty, difday, subpenalty As Integer
difday = Val(L1.Caption) - Val(L2.Caption)
pday = 7
eitday = 8
otherday = difday - eitday
tpenalty = 25
If difday <= pday Then
PENALTY.Caption = 0
ElseIf difday = eitday Then
PENALTY.Caption = tpenalty
ElseIf difday > eitday Then
For i = 0 To otherday - 1
subpenalty = subpenalty + 5
Next i
PENALTY.Caption = tpenalty + subpenalty
End If
the problem is when the month is change the calculation is invalid.
I'm guessing based on your code (as many things are unclear), but this should give the number of days between two dates:
difday = DateDiff("d", StartDate, EndDate)
I've used StartDate and EndDate to signify the start and end of the lone period which are used to set L1 and L2, as you shouldn't be converting from strings to dates for calculations.