/** * 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); }
/** * 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; }