Files
luos/workflow/engine/src/ProcessMaker/Util/DateTime.php
Victor Saisa Lopez 6cd975664b PM-444 "0013316: Be able to assign users to different time zone (user's time zone)" SOLVED
Issue:
    PM-444:  0013316: Be able to assign users to different time zone
    PM-3493: Agregar soporte multiple timezone a los endpoints usando formato fecha ISO 8601
Cause:
    New feature
Solution:
    Added functionality for time zone
2015-11-26 20:11:58 -04:00

362 lines
13 KiB
PHP

<?php
namespace ProcessMaker\Util;
class DateTime
{
const ISO8601 = 'Y-m-d\TH:i:sP';
const REGEXPDATE = '[1-9]\d{3}\-(?:0[1-9]|1[0-2])\-(?:0[1-9]|[12][0-9]|3[01])';
const REGEXPTIME = '(?:[0-1]\d|2[0-3])\:[0-5]\d\:[0-5]\d';
/**
* Get Time Zone Offset by Time Zone ID
*
* @param string $timeZoneId Time Zone ID
*
* @return int Return the Time Zone Offset; false otherwise
*/
public function getTimeZoneOffsetByTimeZoneId($timeZoneId)
{
try {
$dt = new \DateTime(null, new \DateTimeZone($timeZoneId));
//Return
return $dt->getOffset();
} catch (\Exception $e) {
throw $e;
}
}
/**
* Get Time Zone ID by Time Zone Offset
*
* @param int $offset Time Zone Offset
*
* @return string Return the Time Zone ID; UTC ID otherwise
*/
public function getTimeZoneIdByTimeZoneOffset($offset)
{
try {
foreach (\DateTimeZone::listIdentifiers() as $value) {
$timeZoneOffset = self::getTimeZoneOffsetByTimeZoneId($value);
if ($timeZoneOffset !== false && $timeZoneOffset == $offset) {
//Return
return $value;
}
}
//Return
return 'UTC';
} catch (\Exception $e) {
throw $e;
}
}
/**
* Get Time Zone ID by UTC Offset
*
* @param string $utcOffset UTC Offset
*
* @return string Return the Time Zone ID; UTC ID otherwise
*/
public function getTimeZoneIdByUtcOffset($utcOffset)
{
try {
if (preg_match('/^([\+\-])(\d{2}):(\d{2})$/', $utcOffset, $arrayMatch)) {
$sign = $arrayMatch[1];
$h = (int)($arrayMatch[2]);
$m = (int)($arrayMatch[3]);
} else {
//Return
return 'UTC';
}
$offset = (($sign == '+')? '' : '-') . (($h * 60 * 60) + ($m * 60)); //Convert UTC Offset to seconds
//Return
return self::getTimeZoneIdByTimeZoneOffset((int)($offset));
} catch (\Exception $e) {
throw $e;
}
}
/**
* Convert date from Time Zone to Time Zone
*
* @param string $date Date
* @param string $fromTimeZone Time Zone source
* @param string $toTimeZone Time Zone to convert
* @param string $format Format to return date
*
* @return string Return date
*/
public function convertTimeZone($date, $fromTimeZone, $toTimeZone, $format = 'Y-m-d H:i:s')
{
try {
$dt = new \DateTime($date, new \DateTimeZone($fromTimeZone)); //From Time Zone
$dt->setTimeZone(new \DateTimeZone($toTimeZone)); //To Time Zone
//Return
return $dt->format($format);
} catch (\Exception $e) {
throw $e;
}
}
/**
* Convert ISO-8601 to Time Zone
*
* @param string $dateIso8601 Date
* @param string $toTimeZone Time Zone to convert
* @param string $format Format to return date
*
* @return string Return date
*/
public function convertIso8601ToTimeZone($dateIso8601, $toTimeZone, $format = 'Y-m-d H:i:s')
{
try {
$fromTimeZone = 'UTC';
if (preg_match('/^.+([\+\-]\d{2}:\d{2})$/', $dateIso8601, $arrayMatch)) {
$fromTimeZone = self::getTimeZoneIdByUtcOffset($arrayMatch[1]);
}
$dt = \DateTime::createFromFormat(self::ISO8601, $dateIso8601, new \DateTimeZone($fromTimeZone)); //From ISO-8601
$dt->setTimeZone(new \DateTimeZone($toTimeZone)); //To Time Zone
//Return
return $dt->format($format);
} catch (\Exception $e) {
throw $e;
}
}
/**
* Convert ISO-8601/datetime/array-ISO-8601-datetime-data to Time Zone
*
* @param mixed $data Data
* @param string $fromTimeZone Time Zone source
* @param string $toTimeZone Time Zone to convert
* @param array $arrayKey Keys that convert to Time Zone
* @param string $format Format to return data
*
* @return mixed Return data
*/
public function convertDataToTimeZone($data, $fromTimeZone, $toTimeZone, array $arrayKey = [], $format = 'Y-m-d H:i:s')
{
try {
$regexpDatetime = '/^' . self::REGEXPDATE . '\s' . self::REGEXPTIME . '$/';
$regexpIso8601 = '/^' . self::REGEXPDATE . 'T' . self::REGEXPTIME . '[\+\-]\d{2}:\d{2}$/';
if (empty($data)) {
//Return
return $data;
}
switch (gettype($data)) {
case 'string':
if (is_string($data) && preg_match($regexpDatetime, $data)) {
if ($fromTimeZone != $toTimeZone) {
$data = self::convertTimeZone($data, $fromTimeZone, $toTimeZone, $format);
}
}
if (is_string($data) && preg_match($regexpIso8601, $data)) {
$data = self::convertIso8601ToTimeZone($data, $toTimeZone, $format);
}
break;
case 'array':
$regexpKey = (!empty($arrayKey))? '/^(?:' . implode('|', $arrayKey) . ')$/i': '';
array_walk_recursive(
$data,
function (&$value, $key, $arrayData)
{
try {
if ($arrayData['regexpKey'] == '' || preg_match($arrayData['regexpKey'], $key)) {
if (is_string($value) && preg_match($arrayData['regexpDatetime'], $value)) {
if ($arrayData['fromTimeZone'] != $arrayData['toTimeZone']) {
$value = self::convertTimeZone($value, $arrayData['fromTimeZone'], $arrayData['toTimeZone'], $arrayData['format']);
}
}
if (is_string($value) && preg_match($arrayData['regexpIso8601'], $value)) {
$value = self::convertIso8601ToTimeZone($value, $arrayData['toTimeZone'], $arrayData['format']);
}
}
} catch (\Exception $e) {
throw $e;
}
},
['fromTimeZone' => $fromTimeZone, 'toTimeZone' => $toTimeZone, 'format' => $format, 'regexpDatetime' => $regexpDatetime, 'regexpIso8601' => $regexpIso8601, 'regexpKey' => $regexpKey]
);
break;
case 'object':
$data = json_decode(json_encode($data), true);
$data = self::convertDataToTimeZone($data, $fromTimeZone, $toTimeZone, $arrayKey, $format);
$data = json_decode(json_encode($data));
break;
}
//Return
return $data;
} catch (\Exception $e) {
throw $e;
}
}
/**
* Convert datetime/array-datetime-data to ISO-8601
*
* @param mixed $data Data
* @param string $fromTimeZone Time Zone source
* @param string $toTimeZone Time Zone to convert
* @param array $arrayKey Keys that convert to ISO-8601
*
* @return mixed Return data
*/
public function convertDataToIso8601($data, $fromTimeZone, $toTimeZone, array $arrayKey = [])
{
try {
$regexpDatetime = '/^' . self::REGEXPDATE . '\s' . self::REGEXPTIME . '$/';
if (empty($data)) {
//Return
return $data;
}
switch (gettype($data)) {
case 'string':
if (is_string($data) && preg_match($regexpDatetime, $data)) {
if ($fromTimeZone != $toTimeZone) {
$data = self::convertTimeZone($data, $fromTimeZone, $toTimeZone);
}
$dt = \DateTime::createFromFormat('Y-m-d H:i:s', $data, new \DateTimeZone($toTimeZone));
$data = $dt->format(self::ISO8601);
}
break;
case 'array':
$regexpKey = (!empty($arrayKey))? '/^(?:' . implode('|', $arrayKey) . ')$/i': '';
array_walk_recursive(
$data,
function (&$value, $key, $arrayData)
{
try {
if (($arrayData['regexpKey'] == '' || preg_match($arrayData['regexpKey'], $key)) &&
is_string($value) && preg_match($arrayData['regexpDatetime'], $value)
) {
if ($arrayData['fromTimeZone'] != $arrayData['toTimeZone']) {
$value = self::convertTimeZone($value, $arrayData['fromTimeZone'], $arrayData['toTimeZone']);
}
$dt = \DateTime::createFromFormat('Y-m-d H:i:s', $value, new \DateTimeZone($arrayData['toTimeZone']));
$value = $dt->format(self::ISO8601);
}
} catch (\Exception $e) {
throw $e;
}
},
['fromTimeZone' => $fromTimeZone, 'toTimeZone' => $toTimeZone, 'regexpDatetime' => $regexpDatetime, 'regexpKey' => $regexpKey]
);
break;
case 'object':
$data = json_decode(json_encode($data), true);
$data = self::convertDataToIso8601($data, $fromTimeZone, $toTimeZone, $arrayKey);
$data = json_decode(json_encode($data));
break;
}
//Return
return $data;
} catch (\Exception $e) {
throw $e;
}
}
/**
* Convert ISO-8601/datetime/array-ISO-8601-datetime-data to UTC
*
* @param mixed $data Data
* @param array $arrayKey Keys that convert to UTC
* @param string $format Format to return data
*
* @return mixed Return data
*/
public static function convertDataToUtc($data, array $arrayKey = [], $format = 'Y-m-d H:i:s')
{
try {
if (!(isset($_SESSION['__SYSTEM_UTC_TIME_ZONE__']) && $_SESSION['__SYSTEM_UTC_TIME_ZONE__'])) {
//Return
return $data;
}
$fromTimeZone = \ProcessMaker\BusinessModel\User::getUserLoggedTimeZone();
$toTimeZone = 'UTC';
//Return
return self::convertDataToTimeZone($data, $fromTimeZone, $toTimeZone, $arrayKey, $format);
} catch (\Exception $e) {
throw $e;
}
}
/**
* Convert UTC to Time Zone
*
* @param mixed $data Data
* @param array $arrayKey Keys that convert to Time Zone
* @param string $format Format to return data
*
* @return mixed Return data
*/
public static function convertUtcToTimeZone($data, array $arrayKey = [], $format = 'Y-m-d H:i:s')
{
try {
if (!(isset($_SESSION['__SYSTEM_UTC_TIME_ZONE__']) && $_SESSION['__SYSTEM_UTC_TIME_ZONE__'])) {
//Return
return $data;
}
$fromTimeZone = 'UTC';
$toTimeZone = \ProcessMaker\BusinessModel\User::getUserLoggedTimeZone();
//Return
return self::convertDataToTimeZone($data, $fromTimeZone, $toTimeZone, $arrayKey, $format);
} catch (\Exception $e) {
throw $e;
}
}
/**
* Convert UTC to ISO-8601
*
* @param mixed $data Data
* @param array $arrayKey Keys that convert to ISO-8601
*
* @return mixed Return data
*/
public static function convertUtcToIso8601($data, array $arrayKey = [])
{
try {
if (!(isset($_SESSION['__SYSTEM_UTC_TIME_ZONE__']) && $_SESSION['__SYSTEM_UTC_TIME_ZONE__'])) {
//Return
return $data;
}
$fromTimeZone = 'UTC';
$toTimeZone = \ProcessMaker\BusinessModel\User::getUserLoggedTimeZone();
//Return
return self::convertDataToIso8601($data, $fromTimeZone, $toTimeZone, $arrayKey);
} catch (\Exception $e) {
throw $e;
}
}
}