Skip to content

Commit

Permalink
fix/add tests; coding style
Browse files Browse the repository at this point in the history
  • Loading branch information
seth-shaw-asu committed Aug 3, 2023
1 parent 3978075 commit d0867df
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 29 deletions.
2 changes: 1 addition & 1 deletion src/EDTFConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public static function datetimeIso8601Value($data) {
}

/**
* Converts an EDTF text field into an ISO 8601 timestamp string.
* Converts an EDTF text field into an ISO 8601 date.
*
* It assumes the earliest valid date for approximations and intervals.
*
Expand Down
61 changes: 39 additions & 22 deletions src/EDTFUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ public static function validateDate($datetime_str, $strict = FALSE) {
$msgs = [];

if (strpos($datetime_str, 'T') > -1) {
list($date, $time) = explode('T', $datetime_str);
[$date, $time] = explode('T', $datetime_str);
}
else {
$date = (string) $datetime_str;
Expand Down Expand Up @@ -216,22 +216,29 @@ public static function validateDate($datetime_str, $strict = FALSE) {
elseif (strlen(ltrim($parsed_date[self::YEAR_BASE], '-')) > 4) {
$msgs[] = "Years longer than 4 digits must be prefixed with a 'Y'.";
}
elseif (strlen($parsed_date[self::YEAR_BASE]) < 4) {
$msgs[] = "Years must be at least 4 characters long.";
}
$strict_pattern = 'Y';

// Month.
if (array_key_exists(self::MONTH, $parsed_date) && !empty($parsed_date[self::MONTH])) {
// Valid month values?
if (
// Month doesn't exist in mapping or does exist in mapping, but is > 12
// and there is a day part.
(!array_key_exists($parsed_date[self::MONTH], self::MONTHS_MAP) ||
(array_key_exists($parsed_date[self::MONTH], self::MONTHS_MAP) &&
array_key_exists(self::DAY, $parsed_date) &&
$parsed_date[self::MONTH] > 12)) &&
strpos($parsed_date[self::MONTH], 'X') === FALSE) {
// Month doesn't exist in mapping
// and isn't a valid unspecified month value.
(
!array_key_exists($parsed_date[self::MONTH], self::MONTHS_MAP) &&
(intval(str_replace('X', '1', $parsed_date[self::MONTH])) > 12)
) ||
// Sub-year groupings with day values.
(
array_key_exists($parsed_date[self::MONTH], self::MONTHS_MAP) &&
array_key_exists(self::DAY, $parsed_date) &&
$parsed_date[self::MONTH] > 12
) ||
// Unspecifed character comes before number.
(
preg_match('/X+\d/', $parsed_date[self::MONTH])
)
) {
$msgs[] = "Provided month value '" . $parsed_date[self::MONTH] . "' is not valid.";
}
$strict_pattern = 'Y-m';
Expand Down Expand Up @@ -327,8 +334,28 @@ public static function expandYear($year_full, $year_base, $year_exponent) {
*/
public static function iso8601Value(string $edtf) {

if (count(self::validate($edtf)) > 0) {
return '';
}
// Sets.
if (strpos($edtf, '[') !== FALSE || strpos($edtf, '{') !== FALSE) {
// Use first in set.
$dates = preg_split('/(,|\.\.)/', trim($edtf, '{}[]'));
return self::iso8601Value(array_shift($dates));
}
// Intervals.
if (str_contains($edtf, '/')) {
$dates = explode('/', $edtf);
return self::iso8601Value(array_shift($dates));
}

$date_time = explode('T', $edtf);

// Valid EDTF values with time portions are already ISO 8601 timestamps.
if (array_key_exists(1, $date_time) && !empty($date_time[1])) {
return $edtf;
}

preg_match(EDTFUtils::DATE_PARSE_REGEX, $date_time[0], $parsed_date);

$year = '';
Expand Down Expand Up @@ -358,17 +385,7 @@ public static function iso8601Value(string $edtf) {
$day = str_replace('X', '0', $day);
}

$formatted_date = implode('-', array_filter([$year, $month, $day]));

// Time.
if (array_key_exists(1, $date_time) && !empty($date_time[1])) {
$formatted_date .= 'T' . $date_time[1];
}
else {
$formatted_date .= 'T00:00:00';
}

return $formatted_date;
return implode('-', array_filter([$year, $month, $day]));

}

Expand Down
51 changes: 45 additions & 6 deletions tests/src/Kernel/EdtfUtilsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,26 @@ class EdtfUtilsTest extends KernelTestBase {
*
* @var array
*/
private $testCases = [
private $singleDateValidations = [
'1900' => [],
'1900-01' => [],
'1900-01-02' => [],
'190X' => [],
'1900-XX' => [],
'1900-91' => ['Provided month value \'91\' is not valid.'],
'1900-91-01' => ['Provided month value \'91\' is not valid.'],
'1900-X1' => ['Provided month value \'X1\' is not valid.'],
// No validation for months with X.
'1900-3X' => [],
'1900-3X' => ['Provided month value \'3X\' is not valid.'],
// Month 31 without a day matches summer so it's valid.
'1900-31' => [],
'1900-31-01' => ['Provided month value \'31\' is not valid.'],
'190X-5X-8X' => [],
'190X-5X-8X' => ['Provided month value \'5X\' is not valid.'],
'19000' => ['Years longer than 4 digits must be prefixed with a \'Y\'.'],
'Y19000' => [],
'190u' => ['Could not parse the date \'190u\'.'],
'190' => ['Years must be at least 4 characters long.'],
'190-99-52' => ['Years must be at least 4 characters long.',
'190' => [],
'190-99-52' => [
'Provided month value \'99\' is not valid.',
'Provided day value \'52\' is not valid.',
],
Expand All @@ -53,9 +54,47 @@ class EdtfUtilsTest extends KernelTestBase {
* @covers ::validate
*/
public function testEdtfValidate() {
foreach ($this->testCases as $input => $expected) {
foreach ($this->singleDateValidations as $input => $expected) {
$this->assertEquals($expected, EDTFUtils::validate($input, FALSE, FALSE, FALSE));
}
}

/**
* @covers ::iso8601Value
*/
public function testIso8601() {
// EDTF value and ISO 8601 Timestamp results.
// Empty values are invalid dates which return blank.
$tests = [
'1900' => '1900',
'1900-01' => '1900-01',
'1900-01-02' => '1900-01-02',
'190X' => '1900',
'1900-XX' => '1900-01',
'1900-91' => '',
'1900-91-01' => '',
'1900-3X' => '',
'1900-31' => '1900-03',
'190X-5X-8X' => '',
'19000' => '',
'Y19000' => '19000',
'190u' => '',
'190' => '190',
'190-99-52' => '',
'1900-01-02T' => '',
'1900-01-02T1:1:1' => '',
'1900-01-02T01:22:33' => '1900-01-02T01:22:33',
'1900-01-02T01:22:33Z' => '1900-01-02T01:22:33Z',
'1900-01-02T01:22:33+' => '',
'1900-01-02T01:22:33+05:00' => '1900-01-02T01:22:33+05:00',
// Intervals and Sets should return the earliest value.
'1900/2023' => '1900',
'[1900,2023]' => '1900',
'[1900,2023}' => '1900',
];
foreach ($tests as $date => $iso) {
$this->assertEquals($iso, EDTFUtils::iso8601Value($date));
}
}

}

0 comments on commit d0867df

Please sign in to comment.