Well, I'm back with my Java head on after doing some more logical, straight forward and easier to understand 6502 programming. I have a date class with error checking (ie, valid leap-years or dates, 31-04-02 on DD-MM-YY format would be invalid and reset to a default value after reporting an error).

Here's my Date class:

Code :

public class Date
{
/* Let's do this thing properly and set up a look-up table
* which will be used in to return month as string bit at
* the end. We'll store the months in an array of type
* String and as computers count from zero, our first entry
* will be monthToString[0], returning January. */
public static String [] monthToString=
{
"January", "February", "March", "April", "May",
"June", "July", "August", "September", "October",
"November", "December"
};
/* Because I'm doing what should be advanced programming,
* I'm going to use a look-up table for the number of days
* in each month as follows: */
public static int [] noOfDays=
{
31,28,31,30,31,30,31,31,30,31,30,31
};
/* Here is a variable of type char that'll force a line-feed
* when using System.out.print ("text"+ln+"more text"); */
public static char ln=13;
/* The following variable of type String is also used in
* the sub-routine that returns the month as string */
public static String mon="";
/* Okay, here's some variables of type integer (whole numbers)
* which will be used in the constructor thingy */
private int day, month, year;
/* Error catching for type date in DD/MM/YY format to
* check for legal dates, assuming a 19xx or 20xx prefix*/
public Date (int dd, int mm, int yy)
{
day=dd; month=mm; year=yy;
if (month<1 || month>12)
{
System.out.println("?Month not valid error"+ln+
"Reset to default value.");
month=01;
}
if (day<1 || day>31)
{
System.out.println("?Day not valid error"+ln+
"Reset to default value.");
day=01;
}
/* As there is no easy way to store a leap-year in a look-up table
* I'm going to check for the 29th February first and validate it
* later. Of course, this is advanced programming, isn't it? */
if (day>29 && month==2)
{
System.out.println("?Day not valid error"+ln+
"Except for leap-years, Feburary"+
"has only 28 days.");
day=01;
}
/* Now, let's check to see if a legal leap-year has been entered
* by the user, shall we? Oh, we need to do some maths. */
if (day==29 && month==2 && ((year-2000)%4!=0))
{
System.out.println("?Date not valid error"+ln+"Not a leap-year.");
day=28;
}
/* So, we've tested for a valid leap-year, the only thing that could
* trip up our array above for the numbers of days in each month. */
if (day<1 || day>noOfDays[month-1] && month!=2)
{
System.out.println("?Date not valid error"+ln+"Not a legal date.");
day=01;
}
/* That's a whole lot more efficient and advanced than having a
* 'switch case' or a load of 'if' statements checking for each
* condition, isn't it? Okay, I'd use a switch case if I thought
* that the person maintaining the code wasn't very good and needed
* it to be readable, but if you use comments correctly then you
* don't necessarily need code to be more readable, or shouldn't */
}
/* This will initialise the date and then we'll do some stuff
* wid it */
public Date()
{
day=04;month=05;year=77;
}
/* This does something, but I can't remember what? */
public Date (Date other)
{
this (other.day, other.month, other.year);
}
/* This method will return the monthAsString, as suggested by its' name */
public String monthAsString()
{
/* This is very efficient because it has in-built error checking
* actually without testing for loads of conditions */
if (month>0 && month<13)
{
mon=monthToString[month-1];
return mon;
}
/* Just in case any errors have sneaked into validating the month,
* It will return a Month not set message */
else
return "Month not set";
}
/* I'm probably wasting my time trying to make this method
* more efficient. Not sure what benefits it has anyway? */
public boolean earlierThan(Date other)
{
if(year<other.year)
{
return true;
}
else
if (year==other.year && month<other.month)
{
return true;
}
else
if (month==other.month && day<other.day)
{
return true;
}
else
return false;
}
/* This does some sort of test for some reason, again I don't
* recall what it's actually for? */
public boolean equals (Date other)
{
if (day==other.day && month==other.month && year==other.year)
{
return true;
}
else
return false;
}
public String suffix()
{
/* Here is where a switch case is useful, in terms of returning a
* date: because most days as numbers have a th suffix (ie, 4th),
* we'll use a switch case for the exceptions to that rule. */
switch(day)
{
case 1: return "st";
case 2: return "nd";
case 3: return "rd";
case 21: return "st";
case 22: return "nd";
case 23: return "rd";
case 31: return "st";
default: return "th";
}
}
public String toString()
{
/* This is another attempt at error trapping, just in case
* anything above has failled. */
if(month!=0 || day!=0)
{
if(year<10)
{
/* A nested if statement to do some padding on years less than xx10 */
return "The "+day+suffix()+" of "+monthAsString()+" in the year 0"+year;
}
else
return "The "+day+suffix()+" of "+monthAsString()+" in the year "+year;
}
else
return "Date not set";
}
public void copy(Date other)
/* I think this final thing is the equivalent of a buffer perhaps? */
{
day=other.day; month=other.month; year=other.year;
}
}

As I've said, it works whether the date entered is valid or not.

What I want to do now is work out what day 29-02-00 was. Is there some sort of mathematical trickery that will do this? Ie, if I find out for myself what day 29-02-00 was according to the Gregorian calendar, could I then calculate all other days around that? Something like:

There must be an easy way to solve this? Anyone? Edit: I just need the logic or maths, thought someone may have already come across this problem and solved it, providing me with some useful tips :-)

Regards,

Shaun.

April 20th, 2011, 09:09 AM

KevinWorkman

Re: Working out the day from numeric date (dd/mm/yy format).

Why don't you just use the standard Date and Calendar classes?

April 20th, 2011, 10:12 AM

ShaunB

Re: Working out the day from numeric date (dd/mm/yy format).

Because it's an assignment for my Advanced Programming module, which doesn't seem to have a great deal of advanced programming attached to it outside some stuff I did in the first year by mistake and a lot of Java pedantics.

Thanks for the suggestion though. In the real world, I would just use the standard Date and Calander classes.

Regards,

Shaun.

April 20th, 2011, 07:43 PM

Junky

Re: Working out the day from numeric date (dd/mm/yy format).

I didn't read all the code as it is hard to read but you input the year as a 2 digit value. You then subtract 2000 from it. Hmmmmm!

April 21st, 2011, 05:19 AM

ShaunB

Re: Working out the day from numeric date (dd/mm/yy format).

Quote:

Originally Posted by Junky

I didn't read all the code as it is hard to read but you input the year as a 2 digit value. You then subtract 2000 from it. Hmmmmm!

Thanks for the compliment about my Java program code. Code, in computing terms, is only what the processor understands and that's never readable unless you think in hex or binary.

I'm only taking 2000 away from the year to test for a condition regarding leap-years, otherwise (in the format I'm using), 29/02/xx will be valid, ie, every year may be entered as having 29 days in the month of February without any problems. We know, however, that leap-years only happen every four years, and only every 400 when the year ends 00. That much is obvious. So the condition is assuming a base-year of 2000, hence 2000-00=2000, so check that against a modulo of 400 or 4 or something, and see if there's a remainder; if so, it's not a valid date.

I'm using this Date class to validate date of birth entries for students and pupils; therefore, it's very unlikely that any of them will be born in 1900 (not a leap-year), but could be born on 29/02/2000 and only have a birthday every four years as a result.

I've tested the code extensively and it works fine according to my test-plan.

I success with working out the day from the date: The only anomoly in my code is that it thinks that 1900 is a leap-year and so returns the wrong days for January and February of that year (that's easily fixed though). Here is what you need at the beginning of the program:

Code :

/* I'm going to attempt to calculate the day entered based
* on the numeric date entered (oh no! Maths :-( !!!) so, I
* need a look-up table for that... Extra day added for
* leap-years (ie, anything after a legal leap-year has an
* off-set), this first table is for the 20th Century, ie,
* a 19 perfix on the date: */
public static String [] daysOfWeek20th=
{
"Monday","Tuesday","Wednesday","Thursday",
"Friday","Saturday","Sunday","Monday"
};
/* And this is the corrosponding look-up table for the 21st
* century boy! */
public static String [] daysOfWeek21st=
{
"Sunday","Monday","Tuesday","Wednesday","Thursday",
"Friday","Saturday","Sunday"
};
/* Here are the month codes! */
public static int [] monthCodes=
{
6,2,2,5,0,3,5,1,4,6,2,4
};
/* And we need to declare some variables, or at least one: */
public static float a, x, y, z;
public static int v, c;

You'll notice that there are two look-up tables; you'll need a conditional routine to determine which days to return (ie, IF (datePrefix==19) THEN RETURN daysOfWeek20th etc...)

Oh, and before I forget, here's the mathematic-type-bit:

Code :

public String dayFromDate()
{
/* This method will return the day of week based on a numeric
* date entered after 1st March 1900, because 1900 isn't a
* leap-year, whereas 2000 is (ie, leap-years ending 00 only
* happen every 400 years). It's highly unlikely that a student
* will be born before this date, so for our purposes, it works
* fine.
*
* The basic maths are to take the year and add a 25% to it ignoring
* any decimal points (ie, 25% of 01 = 0.25, so we ignore the .25)
* then we have the following month codes: Jan=6, Feb=2, Mar=2,
* Apr=5, May=0, Jun=3, Jul=5, Aug=1, Sep=4, Oct=6, Nov=2, Dec=4
* which is stored in a look-up table. We take the numberic day
* and add it to our sum, (so, month+(abs(month/4))+monthCode+day)
* We then need the absolute value of that and pass that to a
* type int, and then take the remainder of that number when
* divided by 7. If the answer is negative, we add 7 until it's
* positive, then we check for leap-years, and minus 1 off the
* answer if the month is January or February and return the
* dayOfWeek according to the look-up table. Simple! */
a=year+(Math.abs(year/4)); // This takes the year and should
// add 25% to it.
x=monthCodes[month-1]; // This will pass the 'month code'
// to x for our mathematics
y=day; // We need to know the date to do
// calculations with it.
z=a+x+y; // This is used to work out the day
a=Math.abs(z);
c=Math.round(z);
v=c%7;
while(v<1)
{
v=v+7;
}
if ((year-2000)%4!=0)
{
return daysOfWeek21th[v];
}
else
if ((year-2000)%4==0 && (month>0 && month<3))
{
return daysOfWeek20th[v-1];
}
else
if ((year-2000)%4==0 && (month>2))
{
return daysOfWeek21th[v];
}
else
return "Day unknown";
}

Of course, this will only work for the 20th and 21st century according to the Gregorian calander. If you want to work out the days in the 19th century according to the numberic date then you'll need to build a corrosponding look-up table (work it out for yourselves :-P). There are the bugs to fix as well (ie, the problem with 1900 been seen as a leap-year).