<?php
/*
###########################################
Inverse Parallel JD Number Table Calculator
For Both the Julian and Gregorian Calendars
Range:From BC 9999-Jan-01 to AD 9999-Dec-31
-----------------------------
Gregorian Calendar Mode Span:
BC 9999-Jan-01-Tue JD Number -1930634
to
AD 9999-Dec-31-Fri JD Number 5373484
--------------------------
Julian Calendar Mode Span:
BC 9999-Jan-01-Tue JD Number -1930711
to
AD 9999-Dec-31-Mon JD Number 5373557
AUTHOR : Jay Tanner - 2025
LANGUAGE : PHP v8.2.12
LICENSE : Public Domain
###########################################
*/
ob_start();
$cYear = date('Y');
$MinJDNum = -1930711;
$MaxJDNum = 5373557;
// ---------------------------------------------------------------
// Define the program cookie name and set it to expire in 30 days.
$CookieName = 'Parallel-Greg-Julian-JD-Number-Table-Calculator';
$SetToExpireIn30Days = time() + 30*86400;
// ---------------------------------
// Define PHP program and HTML info.
$_AUTHOR_ = "Jay Tanner - $cYear";
$_PROGRAM_VERSION_ = 'v2.0 - '; $at = "at Local Time "; $LTC = "UTC";
$_SCRIPT_FILE_PATH_ = Filter_Input(INPUT_SERVER, 'SCRIPT_FILENAME');
$_REVISION_DATE_ = $_PROGRAM_VERSION_ .'Revised: '. date("Y-M-d-D $at h:i:s A ($LTC", FileMTime($_SCRIPT_FILE_PATH_))."−05:00)";
$_BROWSER_TAB_TEXT_ = "Parallel Gregorian/Julian JD Number Table Calculator";
$_INTERFACE_TITLE_ = "<span style='font-size:15pt;'>Parallel Gregorian/Julian JD Number Table Calculator</span><br>
<span style='font-size:11pt; line-height:175%;'>For the JD Number / Date Span From</span><br>
<span style='font-size:11pt;'>BC 9999-Jan-01 (−1930711) to AD 9999-Dec-31 (5373557)</span><br>
<span style='font-size:9pt; line-height:175%;'>PHP Program by Jay Tanner - $cYear</span>";
// -------------------------------------
// Define main TextArea text and background
// colors and HTML table row span. If an
// error is reported, then these colors
// will change internally to red/white.
$TxColor = 'black';
$BgColor = 'white';
// ---------------------------------------------
// Do this only if [COMPUTE] button was clicked.
$w = Filter_Input(INPUT_POST, 'ComputeButton');
if (!IsSet($w))
{
// ----------------------------------------------------------------------
// If this program is being called externally, rather than being executed
// by clicking the [COMPUTE] button, and an active cookie also exists,
// then restore the previously saved interface settings from it. If
// the user leaves and comes back later, all the interface settings
// will be remembered and restored if the cookie was not deleted.
$w = Filter_Input(INPUT_COOKIE, $CookieName);
if (IsSet($w))
{
$CookieDataString = Filter_Input(INPUT_COOKIE, $CookieName);
list($JDNumArg,$NumDaysArg) = Preg_Split("[\|]", $CookieDataString);
}
else
// -----------------------------------------------------------
// If there is no previous cookie with the interface settings,
// then set the initial default interface startup values and
// store them in a new cookie.
{
$Y = IntVal(date('Y'));
$m = IntVal(date('m'));
$d = IntVal(date('d'));
$JDNumArg = GregorianToJD($m, $d, $Y);
$NumDaysArg = 31;
// -------------------------------------------
// Store current interface settings in cookie.
$CookieDataString = "$JDNumArg|$NumDaysArg";
SetCookie ($CookieName, $CookieDataString, $SetToExpireIn30Days);
} // End of else {...}
} // End of if (!isset(_POST['ComputeButton']))
// ------------------------------------------
// Read values of all interface arguments and
// set all empty arguments to default values.
$w = Filter_Input(INPUT_POST, 'ComputeButton');
if (isset($w))
{
$JDNumArg = trim(Filter_Input(INPUT_POST, 'JDNumArg'));
// --------------------------------------
// Filter any commas from input argument.
$JDNumArg = Str_Replace(',', '', $JDNumArg);
// ----------------------------------------
// Set default JD number argument to today.
if ($JDNumArg == '')
{
$Y = IntVal(date('Y'));
$m = IntVal(date('m'));
$d = IntVal(date('d'));
$JDNumArg = GregorianToJD($m, $d, $Y);
}
/* -----------------------------------------------------------------------
If the argument is NOT numeric, assume it is a calendar date string and
try to compute the corresponding Julian Day Number and then use this
value as the starting JD Number value. If argument is numeric, then
assume it is already a JD Number value within the valid calendar span
and proceed with it. (An error could still be possible.)
*/
if (!Is_Numeric($JDNumArg))
{
$JDNumArg = trim(JD_Num($JDNumArg, 'G'));
}
$MaxDays = 10000;
$MinDays = -$MaxDays;
$NumDaysArg = trim(Filter_Input(INPUT_POST, 'NumDaysArg'));
if (!Is_Numeric($NumDaysArg)) {$NumDaysArg = 0;}
if ($NumDaysArg > $MaxDays) {$NumDaysArg = $MaxDays;}
if ($NumDaysArg < $MinDays) {$NumDaysArg = $MinDays;}
// ------------------------------------
// Store interface argument in cookie.
$CookieDataString = "$JDNumArg|$NumDaysArg";
SetCookie ($CookieName, $CookieDataString, $SetToExpireIn30Days);
}
// *******************************************************************
// *******************************************************************
// ERROR FILTER CODE CAN GO HERE.
// If error detected, then set ErrFlag = TRUE
// and define error message to be displayed.
$ErrFlag = FALSE;
// Check if JD Number is within valid range.
if ($JDNumArg < $MinJDNum or $JDNumArg > $MaxJDNum)
{
$ErrFlag = TRUE;
$ErrMssg = "ERROR:\nThe Starting JD Number is outside of the valid range.\n\nValid JD Number/Date Range:\nMinimum JD Number −1930711 (BC 9999-Jan-01) \nto\nMaximum JD Number 5373557 (AD 9999-Dec-31)";
}
// -------------------------
// Check (NumDaysArg) value.
if (!Is_Numeric($NumDaysArg))
{
$ErrFlag = TRUE;
$ErrMssg = "Invalid argument:\nThe number of days must be an integer value.";
}
else
{
$JDNumArg = $JDNumArg;
$NumDaysArg = SPrintF("%+1d", $NumDaysArg);
}
// ******************************************
// ******************************************
// If error was reported (TRUE), then display
// the error message on a red background.
if ($ErrFlag === TRUE)
{
$TxColor = 'white';
$BgColor = '#CC0000';
$TextArea2Text = '';
$TextArea1Text =
"$ErrMssg\n\n";
}
else
{
// *********************************************************
// BEGIN MAIN COMPUTATIONS HERE IF NO ERRORS DETECTED ABOVE.
// *********************************************************
// Computation or function call code.
$JDNumberTable = Inv_JD_Number_Table($JDNumArg, $NumDaysArg);
// Correct interactive English.
$TableSpanDays = abs($NumDaysArg) + 1;
$s = ($TableSpanDays <> 1)? 's':'';
// *******************************************
// DROP THROUGH HERE AFTER COMPUTATIONS ABOVE.
// *******************************************
$TextArea1Text =
" PARALLEL GREGORIAN/JULIAN JD NUMBER TABLE
Starting JD Number = $JDNumArg
Table Span = $TableSpanDays day$s
$JDNumberTable
";
}
// ****************************
// Define TextArea2 text block.
$TextArea2Text =
"
This program also handles negative JD Numbers.
Entering a blank JD Number argument defaults to the
current date JD Number (UT).
A starting calendar date can also be used, such as:
'BC 1949-5-20' or '2025-Feb-24' or 'AD 170-Nov-03'
The number of days represents the number of days
leading up to or following the starting point.
If the number of days is positive, the listing will
begin on the starting JD number and span that many
days after.
If the number of days is negative, the listing will
begin that many days prior to and span from there
up to the starting point.
If a calendar column has dots ...... in it, it means
that the given JD number is outside the valid range
on that calendar. It may sometimes be a valid JD
number on one calendar but not on the other. As
a general rule, this only happens near the ends
of the calendar system, which should not really
pose any serious problem for general use.";
// **************************************************************************
// Determine number of text columns and rows to use in the output text areas.
// These values vary randomly according to the text block width and length.
// The idea is to eliminate the need for scroll-bars within the text areas
// or worry as much about the variable dimensions of a text display area.
// -----------
// Text Area 1
$Text1Cols = 4 + Max(Array_Map('StrLen', PReg_Split("[\n]", trim($TextArea1Text))));
if ($Text1Cols < 80) {$Text1Cols = 54;} // Default
$Text1Rows = 3 + Substr_Count($TextArea1Text, "\n");
// -----------
// Text Area 2
// Match width of TextArea1.
$Text2Cols = 4 + Max(Array_Map('StrLen', PReg_Split("[\n]", trim($TextArea1Text))));
if ($Text2Cols < 80) {$Text2Cols = 54;} // Default
$Text2Rows = 3 + Substr_Count($TextArea2Text, "\n");
// ---------------------------------
// Set initial uniform tables width.
$TableWidth = '666'; // Width in pixels
// ******************************************
// ******************************************
// GENERATE CLIENT WEB PAGE TO DISPLAY OUTPUT
print <<< _HTML
<!DOCTYPE HTML>
<HTML>
<head>
<title>$_BROWSER_TAB_TEXT_</title>
<meta name='viewport' content='width=device-width, initial-scale=0.90'>
<meta http-equiv='content-type' content='text/html; charset=UTF-8'>
<meta http-equiv='pragma' content='no-cache'>
<meta http-equiv='expires' content='-1'>
<meta name='description' content='Parallel Gregorian/Julian Day Number Calculator'>
<meta name='keywords' content='Julian Day Number Calculator,PHPScienceLabs.com'>
<meta name='author' content='Jay Tanner - https://www.PHPScienceLabs.com'>
<meta name='robots' content='index,follow'>
<meta name='googlebot' content='index,follow'>
<style>
BODY
{
background:black; color:white; font-family:Verdana; font-size:11pt;
line-height:125%;
}
TABLE
{font-family:Verdana;}
TD
{
color:black; background:white; line-height:150%; font-size:10pt;
padding:6px; text-align:center;
}
OL,UL
{font-family:Verdana; font-size:11pt; line-height:150%; text-align:justify;}
LI
{font-family:Verdana; line-height:150%;}
PRE
{
background:white; color:black; font-family:monospace; font-size:11pt;
font-weight:bold; text-align:left; line-height:125%; padding:6px;
border:2px solid black; border-radius:8px;
page-break-before:page;
}
DIV
{
background:white; color:black; font-family:Verdana; font-size:11pt;
font-weight:normal; line-height:125%; padding:6px;
}
TEXTAREA
{
background:white; color:black; font-family:monospace; font-size:11pt;
font-weight:bold; padding:4pt; white-space:pre; border-radius:8px;
line-height:125%;
}
INPUT[type='text']::-ms-clear {width:0; height:0;}
INPUT[type='text']
{
background:white; color:black; font-family:monospace; font-size:13pt;
font-weight:bold; text-align:center; box-shadow:2px 2px 3px #666666;
border:2px solid black; border-radius:4px;
}
INPUT[type='text']:focus
{
font-family:monospace; background:white; box-shadow:2px 2px 3px #666666;
font-size:13pt; border:2px solid blue; text-align:center; font-weight:bold;
border-radius:4px;
}
INPUT[type='submit']
{
background:black; color:cyan; font-family:Verdana; font-size:10pt;
font-weight:bold; border-radius:4px; border:4px solid #777777;
padding:3pt;
}
INPUT[type='submit']:hover
{
background:black; color:white; font-family:Verdana; font-size:10pt;
font-weight:bold; border-radius:4px; border:4px solid red;
padding:3pt;
}
/* -------------------------------------------
Link states below MUST be defined in CSS in
the following sequence to work correctly:
:link, :visited, :hover, :active
*/
A:link
{
font-size:10pt; background:transparent; color:#8080FF; border-radius:4px;
font-family:Verdana; font-weight:bold; text-decoration:none;
line-height:175%; padding:3px; border:1px solid transparent;
}
A:visited
{
font-size:10pt; background:transparent; color:DodgerBlue; border-radius:4px;
}
A:hover
{
font-size:10pt; background:yellow; color:black; border:1px solid black;
box-shadow:1px 1px 3px #222222; border-radius:4px;
}
A:active
{
font-size:10pt; background:yellow; color:black; border-radius:4px;
}
HR {background:red; height:4px; border:0px;}
::selection{background-color:yellow !important; color:black !important;}
::-moz-selection{background-color:yellow !important; color:black !important;}
</style>
</head>
<body>
<form name='form1' method='post' action=''>
<!-- Define main page title/header. --->
<table width="$TableWidth" align='center' border='0' cellspacing='1' cellpadding='3'>
<tr><td colspan="99" style='color:white; background-color:#000066; border:2px solid white; border-radius:8px 8px 0px 0px;'>$_INTERFACE_TITLE_</td></tr>
<!-- Define input argument text boxes --->
<tr><td style='line-height:200%;' title=' STARTING POINT: \n\n BLANK = Current Date/Time \n\n JD Number like: 2433057 \n\n Gregorian Date String Like:\n BC 8817-7-15 \n AD 1949-May-20 \n 2109-Nov-03 '>
<span style='font-size:10pt;'>Starting Gregorian JD Number or Gregorian Date String</span><br>
<input name='JDNumArg' type='text' value="$JDNumArg" size='16' maxlength='14'></td>
<td style='line-height:200%;' title=' Days to span before or after starting point. \n\n Span: 0 to ± 10000 days'><span style='font-size:10pt;'>Number of Days </span><br>
<input name='NumDaysArg' type='text' value="$NumDaysArg" size='7' maxlength='6'>
</td></tr>
<!-- Define [COMPUTE] button --->
<tr>
<td colspan="99" style='background-color:black;'><input name='ComputeButton' type='submit' value=' C O M P U T E '></td>
</tr>
<tr>
<td colspan="2" style='font-size:10pt; color:black; background:black;
text-align:center;' title=' Tries to Open in a New Tab. '>
<b><a href="View-Source-Code.php" target="_blank"
style='font-family:Verdana; color:black; background:yellow;
text-decoration:none; border:1px solid black; padding:4px;
border-radius:4px; font-weight:normal;'>
View/Copy Source Code </a></b>
</td>
</tr>
<tr>
<td colspan="99" style='text-align:center; color:GreenYellow; background-color:black;'>Double-Click Within Text Area to Select ALL Text<br>
<textarea ID='TextArea1' name='TextArea1' style='color:$TxColor; background:$BgColor; padding:6px; border:2px solid white;' cols="$Text1Cols" rows="$Text1Rows" ReadOnly OnDblClick='this.select();' OnMouseUp='return true;'>
$TextArea1Text
</textarea>
</td>
</tr>
<!-- Define TextArea2 --->
<tr>
<td colspan="99" style='text-align:center; color:GreenYellow; background:black;'><br>
<textarea ID='TextArea2' name='TextArea2' style='color:black; background:LightYellow; padding:6px;' cols="$Text2Cols" rows="$Text2Rows" ReadOnly OnDblClick='this.select();' OnMouseUp='return true;'>
$TextArea2Text
</textarea>
</tr>
<tr>
<td colspan="99" style='color:GreenYellow; background:black;'>PHP Program by $_AUTHOR_<br><span style='color:silver; background:black;'>$_REVISION_DATE_</span></td>
</tr>
</table>
</form>
<br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br>
</body>
</HTML>
_HTML;
// END OF PROGRAM
/*
***************************************************************************
API NAME : Custom-API.php
CREATED : 2024-Aug-08-Thu 07:54:46 UTC
FILE SIZE : 4,225 bytes
This custom API contains the following
2 functions:
JD_Num()
Inv_JD_Num()
Inv_JD_Number_Table()
***************************************************************************
*/
/*
###########################################################################
This function is the inverse of the JD number function. Given any
signed JD Number, it will return the corresponding calendar date
string in 'BC|AD Yyyy-Mmm-dd-DoW' format.
CALENDAR YEAR RANGE:
BC 9999 to AD 9999
There is no calendar year 0 (zero).
Mathematical origins of the calendar systems:
BC 4713-Jan-01-Mon JDNum = 0 On old Julian calendar
BC 4714-Nov-24-Mon JDNum = 0 On modern Gregorian calendar
ARGUMENT:
JDNumber = Julian Day number for the calendar date to be computed.
JGAMode = Calendar mode
'G' = Gregorian
'J' = Julian
'A' = Auto-select mode = Default
RETURNS:
Calendar date string in 'BC|AD Yyyy-Mmm-dd-DoW' format
according to the selected calendar mode.
ERRORS:
FALSE is returned if JD number argument is non-numeric.
NO DEPENDENCIES
###########################################################################
*/
function Inv_JD_Num ($JDNumber, $JGAMode='A')
{
GLOBAL $DD; // Used for separating days in the listing.
$JDNum = trim($JDNumber);
// -------------------------------------------
// Define Month and Day-Of-Week abbreviations.
$MONTHS = 'JanFebMarAprMayJunJulAugSepOctNovDec';
$WEEKDAYS = 'SunMonTueWedThuFriSat';
// ----------------------------
// Read calendar mode argument.
// 'G' = Gregorian = Default
// 'J' = Julian
// 'A' = Auto-select
$JGAMode = substr(StrToUpper(trim($JGAMode)),0,1);
if ($JGAMode == '') {$JGAMode = 'A';}
// ----------------------------------------------
// If calendar mode = 'A' = Auto-select, then the
// calendar mode is automatically determined by
// the given JD Number argument.
if ($JGAMode == 'A')
{
$CMode = ($JDNum < 2299161)? 0:1;
$JGAMode = ($CMode == 0)? 'J':'G';
}
else
{
$CMode = ($JGAMode == 'J')? 0:1;
}
// -----------------------------------------
// Compute numerical date elements (y, m, d)
// according to the calendar mode selection.
$A = floor($JDNum + 0.5);
$B = $CMode*floor(($A - 1867216.25) / 36524.25);
$C = $A + $CMode*($B - floor($B/4) + 1);
$D = $C + 1524;
$E = floor(($D - 122.1) / 365.25);
$F = floor(365.25 * $E);
$G = floor(($D - $F) / 30.6001);
$d = $D - $F - floor(30.6001 * $G); // Day num (1 to 31)
$m = $G - 12*floor($G/14) - 1; // Month num (1 to 12)
$y = $E - 4716 + floor((14 - $m) / 12); // Mathematical year
$Y = ($y > 0)? $y : $y-1; // Calendar year (Negative = BC)
// ------------------------------------------------------------
// At this point we have the numerical date elements (y, m, d).
// The next step is to construct the full calendar date text
// string for output. EXAMPLE OUTPUT: 'BC 9998-May-20-Tue'
$i = (7 + ($JDNum + 1) % 7) % 7;
$DoW = substr($WEEKDAYS, 3*$i, 3);
$Y = Str_Replace('-', 'BC ', SPrintF("%+05d", $Y));
$Y = Str_Replace('+', 'AD ', $Y);
$Mmm = substr($MONTHS, 3*($m-1), 3);
$dd = SPrintf("%02d", $d);
$JDNum = SPrintF("% +8d", $JDNum);
$DD = $d;
// DONE.
return "$Y-$Mmm-$dd-$DoW";
} // End of Inv_JD_Num(...)
/*
###########################################################################
Given any JD number and any number of days span within the calendar range,
this function will retuen the corresponding calendar date on both the old
Julian calendar and our modern Gregorian calendar, side-by-side.
This way we can view the same JD numbers on both calendars in parallel.
Input is assumed to be according to the Gregorian calendar.
ARGUMENTS:
StartJDNum = Starting Julian Day number for the table.
NumDays = Number of days to span before (-) or after (+) starting JD.
For a single JD number, simply set NumDays = 0
StopJDNum = JD number at which to stop before or after starting JD.
Current limit = -/+ 10000 days
= 1428 weeks and 4 days
= 27.3785 years
NOTE:
If the starting JD number is greater than the stopping JD number, then the
start/stop JD values are swapped internally. This way the table is always
numbered forward from the earlier date.
DEPENDENCIES:
Inv_JD_Number()
###########################################################################
*/
function Inv_JD_Number_Table ($StartJDNum, $NumDays)
{
GLOBAL $DD; // Used for separating days in the listing.
$StartJDNum = trim($StartJDNum);
/* --------------------------------------
Read number of days argument and limit
it to -+ 10000 days either way. This
can be changed to any convenient value.
*/
$MaxDays = 10000;
$NumDays = trim($NumDays); $ns = ($NumDays < 0)? -1:1;
if (abs($NumDays) > $MaxDays) {$NumDays = $ns * $MaxDays;}
$StopJDNum = $StartJDNum + $NumDays;
$header = "JD Number Gregorian Calendar Julian Calendar
========= |====================|===================\n";
$w = '';
if ($StartJDNum > $StopJDNum)
{$u = $StartJDNum; $StartJDNum = $StopJDNum; $StopJDNum = $u;}
for ($JDNum = $StartJDNum; $JDNum <= $StopJDNum; $JDNum += 1)
{
$J = Inv_JD_Num($JDNum, 'J');
$G = Inv_JD_Num($JDNum, 'G');
$JDNum = SPrintF("% 8d", $JDNum);
// Blank out any BC 10000 lines and AD 10000 lines.
if (substr($J,0,8) == 'BC 10000')
{$J = ' ...... ';}
// Blankout any BC 10000 lines and AD 10000 lines.
if (substr($J,0,8) == 'AD 10000')
{$J = ' ...... ';}
// Blank out any BC 10000 lines and AD 10000 lines.
if (substr($G,0,8) == 'BC 10000')
{$G = ' ...... ';}
// Blankout any BC 10000 lines and AD 10000 lines.
if (substr($G,0,8) == 'AD 10000')
{$G = ' ...... ';}
// ---------------------------------------------------
// Separate the Gregorian months with a column header.
if ($DD == 1 and $JDNum > $StartJDNum) {$w .= "\n$header";}
$w .= "$JDNum | $G | $J\n";
}
return $header.$w;
} // End of Inv_JD_Number_Table (...)
/*
###########################################################################
This function returns the Julian Day Number for any given calendar date
in the range from BC 9999 to AD 9999 on the old Julian calendar or on the
modern Gregorian calendar system.
CALENDAR YEAR RANGE:
BC 9999 to AD 9999
There is no calendar year 0 (zero).
Mathematical origins of the calendar systems:
BC 4713-Jan-01-Mon JDNum = 0 Old Julian Calendar
BC 4714-Nov-24-Mon JDNum = 0 Modern Gregorian Calendar
NOTE:
If a year is given as a negative number, it refers to a BC year
and will be converted to BC|AD format internally.
Month = 1 to 12 or as 3-letter abbreviation string ('Jan' to 'Dec').
Date strings are NOT case-sensitive.
The returned signed JD Number is left-space-padded to 8 characters
to facilitate easy columnar alignment if used for tabulation.
ARGUMENTS:
$BCADDateStr = Date string in BC|AD format.
VALID EXAMPLES:
'BC 9949-May-20'
'AD 1949-5-20'
'1959-1-29'
'-1023-Nov-15'
JGAMode = Calendar mode
'G' = Gregorian
'J' = Julian
'A' = Auto-select mode = Default
ERRORS:
FALSE is returned if an invalid argument is detected.
NO DEPENDENCIES
###########################################################################
*/
function JD_Num ($BCADDateStr, $JGAMode='A')
{
// --------------------------------------------------
// Read and adjust input date string argument format.
$BCADDateStr = PReg_Replace("/\s+/", " ", trim($BCADDateStr));
// -----------------------------------------------------
// If a weekday abbreviation is identified, then remove
// it and use the remaining string as the date argument.
// This allows the output to be used as the input to the
// Inv_JD_Number() function by ignoring the weekday. The
// weekday given to the inverse function may be wrong.
// if (substr(substr($BCADDateStr, -4),0,1) == '-')
// {$BCADDateStr = substr($BCADDateStr,0, StrLen($BCADDateStr)-4);}
// ---------------------------------------------------
// If first character is a minus sign (negative year),
// then convert it into a BC year string.
if (substr($BCADDateStr,0,1) == '-')
{$BCADDateStr = 'BC ' . substr($BCADDateStr, 1, StrLen($BCADDateStr));}
// -----------------------------------------------------------
// If no BC|AD prefix at all, then attach a default AD prefix.
$ww = StrToUpper(substr($BCADDateStr,0,2));
if ($ww <> 'BC' and $ww <> 'AD') {$BCADDateStr = "AD $BCADDateStr";}
/* ------------------------------------
Error if instant bad argument format.
Valid formats:
BC|AD Yyyy-Mmm-dd 1949-May-02 1908-12-25
*/
// if (Substr_Count($BCADDateStr, '-') <> 2) {return FALSE;}
// ------------------------------
// Read and parse date arguments.
list($BCADYear,$Month,$Day) = PReg_Split("[-]", $BCADDateStr);
//exit("85: $BCADYear|$Month|$Day");
// ------------------
// A few adjustments.
$BCADYear = trim($BCADYear);
$Month = trim($Month);
$Day = trim($Day);
// -----------------------------------
// Get BC|AD prefix and calendar year.
$BCAD = StrToUpper(substr($BCADYear, 0,2));
$Y = trim(substr($BCADYear, 2, StrLen($BCADYear)));
// ---------------------------------
// Adjust for BC year, if necessary.
if ($BCAD == 'BC') {$Y = -$Y;}
// ------------------------------------------------------------
// Read calendar year argument value and return FALSE on error.
$w = abs($Y); if ($w == 0 or $w > 9999) {return FALSE;}
// ---------------------------------------------------
// Read month argument. Could be a string or a number.
$m = UCFirst(substr(StrToLower(trim($Month)),0,3));
// Read day argument value.
$d = trim($Day);
// ----------------------------
// Read calendar mode argument.
// 'G' = Gregorian | 'J' = Julian
// 'A' = Auto-select = Default
$JGAMode = substr(StrToUpper(trim($JGAMode)),0,1);
if ($JGAMode == '') {$JGAMode = 'A';}
// -------------------------------------------------
// Define abbreviations for month and weekday names.
$MONTHS = 'JanFebMarAprMayJunJulAugSepOctNovDec';
$WEEKDAYS = 'SunMonTueWedThuFriSat';
$JGDiff = 0;
// -----------------------------------------------------
// If month is a 3-letter abbreviation ('Jan' to 'Dec'),
// then replace it with the month number 1 to 12, if
// possible. Otherwise, return FALSE if it cannot
// resolve the abbreviation text.
if (!Is_Numeric($m))
{
$i = StrPos($MONTHS, $m);
if ($i === FALSE) {return $i;}
$m = 1 + $i/3;
}
// ---------------------------------------
// Error if invalid month number.
if ($m < 1 or $m > 12) {return FALSE;}
// -------------------------------------------------
// Proceed to compute the Julian calendar JD Number.
// This is the base JD Number value. If the Gregorian
// calendar is selected, then the difference between
// the calendars is applied to obtain the Gregorian
// calendar JD Number.
$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;
// ----------------------------------------------
// Handle automatic calendar mode selection.
// If calendar mode = 'A' = Auto-select, then the
// calendar mode is automatically determined by
// the computed JD Number value.
if ($JGAMode == 'A')
{
$JGAMode = ($JDNum < 2299161)? 'J':'G';
}
// ---------------------------------------------
// Handle Gregorian (= default) calendar mode by
// by ADDING the difference in days between the
// Julian and Gregorian JD Numbers, if indicated
// by the JGAMode setting. This value could be
// negative or positive, depending on the given
// date. Default Logic: If not 'J', then 'G'.
//
// GregorianJDNum = JulianJDNum + (+-JGDiff)
if ($JGAMode <> 'J')
{
$A = ($Y < 0)? $Y+1 : $Y;
$B = trim($m);
$C = $A - floor((14-$B) / 12);
$D = floor($C/100);
$JGDiff = (floor($D/4) - $D + 2);
}
$JDNum += $JGDiff;
// -------------------------------------------
// Left-pad signed JD number digits field with
// spaces to span exactly 8 characters width,
// just in case the values are used in a table.
// This helps to arrange the columns neatly.
$JDNum = SPrintF("% 8d", $JDNum);
// DONE:
return $JDNum;
} // End of JD_Num(...)
?>