code: public static function excelToDateTimeObject($excelTimestamp, $timeZone = null)
      {
          $timeZone = ($timeZone === null) ? self::getDefaultTimezone() : self::validateTimeZone($timeZone);
          if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_EXCEL) {
              if ($excelTimestamp < 1.0) {
                  // Unix timestamp base date
                  $baseDate = new \DateTime('1970-01-01', $timeZone);
              } else {
                  // MS Excel calendar base dates
                  if (self::$excelCalendar == self::CALENDAR_WINDOWS_1900) {
                      // Allow adjustment for 1900 Leap Year in MS Excel
                      $baseDate = ($excelTimestamp < 60) ? new \DateTime('1899-12-31', $timeZone) : new \DateTime('1899-12-30', $timeZone);
                  } else {
                      $baseDate = new \DateTime('1904-01-01', $timeZone);
                  }
              }
          } else {
              $baseDate = new \DateTime('1899-12-30', $timeZone);
          }
  
          $days = floor($excelTimestamp);
          $partDay = $excelTimestamp - $days;
          $hours = floor($partDay * 24);
          $partDay = $partDay * 24 - $hours;
          $minutes = floor($partDay * 60);
          $partDay = $partDay * 60 - $minutes;
          $seconds = round($partDay * 60);
  
          if ($days >= 0) {
              $days = '+' . $days;
          }
          $interval = $days . ' days';
  
          return $baseDate->modify($interval)
              ->setTime($hours, $minutes, $seconds);
      }
docs: Convert a MS serialized datetime value from Excel to a PHP Date/Time object.
  
  @param float|int $excelTimestamp MS Excel serialized date/time value
  @param null|DateTimeZone|string $timeZone The timezone to assume for the Excel timestamp,
  if you don't want to treat it as a UTC value
  Use the default (UST) unless you absolutely need a conversion
  
  @throws \Exception
  
  @return \DateTime PHP date/time object