diff --git a/CHANGELOG.md b/CHANGELOG.md index 570879ff18d..d3f6f75d3d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ changes in the following format: PR #1234*** Quality Control, and Behavioural Quality Control. (PR #6041) - Addition of a new `account_request_date` in `users` table that will be used when requesting a new account and will be displayed in the User Accounts module (PR #6191) +- Candidate's age can be retrieved from the Candidate class in days, months, or years (PR #5945) #### Bug Fixes - *Add item here* ### Modules diff --git a/php/libraries/Candidate.class.inc b/php/libraries/Candidate.class.inc index ed991f5f7b2..2b4d76d6711 100644 --- a/php/libraries/Candidate.class.inc +++ b/php/libraries/Candidate.class.inc @@ -688,6 +688,57 @@ class Candidate implements \LORIS\StudyEntities\AccessibleResource return intval($result); } + /** + * Returns DateInterval between candidate's date of birth and a given date, + * or today if no date given. + * + * @param ?DateTime $refDate The reference date from which to calculate the age, + * or null if not provided + * + * @return DateInterval Between DoB and $refDate + */ + public function getAge(?DateTime $refDate = null): DateInterval + { + if (!$refDate) { + $refDate = new DateTime(); + } + + $dob = new DateTime($this->candidateInfo["DoB"]); + + return $dob->diff($refDate); + } + + /** + * Returns the candidate's calculated age today in int years + * + * @return int The candidate's age today as years + */ + public function getAgeInYears(): int + { + return (int)$this->getAge()->format('%y'); + } + + /** + * Returns the candidate's calculated age today in total number of months + * + * @return int The candidate's age today in months + */ + public function getAgeInMonths(): int + { + return (int)$this->getAge()->format('%m') + + 12 * $this->getAgeInYears(); + } + + /** + * Returns the candidate's calculated age today in total number of days + * + * @return int The candidate's age today in days + */ + public function getAgeInDays(): int + { + return (int)$this->getAge()->days; + } + /** * Returns list of consents and their respective statuses for this candidate * diff --git a/test/unittests/CandidateTest.php b/test/unittests/CandidateTest.php index a973584cca3..5ee6c03e38e 100644 --- a/test/unittests/CandidateTest.php +++ b/test/unittests/CandidateTest.php @@ -669,6 +669,62 @@ public function testGetNextVisitNoReturnsOneWhenNextVisitDoesNotExist() $this->_candidate->select($this->_candidateInfo['CandID']); $this->assertEquals(1, $this->_candidate->getNextVisitNo()); } + /** + * Test getAge returns correct DateTime Interval $y, $m, $d properties + * + * @covers Candidate::getAge() + * @return void + */ + public function testGetAgeReturnsCorrectDateTimeInterval() + { + $this->_setUpTestDoublesForSelectCandidate(); + $this->_candidate->select($this->_candidateInfo['CandID']); + + $referenceDate = new DateTime('2020-02-25'); + $this->assertEquals(12, $this->_candidate->getAge($referenceDate)->y); + $this->assertEquals(11, $this->_candidate->getAge($referenceDate)->m); + $this->assertEquals(23, $this->_candidate->getAge($referenceDate)->d); + } + /** + * Test getAgeInYears returns age as int years + * + * @covers Candidate::getAgeInYears() + * @return void + */ + public function testGetAgeInYearsReturnsIntYears() + { + $this->_setUpTestDoublesForSelectCandidate(); + $this->_candidate->select($this->_candidateInfo['CandID']); + + $this->assertEquals($this->_candidate->getAge()->format('%y'), $this->_candidate->getAgeInYears()); + } + /** + * Test getAgeInMonths returns age in months + * + * @covers Candidate::getAgeInMonths() + * @return void + */ + public function testGetAgeInMonthsReturnsMonths() + { + $this->_setUpTestDoublesForSelectCandidate(); + $this->_candidate->select($this->_candidateInfo['CandID']); + + $expectedAge = intval($this->_candidate->getAge()->format('%m')) + 12 * intval($this->_candidate->getAge()->format('%y')); + $this->assertEquals($expectedAge, $this->_candidate->getAgeInMonths()); + } + /** + * Test getAgeInDays returns age in days + * + * @covers Candidate::getAgeInDays() + * @return void + */ + public function testGetAgeInDaysReturnsDays() + { + $this->_setUpTestDoublesForSelectCandidate(); + $this->_candidate->select($this->_candidateInfo['CandID']); + + $this->assertEquals($this->_candidate->getAge()->days, $this->_candidate->getAgeInDays()); + } /** * Test getSessionID returns session ID for a given existing visit *