First a quick review: PHP can convert strings into numbers with the handy this handy function:
$secs = strtotime( "June 18, 2008" );
This will give you an integer representing the number of seconds since January 1st, 1970 (actually, just before midnight December 31st, 1969), referred to as the Unix epoch.
Then you can convert this from seconds into a Julian Date / Julian Day with the PHP function UnixToJD(). The absolute value of this second number is very helpful, it'll be over 2 million, but you can reliably subtract two Julian dates to get the number of days between them.
$jd = UnixToJD( $secs );
Now for the problem, what about dates prior to 1970? This is where things partially break, but there is a workaround (at least for dates > 1901).
First the good news, strtotime STILL WORKS, so you can do:
$negativeSecs = strtotime( "June 18, 1964" );
And you'll get a big negative number, which is fine.
But this breaks:
$jd2 = UnixToJD( $negativeSecs );
You will always get the same date back, effectively UnixToJD( 0 );
But the Julian date range extends way earlier than 1970, more than 2 million days earlier. So the above date in 1964 DOES have a valid, positive Julian day associated with it.
Now for the workaround:
Convert the Unix time, in seconds, into days by simply dividing by the number of seconds in a day, and either rounding off or truncating the value. This is valid for both positive and negative dates. I'll call this "Unix epoch days", the number of days since 1970, and for dates prior to 1970 it's just a negative value.
Then just "add" the Unix days (which will be positive or negative) to the base Julian day for 1/1/1970.
The only odd issue I've found is an "off by one" error caused by the timezone. So if you use this method, try it with dates after 1970 first, and compare the results to using UnixToJD().
And what is the base Julian day? It's either 2440587 or 2440588. I had tried UnixToJD( 0 ), but then the date math is sometimes off by one day when I do subtractions between dates. 2440588 seems to work, but may be affected by timezone and daylight savings time, so beware!
Converting from Unix seconds to days is not quite as easy as a simple division. When you convert a string with a time into seconds, I think it assumes midnight in the local timezone and then adds an offset to correct for what it would be in GMT. So you need to remove that correction before you devide, or you'll have a fractional component.
The revised code goes something like this:
Old way:
$jd1 = UnixToJD( StrToTime( "June 18, 2008" ) ); // OK
$jd2 = UnixToJD( StrToTime( "June 18, 1964" ) ); // Wrong! Prior to 1970
New way:
// Simple constants
$SECS_IN_DAY = 3600 * 24;
$BASE_JD = 2440588; // or 2440587, play with UnixToJD(0)
// Timezone stuff...
// WRONG: $tmpDateObj = date_create();
// Update: Use the specific date, since it will correct for Daylight Savings Time for THAT specific date
$tmpDateObj = date_create( "June 18, 2008" );
$TZ = date_timezone_get( $tmpDateObj );
$TZ_NAME = timezone_name_get( $TZ ); // If you care
$TZ_OFFSET = timezone_offset_get( $TZ, $tmpDateObj ); // Can be positive or negative, but just add it in
// Update: Could also use:
// $TZ_OFFSET = date_offset_get( $tmpDateObj );
// Now the calculations
$jd3 = $BASE_JD + (StrToTime( "June 18, 2008" )+$TZ_OFFSET) / $SECS_IN_DAY;
$jd4 = $BASE_JD + (StrToTime( "June 18, 1964" )+$TZ_OFFSET) / $SECS_IN_DAY; // Adding a negative number is OK
If jd3 or jd4 has a fractional component, 123.4567890, don't just use the int or round functions, you've got something else going on with timezones or daylight saving.
Dates around 1901 / 1902 or earlier will not work, even with this workaround, as they are outside the range of even the negative numbers. The date range is approximately 1970 +/- 67.5 years
Also, some machines don't support negative datetimes at all. And of course all of this assumes you're using a recent PHP5. This code was tested on BSD in PHP5, in the California US timezone during the summer (WITH daylight savings)