==============================================================================
COMPUTING THE SIGNED JULIAN DAY NUMBER

In astronomy, we often refer to extremely ancient dates when performing the
computations for eclipses or other ancient events.  The usual algorithms
stop at BC 4713 or BC 4714, depending on which calendar is being used.

Suppose you wanted the JD number (Julian Day Number) for a calendar date
such as  'BC 8856-Apr-23'  for a theoretical computation.

The native PHP Julian Day number functions cannot handle dates that ancient
because they cannot handle negative Julian Day numbers.

The only solution is to develop a custom function to handle dates prior to
BC 4713 and return negative Julian Day number values as well.

Below is a PHP function designed to return the long-term signed Julian Day
number for any date on the Julian or Gregorian calendar system over a long
40000-year span and it handles negative JD number values as well.

However, it does NOT specifically check for erroneous date arguments.


/*
   ###########################################################################
   This PHP function  computes the signed  Julian Day Number
   on the old Julian or the modern Gregorian calendar system.

   It also handles proleptic dates prior to the mathematical
   origin of either calendar system and can handle negative
   Julian Day numbers.

   A date string argument has the format: 'SignYyyyy/mm/dd'
   Examples:  '-01949/05/20'  or  '-00009/5/20'  or  '19987/12/01'

   ARGUMENTS:
   SignYyyyy = Signed calendar year number <> 0
              -Negative = BC  and  +Positive = AD
               There is no calendar year 0 (zero).

   mm = Month number (1 to 12).
   dd = Day number   (1 to 31).

   JorG = Calendar mode switch.
          'J' = Julian calendar
       or 'G' = Gregorian calendar = Default

   ERRORS:
   Returns FALSE if any of the (Y,m,d) arguments are non-numeric.

   NO EXTERNAL DEPENDENCIES
   ###########################################################################
*/

   function JD_Number ($YmdString, $JorG='G')
{
   $YmdString = trim($YmdString);
   list($Y,$m,$d) = PReg_Split("[\/]", $YmdString);
   $Y = trim($Y);   $m = trim($m);     $d = trim($d);

   $JorG = substr(StrToUpper(trim($JorG)),0,1);
   $JorG = ($JorG == 'J')? 'J' : 'G';

// -------------------------------------------------------
// Error if any of the (Y, m, d) elements are non-numeric.

   if (
       !Is_Numeric($Y)
   or  !Is_Numeric($m)
   or  !Is_Numeric($d)
      )
      {return FALSE;}


// ---------------------------------------------------
// Compute JD number according to the Julian calendar.

   $A     = floor((14-$m) / 12);
   $B     = (($Y < 0)? $Y+1 : $Y) - $A;
   $C     = floor($B/100);
   $JDNum = floor(30.6001*(12*$A + $m+1))+floor(365.25*($B+4716))-1524 + $d;

// If the computation is for the Julian calendar, then we
// are done. Return the JD number for the Julian calendar.
   if ($JorG == 'J') {return $JDNum;}

/* Otherwise,  apply this correction  to convert the JD number on the
   old Julian calendar into  the JD number for our Gregorian calendar.
   This correction may  equate to a negative  or positive value and is
   the difference in days between the two calendar systems on the same
   given date in the context: Diff_Days = (Greg_JDNum − Julian_JDNum).
*/
   $w = floor(((($Y < 0)? $Y+1 : $Y) - floor((14-$m)/12)) / 100);
   $JDNum += (floor($w/4) - $w + 2);

   return $JDNum;
}


******************************************************************************
******************************************************************************
THE ABOVE PHP FUNCTION WITHOUT THE COMMENTS:


   function JD_Num ($YmdString, $JorG='G')
{
   $YmdString = trim($YmdString);
   list($Y,$m,$d) = PReg_Split("[\/]", $YmdString);
   $Y = trim($Y);   $m = trim($m);     $d = trim($d);

   $JorG = substr(StrToUpper(trim($JorG)),0,1);
   $JorG = ($JorG == 'J')? 'J' : 'G';

   if (
       !Is_Numeric($Y)
   or  !Is_Numeric($m)
   or  !Is_Numeric($d)
      )
      {return FALSE;}

   $A     = floor((14-$m) / 12);
   $B     = (($Y < 0)? $Y+1 : $Y) - $A;
   $C     = floor($B/100);
   $JDNum = floor(30.6001*(12*$A + $m+1))+floor(365.25*($B+4716))-1524 + $d;

   if ($JorG == 'J') {return $JDNum;}

   $w = floor(((($Y < 0)? $Y+1 : $Y) - floor((14-$m)/12)) / 100);
   $JDNum += (floor($w/4) - $w + 2);

   return $JDNum;

} // END OF  JD_Num (...)