Example #1
0
    /**
     * Creates a new DateTime object from a string.
     *
     * Supports the following formats:
     *
     *  - An array of the date and time in the current locale's short formats
     *  - All W3C date and time formats (http://www.w3.org/TR/NOTE-datetime)
     *  - MySQL DATE and DATETIME formats (http://dev.mysql.com/doc/refman/5.1/en/datetime.html)
     *  - Relaxed versions of W3C and MySQL formats (single-digit months, days, and hours)
     *  - Unix timestamps
     *
     * @param string|array $date
     * @param stirng|null  $timezone The [PHP timezone identifier](http://php.net/manual/en/timezones.php),
     *                               if not specified in $date. Defaults to 'UTC'.
     *
     * @return DateTime|null|false
     */
    public static function createFromString($date, $timezone = null)
    {
        // Was this a date/time-picker?
        if (is_array($date) && (isset($date['date']) || isset($date['time']))) {
            $dt = $date;
            if (!$timezone) {
                $timezone = craft()->getTimeZone();
            }
            if (empty($dt['date']) && empty($dt['time'])) {
                return null;
            }
            $localeData = craft()->i18n->getLocaleData(craft()->language);
            $dateFormatter = $localeData->getDateFormatter();
            if (!empty($dt['date'])) {
                $date = $dt['date'];
                $format = $dateFormatter->getDatepickerPhpFormat();
                // Check for a two-digit year
                $altFormat = str_replace('Y', 'y', $format);
                if (static::createFromFormat($altFormat, $date) !== false) {
                    $format = $altFormat;
                }
            } else {
                $date = '';
                $format = '';
                // Default to the current date
                $current = new DateTime('now', new \DateTimeZone($timezone));
                $date .= $current->month() . '/' . $current->day() . '/' . $current->year();
                $format .= 'n/j/Y';
            }
            if (!empty($dt['time'])) {
                // Replace the localized "AM" and "PM"
                $localeData = craft()->i18n->getLocaleData();
                $dt['time'] = str_replace(array($localeData->getAMName(), $localeData->getPMName()), array('AM', 'PM'), $dt['time']);
                $date .= ' ' . $dt['time'];
                $format .= ' ' . $dateFormatter->getTimepickerPhpFormat();
            }
        } else {
            $date = trim((string) $date);
            if (preg_match('/^
				(?P<year>\\d{4})                                  # YYYY (four digit year)
				(?:
					-(?P<mon>\\d\\d?)                              # -M or -MM (1 or 2 digit month)
					(?:
						-(?P<day>\\d\\d?)                          # -D or -DD (1 or 2 digit day)
						(?:
							[T\\ ](?P<hour>\\d\\d?)\\:(?P<min>\\d\\d)  # [T or space]hh:mm (1 or 2 digit hour and 2 digit minute)
							(?:
								\\:(?P<sec>\\d\\d)                  # :ss (two digit second)
								(?:\\.\\d+)?                       # .s (decimal fraction of a second -- not supported)
							)?
							(?:[ ]?(?P<ampm>(AM|PM|am|pm))?)?    # An optional space and AM or PM
							(?:Z|(?P<tzd>[+\\-]\\d\\d\\:\\d\\d))?      # Z or [+ or -]hh:ss (UTC or a timezone offset)
						)?
					)?
				)?$/x', $date, $m)) {
                $format = 'Y-m-d H:i:s';
                $date = $m['year'] . '-' . (!empty($m['mon']) ? sprintf('%02d', $m['mon']) : '01') . '-' . (!empty($m['day']) ? sprintf('%02d', $m['day']) : '01') . ' ' . (!empty($m['hour']) ? sprintf('%02d', $m['hour']) : '00') . ':' . (!empty($m['min']) ? $m['min'] : '00') . ':' . (!empty($m['sec']) ? $m['sec'] : '00');
                if (!empty($m['tzd'])) {
                    $format .= 'P';
                    $date .= $m['tzd'];
                }
                if (!empty($m['ampm'])) {
                    $format .= ' A';
                    $date .= ' ' . $m['ampm'];
                }
            } else {
                if (preg_match('/^\\d{10}$/', $date)) {
                    $format = 'U';
                } else {
                    $format = '';
                }
            }
        }
        if ($timezone) {
            $format .= ' e';
            $date .= ' ' . $timezone;
        }
        return static::createFromFormat('!' . $format, $date);
    }
Example #2
0
    /**
     * Creates a new DateTime object from a string.
     *
     * Supports the following formats:
     *
     *  - An array of the date and time in the current locale's short formats
     *  - All W3C date and time formats (http://www.w3.org/TR/NOTE-datetime)
     *  - MySQL DATE and DATETIME formats (http://dev.mysql.com/doc/refman/5.1/en/datetime.html)
     *  - Relaxed versions of W3C and MySQL formats (single-digit months, days, and hours)
     *  - Unix timestamps
     *
     * @param string|array $date
     * @param string|null  $timezone            The [PHP timezone identifier](http://php.net/manual/en/timezones.php)
     *                                          that $date is set to, if not already specified in $date. Defaults to 'UTC'.
     * @param bool         $setToSystemTimeZone Whether to set the resulting DateTime object to the system timezone.
     *
     * @return DateTime|null|false
     */
    public static function createFromString($date, $timezone = null, $setToSystemTimeZone = true)
    {
        // Was this a date/time-picker?
        if (is_array($date) && (isset($date['date']) || isset($date['time']))) {
            $dt = $date;
            if (empty($dt['date']) && empty($dt['time'])) {
                return null;
            }
            $localeData = craft()->i18n->getLocaleData(craft()->language);
            $dateFormatter = $localeData->getDateFormatter();
            if (!empty($dt['date'])) {
                $date = $dt['date'];
                $format = $dateFormatter->getDatepickerPhpFormat();
                // Valid separators are either '-', '.' or '/'.
                if (mb_strpos($format, '.') !== false) {
                    $separator = '.';
                } else {
                    if (mb_strpos($format, '-') !== false) {
                        $separator = '-';
                    } else {
                        $separator = '/';
                    }
                }
                // Ensure that the submitted date is using the locale’s separator
                $date = str_replace(array('-', '.', '/'), $separator, $date);
                // Check for a two-digit year as well
                $altFormat = str_replace('Y', 'y', $format);
                if (static::createFromFormat($altFormat, $date) !== false) {
                    $format = $altFormat;
                }
            } else {
                $date = '';
                $format = '';
                // Default to the current date
                $current = new DateTime('now', new \DateTimeZone($timezone ?: self::UTC));
                $date .= $current->month() . '/' . $current->day() . '/' . $current->year();
                $format .= 'n/j/Y';
            }
            if (!empty($dt['time'])) {
                $timePickerPhpFormat = $dateFormatter->getTimepickerPhpFormat();
                // Replace the localized "AM" and "PM"
                $localeData = craft()->i18n->getLocaleData();
                if (preg_match('/(.*)(' . preg_quote($localeData->getAMName(), '/') . '|' . preg_quote($localeData->getPMName(), '/') . ')(.*)/u', $dt['time'], $matches)) {
                    $dt['time'] = $matches[1] . $matches[3];
                    if ($matches[2] == $localeData->getAMName()) {
                        $dt['time'] .= 'AM';
                    } else {
                        $dt['time'] .= 'PM';
                    }
                    $timePickerPhpFormat = str_replace('A', '', $timePickerPhpFormat) . 'A';
                }
                $date .= ' ' . $dt['time'];
                $format .= ' ' . $timePickerPhpFormat;
            }
        } else {
            $date = trim((string) $date);
            if (preg_match('/^
				(?P<year>\\d{4})                                  # YYYY (four digit year)
				(?:
					-(?P<mon>\\d\\d?)                              # -M or -MM (1 or 2 digit month)
					(?:
						-(?P<day>\\d\\d?)                          # -D or -DD (1 or 2 digit day)
						(?:
							[T\\ ](?P<hour>\\d\\d?)\\:(?P<min>\\d\\d)  # [T or space]hh:mm (1 or 2 digit hour and 2 digit minute)
							(?:
								\\:(?P<sec>\\d\\d)                  # :ss (two digit second)
								(?:\\.\\d+)?                       # .s (decimal fraction of a second -- not supported)
							)?
							(?:[ ]?(?P<ampm>(AM|PM|am|pm))?)?    # An optional space and AM or PM
							(?:Z|(?P<tzd>[+\\-]\\d\\d\\:\\d\\d))?      # Z or [+ or -]hh:ss (UTC or a timezone offset)
						)?
					)?
				)?$/x', $date, $m)) {
                $format = 'Y-m-d H:i:s';
                $date = $m['year'] . '-' . (!empty($m['mon']) ? sprintf('%02d', $m['mon']) : '01') . '-' . (!empty($m['day']) ? sprintf('%02d', $m['day']) : '01') . ' ' . (!empty($m['hour']) ? sprintf('%02d', $m['hour']) : '00') . ':' . (!empty($m['min']) ? $m['min'] : '00') . ':' . (!empty($m['sec']) ? $m['sec'] : '00');
                if (!empty($m['tzd'])) {
                    $format .= 'P';
                    $date .= $m['tzd'];
                }
                if (!empty($m['ampm'])) {
                    $format .= ' A';
                    $date .= ' ' . $m['ampm'];
                }
            } else {
                if (DateTimeHelper::isValidTimeStamp((int) $date)) {
                    $format = 'U';
                } else {
                    $format = '';
                }
            }
        }
        if ($timezone) {
            $format .= ' e';
            $date .= ' ' . $timezone;
        }
        $dt = static::createFromFormat('!' . $format, $date);
        if ($dt !== false && $setToSystemTimeZone) {
            $dt->setTimezone(new \DateTimeZone(craft()->getTimeZone()));
        }
        return $dt;
    }