Skip to content

Commit ba9d428

Browse files
authored
Merge pull request #189 from gRegorLove/issue167
Normalize ordinal dates
2 parents 6e2688f + a91fcf2 commit ba9d428

File tree

3 files changed

+55
-0
lines changed

3 files changed

+55
-0
lines changed

Mf2/Parser.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,26 @@ function convertTimeFormat($time) {
238238
}
239239
}
240240

241+
/**
242+
* Normalize an ordinal date to YYYY-MM-DD
243+
* This function should only be called after validating the $dtValue
244+
* matches regex \d{4}-\d{2}
245+
* @param string $dtValue
246+
* @return string
247+
*/
248+
function normalizeOrdinalDate($dtValue) {
249+
list($year, $day) = explode('-', $dtValue, 2);
250+
$day = intval($day);
251+
if ($day < 367 && $day > 0) {
252+
$date = \DateTime::createFromFormat('Y-z', $dtValue);
253+
$date->modify('-1 day'); # 'z' format is zero-based so need to adjust
254+
if ($date->format('Y') === $year) {
255+
return $date->format('Y-m-d');
256+
}
257+
}
258+
return '';
259+
}
260+
241261
/**
242262
* If a date value has a timezone offset, normalize it.
243263
* @param string $dtValue
@@ -711,6 +731,9 @@ public function parseDT(\DOMElement $dt, &$dates = array(), &$impliedTimezone =
711731
// Is the current part a valid date AND no other date representation has been found?
712732
} elseif (preg_match('/^\d{4}-\d{2}-\d{2}$/', $part) and empty($datePart)) {
713733
$datePart = $part;
734+
// Is the current part a valid ordinal date AND no other date representation has been found?
735+
} elseif (preg_match('/^\d{4}-\d{3}$/', $part) and empty($datePart)) {
736+
$datePart = normalizeOrdinalDate($part);
714737
// Is the current part a valid timezone offset AND no other timezone part has been found?
715738
} elseif (preg_match('/^(Z|[+-]\d{1,2}:?(\d{2})?)$/', $part) and empty($timezonePart)) {
716739
$timezonePart = $part;

tests/Mf2/ParseDTTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,5 +531,24 @@ public function testDtWithoutYear() {
531531
$this->assertEquals('--12-28', $output['items'][0]['properties']['bday'][0]);
532532
}
533533

534+
/**
535+
* @see https://github.com/indieweb/php-mf2/issues/167
536+
* @see https://github.com/microformats/mf2py/blob/master/test/examples/datetimes.html
537+
*/
538+
public function testNormalizeOrdinalDate() {
539+
$input = '<div class="h-event">
540+
<h1 class="p-name">Ordinal date</h1>
541+
<p> When:
542+
<span class="dt-start">
543+
<span class="value">2016-062</span>
544+
<span class="value">12:30AM</span>
545+
(UTC<span class="value">-06:00</span>)
546+
</p>
547+
</div>';
548+
$parser = new Parser($input);
549+
$output = $parser->parse();
550+
551+
$this->assertEquals('2016-03-02 12:30-0600', $output['items'][0]['properties']['start'][0]);
552+
}
534553
}
535554

tests/Mf2/ParserTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,5 +824,18 @@ public function testNotMutatingPassedInDOM() {
824824
Mf2\parse($inputDoc, 'http://snarfed.org/2013-10-23_oauth-dropins');
825825
$this->assertEquals($refDoc, $inputDoc, 'Parsing mutated the DOMDocument.');
826826
}
827+
828+
/**
829+
* Make sure day of year passed to normalizeOrdinalDate() is valid
830+
* @see https://github.com/indieweb/php-mf2/issues/167
831+
*/
832+
public function testInvalidOrdinalDate() {
833+
# 365 days in non-leap years
834+
$this->assertEquals('2018-12-31', Mf2\normalizeOrdinalDate('2018-365'));
835+
$this->assertEquals('', Mf2\normalizeOrdinalDate('2018-366'));
836+
# 366 days in leap years
837+
$this->assertEquals('2016-12-31', Mf2\normalizeOrdinalDate('2016-366'));
838+
$this->assertEquals('', Mf2\normalizeOrdinalDate('2016-367'));
839+
}
827840
}
828841

0 commit comments

Comments
 (0)