PageRenderTime 3ms CodeModel.GetById 91ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 1ms

/symphony/lib/core/class.datetimeobj.php

https://github.com/vlad-ghita/symphony-2
PHP | 450 lines | 176 code | 50 blank | 224 comment | 37 complexity | 6aea729efe43451a45d22ec76c451b76 MD5 | raw file
  1<?php
  2
  3	/**
  4	 * @package core
  5	 */
  6
  7	 /**
  8	  * The DateTimeObj provides static functions regarding dates in Symphony.
  9	  * Symphony will set the default timezone of the system using the value from
 10	  * the Configuration values. Alternatively a new settings can be set using the
 11	  * `setSettings` function. Symphony parses all input dates against the Configuration
 12	  * date formats by default for better support with non English dates.
 13	  */
 14	Class DateTimeObj {
 15
 16		/**
 17		 * Holds the various settings for the formats that the `DateTimeObj` should
 18		 * use when parsing input dates.
 19		 *
 20		 * @since Symphony 2.2.4
 21		 * @var array
 22		 */
 23		private static $settings = array();
 24
 25		/**
 26		 * This function takes an array of settings for `DateTimeObj` to use when parsing
 27		 * input dates. The following settings are supported, `time_format`, `date_format`,
 28		 * `datetime_separator` and `timezone`. This equates to Symphony's default `region`
 29		 * group set in the `Configuration` class. If any of these values are not provided
 30		 * the class will fallback to existing `self::$settings` values
 31		 *
 32		 * @since Symphony 2.2.4
 33		 * @param array $settings
 34		 *  An associative array of formats for this class to use to format
 35		 *  dates
 36		 */
 37		public static function setSettings(array $settings = array()) {
 38			// Date format
 39			if(isset($settings['date_format'])) {
 40				self::$settings['date_format'] = $settings['date_format'];
 41			}
 42
 43			// Time format
 44			if(isset($settings['time_format'])) {
 45				self::$settings['time_format'] = $settings['time_format'];
 46			}
 47
 48			// Datetime separator
 49			if(isset($settings['datetime_separator'])) {
 50				self::$settings['datetime_separator'] = $settings['datetime_separator'];
 51			}
 52			else if (!isset(self::$settings['datetime_separator'])) {
 53				self::$settings['datetime_separator'] = ' ';
 54			}
 55
 56			// Datetime format
 57			if(isset($settings['datetime_format'])) {
 58				self::$settings['datetime_format'] = $settings['datetime_format'];
 59			}
 60			else {
 61				self::$settings['datetime_format'] = self::$settings['date_format'] . self::$settings['datetime_separator'] . self::$settings['time_format'];
 62			}
 63
 64			// Timezone
 65			if(isset($settings['timezone']) && !empty($settings['timezone'])) {
 66				self::$settings['timezone'] = $settings['timezone'];
 67				self::setDefaultTimezone($settings['timezone']);
 68			}
 69		}
 70
 71		/**
 72		 * Accessor function for the settings of the DateTimeObj. Currently
 73		 * the available settings are `time_format`, `date_format`,
 74		 * `datetime_format` and `datetime_separator`. If `$name` is not
 75		 * provided, the entire `$settings` array is returned.
 76		 *
 77		 * @since Symphony 2.2.4
 78		 * @param string $name
 79		 * @return array|string|null
 80		 *  If `$name` is omitted this function returns array.
 81		 *  If `$name` is not set, this fucntion returns `null`
 82		 *  If `$name` is set, this function returns string
 83		 */
 84		public static function getSetting($name = null) {
 85			if(is_null($name)) return self::$settings;
 86
 87			if(isset(self::$settings[$name])) return self::$settings[$name];
 88
 89			return null;
 90		}
 91
 92		/**
 93		 * Uses PHP's date_default_timezone_set function to set the system
 94		 * timezone. If the timezone provided is invalid, a `E_USER_WARNING` will be
 95		 * raised.
 96		 *
 97		 * @link http://php.net/manual/en/function.date-default-timezone-set.php
 98		 * @link http://www.php.net/manual/en/timezones.php
 99		 * @param string $timezone
100		 *  A valid timezone identifier, such as UTC or Europe/Lisbon
101		 */
102		public static function setDefaultTimezone($timezone){
103			if(!@date_default_timezone_set($timezone)) trigger_error(__('Invalid timezone %s', array($timezone)), E_USER_WARNING);
104		}
105
106		/**
107		 * Validate a given date and time string
108		 *
109		 * @param string $string
110		 *	A date and time string or timestamp to validate
111		 * @return boolean
112		 *	Returns true for valid dates, otherwise false
113		 */
114		public static function validate($string) {
115			try {
116				if(is_numeric($string) && (int)$string == $string) {
117					$date = new DateTime('@' . $string);
118				}
119				else {
120					$date = self::parse($string);
121				}
122			}
123			catch(Exception $ex) {
124				return false;
125			}
126
127			// String is empty or not a valid date
128			if(empty($string) || $date === false) {
129				return false;
130			}
131
132			// String is a valid date
133			else {
134				return true;
135			}
136		}
137
138		/**
139		 * Given a `$format`, and a `$timestamp`,
140		 * return the date in the format provided. This function is a basic
141		 * wrapper for PHP's DateTime object. If the `$timestamp` is omitted,
142		 * the current timestamp will be used. Optionally, you pass a
143		 * timezone identifier with this function to localise the output
144		 *
145		 * If you like to display a date in the backend, please make use
146		 * of `DateTimeObj::format()` which allows date and time localization
147		 *
148		 * @see class.datetimeobj.php#format()
149		 * @link http://www.php.net/manual/en/book.datetime.php
150		 * @param string $format
151		 *  A valid PHP date format
152		 * @param null|string $timestamp (optional)
153		 *  A unix timestamp to format. 'now' or omitting this parameter will
154		 *  result in the current time being used
155		 * @param string $timezone (optional)
156		 *  The timezone associated with the timestamp
157		 * @return string|boolean
158		 *  The formatted date, of if the date could not be parsed, false.
159		 */
160		public static function get($format, $timestamp = 'now', $timezone = null) {
161			return self::format($timestamp, $format, false, $timezone);
162		}
163
164		/**
165		 * Formats the given date and time `$string` based on the given `$format`.
166		 * Optionally the result will be localized and respect a timezone differing
167		 * from the system default. The default output is ISO 8601.
168		 *
169		 * @since Symphony 2.2.1
170		 * @param string $string (optional)
171		 *  A string containing date and time, defaults to the current date and time
172		 * @param string $format (optional)
173		 *  A valid PHP date format, defaults to ISO 8601
174		 * @param boolean $localize (optional)
175		 *  Localizes the output, if true, defaults to true
176		 * @param string $timezone (optional)
177		 *  The timezone associated with the timestamp
178		 * @return string|boolean
179		 *  The formatted date, or if the date could not be parsed, false.
180		 */
181		public static function format($string = 'now', $format = DateTime::ISO8601, $localize = true, $timezone = null) {
182
183			// Parse date
184			$date = self::parse($string);
185
186			if($date === false) return false;
187
188			// Timezone
189			// If a timezone was given, apply it
190			if(!is_null($timezone)) {
191				$date->setTimezone(new DateTimeZone($timezone));
192			}
193			// No timezone given, apply the default timezone
194			else if (isset(self::$settings['timezone'])) {
195				$date->setTimezone(new DateTimeZone(self::$settings['timezone']));
196			}
197
198			// Format date
199			$date = $date->format($format);
200
201			// Localize date
202			// Convert date string from English back to the activated Language
203			if($localize === true) {
204				$date = Lang::localizeDate($date);
205			}
206
207			// Return custom formatted date, use ISO 8601 date by default
208			return $date;
209		}
210
211		/**
212		 * Parses the given string and returns a DateTime object.
213		 *
214		 * @since Symphony 2.3
215		 * @param string $string (optional)
216		 *  A string containing date and time, defaults to the current date and time
217		 * @return DateTime|boolean
218		 *  The DateTime object, or if the date could not be parsed, false.
219		 */
220		public static function parse($string) {
221
222			// Current date and time
223			if($string == 'now' || empty($string)) {
224				$date = new DateTime();
225			}
226
227			// Timestamp
228			elseif(is_numeric($string)) {
229				$date = new DateTime('@' . $string);
230			}
231
232			// Attempt to parse the date provided against the Symphony configuration setting
233			// in an effort to better support multilingual date formats. Should this fail
234			// this block will fallback to just passing the date to DateTime constructor,
235			// which will parse the date assuming it's in an American format.
236			else {
237				// Standardize date
238				// Convert date string to English
239				$string = Lang::standardizeDate($string);
240
241				// PHP 5.3: Apply Symphony date format using `createFromFormat`
242				$date = DateTime::createFromFormat(self::$settings['datetime_format'], $string);
243				if($date === false) {
244					$date = DateTime::createFromFormat(self::$settings['date_format'], $string);
245				}
246
247				// Handle dates that are in a different format to Symphony's config
248				// DateTime is much the same as `strtotime` and will handle relative
249				// dates.
250				if($date === false) {
251					try {
252						$date = new DateTime($string);
253					}
254					catch(Exception $ex) {
255						// Invalid date, it can't be parsed
256						return false;
257					}
258				}
259
260				// If the date is still invalid, just return false.
261				if($date === false) {
262					return false;
263				}
264			}
265
266			// Return custom formatted date, use ISO 8601 date by default
267			return $date;
268		}
269
270		/**
271		 * A wrapper for get, this function will force the GMT timezone.
272		 *
273		 * @param string $format
274		 *  A valid PHP date format
275		 * @param null|string $timestamp (optional)
276		 *  A unix timestamp to format. Omitting this parameter will
277		 *  result in the current time being used
278		 * @return string
279		 *  The formatted date in GMT
280		 */
281		public static function getGMT($format, $timestamp = 'now'){
282			return self::format($timestamp, $format, false, 'GMT');
283		}
284
285		/**
286		 * This functions acts as a standard way to get the zones
287		 * available on the system.
288		 *
289		 * @since Symphony 2.3
290		 * @link http://au2.php.net/manual/en/class.datetimezone.php
291		 * @return array
292		 */
293		public static function getZones() {
294			$ref = new ReflectionClass('DateTimeZone');
295			return $ref->getConstants();
296		}
297
298		/**
299		 * This functions acts as a standard way to get the timezones
300		 * regardless of PHP version. It accepts a single parameter,
301		 * zone, which returns the timezones associated with that 'zone'
302		 *
303		 * @since Symphony 2.3
304		 * @link http://au2.php.net/manual/en/class.datetimezone.php
305		 * @link http://au2.php.net/manual/en/datetimezone.listidentifiers.php
306		 * @param string $zone
307		 *  The zone for the timezones the field wants. This maps to the
308		 *  DateTimeZone constants
309		 * @return array
310		 */
311		public static function getTimezones($zone = null) {
312			return DateTimeZone::listIdentifiers(constant('DateTimeZone::' . $zone));
313		}
314
315		/**
316		 * Loads all available timezones using `getTimezones()` and builds an
317		 * array where timezones are grouped by their region (Europe/America etc.)
318		 * The options array that is returned is designed to be used with
319		 * `Widget::Select`
320		 *
321		 * @since Symphony 2.3
322		 * @see core.DateTimeObj#getTimezones()
323		 * @see core.Widget#Select()
324		 * @param string $selected
325		 *  A preselected timezone, defaults to null
326		 * @return array
327		 *  An associative array, for use with `Widget::Select`
328		 */
329		public static function getTimezonesSelectOptions($selected = null){
330			$zones = self::getZones();
331			$groups = array();
332
333			foreach($zones as $zone => $value) {
334				if($value >= 1024) break;
335
336				$timezones = self::getTimezones($zone);
337				$options = array();
338
339				foreach($timezones as $timezone) {
340					$tz = new DateTime('now', new DateTimeZone($timezone));
341
342					$options[] = array($timezone, ($timezone == $selected), sprintf("%s %s",
343						str_replace('_', ' ', substr(strrchr($timezone, '/'),1)),
344						$tz->format('P')
345					));
346				}
347
348				$groups[] = array('label' => ucwords(strtolower($zone)), 'options' => $options);
349			}
350
351			return $groups;
352		}
353
354		/**
355		 * Returns an array of the date formats Symphony supports. These
356		 * formats are a combination of valid PHP format tokens.
357		 *
358		 * @link http://au2.php.net/manual/en/function.date.php
359		 * @since Symphony 2.3
360		 * @return array
361		 */
362		public static function getDateFormats(){
363			return array(
364				'Y/m/d',	// e. g. 2014/01/02
365				'd/m/Y',	// e. g. 01/02/2014
366				'm/d/Y',	// e. g. 01/02/2014
367				'm/d/y',	// e. g. 01/02/14
368				'Y-m-d',	// e. g. 2014-01-02
369				'm-d-Y',	// e. g. 01-02-2014
370				'm-d-y',	// e. g. 01-02-14
371				'd.m.Y',	// e. g. 02.01.2014
372				'j.n.Y',	// e. g. 2.1.2014 - no leading zeros
373				'j.n.y',	// e. g. 2.1.14 - no leading zeros
374				'd.m.Y',	// e. g. 02.01.2014
375				'd.m.y',	// e. g. 02.01.14
376				'd F Y',	// e. g. 02 January 2014
377				'd M Y',	// e. g. 02 Jan 2014
378				'j. F Y',	// e. g. 2. January 2014 - no leading zeros
379				'j. M. Y',	// e. g. 2. Jan. 2014 - no leading zeros
380			);
381		}
382
383		/**
384		 * Returns an array of the date formats Symphony supports by applying
385		 * the format to the current datetime. The array returned is for use with
386		 * `Widget::Select()`
387		 *
388		 * @since Symphony 2.3
389		 * @see core.Widget#Select()
390		 * @param string $selected
391		 *  A preselected date format, defaults to null
392		 * @return array
393		 *  An associative array, for use with `Widget::Select`
394		 */
395		public static function getDateFormatsSelectOptions($selected = null){
396			$formats = self::getDateFormats();
397			$options = array();
398
399			foreach($formats as $option) {
400				$leadingZero = '';
401				if(strpos($option, 'j') !== false || strpos($option, 'n') !== false) {
402					$leadingZero = ' (' . __('no leading zeros') . ')';
403				}
404				$options[] = array($option, $option == $selected, self::format('now', $option) . $leadingZero);
405			}
406
407			return $options;
408		}
409
410		/**
411		 * Returns an array of the time formats Symphony supports. These
412		 * formats are a combination of valid PHP format tokens.
413		 *
414		 * @link http://au2.php.net/manual/en/function.date.php
415		 * @since Symphony 2.3
416		 * @return array
417		 */
418		public static function getTimeFormats(){
419			return array(
420				'H:i:s',	// e. g. 20:45:32
421				'H:i',		// e. g. 20:45
422				'g:i:s a',	// e. g. 8:45:32 pm
423				'g:i a',	// e. g. 8:45 pm
424			);
425		}
426
427		/**
428		 * Returns an array of the time formats Symphony supports by applying
429		 * the format to the current datetime. The array returned is for use with
430		 * `Widget::Select()`
431		 *
432		 * @since Symphony 2.3
433		 * @see core.Widget#Select()
434		 * @param string $selected
435		 *  A preselected time format, defaults to null
436		 * @return array
437		 *  An associative array, for use with `Widget::Select`
438		 */
439		public static function getTimeFormatsSelectOptions($selected = null){
440			$formats = self::getTimeFormats();
441			$options = array();
442
443			foreach($formats as $option) {
444				$options[] = array($option, $option == $selected, self::get($option));
445			}
446
447			return $options;
448		}
449
450	}