Skip to content

Commit

Permalink
implemented safe versions of the classes DateTime and DateTimeImmutable
Browse files Browse the repository at this point in the history
  • Loading branch information
Kharhamel committed Sep 18, 2019
1 parent 277af72 commit 4e0beb3
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 0 deletions.
30 changes: 30 additions & 0 deletions generator/tests/DateTimeImmutableTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php


namespace Safe;


use PHPUnit\Framework\TestCase;
use Safe\Exceptions\DatetimeException;

class DateTimeImmutableTest extends TestCase
{
protected function setUp()
{
require_once __DIR__ . '/../../lib/DateTimeImmutable.php';
}

public function testSafeDatetimeImmutableCrashOnError(): void
{
$this->expectException(DatetimeException::class);
$datetime = DateTimeImmutable::createFromFormat('lol', 'super');
}

public function testSafeDatetimeImmutablePreserveTimeAndTimezone(): void
{
$timezone = new \DateTimeZone('Pacific/Chatham');
$datetime = DateTimeImmutable::createFromFormat('d-m-Y', '20-03-2006', $timezone);
$this->assertEquals('20-03-2006', $datetime->format('d-m-Y'));
$this->assertEquals($timezone, $datetime->getTimezone());
}
}
30 changes: 30 additions & 0 deletions generator/tests/DateTimeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php


namespace Safe;


use PHPUnit\Framework\TestCase;
use Safe\Exceptions\DatetimeException;

class DateTimeTest extends TestCase
{
protected function setUp()
{
require_once __DIR__ . '/../../lib/DateTime.php';
}

public function testSafeDatetimeCrashOnError(): void
{
$this->expectException(DatetimeException::class);
$datetime = DateTime::createFromFormat('lol', 'super');
}

public function testSafeDatetimePreserveTimeAndTimezone(): void
{
$timezone = new \DateTimeZone('Pacific/Chatham');
$datetime = DateTime::createFromFormat('d-m-Y', '20-03-2006', $timezone);
$this->assertEquals('20-03-2006', $datetime->format('d-m-Y'));
$this->assertEquals($timezone, $datetime->getTimezone());
}
}
1 change: 1 addition & 0 deletions generator/tests/SpecialCasesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

class SpecialCasesTest extends TestCase
{

public function testPregReplace()
{
require_once __DIR__.'/../../lib/special_cases.php';
Expand Down
75 changes: 75 additions & 0 deletions lib/DateTime.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

namespace Safe;

use DateInterval;
use DateTimeInterface;
use DateTimeZone;
use Safe\Exceptions\DatetimeException;

//this class is used to implement a safe version of the Datetime
class DateTime extends \DateTime
{
//switch from regular datetime to safe version
private static function createFromRegular(\DateTime $datetime): self
{
$safeDatetime = new self();
$safeDatetime->setTimestamp($datetime->getTimestamp());
$safeDatetime->setTimezone($datetime->getTimezone());
return $safeDatetime;
}

public static function createFromFormat($format, $time, DateTimeZone $timezone = null): self
{
$datetime = parent::createFromFormat($format, $time, $timezone);
if ($datetime === false) {
throw DatetimeException::createFromPhpError();
}
return self::createFromRegular($datetime);
}

/**
* @param DateTimeInterface $datetime2 The date to compare to.
* @param boolean $absolute [optional] Whether to return absolute difference.
* @return DateInterval The DateInterval object representing the difference between the two dates.
*/
public function diff($datetime2, $absolute = false): DateInterval
{
/** @var \DateInterval|false $result */
$result = parent::diff($datetime2, $absolute);
if ($result === false) {
throw DatetimeException::createFromPhpError();
}
return $result;
}

/**
* @param string $modify A date/time string. Valid formats are explained in <a href="https://secure.php.net/manual/en/datetime.formats.php">Date and Time Formats</a>.
* @return DateTime Returns the DateTime object for method chaining.
*/
public function modify($modify): self
{
/** @var DateTime|false $result */
$result = parent::modify($modify);
if ($result === false) {
throw DatetimeException::createFromPhpError();
}
return $result;
}

/**
* @param int $year
* @param int $month
* @param int $day
* @return DateTime
*/
public function setDate($year, $month, $day): self
{
/** @var DateTime|false $result */
$result = parent::setDate($year, $month, $day);
if ($result === false) {
throw DatetimeException::createFromPhpError();
}
return $result;
}
}
78 changes: 78 additions & 0 deletions lib/DateTimeImmutable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

namespace Safe;

use DateInterval;
use DateTimeInterface;
use DateTimeZone;
use Safe\Exceptions\AbstractSafeException;
use Safe\Exceptions\DatetimeException;

//this class is used to implement a safe version of the DatetimeImmutable class
class DateTimeImmutable extends \DateTimeImmutable
{
//switch from regular datetime to safe version
private static function createFromRegular(\DateTimeImmutable $datetime): self
{
$safeDatetime = new self();
$safeDatetime = $safeDatetime->setTimestamp($datetime->getTimestamp());
$safeDatetime = $safeDatetime->setTimezone($datetime->getTimezone());
return $safeDatetime;
}

public static function createFromFormat($format, $time, DateTimeZone $timezone = null): self
{
$datetime = parent::createFromFormat($format, $time, $timezone);
if ($datetime === false) {
throw DatetimeException::createFromPhpError();
}
return self::createFromRegular($datetime);
}

/**
* @param DateTimeInterface $datetime2 <p>The date to compare to.</p>
* @param bool $absolute [optional] <p>Should the interval be forced to be positive?</p>
* @return DateInterval
*/
public function diff($datetime2, $absolute = false): DateInterval
{
/** @var \DateInterval|false $result */
$result = parent::diff($datetime2, $absolute);
if ($result === false) {
throw DatetimeException::createFromPhpError();
}
return $result;
}

/**
* @param string $modify <p>A date/time string. Valid formats are explained in
* {@link https://secure.php.net/manual/en/datetime.formats.php Date and Time Formats}.</p>
* @return DateTimeImmutable
*/
public function modify($modify): self
{
/** @var \DateTimeImmutable|false $result */
$result = parent::modify($modify);
if ($result === false) {
throw DatetimeException::createFromPhpError();
}
return self::createFromRegular($result); //we have to recreate a safe datetime because modify create a new instance of \DateTimeImmutable
}

/**
* @param int $year <p>Year of the date.</p>
* @param int $month <p>Month of the date.</p>
* @param int $day <p>Day of the date.</p>
* @return DateTimeImmutable
*
*/
public function setDate($year, $month, $day): self
{
/** @var \DateTimeImmutable|false $result */
$result = parent::setDate($year, $month, $day);
if ($result === false) {
throw DatetimeException::createFromPhpError();
}
return self::createFromRegular($result); //we have to recreate a safe datetime because modify create a new instance of \DateTimeImmutable
}
}

0 comments on commit 4e0beb3

Please sign in to comment.