// PHP Gregorian date calculation algorithm based on work by Gary Katch
// http://alcor.concordia.ca/~gpkatch/gdate-algorithm.html
// http://alcor.concordia.ca/~gpkatch/gdate-c.html
function dayfromdate($year,$month,$day){
// define as floats
$m = 0.0;
$y = 0.0;
#$m = ($month + 9) % 12;
#$y = $year - $m/10;
$m = bcmod(bcadd($month,9),12);
$y = bcsub($year,(bcdiv($m,10)));
# Gregorian calendar takes the length of a year to be 365.2425 days:
# 365.0000 + 0.2500 - 0.0100 + 0.0025
# or
# 365 + 1/4 - 1/100 + 1/400 using integers
# made into a discrete function this is
# d = 365y + int(y/4) - int(y/100) + int(y/400)
// define as floats
$toreturn = 0.0;
#$toreturn = $y*365 + $y/4 - $y/100 + $y/400 + $monthoffset +$dayoffset
$toreturn = bcmul($y,365);
$toreturn = bcadd($toreturn,bcdiv($y,4));
$toreturn = bcsub($toreturn,bcdiv($y,100));
$toreturn = bcadd($toreturn,bcdiv($y,400));
# month offset
# length of months are not the same, feb is not fixed
# so we start the calendar year with March
# this makes leap days always added on to the end of the year
# and do not change day offsets for the beginning of the months
#$monthoffset = ($month*306 + 5) / 10;
$monthoffset = 0.0;
$monthoffset = bcdiv(bcadd(bcmul($m,306),5),10);
$toreturn = bcadd($toreturn,$monthoffset);
# day offset, start at zero
#$dayoffset = $day - 1;
$dayoffset = 0.0;
$dayoffset = bcsub($day,1);
$toreturn = bcadd($toreturn,$dayoffset);
return $toreturn;
}
function datediff($d1,$d2){
// this is the main function.
// takes two dates of the format YYYY-MM-DD
// and displays the difference in days between the two
// by calling 'dayfromdate', which does all the math
$date1 = split('-',$d1);
$date2 = split('-',$d2);
$year1 = $date1[0];
$month1 = $date1[1];
$day1 = $date1[2];
$year2 = $date2[0];
$month2 = $date2[1];
$day2 = $date2[2];
$res = 0.0;
$res = bcsub(dayfromdate($year1,$month1,$day1),dayfromdate($year2,$month2,$day2));
$result = (string)$res;
return "$d2 is $result days after $d1
\n";
}
function gendate(){
// generate a random gregorian date.. for testing
$year = rand(1600,3000);
$month = rand(1,12);
$day = rand(1,29);
if($month < 10){
$tm = "0".$month;
}else{
$tm = "".$month;
}
if($day < 10){
$td = "0".$day;
}else{
$td = "".$day;
}
$d1 = "$year-$tm-$td";
$d2 = array('y' => $year, 'm' => $month,'d' => $day);
return array('text-date' => $d1,'num-date' => $d2);
}
// unit test code - shows it works for arbitary Gregorian dates..
// run it from the command line to test against mysql5's datediff version
for($i<0;$i<10;$i++){
$d1 = gendate();
$d2 = gendate();
$dd = datediff($d1['text-date'],$d2['text-date']);
echo "[Datediff]" . $dd;
# change below to match your local mysql5 test account! :)
$con = mysql_connect('localhost','seo','seo');
sleep(1);
$res = mysql_query("SELECT DATEDIFF('".$d1['text-date']."','".$d2['text-date']."') as days") or die(mysql_error());
$row = mysql_fetch_array($res);
echo "[MySQL] Mysql reports actual difference is = " . $row['days'] ."
\n";
if(!bccomp($row['days'],$dd)){
echo "Doesn't add up..";
break;
}
echo "--\n";
mysql_close($con);
}
// here is an example test run, showing it is working:
#[Datediff]1710-09-02 is 455209 days after 2956-12-27
#[MySQL] Mysql reports actual difference is = 455209
#--
#[Datediff]2905-02-25 is -466866 days after 1626-12-01
#[MySQL] Mysql reports actual difference is = -466866
#--
#[Datediff]1605-10-23 is 113856 days after 1917-07-16
#[MySQL] Mysql reports actual difference is = 113856
#--
#[Datediff]2401-08-20 is 34469 days after 2496-01-03
#[MySQL] Mysql reports actual difference is = 34469
#--
#[Datediff]1863-09-16 is 16705 days after 1909-06-12
#[MySQL] Mysql reports actual difference is = 16705
#--
#[Datediff]2631-09-06 is 42712 days after 2748-08-15
#[MySQL] Mysql reports actual difference is = 42712
#--
#[Datediff]2714-08-09 is -12026 days after 2681-09-04
#[MySQL] Mysql reports actual difference is = -12026
#--
#[Datediff]1844-11-19 is 229379 days after 2472-11-25
#[MySQL] Mysql reports actual difference is = 229379
#--
#[Datediff]1640-02-11 is 464018 days after 2910-07-21
#[MySQL] Mysql reports actual difference is = 464018
#--
#[Datediff]1779-07-15 is 300513 days after 2602-04-25
#[MySQL] Mysql reports actual difference is = 300513
#--
Ruby won’t let you divide an integer by zero—you’ll get an exception. However, thanks to the IEEE 754 standard for floating point numbers, when you try to divide a float by zero you get a rather special value back:
puts 1.0/0
#-> Infinity
It’s not a constant though, it’s just how that floating point result is represented as a string. However, you can easily assign that value to a constant:
Infinity = 1.0/0
Once you have that, you can use it for all kinds of nifty things; throw it in ranges, use it in comparisons, whatever suits your fancy:
# a rather useless range
everything = -Infinity..Infinity
puts everything.include?(5) #-> true
# use it for representing an unbounded value
storage_limits => { :demo => 0,
:standard => 250.megabytes,
:expert => 1.gigabyte,
:unlimited => Infinity }
if bytes_used < storage_limits[account_level]
# add another file or something
else
# display "out of space" message
end