/symphony/lib/core/class.datetimeobj.php
PHP | 582 lines | 235 code | 59 blank | 288 comment | 34 complexity | a9c689da854d67bcb8f9fc5818369d44 MD5 | raw file
- <?php
- /**
- * @package core
- */
- /**
- * The DateTimeObj provides static functions regarding dates in Symphony.
- * Symphony will set the default timezone of the system using the value from
- * the Configuration values. Alternatively a new settings can be set using the
- * `setSettings` function. Symphony parses all input dates against the Configuration
- * date formats by default for better support with non English dates.
- */
- class DateTimeObj
- {
- /**
- * Holds the various settings for the formats that the `DateTimeObj` should
- * use when parsing input dates.
- *
- * @since Symphony 2.7.0 it contains default values to prevent the case where
- * no settings are set
- * @since Symphony 2.2.4
- * @var array
- */
- private static $settings = array(
- 'time_format' => 'g:i a',
- 'date_format' => 'm/d/Y',
- );
- /**
- * Mapping PHP to Moment date formats.
- */
- protected static $date_mappings = array(
- 'Y/m/d' => 'YYYY/MM/DD', // e. g. 2014/01/02
- 'd/m/Y' => 'DD/MM/YYYY', // e. g. 01/02/2014
- 'm/d/Y' => 'MM/DD/YYYY', // e. g. 01/02/2014
- 'm/d/y' => 'MM/DD/YY', // e. g. 01/02/14
- 'Y-m-d' => 'YYYY-MM-DD', // e. g. 2014-01-02
- 'm-d-Y' => 'MM-DD-YYYY', // e. g. 01-02-2014
- 'm-d-y' => 'MM-DD-YY', // e. g. 01-02-14
- 'j.n.Y' => 'D.M.YYYY', // e. g. 2.1.2014 - no leading zeros
- 'j.n.y' => 'D.M.YY', // e. g. 2.1.14 - no leading zeros
- 'd.m.Y' => 'DD.MM.YYYY', // e. g. 02.01.2014
- 'd.m.y' => 'DD.MM.YYYY', // e. g. 02.01.14
- 'd F Y' => 'DD MMMM YYYY', // e. g. 02 January 2014
- 'd. F Y' => 'DD. MMMM YYYY', // e. g. 02. January 2014
- 'd M Y' => 'DD MMM YYYY', // e. g. 02 Jan 2014
- 'd. M Y' => 'DD. MMM. YYYY', // e. g. 02. Jan 2014
- 'j. F Y' => 'D. MMMM YYYY', // e. g. 2. January 2014 - no leading zeros
- 'j. M. Y' => 'D. MMM. YYYY', // e. g. 2. Jan. 2014 - no leading zeros
- );
- /**
- * Mapping PHP to Moment time formats.
- */
- protected static $time_mappings = array(
- 'H:i:s' => 'HH:mm:ss', // e. g. 20:45:32
- 'H:i' => 'HH:mm', // e. g. 20:45
- 'g:i:s a' => 'h:mm:ss a', // e. g. 8:45:32 pm
- 'g:i a' => 'h:mm a', // e. g. 8:45 pm
- );
- /**
- * This function takes an array of settings for `DateTimeObj` to use when parsing
- * input dates. The following settings are supported, `time_format`, `date_format`,
- * `datetime_separator` and `timezone`. This equates to Symphony's default `region`
- * group set in the `Configuration` class. If any of these values are not provided
- * the class will fallback to existing `self::$settings` values
- *
- * @since Symphony 2.2.4
- * @param array $settings
- * An associative array of formats for this class to use to format
- * dates
- */
- public static function setSettings(array $settings = array())
- {
- // Date format
- if (isset($settings['date_format'])) {
- self::$settings['date_format'] = $settings['date_format'];
- }
- // Time format
- if (isset($settings['time_format'])) {
- self::$settings['time_format'] = $settings['time_format'];
- }
- // Datetime separator
- if (isset($settings['datetime_separator'])) {
- self::$settings['datetime_separator'] = $settings['datetime_separator'];
- } elseif (!isset(self::$settings['datetime_separator'])) {
- self::$settings['datetime_separator'] = ' ';
- }
- // Datetime format
- if (isset($settings['datetime_format'])) {
- self::$settings['datetime_format'] = $settings['datetime_format'];
- } elseif (!isset(self::$settings['datetime_format'])) {
- self::$settings['datetime_format'] = self::$settings['date_format'] . self::$settings['datetime_separator'] . self::$settings['time_format'];
- }
- // Timezone
- if (isset($settings['timezone']) && !empty($settings['timezone'])) {
- self::$settings['timezone'] = $settings['timezone'];
- self::setDefaultTimezone($settings['timezone']);
- } elseif (!isset(self::$settings['timezone'])) {
- self::$settings['timezone'] = ini_get('date.timezone');
- if (empty(self::$settings['timezone'])) {
- self::$settings['timezone'] = 'UTC';
- }
- }
- }
- /**
- * Accessor function for the settings of the DateTimeObj. Currently
- * the available settings are `time_format`, `date_format`,
- * `datetime_format` and `datetime_separator`. If `$name` is not
- * provided, the entire `$settings` array is returned.
- *
- * @since Symphony 2.2.4
- * @param string $name
- * @return array|string|null
- * If `$name` is omitted this function returns array.
- * If `$name` is not set, this fucntion returns `null`
- * If `$name` is set, this function returns string
- */
- public static function getSetting($name = null)
- {
- if (is_null($name)) {
- return self::$settings;
- }
- if (isset(self::$settings[$name])) {
- return self::$settings[$name];
- }
- return null;
- }
- /**
- * Uses PHP's date_default_timezone_set function to set the system
- * timezone. If the timezone provided is invalid, an exception is thrown.
- *
- * @link http://php.net/manual/en/function.date-default-timezone-set.php
- * @link http://www.php.net/manual/en/timezones.php
- * @param string $timezone
- * A valid timezone identifier, such as UTC or Europe/Lisbon
- * @throws Exception
- * If the timezone is not valid.
- */
- public static function setDefaultTimezone($timezone)
- {
- if (!@date_default_timezone_set($timezone)) {
- throw new Exception(__('Invalid timezone %s', array($timezone)));
- }
- }
- /**
- * Validate a given date and time string
- *
- * @param string $string
- * A date and time string or timestamp to validate
- * @return boolean
- * Returns true for valid dates, otherwise false
- */
- public static function validate($string)
- {
- try {
- if (is_numeric($string) && (int)$string == $string) {
- $date = new DateTime('@' . $string);
- } else {
- $date = self::parse($string);
- }
- } catch (Exception $ex) {
- return false;
- }
- // String is empty or not a valid date
- if (empty($string) || $date === false) {
- return false;
- // String is a valid date
- } else {
- return true;
- }
- }
- /**
- * Given a `$format`, and a `$timestamp`,
- * return the date in the format provided. This function is a basic
- * wrapper for PHP's DateTime object. If the `$timestamp` is omitted,
- * the current timestamp will be used. Optionally, you pass a
- * timezone identifier with this function to localise the output
- *
- * If you like to display a date in the backend, please make use
- * of `DateTimeObj::format()` which allows date and time localization
- *
- * @see class.datetimeobj.php#format()
- * @link http://www.php.net/manual/en/book.datetime.php
- * @param string $format
- * A valid PHP date format
- * @param null|string $timestamp (optional)
- * A unix timestamp to format. 'now' or omitting this parameter will
- * result in the current time being used
- * @param string $timezone (optional)
- * The timezone associated with the timestamp
- * @return string|boolean
- * The formatted date, of if the date could not be parsed, false.
- */
- public static function get($format, $timestamp = 'now', $timezone = null)
- {
- return self::format($timestamp, $format, false, $timezone);
- }
- /**
- * Formats the given date and time `$string` based on the given `$format`.
- * Optionally the result will be localized and respect a timezone differing
- * from the system default. The default output is ISO 8601.
- *
- * @since Symphony 2.2.1
- * @param string $string (optional)
- * A string containing date and time, defaults to the current date and time
- * @param string $format (optional)
- * A valid PHP date format, defaults to ISO 8601
- * @param boolean $localize (optional)
- * Localizes the output, if true, defaults to true
- * @param string $timezone (optional)
- * The timezone associated with the timestamp
- * @return string|boolean
- * The formatted date, or if the date could not be parsed, false.
- */
- public static function format($string = 'now', $format = DateTime::ISO8601, $localize = true, $timezone = null)
- {
- // Parse date
- $date = self::parse($string);
- if ($date === false) {
- return false;
- }
- // Timezone
- // If a timezone was given, apply it
- if (!is_null($timezone)) {
- $date->setTimezone(new DateTimeZone($timezone));
- // No timezone given, apply the default timezone
- } elseif (isset(self::$settings['timezone'])) {
- $date->setTimezone(new DateTimeZone(self::$settings['timezone']));
- }
- // Format date
- $date = $date->format($format);
- // Localize date
- // Convert date string from English back to the activated Language
- if ($localize === true) {
- $date = Lang::localizeDate($date);
- }
- // Return custom formatted date, use ISO 8601 date by default
- return $date;
- }
- /**
- * Parses the given string and returns a DateTime object.
- *
- * @since Symphony 2.3
- * @param string $string (optional)
- * A string containing date and time, defaults to the current date and time
- * @return DateTime|boolean
- * The DateTime object, or if the date could not be parsed, false.
- */
- public static function parse($string)
- {
- // Current date and time
- if ($string == 'now' || empty($string)) {
- $date = new DateTime();
- // Timestamp
- } elseif (is_numeric($string)) {
- $date = new DateTime('@' . $string);
- // Attempt to parse the date provided against the Symphony configuration setting
- // in an effort to better support multilingual date formats. Should this fail
- // this block will fallback to just passing the date to DateTime constructor,
- // which will parse the date assuming it's in an American format.
- } else {
- // Standardize date
- // Convert date string to English
- $string = Lang::standardizeDate($string);
- // PHP 5.3: Apply Symphony date format using `createFromFormat`
- $date = DateTime::createFromFormat(self::$settings['datetime_format'], $string);
- if ($date === false) {
- $date = DateTime::createFromFormat(self::$settings['date_format'], $string);
- }
- // Handle dates that are in a different format to Symphony's config
- // DateTime is much the same as `strtotime` and will handle relative
- // dates.
- if ($date === false) {
- try {
- $date = new DateTime($string);
- } catch (Exception $ex) {
- // Invalid date, it can't be parsed
- return false;
- }
- }
- // If the date is still invalid, just return false.
- if ($date === false || $date->format('Y') < 0) {
- return false;
- }
- }
- // Return custom formatted date, use ISO 8601 date by default
- return $date;
- }
- /**
- * A wrapper for get, this function will force the GMT timezone.
- *
- * @param string $format
- * A valid PHP date format
- * @param null|string $timestamp (optional)
- * A unix timestamp to format. Omitting this parameter will
- * result in the current time being used
- * @return string
- * The formatted date in GMT
- */
- public static function getGMT($format, $timestamp = 'now')
- {
- return self::format($timestamp, $format, false, 'GMT');
- }
- /**
- * This functions acts as a standard way to get the zones
- * available on the system.
- *
- * @since Symphony 2.3
- * @link http://au2.php.net/manual/en/class.datetimezone.php
- * @return array
- */
- public static function getZones()
- {
- $ref = new ReflectionClass('DateTimeZone');
- return $ref->getConstants();
- }
- /**
- * This functions acts as a standard way to get the timezones
- * regardless of PHP version. It accepts a single parameter,
- * zone, which returns the timezones associated with that 'zone'
- *
- * @since Symphony 2.3
- * @link http://au2.php.net/manual/en/class.datetimezone.php
- * @link http://au2.php.net/manual/en/datetimezone.listidentifiers.php
- * @param string $zone
- * The zone for the timezones the field wants. This maps to the
- * DateTimeZone constants
- * @return array
- */
- public static function getTimezones($zone = null)
- {
- return DateTimeZone::listIdentifiers(constant('DateTimeZone::' . $zone));
- }
- /**
- * Loads all available timezones using `getTimezones()` and builds an
- * array where timezones are grouped by their region (Europe/America etc.)
- * The options array that is returned is designed to be used with
- * `Widget::Select`
- *
- * @since Symphony 2.3
- * @see core.DateTimeObj#getTimezones()
- * @see core.Widget#Select()
- * @param string $selected
- * A preselected timezone, defaults to null
- * @return array
- * An associative array, for use with `Widget::Select`
- */
- public static function getTimezonesSelectOptions($selected = null)
- {
- $zones = self::getZones();
- $groups = array();
- foreach ($zones as $zone => $value) {
- if ($value >= 1024) {
- break;
- }
- $timezones = self::getTimezones($zone);
- $options = array();
- foreach ($timezones as $timezone) {
- $tz = new DateTime('now', new DateTimeZone($timezone));
- $options[] = array($timezone, ($timezone == $selected), sprintf(
- "%s %s",
- str_replace('_', ' ', substr(strrchr($timezone, '/'), 1)),
- $tz->format('P')
- ));
- }
- $groups[] = array('label' => ucwords(strtolower($zone)), 'options' => $options);
- }
- return $groups;
- }
- /**
- * Returns an array of PHP date formats Symphony supports mapped to
- * their Moment equivalent.
- *
- * @since Symphony 2.6
- * @return array
- */
- public static function getDateFormatMappings()
- {
- return self::$date_mappings;
- }
- /**
- * Returns an array of the date formats Symphony supports. These
- * formats are a combination of valid PHP format tokens.
- *
- * @link http://au2.php.net/manual/en/function.date.php
- * @since Symphony 2.3
- * @return array
- */
- public static function getDateFormats()
- {
- return array_keys(self::$date_mappings);
- }
- /**
- * Returns an array of the date formats Symphony supports. These
- * formats are a combination of valid Moment format tokens.
- *
- * @link http://momentjs.com/docs/#/parsing/
- * @since Symphony 2.6
- * @return array
- */
- public static function getMomentDateFormats()
- {
- return array_values(self::$date_mappings);
- }
- /**
- * Returns the Moment representation of a given PHP format token.
- *
- * @since Symphony 2.6
- * @param string $format
- * A valid PHP date token
- * @return string
- */
- public static function convertDateToMoment($format)
- {
- return self::$date_mappings[$format];
- }
- /**
- * Returns the PHP representation of a given Moment format token.
- *
- * @since Symphony 2.6
- * @param string $format
- * A valid Moment date token
- * @return string
- */
- public static function convertMomentToDate($format)
- {
- $formats = array_flip(self::$date_mappings);
- return $formats[$format];
- }
- /**
- * Returns an array of the date formats Symphony supports by applying
- * the format to the current datetime. The array returned is for use with
- * `Widget::Select()`
- *
- * @since Symphony 2.3
- * @see core.Widget#Select()
- * @param string $selected
- * A preselected date format, defaults to null
- * @return array
- * An associative array, for use with `Widget::Select`
- */
- public static function getDateFormatsSelectOptions($selected = null)
- {
- $formats = self::getDateFormats();
- $options = array();
- foreach ($formats as $option) {
- $leadingZero = '';
- if (strpos($option, 'j') !== false || strpos($option, 'n') !== false) {
- $leadingZero = ' (' . __('no leading zeros') . ')';
- }
- $options[] = array($option, $option == $selected, self::format('now', $option) . $leadingZero);
- }
- return $options;
- }
- /**
- * Returns an array of the time formats Symphony supports. These
- * formats are a combination of valid PHP format tokens.
- *
- * @link http://au2.php.net/manual/en/function.date.php
- * @since Symphony 2.3
- * @return array
- */
- public static function getTimeFormats()
- {
- return array_keys(self::$time_mappings);
- }
- /**
- * Returns an array of the time formats Symphony supports. These
- * formats are a combination of valid Moment format tokens.
- *
- * @link http://momentjs.com/docs/#/parsing/
- * @since Symphony 2.6
- * @return array
- */
- public static function getMomentTimeFormats()
- {
- return array_keys(self::$time_mappings);
- }
- /**
- * Returns the Moment time representation of a given PHP format token.
- *
- * @since Symphony 2.6
- * @param string $format
- * A valid PHP time token
- * @return string
- */
- public static function convertTimeToMoment($format)
- {
- return self::$time_mappings[$format];
- }
- /**
- * Returns the PHP time representation of a given Moment format token.
- *
- * @since Symphony 2.6
- * @param string $format
- * A valid Moment time token
- * @return string
- */
- public static function convertMomentToTime($format)
- {
- $formats = array_flip(self::$time_mappings);
- return $formats[$format];
- }
- /**
- * Returns an array of the time formats Symphony supports by applying
- * the format to the current datetime. The array returned is for use with
- * `Widget::Select()`
- *
- * @since Symphony 2.3
- * @see core.Widget#Select()
- * @param string $selected
- * A preselected time format, defaults to null
- * @return array
- * An associative array, for use with `Widget::Select`
- */
- public static function getTimeFormatsSelectOptions($selected = null)
- {
- $formats = self::getTimeFormats();
- $options = array();
- foreach ($formats as $option) {
- $options[] = array($option, $option == $selected, self::get($option));
- }
- return $options;
- }
- }