/**
  * return iCaldateTime object instance based on date array and timezone(s)
  *
  * @author Kjell-Inge Gustafsson, kigkonsult <*****@*****.**>
  * @since 2.21.11 - 2015-03-28
  * @param array  $date
  * @param array  $params
  * @param array  $tz
  * @param string $dtstartTz
  * @uses iCalUtilityFunctions::$fmt
  * @uses iCaldateTime::getTimezoneName()
  * @uses iCaldateTime::$dateFormat
  * @uses iCaldateTime::$key
  * @return object instance
  */
 public static function factory(array $date, $params = null, $tz = null, $dtstartTz = null)
 {
     if (isset($params['TZID']) && !empty($params['TZID'])) {
         $tz = 'Z' == $params['TZID'] ? 'UTC' : $params['TZID'];
     } elseif (isset($tz['tz']) && !empty($tz['tz'])) {
         $tz = 'Z' == $tz['tz'] ? 'UTC' : $tz['tz'];
     } else {
         $tz = ini_get('date_default_timezone_set');
     }
     $strdate = sprintf(iCalUtilityFunctions::$fmt['Ymd'], (int) $date['year'], (int) $date['month'], (int) $date['day']);
     if (isset($date['hour'])) {
         $strdate .= 'T' . sprintf(iCalUtilityFunctions::$fmt['His'], (int) $date['hour'], (int) $date['min'], (int) $date['sec']);
     }
     try {
         $timezone = new DateTimeZone($tz);
         $d = new iCaldateTime($strdate, $timezone);
     } catch (Exception $e) {
         $d = new iCaldateTime($strdate);
     }
     if (!empty($dtstartTz)) {
         if ('Z' == $dtstartTz) {
             $dtstartTz = 'UTC';
         }
         if ($dtstartTz != $d->getTimezoneName()) {
             // set the same timezone as dtstart
             try {
                 $timezone = new DateTimeZone($dtstartTz);
                 $d->setTimezone($timezone);
             } catch (Exception $e) {
             }
         }
     }
     unset($timezone, $strdate);
     if (isset($params['VALUE']) && 'DATE' == $params['VALUE']) {
         $d->dateFormat = 'Y-m-d';
         $d->key = $d->format('Ymd');
     } else {
         $d->key = $d->format('YmdHis');
     }
     return $d;
 }