blob: abd656c8ddf098ab3fd410096f04c56486429080 [file] [log] [blame]
<?php
namespace LdapRecord\Models\Attributes;
use Carbon\Carbon;
use Carbon\CarbonInterface;
use DateTime;
use LdapRecord\LdapRecordException;
use LdapRecord\Utilities;
class Timestamp
{
/**
* The current timestamp type.
*
* @var string
*/
protected $type;
/**
* The available timestamp types.
*
* @var array
*/
protected $types = [
'ldap',
'windows',
'windows-int',
];
/**
* Constructor.
*
* @param string $type
*
* @throws LdapRecordException
*/
public function __construct($type)
{
$this->setType($type);
}
/**
* Set the type of timestamp to convert from / to.
*
* @param string $type
*
* @throws LdapRecordException
*/
public function setType($type)
{
if (! in_array($type, $this->types)) {
throw new LdapRecordException("Unrecognized LDAP date type [$type]");
}
$this->type = $type;
}
/**
* Converts the value to an LDAP date string.
*
* @param mixed $value
*
* @throws LdapRecordException
*
* @return float|string
*/
public function fromDateTime($value)
{
$value = is_array($value) ? reset($value) : $value;
// If the value is being converted to a windows integer format but it
// is already in that format, we will simply return the value back.
if ($this->type == 'windows-int' && $this->valueIsWindowsIntegerType($value)) {
return $value;
}
// If the value is numeric, we will assume it's a UNIX timestamp.
elseif (is_numeric($value)) {
$value = Carbon::createFromTimestamp($value);
}
// If a string is given, we will pass it into a new carbon instance.
elseif (is_string($value)) {
$value = Carbon::parse($value);
}
// If a date object is given, we will convert it to a carbon instance.
elseif ($value instanceof DateTime) {
$value = Carbon::instance($value);
}
switch ($this->type) {
case 'ldap':
$value = $this->convertDateTimeToLdapTime($value);
break;
case 'windows':
$value = $this->convertDateTimeToWindows($value);
break;
case 'windows-int':
$value = $this->convertDateTimeToWindowsInteger($value);
break;
default:
throw new LdapRecordException("Unrecognized date type [{$this->type}]");
}
return $value;
}
/**
* Determine if the value given is in Windows Integer (NTFS Filetime) format.
*
* @param int|string $value
*
* @return bool
*/
protected function valueIsWindowsIntegerType($value)
{
return is_numeric($value) && strlen((string) $value) === 18;
}
/**
* Converts the LDAP timestamp value to a Carbon instance.
*
* @param mixed $value
*
* @throws LdapRecordException
*
* @return Carbon|false
*/
public function toDateTime($value)
{
$value = is_array($value) ? reset($value) : $value;
if ($value instanceof CarbonInterface || $value instanceof DateTime) {
return Carbon::instance($value);
}
switch ($this->type) {
case 'ldap':
$value = $this->convertLdapTimeToDateTime($value);
break;
case 'windows':
$value = $this->convertWindowsTimeToDateTime($value);
break;
case 'windows-int':
$value = $this->convertWindowsIntegerTimeToDateTime($value);
break;
default:
throw new LdapRecordException("Unrecognized date type [{$this->type}]");
}
return $value instanceof DateTime ? Carbon::instance($value) : $value;
}
/**
* Converts standard LDAP timestamps to a date time object.
*
* @param string $value
*
* @return DateTime|bool
*/
protected function convertLdapTimeToDateTime($value)
{
return DateTime::createFromFormat(
strpos($value, 'Z') !== false ? 'YmdHis\Z' : 'YmdHisT',
$value
);
}
/**
* Converts date objects to a standard LDAP timestamp.
*
* @param DateTime $date
*
* @return string
*/
protected function convertDateTimeToLdapTime(DateTime $date)
{
return $date->format(
$date->getOffset() == 0 ? 'YmdHis\Z' : 'YmdHisO'
);
}
/**
* Converts standard windows timestamps to a date time object.
*
* @param string $value
*
* @return DateTime|bool
*/
protected function convertWindowsTimeToDateTime($value)
{
return DateTime::createFromFormat(
strpos($value, '0Z') !== false ? 'YmdHis.0\Z' : 'YmdHis.0T',
$value
);
}
/**
* Converts date objects to a windows timestamp.
*
* @param DateTime $date
*
* @return string
*/
protected function convertDateTimeToWindows(DateTime $date)
{
return $date->format(
$date->getOffset() == 0 ? 'YmdHis.0\Z' : 'YmdHis.0O'
);
}
/**
* Converts standard windows integer dates to a date time object.
*
* @param int $value
*
* @throws \Exception
*
* @return DateTime|bool
*/
protected function convertWindowsIntegerTimeToDateTime($value)
{
// ActiveDirectory dates that contain integers may return
// "0" when they are not set. We will validate that here.
if (! $value) {
return false;
}
return (new DateTime())->setTimestamp(
Utilities::convertWindowsTimeToUnixTime($value)
);
}
/**
* Converts date objects to a windows integer timestamp.
*
* @param DateTime $date
*
* @return float
*/
protected function convertDateTimeToWindowsInteger(DateTime $date)
{
return Utilities::convertUnixTimeToWindowsTime($date->getTimestamp());
}
}