Convert real-world calendar dates into KoL calendar dates

zarqon

Well-known member
I rigged up some functions for a script I'm writing which might be useful to the mafia community. One function returns the current KoL day (which I know is accessible elsewhere but this makes it easy), and another one takes a real-world date and returns the corresponding date in the KoL calendar.

I'm using this to calculate clan member "birthdays." I get their sign-on date by visiting showplayer.php, then compare date_to_kol(thedate) with today() to see if it's that clannie's KoL-calendar birthday (not real-world KoL birthday).

This could also be used as an alternative method for calculating stat days or holidays, since they always fall on certain KoL calendar days.

Code:
string date_to_kol(string realworld) {
  return visit_url("http://zachbardon.com/mafiatools/datetokol.php?d="+url_encode(realworld));
}
string today() {
  return visit_url("[url]http://zachbardon.com/mafiatools/datetokol.php"[/url]);
}

date_to_kol() accepts a wide variety of formats. You could pass "12/25/2007" or "December 25th, 2007" or "2007 Dec 12" or just about any human-readable date format. Even more useful, you can also give it relative input like "+3 days", which will return the KoL date three days from today. "-1 day" gives you yesterday, and so on.

You'll notice I do all the processing in PHP rather than ASH, since ASH has very very little by way of date/time functions. Also, the PHP page that these functions visit behaves differently depending on whether you're accessing it via mafia vs. a web browser.
 
This data is available via charpane.php without the need for php scripts on your own server. It has been for a very long time. It's basic math.

Before that, a simple batch file on windows could achieve the same results...write an ash script via a batch file. There are ways of doing that same thing on just about every operating system. The bottleneck was time zone issues...returning the wrong in game date just before or after rollover.
 

zarqon

Well-known member
Okay, write me an ASH script that compares today's KoL date to a player's character creation date and sees if they fall on the same day in the KoL calendar, using only charpane.php, showplayer.php and basic math.

Bet you can't.
 
I'll one better ya! I don't even need charpane.php, I'll use an existing ash function to get the date. of course I have to use showplayer.php to get the player's kol Birthday...

anyway here ya go, this code will be good till 2038 (unless there is a change to Kolmafia or kol) at which point almost all software in use today that uses the date, or even the time will need to be upgraded to use 64 bit integers instead of 32 bit integers.
PHP:
String [int] weekdays;
weekdays[0] = "Sun";
weekdays[1] = "Mon";
weekdays[2] = "Tues";
weekdays[3] = "Wednes";
weekdays[4] = "Thurs";
weekdays[5] = "Fri";
weekdays[6] = "Sat";

String [int] months;
months[1] = "January";
months[2] = "Febuary";
months[3] = "March";
months[4] = "April";
months[5] = "May";
months[6] = "June";
months[7] = "July";
months[8] = "August";
months[9] = "September";
months[10] = "October";
months[11] = "November";
months[12] = "December";

string [int] suffix;
suffix[0] = "th";
suffix[1] = "st";
suffix[2] = "nd";
suffix[3] = "rd";
suffix[4] = "th";
suffix[5] = "th";
suffix[6] = "th";
suffix[7] = "th";
suffix[8] = "th";
suffix[9] = "th";

int dayofweek(string date)
{
  int c = substring(date,0,2).to_int();
  int y = substring(date,2,4).to_int();
  int m = substring(date,4,6).to_int();
  int d = substring(date, 6, 8 ).to_int();
  if( m<3 )  //for Zeller's Rule march is the first month and febuary is last.
    {
      m=m+10;
      y=y-1;
    }
    else
    {m=m-2;}
  int temp1 = ( ( ( 13*m ) -1 ) /5 );
  int temp2 = (y/4);
  int temp3 = (C/4);
  int f = d + temp1 + y + temp2 + temp3 - (2*C);
  if ( f < 0 ){return (f % 7) + 7;}
  return f % 7;
}

string format_date(string date)
{
  int y = substring( date,0,4).to_int();
  int m = substring(date,4,6).to_int();
  int d = substring(date,6,8).to_int();
  
  string day;
  if(d = 11 || d = 12 || d = 13)
    {day = d + suffix[0];}
    else
    {day = d + suffix[d];}

 //pretty formatting
 //return weekdays[dayofweek(date)] + "day, " + months[m] + " " + day + " " + y;
 return months[m] + " " + d + ", " + y;
}

string kol_birthday(int playernum)
{
  string source = visit_url("showplayer.php?who=" + playernum);
  string result = substring(source, index_of(source, "Account Created:[/b]</td><td>") + length("Account Created:[/b]</td><td>"));
  return  substring(result, 0, index_of(result, "</td>"));
}

boolean check_birthday(int playernum)
{
string date = today_to_string().format_date();
string birthdate = kol_birthday(playernum);
if(substring(date, 0, length(date) - 4) == substring(birthdate, 0, length(birthdate) - 4))
  {
  return true;
  }
return false;
}

print("today is " + today_to_string().format_date());
print("efilnikufecin was born into the kingdom on " + kol_birthday(601149));
if(check_birthday(601149))
  {
  Print("Hooray!!! Today is efilnikufecin's kol birthday!");
  }
  else
  {
  Print("Today is not efilnikufecin's kol birthday.");
  }

note there is some excess. no need re-inventing the wheel! I just recycled code I wrote to give the date given by kolmafia a better appearance.

Hop on a search engine and look up Zeller's Rule.

By the way, leap year babies only get a birthday every 4 years :p

Now should I take a step back and use charpane.php's unix encoded timestamp? You have to remember that the method of encoding time into a unix timestamp was written by someone, and copied into many many pieces of software using just basic math. If they can do it, then with a little research I can do it, and so can you.

The unix timestamp is simply the number of seconds elapsed since January 1, 1970 GMT. divide by 60, you have minutes, divide minutes by 60 for the number of hours. Divide hours by 24 for number of days, then start working on months, and years. That's where it gets a little complex, but it isn't so bad.
 

zarqon

Well-known member
Just to get us on the same page, I was referring to the KoL calendar, not the real-world calendar. KoL birthdays happen every 96 days, not every year.

So look at showplayer.php, maybe the player's account birthdate was February 29th, 2008. That translates to April 8 in the KoL calendar. The next time it's April 8 in KoL falls on June 5th in the real world (96 days later). I want to be able to take a real-world date and convert to the KoL calender, for any given date.

If you can write a script to do that using only showplayer.php and math, I'll be impressed.

I managed to do it with about 15 lines of PHP (using Unix timestamps of course). Also, by keeping it on a remote server and compensating for time zone difference in the script, time zones are a nonissue.

Good luck! :)
 
you are the first kol player I have heard refer to a kol birthday in kol time. Even Jick and Co. go by the regular calendar to give out the anniversary gift boxes. The original statement was about kol birthdays, not getting the kol date. I will continue with kol birthdays.

Heck I don't know if it works or not, honestly I don't think it's really worth the effort to search out someone who's kol-birthday (as defined by you) is today to test it. If you know of someone though, by all means...tell me if this thing really works!

PHP:
float abs(float input)
{
 if(input<0)
  return input - input - input;
 return input;
}

boolean isleapyear(int year)
{
if((year % 400) = 0) { return true; } else { if(!((year % 100) = 0)) { if((year % 4) = 0) { return true; } } }
return false;
}

int hi(int a, int b)
{
if(a<b) {return b;}
return a;
}

int leapsbetween(int firstYear, int lastYear)
{
int count = hi(firstyear, 4);
int result = 0;
if(count < hi(lastYear, 4))
 {
 while(count != hi(lastYear, 4))
  {
   if(isleapyear(count)) {result = result + 1;}
   count = count + 1;
  }
 }
return result;
}

int daystillfirst(int month, int year)
{
int result;
if(month = 1){return 0;}
if(month = 2){return 31;}
if(month = 3){result = 60;}
if(month = 4){result = 91;}
if(month = 5){result = 121;}
if(month = 6){result = 152;}
if(month = 7){result = 182;}
if(month = 8){result = 213;}
if(month = 9){result = 244;}
if(month = 10){result = 274;}
if(month = 11){result = 305;}
if(month = 12){result = 335;}
if(isleapyear(year)){result = result + 1;}
return result;
}

int howLong(int yr, int mo, int dy, int thisYear, int thisMonth, int thisDay)
{  //Parameters are calendar Year,Month,Day
int years = thisYear - yr;
int date1 = (yr * 365) + leapsbetween(1, yr) + daystillfirst(mo, yr) + dy;
int date2 = (thisyear * 365) + leapsbetween(1, thisYear) + daystillfirst(thisMonth, thisYear) + thisDay;
return abs(date2 - date1);
}

int diffDays(string startdate, string enddate)
{   //both params are formatted mm/dd/yyyy
 int sm = substring(startdate,0,2).to_int();
 int sd = substring(startdate,4,5).to_int();
 int sy = substring(startdate,7,10).to_int();
 int em = substring(enddate,0,2).to_int();
 int ed = substring(enddate,4,5).to_int();
 int ey = substring(enddate,7,10).to_int();
 return howLong(sy, sm, sd, ey, em, ed);
}

string kol_birthday(int playernum)
{
 string source = visit_url("showplayer.php?who=" + playernum);
 string result = substring(source, index_of(source, "Account Created:</b></td><td>") + length("Account Created:</b></td><td>"));
 return substring(result, 0, index_of(result, "</td>"));
}

string format_kolmafia_date(string date)
{
 string y = substring(date,0,4);
 string m = substring(date,4,6);
 string d = substring(date,6,8);
 return m + "/" + d + "/" + y;
}

string format_kol_birth_date(string date)
{
 string formatteddate = date;
 formatteddate = replace_string(formatteddate,"January","01");
 formatteddate = replace_string(formatteddate,"Febuary","02");
 formatteddate = replace_string(formatteddate,"March","03");
 formatteddate = replace_string(formatteddate,"April","04");
 formatteddate = replace_string(formatteddate,"May","05");
 formatteddate = replace_string(formatteddate,"June","06");
 formatteddate = replace_string(formatteddate,"July","07");
 formatteddate = replace_string(formatteddate,"August","08");
 formatteddate = replace_string(formatteddate,"September","09");
 formatteddate = replace_string(formatteddate,"October","10");
 formatteddate = replace_string(formatteddate,"November","11");
 formatteddate = replace_string(formatteddate,"December","12");
 formatteddate = replace_string(formatteddate,", ","/");
 return replace_string(formatteddate," ","/");
}

void main()
{
string date = today_to_string().format_kolmafia_date();
string birthday = kol_birthday(601149).format_kol_birth_date();
int difference = diffDays(date, birthday);
if((difference % 64) = 0)
 Print("Hooray!!! Today is efilnikufecin's kol birthday!");
 else
 {
 Print("Today is not efilnikufecin's kol birthday.");
 }
}
 

zarqon

Well-known member
Wow, I didn't expect you to actually do it. I'm impressed. It's waaayyy easier in PHP because you don't have to create functions like abs() and strtotime().

For the record, let's call them KoL-calendar birthdays.

For those that would rather not import all that impressive code, you can use my little functions up top. :)
 
Top