diff --git a/Mf2/Parser.php b/Mf2/Parser.php index 1ba275f..de4abd0 100644 --- a/Mf2/Parser.php +++ b/Mf2/Parser.php @@ -238,6 +238,26 @@ function convertTimeFormat($time) { } } +/** + * Normalize an ordinal date to YYYY-MM-DD + * This function should only be called after validating the $dtValue + * matches regex \d{4}-\d{2} + * @param string $dtValue + * @return string + */ +function normalizeOrdinalDate($dtValue) { + list($year, $day) = explode('-', $dtValue, 2); + $day = intval($day); + if ($day < 367 && $day > 0) { + $date = \DateTime::createFromFormat('Y-z', $dtValue); + $date->modify('-1 day'); # 'z' format is zero-based so need to adjust + if ($date->format('Y') === $year) { + return $date->format('Y-m-d'); + } + } + return ''; +} + /** * If a date value has a timezone offset, normalize it. * @param string $dtValue @@ -711,6 +731,9 @@ public function parseDT(\DOMElement $dt, &$dates = array(), &$impliedTimezone = // Is the current part a valid date AND no other date representation has been found? } elseif (preg_match('/^\d{4}-\d{2}-\d{2}$/', $part) and empty($datePart)) { $datePart = $part; + // Is the current part a valid ordinal date AND no other date representation has been found? + } elseif (preg_match('/^\d{4}-\d{3}$/', $part) and empty($datePart)) { + $datePart = normalizeOrdinalDate($part); // Is the current part a valid timezone offset AND no other timezone part has been found? } elseif (preg_match('/^(Z|[+-]\d{1,2}:?(\d{2})?)$/', $part) and empty($timezonePart)) { $timezonePart = $part; diff --git a/tests/Mf2/ParseDTTest.php b/tests/Mf2/ParseDTTest.php index 6aabc44..fb917d6 100644 --- a/tests/Mf2/ParseDTTest.php +++ b/tests/Mf2/ParseDTTest.php @@ -531,5 +531,24 @@ public function testDtWithoutYear() { $this->assertEquals('--12-28', $output['items'][0]['properties']['bday'][0]); } + /** + * @see https://github.com/indieweb/php-mf2/issues/167 + * @see https://github.com/microformats/mf2py/blob/master/test/examples/datetimes.html + */ + public function testNormalizeOrdinalDate() { + $input = '
When: + + 2016-062 + 12:30AM + (UTC-06:00) +
+