That's an OADate (OLE Automation Date). What you're getting back float(42987)
IS the exact value underneath. Excel just displays it as a date in whatever format you chose.
Use this class to convert it.
class OLEAutomationDateConverter
{
/**
* Get the OLE Automation Date epoch
*
* @return DateTimeImmutable
*/
public static function BaseDate()
{
static $baseDate = null;
if ($baseDate == null) {
$baseDate = new DateTimeImmutable('1899-12-30 00:00:00');
}
return $baseDate;
}
/**
* Convert a DateTime object to a float representing an OLE Automation Date
*
* @param DateTimeInterface $dateTime
* @return float
*/
public static function DateTimeToOADate(DateTimeInterface $dateTime)
{
$interval = self::BaseDate()->diff($dateTime);
$mSecs = ($interval->h * 3600000)
+ ($interval->i * 60000)
+ ($interval->s * 1000)
+ floor($dateTime->format('u') / 1000);
return $interval->days + ($mSecs / 86400000);
}
/**
* Convert a float representing an OLE Automation Date to a DateTime object
*
* The returned value has a microsecond component, but resolution is millisecond and even
* this should not be relied upon as it is subject to floating point precision errors
*
* @param float $oaDate
* @return DateTime
*/
public static function OADateToDateTime($oaDate)
{
$days = floor($oaDate);
$msecsFloat = ($oaDate - $days) * 86400000;
$msecs = floor($msecsFloat);
$hours = floor($msecs / 3600000);
$msecs %= 3600000;
$mins = floor($msecs / 60000);
$msecs %= 60000;
$secs = floor($msecs / 1000);
$msecs %= 1000;
$dateTime = self::BaseDate()
->add(new DateInterval(sprintf('P%sDT%sH%sM%sS', $days, $hours, $mins, $secs)))
->format('Y-m-d H:i:s');
return new DateTime("$dateTime.$msecs");
}
}
Alternatively, if you can use javascript, use the moment library. There's a function to convert OADates TO and FROM.
https://github.com/markitondemand/moment-msdate#about-ole-automation-dates
Convert an OA date to a moment (or to a JavaScript date):
moment.fromOADate(41493)
returns Wed Aug 07 2013 00:00:00 GMT-0600 (MDT)
For exact date and time (time is the value right of the decimal):
moment.fromOADate(41493.706892280097000)
returns Wed Aug 07 2013 16:57:55 GMT-0600 (MDT)
By default moment.fromOADate()
uses the server time as the offset to UTC a second argument can be provided that indicates the offset of the OA date to UTC in minutes.
moment.fromOADate(42754.835023148145, 360)
returns Fri Jan 20 2017 02:02:25 GMT+0000 (UTC)
For Moment formatting:
//convert OA date into Moment (JavaScript date)
var momentDate = moment.fromOADate(41493.706892280097000);
//use Moment's awesomeness
var formattedDate = momentDate.format('MMM Do YY);
//formattedDate === "Aug 7th 13"
This could easily be chained together as:
moment.fromOADate(41493.706892280097000).format('MMM Do YY); //Aug 7th 13
Note: OLE Automation dates are unspecified, meaning they’re based on the local timezone by default.