$type)
				{
					$d = array();
					$text .= "\n".$key.": [";
					foreach($type as $val)
					{
						$d[] = '"'.$val.'"';
					}
					$text .= implode(",",$d);
					$text .= "],";
				}
				$text .= '
		meridiem: ["am", "pm"]
		};
		}(jQuery));';
		return $text;
	}
	/**
	 * Return an array of language terms representing months
	 * @param $type string : month, month-short, day, day-short, day-shortest
	 * @return array|bool
	 */
	public function terms($type='month')
	{
		if($type == 'month' || $type == 'month-short')
		{
			$val = ($type == 'month-short') ? '%b' : '%B';  //eg. 'Aug' / 'August'
			$marray = array();
			for ($i = 1; $i < 13; $i++)
			{
				$marray[$i] = eShims::strftime($val, mktime(1, 1, 1, $i, 1, 2000));
			}
			return $marray;
		}	
		
		if(strpos($type, 'day') === 0)
		{
			$days = array();
			for ($i=2; $i < 9; $i++) 
			{
				switch ($type) 
				{
					case 'day-shortest': // eg. 'Tu'
						$days[] = substr(eShims::strftime('%a', mktime(1, 1, 1, 6, $i, 2014)), 0, 2);
					break;
					
					case 'day-short':  // eg. 'Tue'
						$days[] = eShims::strftime('%a', mktime(1, 1, 1, 6, $i, 2014));
					break;
					
					default:  // eg. 'Tuesday'
						$days[] = eShims::strftime('%A', mktime(1, 1, 1, 6, $i, 2014));
					break;
				}
			}
			
			return $days;
		}	
		
		
		
		return false;
	}
	
	
	
	
	
	
	
	/**
	 * Convert datestamp to human readable date.
	 * System time offset is considered.
	 * 
	 * @param integer $datestamp unix stamp
	 * @param string $mask [optional] long|short|forum|relative or any strftime() valid string
	 * 
	 * @return string parsed date
	 */
	function convert_date($datestamp, $mask = '')
	{
		$datestamp = (int) $datestamp;
		if($datestamp == 0) return "";
		if(empty($mask))
		{
			$mask = 'long';
		}
		switch($mask)
		{
			case 'long':
				$mask = e107::getPref('longdate');
			//	$datestamp += TIMEOFFSET;
			break;
			
			case 'short':
				$mask = e107::getPref('shortdate');
			//	$datestamp += TIMEOFFSET;
			break;
			
			case 'input': 
			case 'inputdate': 
				$mask = e107::getPref('inputdate', '%d/%m/%Y %H:%M');
				// $mask .= " ".e107::getPref('inputtime', '%H:%M');
			break;
			
			case 'inputdatetime': 
				$mask = e107::getPref('inputdate', '%d/%m/%Y %H:%M');
				$mask .= " ".e107::getPref('inputtime', '%H:%M');
			break;
			
			case 'inputtime': 
				$mask = e107::getPref('inputtime', '%H:%M');
			break;
			case 'forum': // DEPRECATED - temporary here from BC reasons only
		//	default: 
				//BC - old 'forum' call
				if(strpos($mask, '%') === FALSE)
				{
					$mask = e107::getPref('forumdate');
				}
			//	$datestamp += TIMEOFFSET;
			break;
			
			case 'relative':
				return $this->computeLapse($datestamp, time(), false, true, 'short') ;
			break;
			
			default:
				if(strpos($mask, '%') === FALSE)
				{
					$mask = $this->toMask($mask,true);
				}				
			break;
		}
		$dateString = eShims::strftime($mask, $datestamp);
		if (!e107::getParser()->isUTF8($dateString))
		{
			$dateString = utf8_encode($dateString);
		}
		return $dateString;
	}
	/**
	 * @deprecated - for internal use only.
	 * @see $tp->toDate() as a replacement. 
	 * Converts between unix timestamp and human-readable date-time OR vice-versa. (auto-detected)
	 * @param string $string unix timestamp OR human-readable date-time.
	 * @param string $mask (optional) long | short | input
	 * @return bool|int|string
	 */
	function convert($string=null, $mask = 'inputdate')
	{
		trigger_error(''.__METHOD__.' is deprecated. Use $tp->toDate() instead.', E_USER_DEPRECATED); // NO LAN
		if($string == null) return false;
		return is_numeric($string) ? $this->convert_date($string, $mask) : $this->toTime($string, $mask);
	}
	
	
	/** 
	 * Converts to new date-mask format or vice-versa when $legacy is TRUE
	 *
	 * string       $mask
	 * string|bool  $legacy false= strftime > datetimepicker,  true = datetimepicker > strftime, 'DateTime' = strftime > DateTime format.
	 * @see https://secure.php.net/manual/en/function.strftime.php
	 * @see https://github.com/AuspeXeu/bootstrap-datetimepicker
	 * @see https://secure.php.net/manual/en/datetime.createfromformat.php
	 */
	function toMask($mask, $legacy = false)
	{
		//strftime() -> datetimepicker format.
		$convert = array(
			'%Y'	=> 'yyyy',	// Year 4-digits  '2013'
			'%d'	=> 'dd',    // day of the month 2-digits
			'%m'	=> 'mm',	// month number 2-digits
			'%B'	=> 'MM', 	// Full month name, based on the locale
			'%A'	=> 'DD', 	// A full textual representation of the day
	
			'%y'	=> 'yy',
			'%a'	=> 'D', 	// An abbreviated textual representation of the day
			'%b'	=> 'M', 	// Abbreviated month name, based on the locale
			'%h'	=> 'M', 	// Abbreviated month name, based on the locale (an alias of %b)
			'%I'	=> 'HH',	// Two digit representation of the hour in 12-hour format 
			'%l'	=> 'H',		// 12 hour format - no leading zero
			
			'%H'	=> 'hh',	// 24 hour format - leading zero
			'%M'	=> 'ii',	// Two digit representation of the minute 
			'%S'	=> 'ss',	// Two digit representation of the second 
			'%P'	=> 'p',		// %P	lower-case 'am' or 'pm' based on the given time
			'%p'	=> 'P',	    // %p   UPPER-CASE 'AM' or 'PM' based on the given time
		
			'%T' 	=> 'hh:mm:ss',
			'%r' 	=> "hh:mmm:ss TT" // 12 hour format
		);
		// strftime() > DateTime::
		if($legacy === 'DateTime')
		{
			$convert = array(
				'%Y'	=> 'Y',	    // Year 4-digits  '2013'
				'%d'	=> 'd',     // Two-digit day of the month (with leading zeros) (01 through 31)
				'%e'    => 'j',     // Day of the month, with a space preceding single digits. Not implemented on Windows with strftime.
				'%m'	=> 'm',     // Two digit representation of the month (01 throught 12)
				'%B'	=> 'F', 	// Full month name, based on the locale
				'%A'	=> 'l', 	// A full textual representation of the day
				'%y'	=> 'y',
				'%a'	=> 'D', 	// An abbreviated textual representation of the day
				'%b'	=> 'M', 	// Abbreviated month name, based on the locale
				'%h'	=> 'M', 	// Abbreviated month name, based on the locale (an alias of %b)
				'%k'    => 'G',    // Hour in 24-hour format, with a space preceding single digits (0 through 23)
				'%I'	=> 'h', 	// Two digit representation of the hour in 12-hour format (	01 through 12)
				'%l'	=> 'g',		// 12 hour format - no leading zero (1 through 12)
				'%H'	=> 'H',	    // Two digit representation of the hour in 24-hour format (00 through 23)
				'%M'	=> 'i',	    // Two digit representation of the minute (00 through 59)
				'%S'	=> 's',	    // Two digit representation of the second (00 through 59)
				'%P'	=> 'a',		// lower-case 'am' or 'pm' based on the given time
				'%p'	=> 'A', 	// UPPER-CASE 'AM' or 'PM' based on the given time
				'%Z'    => 'e',      // The time zone abbreviation. Not implemented as described on Windows with strftime.
				// TODO Add anything that is missing.
		//		'%T' 	=> 'hh:mm:ss',
		//		'%r' 	=> "hh:mmm:ss TT" // 12 hour format
			);
		}
		$s = array_keys($convert);
		$r = array_values($convert);	
		
		if(strpos($mask, '%') === false && $legacy === true)
		{
			$ret = str_replace($r, $s,$mask);
			return str_replace('%%p', '%P', $ret); // quick fix.
		}
		elseif(strpos($mask,'%')!==false)
		{
			return str_replace($s,$r, $mask);
		}
		
		return $mask; 
		
		// Keep this info here: 
		/*
				 * $options allowed keys:
	
		 * 
		 *   d - day of month (no leading zero)
		    dd - day of month (two digit)
		    o - day of the year (no leading zeros)
		    oo - day of the year (three digit)
		    D - day name short
		    DD - day name long
		    m - month of year (no leading zero)
		    mm - month of year (two digit)
		    M - month name short
		    MM - month name long
		    y - year (two digit)
		    yy - year (four digit)
		    @ - Unix timestamp (ms since 01/01/1970)
		     ! - Windows ticks (100ns since 01/01/0001)
		    '...' - literal text
		    '' - single quote
		    anything else - literal text 
		
		    ATOM - 'yy-mm-dd' (Same as RFC 3339/ISO 8601)
		    COOKIE - 'D, dd M yy'
		    ISO_8601 - 'yy-mm-dd'
		    RFC_822 - 'D, d M y' (See RFC 822)
		    RFC_850 - 'DD, dd-M-y' (See RFC 850)
		    RFC_1036 - 'D, d M y' (See RFC 1036)
		    RFC_1123 - 'D, d M yy' (See RFC 1123)
		    RFC_2822 - 'D, d M yy' (See RFC 2822)
		    RSS - 'D, d M y' (Same as RFC 822)
		    TICKS - '!'
		    TIMESTAMP - '@'
		    W3C - 'yy-mm-dd' (Same as ISO 8601)
		 * 
		 * h    Hour with no leading 0
		 * hh    Hour with leading 0
		 * m    Minute with no leading 0
		 * mm    Minute with leading 0
		 * s    Second with no leading 0
		 * ss    Second with leading 0
		 * l    Milliseconds always with leading 0
		 * t    a or p for AM/PM
		 * T    A or P for AM/PM
		 * tt    am or pm for AM/PM
		 * TT    AM or PM for AM/PM 
			
			*/
	}
	
	/**
	 * Convert date string back to integer (unix timestamp)
	 * NOTE: after some tests, strptime (compat mode) is adding +1 sec. after parsing to time, investigate!
	 * 
	 * @param string $date_string
	 * @param string $mask [optional]
	 * @return integer
	 */
	function toTime($date_string, $mask = 'input')
	{
		switch($mask)
		{
			case 'long':
				$mask = e107::getPref('longdate');
			break;
			
			case 'short':
				$mask = e107::getPref('shortdate');
			break;
			case 'input': 
			case 'inputdate': 
				$mask = e107::getPref('inputdate', '%Y/%m/%d');
			break;
			
			case 'inputdatetime': 
				$mask = e107::getPref('inputdate', '%Y/%m/%d');
				$mask .= " ".e107::getPref('inputtime', '%H:%M');
			break;
			
			case 'inputtime': 
				$mask = e107::getPref('inputtime', '%H:%M');
			break;
		}
		// convert to PHP 5+ @see https://secure.php.net/manual/en/datetime.createfromformat.php
		$newMask = $this->toMask($mask, 'DateTime');
		$tdata = date_parse_from_format($newMask, $date_string);
		return mktime(
			$tdata['hour'],
			$tdata['minute'],
			$tdata['second'],
			$tdata['month'] ,
			$tdata['day'],
			$tdata['year']
		);
		// also in php compat handler for plugins that might use it.
		/*
		$tdata = $this->strptime($date_string, $mask);
		
		
		if(empty($tdata))
		{
			if(!empty($date_string) && ADMIN)
			{
				e107::getMessage()->addDebug( "PROBLEM WITH CONVERSION from ".$date_string." to unix timestamp");	
			}
			return null;
		}
		
		if(STRPTIME_COMPAT !== TRUE) // returns months from 0 - 11 on Unix so we need to +1 
		{
			$tdata['tm_mon'] = $tdata['tm_mon'] +1;	 
		}
				
		
		$unxTimestamp = mktime( 
			$tdata['tm_hour'], 
			$tdata['tm_min'], 
			$tdata['tm_sec'], 
			$tdata['tm_mon'] , 
			$tdata['tm_mday'], 
			($tdata['tm_year'] + 1900) 
		); 
		return $unxTimestamp;
		*/
	}
// -----------------------
	/**
	 * Tolerant date/time input routine - doesn't force use of specific delimiters, and can sometimes allow no delimiters at all
	 * The format string defines the critical day/month/year order.
	 * As examples, with suitable format specifiers all of the following will be interpreted into valid (and sensible) dates/times:
	 *  09122003 153045		-> 9-12-03 at 15:30:45 (requires dmy or mdy format specifier)
	 *	20031209 12:30:32	-> 9-12-03 at 12:30:32 (requires ymd specifier)
	 *	091203 1530			-> 9-12-09 at 15:30:00
	 *  9/12/3 12			-> 9-12-09 at 12:00:00
	 *	6-3/4 15-45:27		-> 6-3-04 at 15:45:27
	 *
	 * @param string $input - usually date/time string with numeric values for relevant fields, and almost any separator. e.g. dd-mm-yy hh:mm
	 *							Date and time must be separated by one or more spaces. In times, minutes and seconds are optional, and default to zero
	 *							One special value is allowed - 'now'
	 * @param string $decode - one of 'date', 'time', 'datetime', 'timedate'
	 * @param string $format - sets field order for dates. Valid strings are dmy, mdy, ymd. Add suffix 'z' to return UTC/GMT
	 * @param boolean $endDay - if TRUE, and no time entered, includes a time of 23:59:59 in the entered date
	 *
	 * @return integer time stamp.  returns zero on any error
	 */
	public function decodeDateTime($input, $decode = 'date', $format = 'dmy', $endDay = FALSE)
	{
		if ($input == 'now') return time();		// Current time   TODO: option to return UTC or local time here
		$useLocale = TRUE;
		if (substr($format,-1,1) == 'z')
		{
			$useLocale = FALSE;
			$format = substr($format,0,-1);		// Remove local disable string
		}
		switch ($decode)
		{
			case 'date' :
				$timeString = '';
				$dateString = $input;
				break;
			case 'time' :
				$timeString = $input;
				$dateString = '';
				break;
			case 'datetime' :		// Date then time, separated by space
				$input = str_replace('  ',' ', $input);
				list($dateString, $timeString) = explode(' ',$input,2);
				break;
			case 'timedate' :		// Time then date, separated by space
				$input = str_replace('  ',' ', $input);
				list($timeString, $dateString) = explode(' ',$input,2);
				break;
			default :
				return 0;
		}
		$timeString = trim($timeString);
		$dateString = trim($dateString);
		$dateVals = array (1 => 0, 2 => 0, 3 => 0);		// Preset date in case 
		$timeVals = array (1 => 0, 2 => 0, 3 => 0);		// Preset time in case 
		if ($dateString)
		{
			if (is_numeric($dateString))
			{
				if (strlen($dateString) == 6)
				{	// Probably fixed format numeric without separators
					$dateVals = array(1 => substr($dateString,0,2), 2 => substr($dateString,2,2), 3 => substr($dateString,-2));
				}
				elseif (strlen($dateString) == 8)
				{	// Trickier - year may be first or last!
					if ($format == 'ymd')
					{
						$dateVals = array(1 => substr($dateString,0,4), 2 => substr($dateString,4,2), 3 => substr($dateString,-2));
					}
					else
					{
						$dateVals = array(1 => substr($dateString,0,2), 2 => substr($dateString,2,2), 3 => substr($dateString,-4));
					}
				}
			}
			else
			{  // Assume standard 'nn-nn-nn', 'nnnn-nn-nn' or 'nn-nn-nnnn' type format
				if (!preg_match('#(\d{1,4})\D(\d{1,2})\D(\d{1,4})#', $dateString, $dateVals))
				{
					return 0;			// Can't decode date
				}
			}
		}
		if ($timeString)
		{
			if (is_numeric($timeString))
			{
				if (strlen($timeString) == 6)
				{	// Assume hhmmss
					$timeVals = array(1 => substr($timeString,0,2), 2 => substr($timeString,2,2), 3 => substr($timeString,-2));
				}
				elseif (strlen($timeString) == 4)
				{	// Assume hhmm
					$timeVals = array(1 => substr($timeString,0,2), 2 => substr($timeString,-2), 3 => 0);
				}
				else
				{	// Hope its just hours!
					if ($timeString < 24)
					{
						$timeVals[1] = $timeString;
					}
				}
			}
			else
			{
				preg_match('#(\d{1,2})(?:\D(\d{1,2}))?(?:\D(\d{1,2}))?#', $timeString, $timeVals);
			}
		}
		elseif ($endDay)
		{
			$timeVals = array (1 => 23, 2 => 59, 3 => 59);		// Last second of day
		}
		// Got all the values now - the rest is simple!
		switch ($format)
		{
			case 'dmy' :
				$month = $dateVals[2]; $day = $dateVals[1]; $year = $dateVals[3]; break;
			case 'mdy' :
				$month = $dateVals[1]; $day = $dateVals[2]; $year = $dateVals[3]; break;
			case 'ymd' :
				$month = $dateVals[2]; $day = $dateVals[3]; $year = $dateVals[1]; break;
			default :
				echo "Unsupported format string: {$format}
";
				return 0;
		}
		if ($useLocale)
		{
			return mktime($timeVals[1], $timeVals[2], $timeVals[3], $month, $day, $year);
		}
		return gmmktime($timeVals[1], $timeVals[2], $timeVals[3], $month, $day, $year);
	}
	/**
	 * Calculate difference between two dates for display in terms of years/months/weeks....
	 * 
	 * @param integer $older_date - time stamp
	 * @param integer|boolean $newer_date - time stamp.  Defaults to current time if FALSE
	 * @param boolean $mode -if TRUE, return value is an array. Otherwise return value is a string
	 * @param boolean $show_secs
	 * @param string $format - controls display format. 'short' misses off year. 'long' includes everything
	 * @return array|string according to $mode, array or string detailing the time difference
	 */
	function computeLapse($older_date, $newer_date = FALSE, $mode = FALSE, $show_secs = TRUE, $format = 'long') 
	{
		$older_date = (int) $older_date;
		if($older_date == 0) return "";
		if(empty($newer_date))
		{
			$newer_date = time();
		}
		if($format === 'short')
		{
			$sec = LANDT_09;
			$secs = LANDT_09s;
			$min = LANDT_08;
			$mins = LANDT_08s;
		}
		else
		{
			$sec = LANDT_07;
			$secs = LANDT_07s;
			$min = LANDT_06;
			$mins = LANDT_06s;
		}
		$dateString1 = date("Y-m-d H:i:s", $older_date);
		$dateString2 = date("Y-m-d H:i:s", $newer_date);
		$date1 = new DateTime($dateString1);
		$date2 = new DateTime($dateString2);
		$interval = $date1->diff($date2);
		$result = array(
			'years'     => array($interval->y, LANDT_01,LANDT_01s),
			'months'    => array($interval->m, LANDT_02, LANDT_02s),
			'weeks'     => array(floor($interval->d/7), LANDT_03, LANDT_03s),
			'days'      => array($interval->d % 7,LANDT_04, LANDT_04s),
			'hours'     => array($interval->h, LANDT_05, LANDT_05s),
			'minutes'   => array($interval->i, $min, $mins),
			'seconds'   => array($interval->s, $sec, $secs),
		);
		if($show_secs !== true)
		{
			unset($result['seconds']);
		}
		$ret = array();
		foreach($result as $val)
		{
			if($val[0] < 1)
			{
				continue;
			}
			$ret[] = ($val[0] == 1) ? $val[0]." ".$val[1] : $val[0]." ".$val[2];
			if($format === 'short') { break; }
		}
		if(empty($ret) || strpos($ret[0],$sec) !== false)
		{
			$justNow = deftrue('LANDT_10',"Just now");
			return $mode ? array($justNow) : $justNow;
		}
        if($older_date < $newer_date) // past
        {
            $replace = implode(", ", $ret);
            $xago = e107::getParser()->lanVars(LANDT_XAGO, $replace);
            return ($mode ? $ret : $xago);
        }
        else // future
        {
            $replace = implode(", ", $ret);
            $inx = e107::getParser()->lanVars(LANDT_INX, $replace);
            return ($mode ? $ret : $inx);
        }
	//	print_r($ret);
/*
  If we want an absolutely accurate result, main problems arise from the varying numbers of days in a month.
  If we go over a month boundary, then we need to add days to end of start month, plus days in 'end' month
  If start day > end day, we cross a month boundary. Calculate last day of start date. Otherwise we can just do a simple difference.
*/
/*
		$newer_date = ($newer_date === FALSE ? (time()) : $newer_date);
		if($older_date>$newer_date)
		{  // Just in case the wrong way round
		  $tmp=$newer_date; 
		  $newer_date=$older_date; 
		  $older_date=$tmp; 
		}
		$new_date = getdate($newer_date);
		$old_date = getdate($older_date);
		$result   = array();
		$outputArray = array();
		$params   = array(
					  6 => array('seconds',60, $sec, $secs),
					  5 => array('minutes',60, $min, $mins),
					  4 => array('hours',24, LANDT_05, LANDT_05s),
					  3 => array('mday', -1, LANDT_04, LANDT_04s),
					  2 => array('',-3, LANDT_03, LANDT_03s),
					  1 => array('mon',12, LANDT_02, LANDT_02s),
					  0 => array('year', -2, LANDT_01,LANDT_01s)
					);
		$cy = 0;
		foreach ($params as $parkey => $parval)
		{
		  if ($parkey == 2)
		  {
		    $result['2'] = floor($result['3']/7);
			$result['3'] = fmod($result['3'],7);
		  }
		  else
		  {
		    $tmp = $new_date[$parval[0]] - $old_date[$parval[0]] - $cy;
			$scy = $cy;
		    $cy = 0;
		    if ($tmp < 0)
		    {
		      switch ($parval[1])
			  {
			    case -1 :    // Wrapround on months - special treatment
			      $tempdate = getdate(mktime(0,0,0,$old_date['mon']+1,1,$old_date['year']) - 1);  // Last day of month
				  $tmp = $tempdate['mday'] - $old_date['mday'] + $new_date['mday'] - $scy;
				  $cy = 1;
			      break;
			    case -2 :		// Year wraparound - shouldn't happen
				case -3 : 		// Week processing - this shouldn't happen either
				  echo "Code bug!
";
			      break;
			    default :
		          $cy = 1;
				  $tmp += $parval[1];
			}
		  }
		  $result[$parkey] = $tmp;
		  }
		}
		// Generate output array, add text
		for ($i = 0; $i < ($show_secs ? 7 : 6); $i++)
		{
		  if (($i > 4) || ($result[$i] != 0))
		  {  // Only show non-zero values, except always show minutes/seconds
		    $outputArray[] = $result[$i]." ".($result[$i] == 1 ? $params[$i][2] : $params[$i][3]) ;
			
			
		  }
		  if($format == 'short' && count($outputArray) == 1) { break; }
		}
		if(empty($outputArray[1]) && ($outputArray[0] == "0 ".$mins))
		{
			return deftrue('LANDT_10',"Just now");
		}
		// Check if it is 'past' or 'future'
		if($older_date > $newer_date) // past
		{
			return ($mode ? $outputArray : implode(", ", $outputArray) . " " . LANDT_AGO);	
		}	
		else // future
		{
			return ($mode ? $outputArray : LANDT_IN ." ". implode(", ", $outputArray));
		}
		*/
	}
	/**
	 * Parse a time/date generated with strftime()
	 * With extra output keys for localized month
	 *
	 * @deprecated Use eShims::strptime() instead
	 * @see eShims::strptime()
	 * @param string $str date string to parse (e.g. returned from strftime()).
	 * @param        $format
	 * @return array|bool Returns an array with the $str parsed, or false on error.
	 */
	public function strptime($str, $format)
	{
		trigger_error('' . __METHOD__ . ' is deprecated.  Use eShims::strptime() instead', E_USER_DEPRECATED); // NO LAN
		$vals = eShims::strptime($str, $format); // PHP5 is more accurate than below.
		$vals['tm_amon'] = eShims::strftime('%b', mktime(0, 0, 0, $vals['tm_mon'] + 1));
		$vals['tm_fmon'] = eShims::strftime('%B', mktime(0, 0, 0, $vals['tm_mon'] + 1));
		return $vals;
	}
	/**
	 * @param $mode
	 * @return bool
	 */
	function supported($mode = FALSE)
	{
		$strftimeFormats = array(
		    'A' => 'A full textual representation of the day',
		    'B' => 'Full month name, based on the locale',
		    'C' => 'Two digit representation of the century (year divided by 100, truncated to an integer)',
		    'D' => 'Same as "%m/%d/%y"',
		    'E' => '',
		    'F' => 'Same as "%Y-%m-%d"',
		    'G' => 'The full four-digit version of %g',
		    'H' => 'Two digit representation of the hour in 24-hour format',
		    'I' => 'Two digit representation of the hour in 12-hour format',
		    'J' => '',
		    'K' => '',
		    'L' => '',
		    'M' => 'Two digit representation of the minute',
		    'N' => '',
		    'O' => '',
		    'P' => 'lower-case "am" or "pm" based on the given time',
		    'Q' => '',
		    'R' => 'Same as "%H:%M"',
		    'S' => 'Two digit representation of the second',
		    'T' => 'Same as "%H:%M:%S"',
		    'U' => 'Week number of the given year, starting with the first Sunday as the first week',
		    'V' => 'ISO-8601:1988 week number of the given year, starting with the first week of the year with at least 4 weekdays, with Monday being the start of the week',
		    'W' => 'A numeric representation of the week of the year, starting with the first Monday as the first week',
		    'X' => 'Preferred time representation based on locale, without the date',
		    'Y' => 'Four digit representation for the year',
		    //'Z' => 'The time zone offset/abbreviation option NOT given by %z (depends on operating system)',
		    'a' => 'An abbreviated textual representation of the day',
		    'b' => 'Abbreviated month name, based on the locale',
		    'c' => 'Preferred date and time stamp based on local',
		    'd' => 'Two-digit day of the month (with leading zeros)',
		    'e' => 'Day of the month, with a space preceding single digits',
		    'f' => '',
		    'g' => 'Two digit representation of the year going by ISO-8601:1988 standards (see %V)',
		    'h' => 'Abbreviated month name, based on the locale (an alias of %b)',
		    'i' => '',
		    'j' => 'Day of the year, 3 digits with leading zeros',
		    'k' => '',
		    'l' => 'Hour in 12-hour format, with a space preceeding single digits',
		    'm' => 'Two digit representation of the month',
		    'n' => 'A newline character ("\n")',
		    'o' => '',
		    'p' => 'UPPER-CASE "AM" or "PM" based on the given time',
		    'q' => '',
		    'r' => 'Same as "%I:%M:%S %p"',
		    's' => 'Unix Epoch Time timestamp',
		    't' => 'A Tab character ("\t")',
		    'u' => 'ISO-8601 numeric representation of the day of the week',
		    'v' => '',
		    'w' => 'Numeric representation of the day of the week',
		    'x' => 'Preferred date representation based on locale, without the time',
		    'y' => 'Two digit representation of the year',
		    //'z' => 'Either the time zone offset from UTC or the abbreviation (depends on operating system)',
		    '%' => 'A literal percentage character ("%")',
		);
		if (stripos(PHP_OS, 'WIN') === false)
		{
			// This formats are not avaiilable on windows and will make the script fail on use.
			$strftimeFormats['Z'] = 'The time zone offset/abbreviation option NOT given by %z (depends on operating system)';
			$strftimeFormats['z'] = 'Either the time zone offset from UTC or the abbreviation (depends on operating system)';
		}
		
		// Results.
		$strftimeValues = array();
		
		// Evaluate the formats whilst suppressing any errors.
		foreach($strftimeFormats as $format => $description)
		{
			$strftimeValues[$format] = eShims::strftime("%{$format}");
		}
		
		// Find the longest value.
		$maxValueLength = 2 + max(array_map('strlen', $strftimeValues));
		
		$ret = array(
			'enabled' 	=> array(),
			'disabled' 	=> array()
		);
		
		// Report known formats.
		foreach($strftimeValues as $format => $value)
		{
			$ret['enabled'][] = $format;
		    echo ($mode =='list') ? "Known format   : '{$format}' = ". str_pad("'{$value}'", $maxValueLength). " ( {$strftimeFormats[$format]} )
" : "";
		}
		
		// Report unknown formats.
		foreach(array_diff_key($strftimeFormats, $strftimeValues) as $format => $description)
		{
			$ret['disabled'][] = $format;
		    echo ($mode =='list') ? "Unknown format : '{$format}'   ". str_pad(' ', $maxValueLength). ($description ? " ( {$description} )" : ''). "
" : "";
		}	
		
		return in_array($mode,$ret['enabled']); 
		
		
	}
	/**
	 * Check if TimeZone is valid
	 * @param $timezone
	 * @return bool
	 */
	function isValidTimezone($timezone)
	{
		return in_array($timezone, timezone_identifiers_list());
	}
	/**
	 * @param $datestamp
	 * @return array
	 */
	public function dateFormats($datestamp = null)
	{
		if(empty($datestamp))
		{
			$datestamp = time();
		}
		$formats = array(
						"%A, %d %B, %Y",
						"%A, %d %b, %Y",
						"%a, %d %B, %Y",
						"%a, %d %b, %Y",
						
						"%A, %B %d, %Y",
						"%A, %b %d, %Y",
						"%A, %b %d, %y",
						
						"%B %d, %Y",
						"%b %d, %Y",
						"%b %d, %y",
						
						"%d %B, %Y",
						"%d %b, %Y",
						"%d %b, %y",
						
						"%Y-%m-%d",
						"%d-%m-%Y",
						"%m/%d/%Y",
						"%d.%m.%Y"
					);
		$ret = [];
		foreach($formats as $f)
		{
			$ret[$f] = eShims::strftime($f,$datestamp);
		}
		return $ret;
	}
	/**
	 * @param $datestamp
	 * @return array
	 */
	function timeFormats($datestamp=null)
	{
		if(empty($datestamp))
		{
			$datestamp = time();
		}
		$inputtime = array();
		$inputtime["%I:%M %p"]	= eShims::strftime("%I:%M %p",$datestamp);
		if(e107::getDate()->supported('P'))
		{
			$inputtime["%I:%M %P"]	= eShims::strftime("%I:%M %P",$datestamp);
		}
		if(e107::getDate()->supported('l'))
		{
			$inputtime["%l:%M %p"]	= eShims::strftime("%l:%M %p",$datestamp);
			$inputtime["%l:%M %P"]	= eShims::strftime("%l:%M %P",$datestamp);
		}
		$inputtime["%H:%M"]		= eShims::strftime("%H:%M",$datestamp);
		$inputtime["%H:%M:%S"]	= eShims::strftime("%H:%M:%S",$datestamp);
		return $inputtime;
	}
}
/**
 * BC Fix convert
 */
class convert extends e_date
{
}