<?php
namespace ICalendarOrg;
class ZDateHelper
{
public static function addDate(int $date, int $hour, int $min, int $sec, int $month, int $day, int $year, string $tzid = 'UTC')
{
\date_default_timezone_set($tzid);
$sqldate = self::toSQLDateTime($date);
$tdate = [];
$tdate['year'] = (int)\substr($sqldate, 0, 4);
$tdate['mon'] = (int)\substr($sqldate, 5, 2);
$tdate['mday'] = (int)\substr($sqldate, 8, 2);
$tdate['hours'] = (int)\substr($sqldate, 11, 2);
$tdate['minutes'] = (int)\substr($sqldate, 14, 2);
$tdate['seconds'] = (int)\substr($sqldate, 17, 2);
$newdate = \mktime($tdate['hours'] + $hour, $tdate['minutes'] + $min, $tdate['seconds'] + $sec, $tdate['mon'] + $month, $tdate['mday'] + $day, $tdate['year'] + $year);
\date_default_timezone_set('UTC');
return $newdate;
}
public static function DayInMonth(int $month, int $year) : int
{
$daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
if (2 != $month)
{
return $daysInMonth[$month - 1];
}
return (\checkdate($month, 29, $year)) ? 29 : 28;
}
public static function DTNow(string $tzid) : \DateTime
{
try
{
$dtz = new \DateTimeZone($tzid);
}
catch (\Exception $e)
{
$dtz = null;
}
return new \DateTime('now', $dtz);
}
public static function fromiCaltoUnixDateTime(string $datetime) : int
{
$formats = [];
$formats[] = '/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/';
$formats[] = '/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]T[0-9][0-9][0-9][0-9][0-9][0-9]/';
$formats[] = '/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]T[0-9][0-9][0-9][0-9][0-9][0-9]Z/';
$ok = false;
foreach ($formats as $format)
{
if (\preg_match($format, $datetime))
{
$ok = true;
break;
}
}
if (! $ok)
{
return 0;
}
$year = (int)\substr($datetime, 0, 4);
$month = (int)\substr($datetime, 4, 2);
$day = (int)\substr($datetime, 6, 2);
$hour = 0;
$minute = 0;
$second = 0;
if (\strlen($datetime) > 8 && 'T' == $datetime[8])
{
$hour = (int)\substr($datetime, 9, 2);
$minute = (int)\substr($datetime, 11, 2);
$second = (int)\substr($datetime, 13, 2);
}
return \gmmktime($hour, $minute, $second, $month, $day, $year);
}
public static function fromSqlDateTime(?string $datetime = null) : string
{
\date_default_timezone_set('UTC');
if (null == $datetime)
{
$datetime = \time();
}
else
{
$datetime = \strtotime($datetime);
}
return \date('Ymd\THis', $datetime);
}
public static function fromUnixDate(?int $datetime = null) : string
{
\date_default_timezone_set('UTC');
if (null == $datetime)
{
$datetime = \time();
}
return \date('Ymd', $datetime);
}
public static function fromUnixDateTime(?int $datetime = null) : string
{
\date_default_timezone_set('UTC');
if (null == $datetime)
{
$datetime = \time();
}
return \date('Ymd\THis', $datetime);
}
public static function fromUnixDateTimetoiCal(int $datetime) : string
{
\date_default_timezone_set('GMT');
return \gmdate("Ymd\THis", $datetime);
}
public static function getAbsDate(string $date, string $rdate = '') : string
{
if (\str_replace(['y', 'm', 'd', 'h', 'n'], '', \strtolower($date)) != \strtolower($date))
{
\date_default_timezone_set('UTC');
if ('' == $rdate)
{
$udate = \time();
}
else
{
$udate = self::toUnixDateTime($rdate);
}
$values = \explode(',', \strtolower($date));
$y = 0;
$m = 0;
$d = 0;
$h = 0;
$n = 0;
foreach ($values as $value)
{
$rtype = \substr($value, \strlen($value) - 1);
$rvalue = (\substr($value, 0, \strlen($value) - 1));
switch ($rtype)
{
case 'y':
$y = (int)$rvalue;
break;
case 'm':
$m = (int)$rvalue;
break;
case 'd':
$d = (int)$rvalue;
break;
case 'h':
$h = (int)$rvalue;
break;
case 'n':
$n = (int)$rvalue;
break;
}
if ('-' == $rvalue[0])
{
$udate = \mktime(0, 0, 0, (int)\date('m', $udate), (int)\date('d', $udate), (int)\date('Y', $udate));
}
else
{
$udate = \mktime(0, -1, 0, (int)\date('m', $udate), (int)\date('d', $udate) + 1, (int)\date('Y', $udate));
}
$udate = self::addDate($udate, $h, $n, 0, $m, $d, $y);
}
$date = self::toSQLDateTime($udate);
}
return $date;
}
public static function getDateFromDay(int $date, int $week, int $wday, string $tzid = 'UTC') : int
{
$tdate = \getdate($date);
$monthbegin = \gmmktime(0, 0, 0, $tdate['mon'], 1, $tdate['year']);
$monthend = self::addDate($monthbegin, 0, 0, 0, 1, -1, 0, $tzid);
$day = self::addDate($date, 0, 0, 0, 0, 1 - $tdate['mday'], 0, $tzid);
$month = [[]];
while ($day <= $monthend)
{
$tdate = \getdate($day);
$month[$tdate['wday']][] = $day;
$day = self::addDate($day, 0, 0, 0, 0, 1, 0, $tzid);
}
$dayinmonth = 0;
if ($week >= 0)
{
$dayinmonth = $month[$wday][$week];
}
else
{
$dayinmonth = $month[$wday][\count($month[$wday]) - 1];
}
return $dayinmonth;
}
public static function iCalDurationtoSeconds(string $duration) : int
{
$secs = 0;
if ('P' == $duration[0])
{
$duration = \str_replace(['H', 'M', 'S', 'T', 'D', 'W', 'P'], ['H,', 'M,', 'S,', '', 'D,', 'W,', ''], $duration);
$dur2 = \explode(',', $duration);
foreach ($dur2 as $dur)
{
$val = (int)$dur;
if (\strlen($dur) > 0)
{
switch ($dur[\strlen($dur) - 1])
{
case 'H':
$secs += 60 * 60 * $val;
break;
case 'M':
$secs += 60 * $val;
break;
case 'S':
$secs += $val;
break;
case 'D':
$secs += 60 * 60 * 24 * $val;
break;
case 'W':
$secs += 60 * 60 * 24 * 7 * $val;
break;
}
}
}
}
return $secs;
}
public static function inDay(int $daystart, int $begin, int $end) : bool
{
$dayend = self::addDate($daystart, 0, 0, 0, 0, 1, 0);
$end = \max($begin, $end);
$inday =
($daystart <= $begin && $begin < $dayend)
|| ($daystart < $end && $end < $dayend)
|| ($begin <= $daystart && $end > $dayend);
return $inday;
}
public static function isAfterToday(int $date, string $tzid = 'UTC') : bool
{
$dt = self::DTNow($tzid);
$now = \time() + $dt->getTimezone()->getOffset($dt);
return \mktime(0, 0, 0, (int)\date('m', $now), (int)\date('d', $now), (int)\date('Y', $now)) <
\mktime(0, 0, 0, (int)\date('m', $date), (int)\date('d', $date), (int)\date('Y', $date));
}
public static function isBeforeToday(int $date, string $tzid = 'UTC') : bool
{
$dt = self::DTNow($tzid);
$now = \time() + $dt->getTimezone()->getOffset($dt);
return \mktime(0, 0, 0, (int)\date('m', $now), (int)\date('d', $now), (int)\date('Y', $now)) >
\mktime(0, 0, 0, (int)\date('m', $date), (int)\date('d', $date), (int)\date('Y', $date));
}
public static function isFuture(int $date, string $tzid = 'UTC') : bool
{
$dt = self::DTNow($tzid);
$now = \time() + $dt->getTimezone()->getOffset($dt);
return $date > $now;
}
public static function isPast(int $date, string $tzid = 'UTC') : bool
{
$dt = self::DTNow($tzid);
$now = \time() + $dt->getTimezone()->getOffset($dt);
return $date < $now;
}
public static function isToday(int $date, string $tzid = 'UTC') : bool
{
$dt = self::DTNow($tzid);
$now = \time() + $dt->getTimezone()->getOffset($dt);
return \gmdate('Y-m-d', $date) == \gmdate('Y-m-d', $now);
}
public static function isTomorrow(int $date, string $tzid = 'UTC') : bool
{
$dt = self::DTNow($tzid);
$now = \time() + $dt->getTimezone()->getOffset($dt);
return \gmdate('Y-m-d', $date) == \gmdate('Y-m-d', $now + 60 * 60 * 24);
}
public static function isWeekend(int $date) : bool
{
$dow = \gmdate('w', $date);
return 0 == $dow || 6 == $dow;
}
public static function now(string $tzid = 'UTC') : int
{
$dt = self::DTNow($tzid);
$now = \time() + $dt->getTimezone()->getOffset($dt);
return $now;
}
public static function toiCalDate(?int $datetime = null) : string
{
\date_default_timezone_set('UTC');
if (null == $datetime)
{
$datetime = \time();
}
return \gmdate('Ymd', $datetime);
}
public static function toiCalDateTime(?int $datetime = null) : string
{
\date_default_timezone_set('UTC');
if (null == $datetime)
{
$datetime = \time();
}
return \gmdate("Ymd\THis", $datetime);
}
public static function toLocalDateTime(string $sqldate, string $tzid = 'UTC') : string
{
try
{
$timezone = new \DateTimeZone($tzid);
}
catch (\Exception $e)
{
return $sqldate;
}
$udate = self::toUnixDateTime($sqldate);
$daydatetime = new \DateTime('@' . $udate);
$tzoffset = $timezone->getOffset($daydatetime);
return self::toSQLDateTime($udate + $tzoffset);
}
public static function toSQLDate(int $t = 0) : string
{
\date_default_timezone_set('GMT');
if (0 == $t)
{
return \gmdate('Y-m-d', self::now());
}
return \gmdate('Y-m-d', $t);
}
public static function toSQLDateTime(int $t = 0) : string
{
\date_default_timezone_set('GMT');
if (0 == $t)
{
return \gmdate('Y-m-d H:i:s', self::now());
}
return \gmdate('Y-m-d H:i:s', $t);
}
public static function toUnixDate(string $datetime) : int
{
$year = (int)\substr($datetime, 0, 4);
$month = (int)\substr($datetime, 5, 2);
$day = (int)\substr($datetime, 8, 2);
return \mktime(0, 0, 0, $month, $day, $year);
}
public static function toUnixDateTime(string $datetime) : int
{
$datetime = self::getAbsDate($datetime);
$year = (int)\substr($datetime, 0, 4);
$month = (int)\substr($datetime, 5, 2);
$day = (int)\substr($datetime, 8, 2);
$hour = 0;
$minute = 0;
$second = 0;
if (\strlen($datetime) > 10)
{
$hour = (int)\substr($datetime, 11, 2);
$minute = (int)\substr($datetime, 14, 2);
$second = (int)\substr($datetime, 17, 2);
}
return \gmmktime($hour, $minute, $second, $month, $day, $year);
}
public static function toUTCDateTime(string $sqldate, string $tzid = 'UTC') : string
{
\date_default_timezone_set('UTC');
try
{
$dtz = new \DateTimeZone($tzid);
$date = new \DateTime($sqldate, $dtz);
}
catch (\Exception $e)
{
return $sqldate;
}
$offset = $dtz->getOffset($date);
if ($offset >= 0)
{
$date->sub(new \DateInterval('PT' . $offset . 'S'));
}
else
{
$date->add(new \DateInterval('PT' . \abs($offset) . 'S'));
}
return $date->format('Y-m-d H:i:s');
}
}