gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

C/C++ > Finding a Day?

#142917 - spinal_cord - Mon Oct 15, 2007 1:53 am

This is bugging me a little, does anyone have a working algorithm for finding the current weak day, given the date?

kind of like day=dayname(dd,mm,yy)
I have tried a handful of algorithms and none of them seem to work.
_________________
I'm not a boring person, it's just that boring things keep happening to me.
Homepage

#142927 - keldon - Mon Oct 15, 2007 6:12 am

http://en.wikipedia.org/wiki/Leap_year

You can then set any date as a reference point, count the days and you're set.

#142953 - spinal_cord - Mon Oct 15, 2007 1:19 pm

Any idea what I've done wrong here?
Code:
int Day(int d,int m,int y)
{
   int wday=6; // 1 Jan 2000 was saturday
   int day,month,year,today;
   char month_length[24]={31,28,31,30,31,30,31,31,30,31,30,31, 31,29,31,30,31,30,31,31,30,31,30,31};
   int IsLeap=0;
   if (y % 4 ==0)  IsLeap=1;
   if (y % 100 ==0) IsLeap=0;
   if (y % 400 ==0) IsLeap=1;
   for(year=0; year<y; year++)
   {
      for(month=0; month<month_length[m+(12*IsLeap)]; month++)
      {
         for(day=0; day<d; day++)
         {
            if(wday++ == 7)wday=0;
            if(y==year && m==month && d==day)today=wday;
         }
      }
   }   
   return today;
}

_________________
I'm not a boring person, it's just that boring things keep happening to me.
Homepage

#142969 - sajiimori - Mon Oct 15, 2007 6:36 pm

You're only calculating IsLeap once, although you're crossing multiple years.

You're iterating over lots of months! At least 28 of them per year...

#142991 - Mighty Max - Mon Oct 15, 2007 10:30 pm

A better approach would just to calculate the amount of passed days (365[+1]) for full years, month_length for full onths, and and (d-1) [since no day passed from 1st to the 1st] for the current month.

This amount modulo 7 should give you the day-shift to your reference 1st Jan.

Iterating through each day in all those years is just a pile of wasted cpu time.
_________________
GBAMP Multiboot

#143040 - keldon - Tue Oct 16, 2007 7:07 am

Your initial task is to generate a number based on the date. First begin by finding out what day of the year it is, then how many days the start of the year is from 0AD.

If you're wondering what's the quickest and easiest way to do that, it is just a case of ...
Code:

int get_day_hash (int,int,int);
int get_day_of_year (int,int,int);
int get_day_by_year (int);


enum MONTH_DAYS
{
   JAN = 31,
   FEB = JAN + 28,
   MAR = FEB + 31,
   APR = MAR + 30,
   MAY = APR + 31,
   JUN = MAY + 30,
   JUL = JUN + 31,
   AUG = JUL + 31,
   SEP = AUG + 30,
   OCT = SEP + 31,
   NOV = OCT + 30,
   DEC = NOV + 31
};

static const int day_on_month [] =
{
   JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC
};

// january == 1, days start at 1
int get_day_hash ( int dd, int mm, int yyyy )
{
   return get_day_by_year (yyyy) + get_day_of_year(dd,mm,yyyy);
}

int get_day_by_year ( int yyyy )
{
   int num_leap_years;
   
   // get number of leap years
   num_leap_years = 0;
   num_leap_years += (yyyy / 4);
   num_leap_years -= (yyyy / 100);
   num_leap_years += (yyyy / 400);
   
   // ... and like magic
   return (yyyy * 365) + num_leap_years;
}

// january == 1, days start at 1
int get_day_of_year ( int dd, int mm, int yyyy )
{
   BOOL is_leap_year;
   int day_of_year;

   if ( (0 == (yyyy % 4)) && !(0 == (yyyy % 100)) )
   {
      is_leap_year = TRUE;
   }
   else if ( 0 == (yyyy % 400) )
   {
      is_leap_year = TRUE;
   }
   else
   {
      is_leap_year = FALSE;
   }

   day_of_year = day_on_month [mm-1] + (dd+1);
   
   if ( is_leap_year && (mm >= 2 ) )
   {
      ++ day_of_year;
   }
   
   return day_of_year;
}


I tested it with my date of birth and today's date and it works for that. Just modulo 7 for the day, and scrutinise every line of code to make sure I've got the numbers right.

#143090 - Salz` - Tue Oct 16, 2007 7:26 pm

keldon wrote:
...
Code:

...
   if ( is_leap_year && (mm >= 2 ) )
   {
      ++ day_of_year;
   }
...
}


maybe my fault, but i think that would return an wrong result. cause if you're in an leap year and it's the 2.2 you would add 1 to the day and that ends in day 34. I think it have to
Code:

   if ( is_leap_year && (mm > 2 ) )
   {
      ++ day_of_year;
   }

please correct me, if i'm wrong.

#143100 - keldon - Tue Oct 16, 2007 9:34 pm

Yes, my mistake; I originally wrote the method with days and months starting at 0 - that would be the need for scrutinizing. But logically it should be sound!

#143415 - spinal_cord - Sun Oct 21, 2007 1:29 am

I found something on a basic coding page, translating to c was no problem, fairly small and dimple code.
Code:
int Day(int day,int month,int year)
{
  int a = (14 - month)/12;
  int y = year - a;
  int m = month + 12*a - 2;
  int d = (day + y + y/4 - y/100 + y/400 + (31*m)/12);
  return ((d % 7) + 1);
}


seems to work just fine.
_________________
I'm not a boring person, it's just that boring things keep happening to me.
Homepage

#143436 - keldon - Sun Oct 21, 2007 10:16 am

Very small and clever method, derived from the doomsday algorithm (methinks)!