Skip to content

Instantly share code, notes, and snippets.

@timvisee
Created May 3, 2015 16:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timvisee/5c8bfbf6ece599ab8734 to your computer and use it in GitHub Desktop.
Save timvisee/5c8bfbf6ece599ab8734 to your computer and use it in GitHub Desktop.
<?php
/**
* DateTime.php
*
* A class to representation date and time as an object.
* This class allows you to get the current date and time of the server, to format the date and time in many different
* ways using different timezones and also to travel through time.
* Note: Even though this class uses futuristic technology to make date and time calculations, it doesn't allow humans
* to travel through time.
*
* @author Tim Visee
* @website http://timvisee.com/
* @copyright Copyright (c) Carbon CMS 2015. All rights reserved.
*/
namespace carbon\core\datetime;
use carbon\core\datetime\interval\DateInterval;
use carbon\core\datetime\period\DatePeriod;
use carbon\core\datetime\zone\DateTimeZone;
use carbon\core\datetime\zone\DateTimeZoneUtils;
use carbon\core\util\StringUtils;
use Closure;
use DateTime as PHPDateTime;
use DateTimeZone as PHPDateTimeZone;
use Exception;
// Prevent direct requests to this file due to security reasons
defined('CARBON_CORE_INIT') or die('Access denied!');
/**
* A class to represent, format and transform date and time.
*
* Used the Carbon DateTime library as basis for this class.
*
* @package carbon\core\datetime
*
* @TODO Should we keep these properties, they were removed from the DateInterval class?
*
* @property int $year The year.
* @property int $yearIso The ISO year.
* @property int $month The month.
* @property int $day The day.
* @property int $hour The hour.
* @property int $minute The minute.
* @property int $second The second.
* @property int $timestamp seconds since the Unix Epoch
* @property DateTimeZone|PHPDateTimeZone|string|DateTime|PHPDateTime|null $timezone A DateTimeZone or PHPDateTimeZone
* instance, the timezone ID as a string, a DateTime or PHPDateTime instance to use it's timezone or null to use
* the default timezone.
* @property DateTimeZone $tz Alias of $timezone.
* @property-read int $micro Read the number of micro seconds.
* @property-read int $dayOfWeek Get the day of the week as a number, 0 (for Sunday) through 6 (for Saturday).
* @property-read int $dayOfYear Get the day of the year, 0 through 365.
* @property-read int $weekOfMonth Get the week of the month, 1 through 5.
* @property-read int $weekOfYear Get the ISO-8601 week number of year, weeks starting on Monday.
* @property-read int $daysInMonth Get the number of days in the given month.
* @property-read int $age Get the number of years passed since now().
* @property-read int $quarter Get the the quarter of this instance, from 1 to 4.
* @property-read int $offset Get the timezone offset in seconds from UTC.
* @property-read int $offsetHours Get the timezone offset in hours from UTC.
* @property-read bool $dst Check whether daylight saving time is enabled, true if DST, false otherwise.
* @property-read bool $local Check whether the timezone is local, true if local, false otherwise.
* @property-read bool $utc Check whether the timezone is UTC, true if UTC, false otherwise.
* @property-read string $timezoneName Get the timezone name or ID.
* @property-read string $tzName Alias for $timezoneName.
*/
class DateTime extends PHPDateTime {
// TODO: Does this class have support for all date's, (an almost-infinite range)!
// TODO: Return null on failure, instead of false, for everything?
// TODO: Create a class for DateInterval, with the possibility to add or subtract from this date and time.
// TODO: Option to set a preferred parsing format?
// TODO: Support for all types of calendars!
// TODO: Add the possibility to extend this class, with some functions, closures and so on.
// TODO: Make sure the mock DateTime is used everywhere it's needed, such as the now(); method!
// TODO: Add proper exceptions for everything!
// TODO: Should we overwrite all/most methods provided by the base class.
// TODO: Should we name these differently, because the name is currently the same as PHP's classes
// TODO: Make sure all DateTime and PHPDateTime instances are correct!
// TODO: Rename subtract methods to sub
/**
* The day constant for sunday, this defines an integer for this week day.
*
* @const int Day index.
*/
const SUNDAY = 0;
/**
* The day constant for monday, this defines an integer for this week day.
*
* @const int Day index.
*/
const MONDAY = 1;
/**
* The day constant for tuesday, this defines an integer for this week day.
*
* @const int Day index.
*/
const TUESDAY = 2;
/**
* The day constant for wednesday, this defines an integer for this week day.
*
* @const int Day index.
*/
const WEDNESDAY = 3;
/**
* The day constant for thursday, this defines an integer for this week day.
*
* @const int Day index.
*/
const THURSDAY = 4;
/**
* The day constant for friday, this defines an integer for this week day.
*
* @const int Day index.
*/
const FRIDAY = 5;
/**
* The day constant for saturday, this defines an integer for this week day.
*
* @const int Day index.
*/
const SATURDAY = 6;
/**
* Define the names of each weekday as an array, indexed by the day constants.
*
* @var Array An array containing all weekday names.
*/
protected static $DAY_NAMES = array(
self::SUNDAY => 'Sunday',
self::MONDAY => 'Monday',
self::TUESDAY => 'Tuesday',
self::WEDNESDAY => 'Wednesday',
self::THURSDAY => 'Thursday',
self::FRIDAY => 'Friday',
self::SATURDAY => 'Saturday'
);
/**
* Terms used to detect if a time passed is a relative date for testing purposes.
*
* @var Array An array of relative keywords.
*/
protected static $RELATIVE_KEYWORDS = Array(
'this',
'next',
'last',
'tomorrow',
'yesterday',
'+',
'-',
'first',
'last',
'ago'
);
/**
* Defines the format to use for most getter names.
*
* @var Array An array of getter formats.
*/
protected static $GETTER_FORMATS = Array(
'year' => 'Y',
'yearIso' => 'o',
'month' => 'n',
'day' => 'j',
'hour' => 'G',
'minute' => 'i',
'second' => 's',
'micro' => 'u',
'dayOfWeek' => 'w',
'dayOfYear' => 'z',
'weekOfYear' => 'W',
'daysInMonth' => 't',
'timestamp' => 'U'
);
// TODO: Move this stuff to a DateTimeUnits class?
/**
* Defines the years per century, for time calculations.
*
* @const int Years per century.
*/
const YEARS_PER_CENTURY = 100;
/**
* Defines the years per decade, for time calculations.
*
* @const int Years per decade.
*/
const YEARS_PER_DECADE = 10;
/**
* Defines the months per year, for time calculations.
*
* @const int Months per year.
*/
const MONTHS_PER_YEAR = 12;
/**
* Defines the weeks per year, for time calculations.
*
* @const int Weeks per year.
*/
const WEEKS_PER_YEAR = 52;
/**
* Defines the days per week, for time calculations.
*
* @const int Days per week.
*/
const DAYS_PER_WEEK = 7;
/**
* Defines the hours per day, for time calculations.
*
* @const int Hours per day.
*/
const HOURS_PER_DAY = 24;
/**
* Defines the minutes per hour, for time calculations.
*
* @const int Minutes per hour.
*/
const MINUTES_PER_HOUR = 60;
/**
* Defines the seconds per minute, for time calculations.
*
* @const int Seconds per minute.
*/
const SECONDS_PER_MINUTE = 60;
/**
* Defines the default date format used when date and time is represented as a string.
*
* @const string The default date and time format.
*/
const DEFAULT_FORMAT = 'Y-m-d H:i:s';
/**
* Defines the default date format used when a date is represented as a string.
*
* @const string The default date format.
*/
const DEFAULT_FORMAT_DATE = 'Y-m-d';
/**
* Defines the default time format used when time is represented as a string.
*
* @const string The default time format.
*/
const DEFAULT_FORMAT_TIME = 'H:i:s';
/**
* Defines the default date and time format that includes everything in the string.
*
* @const string The default complete date and time format.
*/
// TODO: Give this constant a proper name!
const DEFAULT_FORMAT_COMPLETE = 'Y-m-d H:i:s.u e O';
/**
* An optional mock DateTime instance to return when the now() method is called.
*
* @var DateTime The mock DateTime instance, or null to use the default.
*/
protected static $mockNow;
/**
* Constructor.
*
* @param string|DateTime|PHPDateTime $dateTime [optional] The date and time as a string, the date and time as
* DateTime or PHPDateTime instance or null to use the current time.
* @param DateTimeZone|PHPDateTimeZone|string|DateTime|PHPDateTime $timezone [optional] The timezone the specified
* time is in, or null to use the default timezone. A DateTime or PHPDateTime instance to use it's timezone.
*
* @throws Exception Throws an exception on failure.
*/
public function __construct($dateTime = null, $timezone = null) {
// Parse the timezone if it isn't null and make sure it's valid
if($timezone !== null)
if(($timezone = DateTimeZoneUtils::parse($timezone, null)) === null)
// TODO: Add a better exception, with a better description!
throw new Exception('Invalid timezone!');
// Handle DateTime instances
if($dateTime instanceof self) {
// Construct the parent object with the proper properties
parent::__construct($dateTime->toCompleteString(), $dateTime->getTimezone());
return $this;
}
// Handle PHPDateTime instances
if($dateTime instanceof parent) {
// Construct the parent object with the proper properties
parent::__construct($dateTime->format(self::DEFAULT_FORMAT_COMPLETE), $dateTime->getTimezone());
return $this;
}
// Check whether we should use the now time
if(empty($dateTime) || StringUtils::equals($dateTime, 'now', false, true))
// Return a new instance of the mock time if set
if(static::hasMockNow())
return clone static::getMockNow();
// Check whether the time contains relative keywords
if(static::hasRelativeKeywords($dateTime)) {
// Get a new DateTime instance, and modify the date and time according to the time parameter
$dateTime = static::now()->modify($dateTime);
// Shift the timezone if it's set
if($timezone !== null && !$timezone->equals(static::getMockNow()))
$dateTime->setTimezone($timezone);
else
$timezone = $dateTime->getTimezone();
// Update the time parameter with the modified time
$dateTime = $dateTime->toCompleteString();
}
// Construct the parent object
parent::__construct($dateTime, $timezone);
return $this;
}
/**
* Create a copy of a DateTime instance.
*
* @param DateTime $other The other instance.
*
* @return static The new DateTime instance.
*/
// TODO: Parse the parameter for better flexibility, make sure an instance isn't created twice.
public static function instance(self $other) {
return new static($other->format(self::DEFAULT_FORMAT_COMPLETE), $other->getTimeZone());
}
/**
* Create a copy of this DateTime instance.
*
* @return static A new DateTime zone instance.
*/
public function copy() {
return static::instance($this);
}
/**
* Create a copy of this DateTime instance. Called by PHP when the DateTime object is cloned.
*
* @return static A new DateTime zone instance
*/
public function __clone() {
return $this->copy();
}
/**
* Parse date and time with a specific timezone. A new instance may be created if required.
*
* If the $time parameter is a DateTime zone instance, the instance will be returned and the $timezone parameter is
* ignored. If the $time parameter is anything other than a DateTime zone the date, time and the timezone is parsed
* through the constructor.
*
* This method allows better fluent syntax because it makes method chaining possible.
*
* @param DateTime|string|null $dateTime [optional] A DateTime instance, the time as a string, or null to use the
* current time.
* @param DateTimeZone|PHPDateTimeZone|string|DateTime|PHPDateTime|null $timezone [optional] The timezone the
* specified time is in, or null to use the default timezone if the $time param isn't a DateTime instance. A
* DateTime or PHPDateTime instance to use it's timezone.
*
* @return DateTime|null The parsed DateTime instance, or null on failure.
*/
// TODO: Should we move the parse code to this class, instead of the utils class?
public static function parse($dateTime = null, $timezone = null) {
return DateTimeUtils::parse($dateTime, $timezone, null);
}
/**
* Create a DateTime instance for the current date and time.
*
* @param DateTimeZone|PHPDateTimeZone|string $timezone [optional] The preferred timezone to use, or null to use
* the default timezone.
* @param bool $real [optional] True to return the real now() value which ignores the mock date and time, false to
* return the normal value.
*
* @return static The DateTime instance.
*/
public static function now($timezone = null, $real = false) {
// Check whether the regular or the real now should be returned
if(!$real)
return new static(null, $timezone);
// Return the real now time
return new static(new parent('now', $timezone), $timezone);
}
/**
* Create a DateTime instance for the start of the current day.
*
* @param DateTimeZone|PHPDateTimeZone|string $timezone [optional] The preferred timezone to use, or null to use
* the default timezone.
* @param bool $real [optional] True to use the real now() value which ignores the mock date and time, false to
* return the normal value.
*
* @return static The DateTime instance.
*/
public static function today($timezone = null, $real = false) {
return static::now($timezone, $real)->startOfDay();
}
/**
* Create a DateTime instance for the start of tomorrow.
*
* @param DateTimeZone|PHPDateTimeZone|string $timezone [optional] The preferred timezone to use, or null to use
* the default timezone.
* @param bool $real [optional] True to use the real now() value which ignores the mock date and time, false to
* return the normal value.
*
* @return static The DateTime instance.
*/
public static function tomorrow($timezone = null, $real = false) {
return static::today($timezone, $real)->addDay();
}
/**
* Create a DateTime instance for the start of yesterday.
*
* @param DateTimeZone|PHPDateTimeZone|string $timezone [optional] The preferred timezone to use, or null to use
* the default timezone.
* @param bool $real [optional] True to use the real now() value which ignores the mock date and time, false to
* return the normal value.
*
* @return static The DateTime instance.
*/
public static function yesterday($timezone = null, $real = false) {
return static::today($timezone, $real)->subtractDay();
}
/**
* Create a DateTime instance for the greatest supported date and time.
*
* @return static The DateTime instance.
*/
public static function greatestDate() {
return static::createFromTimestamp(PHP_INT_MAX);
}
/**
* Create a DateTime instance for the lowest supported date and time.
*
* @return static The DateTime instance.
*/
public static function lowestDate() {
return static::createFromTimestamp(~PHP_INT_MAX);
}
/**
* Create a new DateTime instance from a specific date and time.
*
* If the $year, $month or $day parameters are set to null their now() value will be used.
*
* If $hour is null it will be set to its now() value and the default values for $minute and $second will be their
* now() values. If $hour is not null, then the default values for $minute and $second will be 0.
*
* @param int $year [optional] The specified year, or null to use the current year.
* @param int $month [optional] The specified month, or null to use the current month.
* @param int $day [optional] The specified day, or null to use the current day.
* @param int $hour [optional] The specified hour, or null to use the current hour.
* @param int $minute [optional] The specified minute, or null.
* @param int $second [optional] The specified second, or null.
* @param DateTimeZone|PHPDateTimeZone|string|DateTime|PHPDateTime|null $timezone [optional] The preferred timezone
* to use, or null to use the default timezone. A DateTime or PHPDateTime instance to use it's timezone.
*
* @return static The DateTime instance.
*/
// TODO: Does this method return null on some sort of failure?
// TODO: Redo this method!
// TODO: Does this only return full hours when no parameter is given?
public static function create($year = null, $month = null, $day = null, $hour = null, $minute = null,
$second = null, $timezone = null) {
// Specify the date and time parts
$year = $year === null ? date('Y') : $year;
$month = $month === null ? date('n') : $month;
$day = $day === null ? date('j') : $day;
$hour = $hour === null ? date('G') : $hour;
$minute = $minute === null ? ($hour === null ? date('i') : 0) : $minute;
$second = $second === null ? ($hour === null ? date('s') : 0) : $second;
// Create a DateTime instance from the time parts
return static::createFromFormat('Y-n-j G:i:s',
sprintf('%s-%s-%s %s:%02s:%02s', $year, $month, $day, $hour, $minute, $second), $timezone);
}
/**
* Create a DateTime instance with a specific date. The time portion is set to now.
*
* If the $year, $month or $day parameters are set to null their now() value will be used.
*
* @param int $year [optional] The specified year, or null to use the current year.
* @param int $month [optional] The specified month, or null to use the current month.
* @param int $day [optional] The specified day, or null to use the current day.
* @param DateTimeZone|PHPDateTimeZone|string $timezone The preferred timezone to use, or null to use the default
* timezone.
*
* @return static The DateTime instance.
*/
public static function createFromDate($year = null, $month = null, $day = null, $timezone = null) {
return static::create($year, $month, $day, null, null, null, $timezone);
}
/**
* Create a DateTime instance with a specific time. The date portion is set to today.
*
* If $hour is null it will be set to its now() value and the default values for $minute and $second will be their
* now() values. If $hour is not null, then the default values for $minute and $second will be 0.
*
* @param int $hour [optional] The specified hour, or null to use the current hour.
* @param int $minute [optional] The specified minute, or null.
* @param int $second [optional] The specified second, or null.
* @param DateTimeZone|PHPDateTimeZone|string $timezone The preferred timezone to use, or null to use the default
* timezone.
*
* @return static The DateTime instance.
*/
public static function createFromTime($hour = null, $minute = null, $second = null, $timezone = null) {
return static::create(null, null, null, $hour, $minute, $second, $timezone);
}
/**
* Create a DateTime instance from a string with a specified format.
*
* @param string $format The format used to parse the date time.
* @param string $time The date time to parse as a string.
* @param DateTimeZone|PHPDateTimeZone|string $timezone The preferred timezone to use, or null to use the default
* timezone.
*
* @return static The DateTime instance or null on failure.
*/
// TODO: Review this method!
public static function createFromFormat($format, $time, $timezone = null) {
// Try to create a DateTime instance based on the input
if($timezone !== null)
$dateTime = parent::createFromFormat($format, $time, DateTimeZoneUtils::safeCreateDateTimeZone($timezone));
else
$dateTime = parent::createFromFormat($format, $time);
// Make sure the object is valid
if($dateTime === false)
return null;
// Parse and return the date time
return self::parse($dateTime, $timezone);
}
/**
* Create a DateTime instance based on a Unix timestamp.
*
* @param int $timestamp The timestamp to get the DateTime instance for.
* @param DateTimeZone|PHPDateTimeZone|string $timezone The preferred timezone to use, or null to use the default
* timezone.
*
* @return static The DateTime instance, or null on failure.
*/
public static function createFromTimestamp($timestamp, $timezone = null) {
// Create a DateTime instance and make sure it's valid
if(($dateTime = static::now($timezone)->setTimestamp($timestamp)) === false)
return null;
// Return the DateTime instance
return $dateTime;
}
/**
* Create a DateTime instance based on a UTC timestamp.
*
* @param int $timestamp The UTC timestamp.
*
* @return static The DateTime instance.
*/
public static function createFromTimestampUTC($timestamp) {
return new static('@' . $timestamp);
}
/**
* Get the year.
*
* @return int The year.
*/
public function getYear() {
return (int) $this->format(static::$GETTER_FORMATS['year']);
}
/**
* Change the year.
*
* @param int $year The year.
*
* @return static|null A DateTime instance on success for method chaining, null on failure.
*/
public function setYear($year) {
// Set the year
try {
$this->year = $year;
return $this;
} catch(Exception $ex) {
return null;
}
}
/**
* Get the month.
*
* @return int The month.
*/
public function getMonth() {
return (int) $this->format(static::$GETTER_FORMATS['month']);
}
/**
* Change the month.
*
* @param int $month The month.
*
* @return static|null A DateTime instance on success for method chaining, null on failure.
*/
public function setMonth($month) {
// Set the month
try {
$this->month = $month;
return $this;
} catch(Exception $ex) {
return null;
}
}
/**
* Get the day.
*
* @return int The day.
*/
public function getDay() {
return (int) $this->format(static::$GETTER_FORMATS['day']);
}
/**
* Change the day.
*
* @param int $day The day.
*
* @return static|null A DateTime instance on success for method chaining, null on failure.
*/
public function setDay($day) {
// Set the day
try {
$this->day = $day;
return $this;
} catch(Exception $ex) {
return null;
}
}
/**
* Get the hour.
*
* @return int The hour.
*/
public function getHour() {
return (int) $this->format(static::$GETTER_FORMATS['hour']);
}
/**
* Change the hour.
*
* @param int $hour The hour.
*
* @return static|null A DateTime instance on success for method chaining, null on failure.
*/
public function setHour($hour) {
// Set the hour
try {
$this->hour = $hour;
return $this;
} catch(Exception $ex) {
return null;
}
}
/**
* Get the minute.
*
* @return int The minute.
*/
public function getMinute() {
return (int) $this->format(static::$GETTER_FORMATS['minute']);
}
/**
* Change the minute.
*
* @param int $minute The minute.
*
* @return static|null A DateTime instance on success for method chaining, null on failure.
*/
public function setMinute($minute) {
// Set the minute
try {
$this->minute = $minute;
return $this;
} catch(Exception $ex) {
return null;
}
}
/**
* Get the second.
*
* @return int The second.
*/
public function getSecond() {
return (int) $this->format(static::$GETTER_FORMATS['second']);
}
/**
* Change the second.
*
* @param int $second The second.
*
* @return static|null A DateTime instance on success for method chaining, null on failure.
*/
public function setSecond($second) {
// Set the second
try {
$this->second = $second;
return $this;
} catch(Exception $ex) {
return null;
}
}
/**
* Set the timestamp.
*
* @param int $timestamp The timestamp.
*
* @return static|null A DateTime instance on success for method chaining, null on failure.
*/
public function setTimestamp($timestamp) {
// Set the timestamp
try {
$this->timestamp = $timestamp;
return $this;
} catch(Exception $ex) {
return null;
}
}
/**
* Get the timezone.
*
* @return DateTimeZone|null The timezone, or null on failure.
*/
public function getTimezone() {
return DateTimeZoneUtils::parse(parent::getTimezone());
}
/**
* Set the timezone.
*
* @param DateTimeZone|PHPDateTimeZone|string|DateTime|PHPDateTime $timezone A DateTimeZone or PHPDateTimeZone
* instance or the timezone ID as a string. A DateTime or PHPDateTime instance to use it's timezone.
*
* @return static|null A DateTime instance on success for method chaining, null on failure.
*/
public function setTimezone($timezone) {
// Parse the timezone, return null on failure
if(($timezone = DateTimeZoneUtils::parse($timezone)) === null)
return null;
// Set the timezone, and return the current instance for method chaining
parent::setTimezone($timezone);
return $this;
}
/**
* Get a mock DateTime instance which is returned when the now() method is called.
*
* @return DateTime The mock DateTime instance, or null when no mock instance is set.
*/
public static function getMockNow() {
return static::$mockNow;
}
/**
* Check whether a mock DateTime instance is set.
*
* @return bool True if any mock DateTime instance is set, false otherwise.
*/
public static function hasMockNow() {
return static::getMockNow() !== null;
}
/**
* Set a mock DateTime instance which is returned when the now() method is called.
* A new DateTime instance will be created if $mockNow needs to be parsed into a DateTime instance.
* This affects all methods using the now() method as default when no time data is supplied.
*
* The timezone doesn't have any effect on this method.
*
* To reset the mock instance, call this method using the default parameter of null.
*
* @param DateTime|PHPDateTime|string|null $mockNow [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to reset the mock date and time.
*
* @return bool True on success, false on failure.
*/
public static function setMockNow($mockNow = null) {
// Check whether the mock instance should be reset
if($mockNow === null) {
static::$mockNow = null;
return true;
}
// Parse the mock date and time, return false on failure
if(($mockNow = static::parse($mockNow)) === null)
return false;
// Set the mock instance, return the result
static::$mockNow = $mockNow;
return true;
}
/**
* Get the micro.
*
* @return int The micro.
*/
public function getMicro() {
return (int) $this->format(static::$GETTER_FORMATS['micro']);
}
/**
* Get the day of the week.
*
* @return int The day of the week.
*/
public function getDayOfWeek() {
return (int) $this->format(static::$GETTER_FORMATS['dayOfWeek']);
}
/**
* Get the day of the year.
*
* @return int The day of the year.
*/
public function getDayOfYear() {
return (int) $this->format(static::$GETTER_FORMATS['dayOfYear']);
}
/**
* Get the week of the year.
*
* @return int The week of the year.
*/
public function getWeekOfYear() {
return (int) $this->format(static::$GETTER_FORMATS['weekOfYear']);
}
/**
* Get the number of days in this month.
*
* @return int The number of days.
*/
public function getDaysInMonth() {
return (int) $this->format(static::$GETTER_FORMATS['daysInMonth']);
}
/**
* Set the date of the object.
*
* @param int|null $year [optional] The year, or null to leave the year unchanged.
* @param int|null $month [optional] The month, or null to leave the month unchanged.
* @param int|null $day [optional] The day, or null to leave the day unchanged.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function setDate($year = null, $month = null, $day = null) {
// Make sure the parameters are valid or null
if(($year !== null && !is_int($year)) || ($month !== null && !is_int($month)) ||
($day !== null && !is_int($day))
)
return null;
// Handle the null parameters
if($year === null)
$year = $this->getYear();
if($month === null)
$month = $this->getMonth();
if($day === null)
$day = $this->getDay();
// Set the date using the parent function, return this or null on failure
return parent::setDate($year, $month, $day) === false ? null : $this;
}
/**
* Set the time of the object.
*
* @param int|null $hour [optional] The hour, or null to leave the hour unchanged.
* @param int|null $minute [optional] The minute, or null to leave the minute unchanged.
* @param int|null $second [optional] The second, or null to leave the second unchanged.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function setTime($hour = null, $minute = null, $second = null) {
// Make sure the parameters are valid or null
if(($hour !== null && !is_int($hour)) || ($minute !== null && !is_int($minute)) ||
($second !== null && !is_int($second))
)
return null;
// Handle the null parameters
if($hour === null)
$hour = $this->getHour();
if($minute === null)
$minute = $this->getMinute();
if($second === null)
$second = $this->getSecond();
// Set the time using the parent function, return this or null on failure
return parent::setTime($hour, $minute, $second) === false ? null : $this;
}
/**
* Get a part of the DateTime object.
*
* @param string $name The getter name.
*
* @return string|int|DateTimeZone|PHPDateTimeZone
*
* @throws \InvalidArgumentException
*/
// TODO: Handle these getters through the real get... setters!
public function __get($name) {
// Parse the getter based on the getter formats list
if(array_key_exists($name, static::$GETTER_FORMATS))
return (int) $this->format(static::$GETTER_FORMATS[$name]);
// Get the week number of the month
if(StringUtils::equals($name, 'weekOfMonth', false))
return (int) ceil($this->day / static::DAYS_PER_WEEK);
// Get the age
if(StringUtils::equals($name, 'age', false))
return $this->getAge();
// Ge the current quarter number
if(StringUtils::equals($name, 'quarter', false))
return (int) ceil($this->month / 3);
// Get the offset
if(StringUtils::equals($name, 'offset', false))
return $this->getOffset();
// Get the offset hours
if(StringUtils::equals($name, 'offsetHours', false))
return $this->getOffset() / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR;
// Check whether daylight saving time is active
if(StringUtils::equals($name, 'dst', false))
return $this->format('I') == '1';
// Check if the timezone is local
if(StringUtils::equals($name, 'local', false))
return $this->getTimezone()->isLocal(DateTimeZoneUtils::getDefaultTimezone());
// Check whether the time is in UTC
if(StringUtils::equals($name, 'utc', false))
return $this->offset == 0;
// Get the timezone
if(StringUtils::equals($name, Array('timezone', 'tz'), false))
return $this->getTimezone();
// Get the timezone name
if(StringUtils::equals($name, Array('timezoneName', 'tzName'), false))
return $this->getTimezone()->getName();
// The field name is unknown, throw an exception
// TODO: Should we throw an error, or is returning nothing fine?
throw new \InvalidArgumentException('Unknown getter \'' . $name . '\'');
}
/**
* Check if an attribute exists on the object.
*
* @param string $name The name of the attribute.
*
* @return bool True if the attribute exists, false otherwise.
*/
public function __isset($name) {
try {
// Try to get an attribute
$this->__get($name);
} catch(\InvalidArgumentException $e) {
// The attribute doesn't exist, return the result
return false;
}
// The attribute does exist, return the result
return true;
}
/**
* Set a part of the DateTime object.
*
* @param string $name The name of the attribute to set.
* @param string|int|DateTimeZone|PHPDateTimeZone $value The value to set it to.
*
* @throws Exception|\InvalidArgumentException Throws an exception on failure.
*/
// TODO: Handle these setters through the real set... setters!
public function __set($name, $value) {
// Set the year
if(StringUtils::equals($name, 'year', true)) {
if($this->setDate($value, null, null) === null)
throw new \DomainException('Invalid type for \'' . $name . '\'');
return;
}
// Set the month
if(StringUtils::equals($name, 'month', true)) {
if($this->setDate(null, $value, null) === null)
throw new \DomainException('Invalid type for \'' . $name . '\'');
return;
}
// Set the day
if(StringUtils::equals($name, 'day', true)) {
if($this->setDate(null, null, $value) === null)
throw new \DomainException('Invalid type for \'' . $name . '\'');
return;
}
// Set the hour
if(StringUtils::equals($name, 'hour', true)) {
if($this->setTime($value, null, null) === null)
throw new \DomainException('Invalid type for \'' . $name . '\'');
return;
}
// Set the minute
if(StringUtils::equals($name, 'minute', true)) {
if($this->setTime(null, $value, null) === null)
throw new \DomainException('Invalid type for \'' . $name . '\'');
return;
}
// Set the second
if(StringUtils::equals($name, 'second', true)) {
if($this->setTime(null, null, $value) === null)
throw new \DomainException('Invalid type for \'' . $name . '\'');
return;
}
// Set the timestamp
if(StringUtils::equals($name, 'timestamp', true)) {
if(parent::setTimestamp($value) === false)
throw new \DomainException('Invalid type for \'' . $name . '\'');
return;
}
// Set the timezone
if(StringUtils::equals($name, Array('timezone', 'tz'), true)) {
if($this->setTimezone($value) === null)
throw new \DomainException('Invalid type for ' . $name);
return;
}
// Failed to set the attribute, throw an exception
// TODO: Should we throw an error, or is returning nothing fine?
throw new \InvalidArgumentException('Unknown setter \'' . $name . '\'');
}
/**
* Set the date and time of the object.
*
* @param int|null $year [optional] The year, or null to leave the year unchanged.
* @param int|null $month [optional] The month, or null to leave the month unchanged.
* @param int|null $day [optional] The day, or null to leave the day unchanged.
* @param int|null $hour [optional] The hour, or null to leave the hour unchanged.
* @param int|null $minute [optional] The minute, or null to leave the minute unchanged.
* @param int|null $second [optional] The second, or null to leave the second unchanged.
*
* @return static|null The DateTime instance, or null on failure
*/
public function setDateTime($year, $month, $day, $hour, $minute, $second = 0) {
// Set the date, return null on failure
if($this->setDate($year, $month, $day) === null)
return null;
// Set the time and return this, return null on failure
return $this->setTime($hour, $minute, $second) === null ? null : $this;
}
/**
* Check whether there is a relative keyword in the date and time string, this is to create dates relative to now
* for test instances. e.g.: next tuesday
*
* @param string $time The date and time string to check.
*
* @return bool True if there is a relative keyword in the date and time string, false otherwise.
*/
public static function hasRelativeKeywords($time) {
// Check whether the time string contains any relative keywords
// Skip a common time format
if(preg_match('/[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}/', $time) !== 1)
foreach(static::$RELATIVE_KEYWORDS as $keyword)
if(StringUtils::contains($time, $keyword, false))
return true;
// The time string doesn't contain any relative keywords, return the result
return false;
}
// TODO: Put all translation and to string stuff here...!
/**
* Check whether the date equals to the date of the specified date and time parameter.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] The other DateTime or PHPDateTime instance, the
* date and time as a string or null to use the now() time.
*
* @return bool True if the date equals the date of the specified date and time, false otherwise. False will also
* be returned if the specified date and time was invalid.
*/
public function equals($dateTime = null) {
// Parse the date and time, return false on failure
if(($dateTime = static::parse($dateTime)) === null)
return null;
// Compare the date and time of both objects, return the result
return StringUtils::equals($this->toCompleteString(), $dateTime->toCompleteString());
}
/**
* Check whether the date is greater than the date of the specified date and time parameter.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] The other DateTime or PHPDateTime instance, the
* date and time as a string or null to use the now() time.
*
* @return bool|null True if the date is greater than the specified date and time, false otherwise. Null will be
* returned if the specified date and time was invalid.
*/
public function isGreaterThan($dateTime = null) {
// Parse the date and time, return false on failure
if(($dateTime = static::parse($dateTime)) === null)
return null;
// Compare the date and time, return the result
return $this > $dateTime;
}
/**
* Check whether the date is greater or equal to the date of the specified date and time parameter.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] The other DateTime or PHPDateTime instance, the
* date and time as a string or null to use the now() time.
*
* @return bool|null True if the date is greater or equal to the specified date and time, false otherwise. Null
* will be returned if the specified date and time was invalid.
*/
public function isGreaterOrEqualTo($dateTime = null) {
// Parse the date and time, return false on failure
if(($dateTime = static::parse($dateTime)) === null)
return null;
// Compare the date and time, return the result
return $this >= $dateTime;
}
/**
* Check whether the date is less than the date of the specified date and time parameter.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] The other DateTime or PHPDateTime instance, the
* date and time as a string or null to use the now() time.
*
* @return bool|null True if the date is less than the specified date and time, false otherwise. Null will be
* returned if the specified date and time was invalid.
*/
public function isLessThan($dateTime = null) {
// Parse the date and time, return false on failure
if(($dateTime = static::parse($dateTime)) === null)
return null;
// Compare the date and time, return the result
return $this < $dateTime;
}
/**
* Check whether the date is less or equal to the date of the specified date and time parameter.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] The other DateTime or PHPDateTime instance, the
* date and time as a string or null to use the now() time.
*
* @return bool|null True if the date is less or equal to the specified date and time, false otherwise. Null will
* be returned if the specified date and time was invalid.
*/
public function isLessOrEqualTo($dateTime = null) {
// Parse the date and time, return false on failure
if(($dateTime = static::parse($dateTime)) === null)
return null;
// Compare the date and time, return the result
return $this <= $dateTime;
}
/**
* Check whether the specified date and time is between a and b.
* The $a and $b parameter may not be null at the same time or false will be returned.
*
* @param DateTime|PHPDateTime|string|null $a The date and time as DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
* @param DateTime|PHPDateTime|string|null $b The date and time as DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
* @param bool $equals [optional] True to also return true if the date equals one of the specified date and times,
* false otherwise.
*
* @return bool|null True if the date is between the specified date and time, or if it equals one of the date and
* times while $equals is set to true. False will be returned otherwise. Null will be returned on failure.
*/
public function isBetween($a = null, $b = null, $equals = true) {
// The a and b parameters may not be null at the same time
if($a === null && $b === null)
return null;
// Parse the date and times, return null on failure
if(($a = static::parse($a)) === null || ($b = static::parse($b)) === null)
return null;
// Get the lowest and greatest date
$aGreater = $a->isGreaterThan($b);
$lowest = $aGreater ? $b : $a;
$greatest = $aGreater ? $a : $b;
// Check whether the dates may equal
if($equals)
// Check whether the date is in between or equals, return the result
return $this->isGreaterOrEqualTo($lowest) && $this->isLessOrEqualTo($greatest);
// Check whether the date is in between, return the result
return $this->isGreaterThan($lowest) && $this->isLessThan($greatest);
}
/**
* Get the greatest date and time of this instance and the specified date and time.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
*
* @return DateTime|null The greatest DateTime instance, or null on failure.
*/
public function max($dateTime = null) {
// Parse the date and time, return false on failure
if(($dateTime = self::parse($dateTime)) === null)
return null;
// Return the greatest date and time
return $this->isGreaterOrEqualTo($dateTime) ? $this : $dateTime;
}
/**
* Get the lowest date and time of this instance and the specified date and time.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
*
* @return DateTime|null The lowest DateTime instance, or null on failure.
*/
public function min($dateTime = null) {
// Parse the date and time, return false on failure
if(($dateTime = self::parse($dateTime)) === null)
return null;
// Return the greatest date and time
return $this->isLessOrEqualTo($dateTime) ? $this : $dateTime;
}
/**
* Check whether this is a weekday (monday to friday).
*
* @return bool True if this is a weekday, false otherwise.
*/
public function isWeekday() {
return $this->dayOfWeek != static::SUNDAY && $this->dayOfWeek != static::SATURDAY;
}
/**
* Check whether this is a weekend day (saturday or sunday).
*
* @return bool True if this is a weekend day, false otherwise.
*/
public function isWeekend() {
return !$this->isWeekday();
}
/**
* Check whether this is today.
*
* @return bool True if this is today, false if not.
*/
public function isToday() {
return StringUtils::equals($this->toDateString(), static::now($this->getTimezone())->toDateString());
}
/**
* Check whether this is tomorrow.
*
* @return bool True if this is tomorrow, false if not.
*/
public function isTomorrow() {
return StringUtils::equals($this->toDateString(), static::tomorrow($this->getTimezone())->toDateString());
}
/**
* Check whether this is yesterday.
*
* @return bool True if this is yesterday, false if not.
*/
public function isYesterday() {
return StringUtils::equals($this->toDateString(), static::yesterday($this->getTimezone())->toDateString());
}
/**
* Check whether this is in the future. If the date and time equals the now() date and time false is returned.
*
* @return bool True if this is in the future, false if not.
*/
public function isFuture() {
return $this->isGreaterThan(static::now($this->getTimezone()));
}
/**
* Check whether this is in the past. If the date and time equals the now() date and time false is returned.
*
* @return bool True if this is in the past, false if not.
*/
public function isPast() {
return $this->isLessThan(static::now($this->getTimezone()));
}
/**
* Check whether this is a leap year.
*
* @return bool True if this is a leap year, false if not.
*/
public function isLeapYear() {
return StringUtils::equals($this->format('L'), '1');
}
/**
* Check whether the year equals the specified date.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
*
* @return bool True if year is the same as the specified date, false otherwise. False will also be returned on
* failure.
*/
public function isSameYear($dateTime) {
// Parse the date and time, return false on failure
if(($dateTime = static::parse($dateTime, $this->getTimezone())) === null)
return false;
// Check whether the week is equal, return the result
return StringUtils::equals($this->format('Y'), $dateTime->format('Y'));
}
/**
* Check whether the month equals the specified date.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
*
* @return bool True if month is the same as the specified date, false otherwise. False will also be returned on
* failure.
*/
public function isSameMonth($dateTime) {
// Parse the date and time, return false on failure
if(($dateTime = static::parse($dateTime, $this->getTimezone())) === null)
return false;
// Check whether the week is equal, return the result
return StringUtils::equals($this->format('Y-m'), $dateTime->format('Y-m'));
}
/**
* Check whether the ISO-8601 week equals the specified date.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
*
* @return bool True if the ISO-8601 week is the same as the specified date, false otherwise. False will also be
* returned on failure.
*/
public function isSameWeek($dateTime) {
// Parse the date and time, return false on failure
if(($dateTime = static::parse($dateTime, $this->getTimezone())) === null)
return false;
// Check whether the week is equal, return the result
return StringUtils::equals($this->format('Y-W'), $dateTime->format('Y-W'));
}
/**
* Check whether the date is equal to the specified date.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
*
* @return bool True if the date is the same as the specified date, false otherwise. False will also be returned on
* failure.
*/
public function isSameDate($dateTime) {
// Parse the date and time, return false on failure
if(($dateTime = static::parse($dateTime, $this->getTimezone())) === null)
return false;
// Check whether the date is equal
return StringUtils::equals($this->toDateString(), $dateTime->toDateString());
}
/**
* Check whether the hour equals the specified date.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
* @param bool $checkDate [optional] True to make sure the dates are equal, false to just compare the time.
*
* @return bool True if hour is the same as the specified date, false otherwise. False will also be returned on
* failure.
*/
public function isSameHour($dateTime, $checkDate = true) {
// Parse the date and time, return false on failure
if(($dateTime = static::parse($dateTime, $this->getTimezone())) === null)
return false;
// Compare the date
if($checkDate)
if(!$this->isSameDate($dateTime))
return false;
// Check whether the week is equal, return the result
return StringUtils::equals($this->format('H'), $dateTime->format('H'));
}
/**
* Check whether the minute equals the specified date.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
* @param bool $checkDate [optional] True to make sure the dates are equal, false to just compare the time.
*
* @return bool True if minute is the same as the specified date, false otherwise. False will also be returned on
* failure.
*/
public function isSameMinute($dateTime, $checkDate = true) {
// Parse the date and time, return false on failure
if(($dateTime = static::parse($dateTime, $this->getTimezone())) === null)
return false;
// Compare the date
if($checkDate)
if(!$this->isSameDate($dateTime))
return false;
// Check whether the week is equal, return the result
return StringUtils::equals($this->format('H:i'), $dateTime->format('H:i'));
}
/**
* Check whether the second equals the specified date.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
* @param bool $checkDate [optional] True to make sure the dates are equal, false to just compare the time.
*
* @return bool True if second is the same as the specified date, false otherwise. False will also be returned on
* failure.
*/
public function isSameTime($dateTime, $checkDate = true) {
// Parse the date and time, return false on failure
if(($dateTime = static::parse($dateTime, $this->getTimezone())) === null)
return false;
// Compare the date
if($checkDate)
if(!$this->isSameDate($dateTime))
return false;
// Check whether the week is equal, return the result
return StringUtils::equals($this->toTimeString(), $dateTime->toTimeString());
}
/**
* Alter the date and time by incrementing or decrementing based on the modify parameter in a format accepted by
* strtotime(). If an empty string, or null is provided null will be returned.
*
* @param string $modify A date/time string in a format accepted by PHPs strtotime();.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function modify($modify) {
// Make sure the modify parameter isn't empty
if(empty($modify))
return $this;
// Modify the date and time using the parent method, return null on failure
if(parent::modify($modify) === false)
return null;
// Return the current instance for method chaining
return $this;
}
/**
* Travel the specified number of years forward in time. A positive number of years will travel forward in time,
* while a negative number of years travels backward.
*
* @param int $years The number of years to travel forward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function addYears($years) {
// Make sure the years value is an integer
if(!is_int($years))
return null;
// Travel the specified number of years in time
// TODO: Should we prefix this add sign, or make it dynamic? (For all similar methods)
if($this->modify($years . ' year') === false)
return null;
// Return this for method chaining
return $this;
}
/**
* Travel a year, or the specified number of years forward in time. A positive number of years will travel forward
* in time, while a negative number of years travels backward.
*
* @param int $years [optional] The number of years to travel forward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function addYear($years = 1) {
return $this->addYears($years);
}
/**
* Travel the specified number of years backward in time. A positive number of years will travel backward in time,
* while a negative number of years travels forward.
*
* @param int $years The number of years to travel backward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
// TODO: Should we rename these methods to sub..., because that same term is used in PHPs methods!?
public function subYears($years) {
return $this->addYears($years * -1);
}
/**
* Travel a year, or the specified number of years backward in time. A positive number of years will travel
* backward in time, while a negative number of years will travel forward.
*
* @param int $years [optional] The number of years to travel backward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function subYear($years = 1) {
return $this->subYears($years);
}
/**
* Travel the specified number of months forward in time. A positive number of months will travel forward in time,
* while a negative number of months travels backward.
*
* @param int $months The number of months to travel forward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function addMonths($months) {
// Make sure the months value is an integer
if(!is_int($months))
return null;
// Travel the specified number of months in time
if($this->modify($months . ' month') === false)
return null;
// Return this for method chaining
return $this;
}
/**
* Travel a month, or the specified number of months forward in time. A positive number of months will travel
* forward in time, while a negative number of months travels backward.
*
* @param int $months [optional] The number of months to travel forward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function addMonth($months = 1) {
return $this->addMonths($months);
}
/**
* Travel the specified number of months backward in time. A positive number of months will travel backward in
* time, while a negative number of months travels forward.
*
* @param int $months The number of months to travel backward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function subMonths($months) {
return $this->addMonths($months * -1);
}
/**
* Travel a month, or the specified number of months backward in time. A positive number of months will travel
* backward in time, while a negative number of months will travel forward.
*
* @param int $months [optional] The number of months to travel backward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function subMonth($months = 1) {
return $this->subtractMonths($months);
}
/**
* Travel the specified number of days forward in time. A positive number of days will travel forward in time,
* while a negative number of days travels backward.
*
* @param int $days The number of days to travel forward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function addDays($days) {
// Make sure the days value is an integer
if(!is_int($days))
return null;
// Travel the specified number of days in time
if($this->modify($days . ' day') === false)
return null;
// Return this for method chaining
return $this;
}
/**
* Travel a day, or the specified number of days forward in time. A positive number of days will travel forward in
* time, while a negative number of days travels backward.
*
* @param int $days [optional] The number of days to travel forward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function addDay($days = 1) {
return $this->addDays($days);
}
/**
* Travel the specified number of days backward in time. A positive number of days will travel backward in time,
* while a negative number of days travels forward.
*
* @param int $days The number of days to travel backward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function subDays($days) {
return $this->addDays($days * -1);
}
/**
* Travel a day, or the specified number of days backward in time. A positive number of days will travel backward
* in time, while a negative number of days will travel forward.
*
* @param int $days [optional] The number of days to travel backward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function subDay($days = 1) {
return $this->subtractDays($days);
}
/**
* Travel the specified number of weekdays forward in time. A positive number of weekdays will travel forward in
* time, while a negative number of weekdays travels backward.
*
* @param int $weekdays The number of weekdays to travel forward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function addWeekdays($weekdays) {
// Make sure the weekdays value is an integer
if(!is_int($weekdays))
return null;
// Travel the specified number of weekdays in time
if($this->modify($weekdays . ' weekday') === false)
return null;
// Return this for method chaining
return $this;
}
/**
* Travel a weekday, or the specified number of weekdays forward in time. A positive number of weekdays will travel
* forward in time, while a negative number of weekdays travels backward.
*
* @param int $weekdays [optional] The number of weekdays to travel forward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function addWeekday($weekdays = 1) {
return $this->addWeekdays($weekdays);
}
/**
* Travel the specified number of weekdays backward in time. A positive number of weekdays will travel backward in
* time, while a negative number of weekdays travels forward.
*
* @param int $weekdays The number of weekdays to travel backward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function subWeekdays($weekdays) {
return $this->addWeekdays($weekdays * -1);
}
/**
* Travel a weekday, or the specified number of weekdays backward in time. A positive number of weekdays will
* travel backward in time, while a negative number of weekdays will travel forward.
*
* @param int $weekdays [optional] The number of weekdays to travel backward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function subWeekday($weekdays = 1) {
return $this->subtractWeekdays($weekdays);
}
/**
* Travel the specified number of weeks forward in time. A positive number of weeks will travel forward in time,
* while a negative number of weeks travels backward.
*
* @param int $weeks The number of weeks to travel forward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function addWeeks($weeks) {
// Make sure the weeks value is an integer
if(!is_int($weeks))
return null;
// Travel the specified number of weeks in time
if($this->modify($weeks . ' week') === false)
return null;
// Return this for method chaining
return $this;
}
/**
* Travel a week, or the specified number of weeks forward in time. A positive number of weeks will travel forward
* in time, while a negative number of weeks travels backward.
*
* @param int $weeks [optional] The number of weeks to travel forward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function addWeek($weeks = 1) {
return $this->addWeeks($weeks);
}
/**
* Travel the specified number of weeks backward in time. A positive number of weeks will travel backward in time,
* while a negative number of weeks travels forward.
*
* @param int $weeks The number of weeks to travel backward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function subWeeks($weeks) {
return $this->addWeeks($weeks * -1);
}
/**
* Travel a week, or the specified number of weeks backward in time. A positive number of weeks will travel
* backward in time, while a negative number of weeks will travel forward.
*
* @param int $weeks [optional] The number of weeks to travel backward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function subWeek($weeks = 1) {
return $this->subtractWeeks($weeks);
}
/**
* Travel the specified number of hours forward in time. A positive number of hours will travel forward in time,
* while a negative number of hours travels backward.
*
* @param int $hours The number of hours to travel forward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function addHours($hours) {
// Make sure the hours value is an integer
if(!is_int($hours))
return null;
// Travel the specified number of hours in time
if($this->modify($hours . ' hour') === false)
return null;
// Return this for method chaining
return $this;
}
/**
* Travel a hour, or the specified number of hours forward in time. A positive number of hours will travel forward
* in time, while a negative number of hours travels backward.
*
* @param int $hours [optional] The number of hours to travel forward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function addHour($hours = 1) {
return $this->addHours($hours);
}
/**
* Travel the specified number of hours backward in time. A positive number of hours will travel backward in time,
* while a negative number of hours travels forward.
*
* @param int $hours The number of hours to travel backward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function subHours($hours) {
return $this->addHours($hours * -1);
}
/**
* Travel a hour, or the specified number of hours backward in time. A positive number of hours will travel
* backward in time, while a negative number of hours will travel forward.
*
* @param int $hours [optional] The number of hours to travel backward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function subHour($hours = 1) {
return $this->subtractHours($hours);
}
/**
* Travel the specified number of minutes forward in time. A positive number of minutes will travel forward in
* time, while a negative number of minutes travels backward.
*
* @param int $minutes The number of minutes to travel forward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function addMinutes($minutes) {
// Make sure the minutes value is an integer
if(!is_int($minutes))
return null;
// Travel the specified number of minutes in time
if($this->modify($minutes . ' minute') === false)
return null;
// Return this for method chaining
return $this;
}
/**
* Travel a minute, or the specified number of minutes forward in time. A positive number of minutes will travel
* forward in time, while a negative number of minutes travels backward.
*
* @param int $minutes [optional] The number of minutes to travel forward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function addMinute($minutes = 1) {
return $this->addMinutes($minutes);
}
/**
* Travel the specified number of minutes backward in time. A positive number of minutes will travel backward in
* time, while a negative number of minutes travels forward.
*
* @param int $minutes The number of minutes to travel backward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function subMinutes($minutes) {
return $this->addMinutes($minutes * -1);
}
/**
* Travel a minute, or the specified number of minutes backward in time. A positive number of minutes will travel
* backward in time, while a negative number of minutes will travel forward.
*
* @param int $minutes [optional] The number of minutes to travel backward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function subMinute($minutes = 1) {
return $this->subtractMinutes($minutes);
}
/**
* Travel the specified number of seconds forward in time. A positive number of seconds will travel forward in
* time, while a negative number of seconds travels backward.
*
* @param int $seconds The number of seconds to travel forward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function addSeconds($seconds) {
// Make sure the seconds value is an integer
if(!is_int($seconds))
return null;
// Travel the specified number of seconds in time
if($this->modify($seconds . ' second') === false)
return null;
// Return this for method chaining
return $this;
}
/**
* Travel a second, or the specified number of seconds forward in time. A positive number of seconds will travel
* forward in time, while a negative number of seconds travels backward.
*
* @param int $seconds [optional] The number of seconds to travel forward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function addSecond($seconds = 1) {
return $this->addSeconds($seconds);
}
/**
* Travel the specified number of seconds backward in time. A positive number of seconds will travel backward in
* time, while a negative number of seconds travels forward.
*
* @param int $seconds The number of seconds to travel backward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function subSeconds($seconds) {
return $this->addSeconds($seconds * -1);
}
/**
* Travel a second, or the specified number of seconds backward in time. A positive number of seconds will travel
* backward in time, while a negative number of seconds will travel forward.
*
* @param int $seconds [optional] The number of seconds to travel backward in time.
*
* @return DateTime|null The DateTime instance for method chaining, or null on failure.
*/
public function subSecond($seconds = 1) {
return $this->subtractSeconds($seconds);
}
/**
* Get the difference between this and another date and time object.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() date and time.
* @param bool $absolute
*
* @return \DateInterval|null The difference as DateInterval or null on failure.
*/
// TODO: Return the CarbonCMS DateInterval here!
public function diff($dateTime = null, $absolute = true) {
// Parse the date and time, return null on failure
if(($dateTime = static::parse($dateTime, $this->getTimezone())) === null)
return null;
// TODO: Return a CarbonCMS DateInterval instance!
// Call the parent method and return the result, return null on failure
return ($diff = parent::diff($dateTime, $absolute)) === false ? null : $diff;
}
/**
* Get the difference by the given interval using a filter closure.
* The callback will be called for each period in the given time frame. If the callback returns true the period is
* included as difference, false should be returned otherwise.
*
* @param DateInterval $dateInterval An interval to traverse by.
* @param Closure $callback The callback function to call for each period as filter.
* @param DateTime|PHPDateTime|string|null $dateTime [optional] The DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() date and time.
* @param boolean $absolute [optional] True to get the absolute difference, false otherwise.
*
* @return int|null The difference of the date interval in the given time frame. Null will be returned on failure.
*/
public function diffFiltered($dateInterval, Closure $callback, $dateTime = null, $absolute = true) {
// TODO: Parse the date interval!
// Parse the date and time, return null on failure
if(($dateTime = static::parse($dateTime, $this->getTimezone())) === null)
return null;
// Define the start and end times, define whether the value should be inverted
$inverse = !$this->isLessThan($dateTime);
$start = $inverse ? $this : $dateTime;
$end = $inverse ? $dateTime : $start;
// Run the callback for all periods
$period = new DatePeriod($start, $dateInterval, $end);
$values = array_filter(iterator_to_array($period), function (DateTime $date) use ($callback) {
return call_user_func($callback, self::instance($date));
});
// Get the difference result
$diff = count($values);
// Return the difference result, inverse the value if needed
return $inverse && !$absolute ? ($diff * -1) : $diff;
}
/**
* Get the difference between this and the specified date in years.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() date and time.
* @param boolean $absolute [optional] Get the absolute of the difference in years.
*
* @return int|null The difference in years or null on failure.
*/
public function diffInYears($dateTime = null, $absolute = true) {
// Parse the date and time, return null on failure
if(($dateTime = static::parse($dateTime, $this->getTimezone())) === null)
return null;
// Get the difference and make sure it's valid
if(($difference = $this->diff($dateTime, $absolute)) === false)
return null;
// Get and return the difference in years
return (int) $difference->format('%r%y');
}
/**
* Get the difference between this and the specified date in months.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() date and time.
* @param boolean $absolute [optional] Get the absolute of the difference in months.
*
* @return int|null The difference in months or null on failure.
*/
public function diffInMonths($dateTime = null, $absolute = true) {
// Parse the date and time, return null on failure
if(($dateTime = static::parse($dateTime, $this->getTimezone())) === null)
return null;
// Get the differences and make sure it's valid
if(($differenceYears = $this->diffInYears($dateTime, $absolute)) === null)
return null;
if(($difference = $this->diff($dateTime, $absolute)) === false)
return null;
// Get and return the difference in months
return $differenceYears * static::MONTHS_PER_YEAR + (int) $difference->format('%r%m');
}
/**
* Get the difference between this and the specified date in weeks.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() date and time.
* @param boolean $absolute [optional] Get the absolute of the difference in weeks.
*
* @return int|null The difference in weeks or null on failure.
*/
public function diffInWeeks($dateTime = null, $absolute = true) {
// Get the difference in days, and make sure it's valid
if(($differenceDays = $this->diffInDays($dateTime, $absolute)) === null)
return null;
// Get and return the difference in weeks
return (int) ($differenceDays / static::DAYS_PER_WEEK);
}
/**
* Get the difference in weekdays.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() date and time.
* @param boolean $absolute Get the absolute of the difference.
*
* @return int The difference in weekdays, or null on failure.
*/
public function diffInWeekdays($dateTime = null, $absolute = true) {
return $this->diffInDaysFiltered(function (DateTime $date) {
return $date->isWeekday();
}, $dateTime, $absolute);
}
/**
* Get the difference in weekend days.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() date and time.
* @param boolean $absolute Get the absolute of the difference.
*
* @return int The difference in weekend days, or null on failure.
*/
public function diffInWeekendDays($dateTime = null, $absolute = true) {
return $this->diffInDaysFiltered(function (DateTime $date) {
return $date->isWeekend();
}, $dateTime, $absolute);
}
/**
* Get the difference between this and the specified date in days.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() date and time.
* @param boolean $absolute [optional] Get the absolute of the difference in days.
*
* @return int|null The difference in days or null on failure.
*/
public function diffInDays($dateTime = null, $absolute = true) {
// Parse the date and time, return null on failure
if(($dateTime = static::parse($dateTime, $this->getTimezone())) === null)
return null;
// Get the difference and make sure it's valid
if(($difference = $this->diff($dateTime, $absolute)) === false)
return null;
// Get and return the difference in days
return (int) $difference->format('%r%a');
}
/**
* Get the difference in days using a filter closure
*
* @param Closure $callback The callback function to call for each day as filter.
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() date and time.
* @param boolean $absolute Get the absolute of the difference.
*
* @return int|null The difference in days. Null will be returned on failure.
*/
public function diffInDaysFiltered(Closure $callback, $dateTime = null, $absolute = true) {
return $this->diffFiltered(DateInterval::day(), $callback, $dateTime, $absolute);
}
/**
* Get the difference between this and the specified date in hours.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() date and time.
* @param boolean $absolute [optional] Get the absolute of the difference in hours.
*
* @return int|null The difference in hours or null on failure.
*/
public function diffInHours($dateTime = null, $absolute = true) {
// Parse the date and time, return null on failure
if(($dateTime = static::parse($dateTime, $this->getTimezone())) === null)
return null;
// Get the difference in seconds and make sure it's valid
if(($differenceSeconds = $this->diffInSeconds($dateTime, $absolute)) === null)
return null;
// Get and return the difference in hours
return (int) ($differenceSeconds / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR);
}
/**
* Get the difference in hours using a filter closure
*
* @param Closure $callback The callback function to call for each hour as filter.
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() date and time.
* @param boolean $absolute Get the absolute of the difference.
*
* @return int|null The difference in hours. Null will be returned on failure.
*/
public function diffInHoursFiltered(Closure $callback, $dateTime = null, $absolute = true) {
return $this->diffFiltered(DateInterval::hour(), $callback, $dateTime, $absolute);
}
/**
* Get the difference between this and the specified date in minutes.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() date and time.
* @param boolean $absolute [optional] Get the absolute of the difference in minutes.
*
* @return int|null The difference in minutes or null on failure.
*/
public function diffInMinutes($dateTime = null, $absolute = true) {
// Parse the date and time, return null on failure
if(($dateTime = static::parse($dateTime, $this->getTimezone())) === null)
return null;
// Get the difference in seconds, and make sure it's valid
if(($differenceSeconds = $this->diffInSeconds($dateTime, $absolute)) === null)
return null;
// Get and return the difference in minutes
return (int) ($differenceSeconds / static::SECONDS_PER_MINUTE);
}
/**
* Get the difference between this and the specified date in seconds.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() date and time.
* @param boolean $absolute [optional] Get the absolute of the difference in seconds.
*
* @return int|null The difference in seconds or null on failure.
*/
public function diffInSeconds($dateTime = null, $absolute = true) {
// Parse the date and time, return null on failure
if(($dateTime = static::parse($dateTime, $this->getTimezone())) === null)
return null;
// Calculate the timestamp difference
$timestampDifference = $dateTime->getTimestamp() - $this->getTimestamp();
// Return the result in absolute or regular form
return $absolute ? abs($timestampDifference) : $timestampDifference;
}
/**
* Get the number of seconds since midnight.
*
* @return int The number of seconds.
*/
public function secondsSinceMidnight() {
return $this->diffInSeconds($this->copy()->startOfDay());
}
/**
* Get the number of seconds until the end of the day, which is 23:23:59.
*
* @return int The number of seconds.
*/
public function secondsUntilEndOfDay() {
return $this->diffInSeconds($this->copy()->endOfDay());
}
// TODO: Should we add the diffForHumans(); method from Carbon DateTime, and their related methods?
/**
* Set the time to the start of the day, which is 00:00:00.
*
* @return static The DateTime instance.
*/
public function startOfDay() {
return $this->setHour(0)->setMinute(0)->setSecond(0);
}
/**
* Set the time to the end of the day, which is 23:59:59.
*
* @return static The DateTime instance.
*/
public function endOfDay() {
return $this->setHour(23)->setMinute(59)->setSecond(59);
}
/**
* Reset the date to the first day of the month and the time to the beginning of that day, which is 00:00:00.
*
* @return static The DateTime instance.
*/
public function startOfMonth() {
return $this->setDay(1)->startOfDay();
}
/**
* Resets the date to the last day of the month and the time to the end of that day, which is 23:59:59.
*
* @return static The DateTime instance.
*/
public function endOfMonth() {
return $this->setDay($this->daysInMonth)->endOfDay();
}
/**
* Resets the date to the start of the year and the time to the beginning of that day, which is 00:00:00.
*
* @return static The DateTime instance.
*/
public function startOfYear() {
return $this->setMonth(1)->startOfMonth();
}
/**
* Resets the date to the end of t he year and the time to the end of that day, which is 23:59:59.
*
* @return static The DateTime instance.
*/
public function endOfYear() {
return $this->setMonth(static::MONTHS_PER_YEAR)->endOfMonth();
}
/**
* Resets the date to the start of the decade and the time to the beginning of that day, which is 00:00:00.
*
* @return static The DateTime instance.
*/
public function startOfDecade() {
return $this->startOfYear()->setYear($this->year - ($this->year % static::YEARS_PER_DECADE));
}
/**
* Resets the date to the end of the decade and the time to the end of that day, which is 23:59:59.
*
* @return static
*/
public function endOfDecade() {
return $this->endOfYear()->setYear($this->year -
($this->year % static::YEARS_PER_DECADE + static::YEARS_PER_DECADE - 1));
}
/**
* Resets the date to the start of the century and the time to the beginning of that day, which is 00:00:00.
*
* @return static The DateTime instance.
*/
public function startOfCentury() {
return $this->startOfYear()->setYear($this->year - ($this->year % static::YEARS_PER_CENTURY));
}
/**
* Resets the date to the end of the century and the time to the end of that day, which is 23:59:59.
*
* @return static The DateTime instance.
*/
public function endOfCentury() {
return $this->endOfYear()->setYear($this->year -
($this->year % static::YEARS_PER_CENTURY + static::YEARS_PER_CENTURY - 1));
}
/**
* Resets the date to the first day of the ISO-8601 week (Monday) and the time to the beginning of that day, which
* is 00:00:00.
*
* @return static The DateTime instance.
*/
public function startOfWeek() {
// Set the date to the first day of the week
if($this->dayOfWeek != static::MONDAY)
$this->previous(static::MONDAY);
// Set the time to the start of the day
return $this->startOfDay();
}
/**
* Resets the date to the end of the ISO-8601 week (Sunday) and time the end of that day, which is 23:59:59.
*
* @return static The DateTime instance.
*/
public function endOfWeek() {
// Set the date to the last day of the week
if($this->dayOfWeek != static::SUNDAY)
$this->next(static::SUNDAY);
// Set the time to the end of the day
return $this->endOfDay();
}
/**
* Modify to the next occurrence of a given day of the week. If no specific day is provided, the next occurrence of
* the current day of the week is used. This will also reset the time to the start of that day.
*
* @param int|null $dayOfWeek [optional] The day of the week, using the day constants such as static::SUNDAY. Or
* null to get the next occurrence of the current day.
*
* @return static The DateTime instance.
*/
public function next($dayOfWeek = null) {
// Use the current day of the week if none was provided
if($dayOfWeek === null)
$dayOfWeek = $this->dayOfWeek;
// Find the next occurrence of the day of the week, and return the result
return $this->modify('next ' . static::$DAY_NAMES[$dayOfWeek])->startOfDay();
}
/**
* Modify to the previous occurrence of a given day of the week. If no specific day is provided, the previous
* occurrence of the current day of the week is used. This will also reset the time to the start of that day.
*
* @param int|null $dayOfWeek [optional] The day of the week, using the day constants such as static::SUNDAY. Or
* null to get the previous occurrence of the current day.
*
* @return static The DateTime instance.
*/
public function previous($dayOfWeek = null) {
// Use the current day of the week if none was provided
if($dayOfWeek === null)
$dayOfWeek = $this->dayOfWeek;
// Find the previous occurrence of the day of the week, and return the result
return $this->modify('last ' . static::$DAY_NAMES[$dayOfWeek])->startOfDay();
}
/**
* Modify to the first occurrence of a given day of the week. If no specific day is provided, the first day of the
* month is used. This will also reset the time to the start of that day.
*
* @param int|null $dayOfWeek [optional] The day of the week, using the day constants such as static::SUNDAY. Or
* null to get the first day of the month.
*
* @return static|null The DateTime instance, or null on failure.
*/
public function firstOfMonth($dayOfWeek = null) {
// Use the first day of the week if none was provided
if($dayOfWeek === null)
return $this->setDay(1)->startOfDay();
// Get the first day occurrence in the month, and make sure it's valid
if(($dateTime = $this->modify('first ' . static::$DAY_NAMES[$dayOfWeek] . ' of ' . $this->format('F') . ' ' .
$this->year)) === null
)
return null;
// Parse the date and time
if(($dateTime = static::parse($dateTime)) === null)
return null;
// Set the time to the start of the day and return the result
return $dateTime->startOfDay();
}
/**
* Modify to the last occurrence of a given day of the week. If no specific day is provided, the last day of the
* month is used. This will also reset the time to the start of that day.
*
* @param int|null $dayOfWeek [optional] The day of the week, using the day constants such as static::SUNDAY. Or
* null to get the first day of the month.
*
* @return static The DateTime instance.
*/
public function lastOfMonth($dayOfWeek = null) {
// Use the last day of the month if none was provided
if($dayOfWeek === null)
return $this->setDay($this->daysInMonth);
// Get the last day occurrence in the month
$dateTime =
$this->modify('last ' . static::$DAY_NAMES[$dayOfWeek] . ' of ' . $this->format('F') . ' ' . $this->year);
// Parse the date and time
if(($dateTime = static::parse($dateTime)) === null)
return null;
// Set the time to the start of the day and return the result
return $dateTime->startOfDay();
}
/**
* Modify to the given occurrence of a given day of the week in the current month.
* If the given day is outside the current month no modifications are made an null is returned.
* This will also reset the time to the beginning of the day.
*
* @param int $nth The occurrence of the day of the week.
* @param int $dayOfWeek The day of the week, using the day constants such as static::SUNDAY.
*
* @return static|null The DateTime instance, or null on failure.
*/
public function nthOfMonth($nth, $dayOfWeek) {
// Get a copy of the date and time set to the first day of the month
$dateTime = $this->copy()->firstOfMonth();
// Store the year and month, to use for checking later
$check = $dateTime->format('Y-m');
// Add the number of days to the date and time
if($dateTime->modify('+' . $nth . ' ' . static::$DAY_NAMES[$dayOfWeek]) === null)
return null;
// Make sure the year and month are still the same
if($dateTime->format('Y-m') !== $check)
return null;
// Modify and return the date and time
return $this->modify($dateTime);
}
/**
* Modify to the first occurrence of a given day of the week in the current quarter. If no day of the week if
* provided, modify to the first day of the current quarter. This will also reset the time to the beginning of that
* day.
*
* @param int|null $dayOfWeek [optional] The day of the week, using the day constants such as static::SUNDAY. Or
* null to get the first day of the current quarter.
*
* @return static|null The DateTime instance, or null on failure.
*/
public function firstOfQuarter($dayOfWeek = null) {
return $this->setDay(1)->setMonth($this->quarter * 3 - 2)->firstOfMonth($dayOfWeek);
}
/**
* Modify to the last occurrence of the given day of the week in the current quarter. If no day of the week is
* provided, modify to the first day of the current quarter. This will also reset the time to the beginning of that
* day.
*
* @param int|null $dayOfWeek [optional] The day of the week, using day constants such as static::SUNDAY. Or null
* to get the last day of the current quarter.
*
* @return static|null The DateTime instance, or null on failure.
*/
public function lastOfQuarter($dayOfWeek = null) {
return $this->setDay(1)->setMonth($this->quarter * 3)->lastOfMonth($dayOfWeek);
}
/**
* Modify to the given occurrence of a given day of the week in the current quarter.
* If the given day is outside the current quarter no modifications are made an null is returned.
* This will also reset the time to the beginning of that day.
*
* @param int $nth The occurrence of the day of the week.
* @param int $dayOfWeek The day of the week, using the day constants such as static::SUNDAY.
*
* @return static|null The DateTime instance, or null on failure.
*/
public function nthOfQuarter($nth, $dayOfWeek) {
// Get a copy of the date and time set to the first day of the month
$dateTime = $this->copy()->setDay(1)->setMonth($this->quarter * 3);
// Get the last month and the year of the quarter
$last_month = $dateTime->getMonth();
$year = $dateTime->getYear();
// Get the nth occurrence of the day of the week in this quarter
// TODO: Why is the modify method not recognized?
$dateTime->firstOfQuarter()->modify('+' . $nth . ' ' . static::$DAY_NAMES[$dayOfWeek]);
// Make sure the date is not outside the current quarter
if($last_month < $dateTime->getMonth() || $year !== $dateTime->getYear())
return null;
// Modify the date and time, return the result
return $this->modify($dateTime);
}
/**
* Modify to the first occurrence of a given day of the week in the current year. If no day of the week is provided
* the first day of the year is used. This will also reset the time to the beginning of that day.
*
* @param int|null $dayOfWeek [optional] The day of the week, using day constants such as static::SUNDAY. Or null
* to get the first day of the current year.
*
* @return static|null The DateTime instance, or null on failure.
*/
public function firstOfYear($dayOfWeek = null) {
return $this->setMonth(1)->firstOfMonth($dayOfWeek);
}
/**
* Modify to the last occurrence of a given day of the week in the current year. If no day of the week is provided
* the last day of the year is used. This will also reset the time to the beginning of that day.
*
* @param int|null $dayOfWeek [optional] The day of the week, using day constants such as static::SUNDAY. Or null
* to get the last day of the current year.
*
* @return static|null The DateTime instance, or null on failure.
*/
public function lastOfYear($dayOfWeek = null) {
return $this->setMonth(static::MONTHS_PER_YEAR)->lastOfMonth($dayOfWeek);
}
/**
* Modify to the given occurrence of a given day of the week in the current year.
* If the given day is outside the current year no modifications are made an null is returned.
* This will also reset the time to the beginning of that day.
*
* @param int $nth The occurrence of the day of the week.
* @param int $dayOfWeek The day of the week, using the day constants such as static::SUNDAY.
*
* @return static|null The DateTime instance, or null on failure.
*/
public function nthOfYear($nth, $dayOfWeek) {
// Create a copy of the date and time, and get the nth day of the week
$dateTime = $this->copy()->firstOfYear()->modify('+' . $nth . ' ' . static::$DAY_NAMES[$dayOfWeek]);
// Make sure the date isn't outside the current year
if($this->year != $dateTime->year)
return null;
// Modify and return the date and time
return $this->modify($dateTime);
}
/**
* Get the age of the date and time compared to the current date and time specified by the now() method.
*
* @return int The age of the date and time.
*/
public function getAge() {
return $this->diffInYears(null, false);
}
/**
* Check if it's the birthday. This check whether the month and day are equal to the specified date and time.
*
* @param DateTime|PHPDateTime|string|null $birthday [optional] The DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() date and time.
*
* @return boolean True if it's the birthday, false otherwise. False is also returned on failure.
*/
public function isBirthday($birthday) {
// Parse the date and time, return null on failure
if(($birthday = static::parse($birthday, $this->getTimezone())) === null)
return null;
// Check whether the month and day are equal, return the result
return StringUtils::equals($this->format('md'), $birthday->format('md'));
}
/**
* Modify the date and time to the average of the date and time and the specified date and time.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] The DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() date and time.
*
* @return static|null The DateTime instance, or null on failure.
*/
public function average($dateTime = null) {
// Parse the date and time, return null on failure
if(($dateTime = static::parse($dateTime, $this->getTimezone())) === null)
return null;
// Calculate the difference in seconds and make sure it's valid
if(($differenceSeconds = $this->diffInSeconds($dateTime, false)) === null)
return null;
// Apply the average difference and return the result
return $this->addSeconds((int) ($differenceSeconds / 2));
}
/**
* Get the date and time as a string formatted according to given format.
*
* @param string|null $format [optional] The desired format for the date and time, or null to use the default
* format.
*
* @return string|null The date and time as a string, or null on failure.
*/
public function format($format = null) {
// Use the default format if the format parameter is null
if($format === null)
$format = self::DEFAULT_FORMAT;
// Get and return the date and time with the proper format, return null on failure
return ($result = parent::format($format)) === false ? null : $result;
}
/**
* Format the date and time as a string.
*
* @param string|null $format [optional] The format to return the date and time with as a string.
*
* @return string|null The date and time as a string, or null on failure.
*/
// TODO: Should we use some kind of human readable formatting, or should we create a different function for this?
public function toString($format = null) {
// Use the default format if it's set to null
if($format === null)
$format = static::DEFAULT_FORMAT;
// Get the date and time as a string with the proper format and return the result, return null on failure
return ($result = $this->format($format)) === false ? null : $result;
}
/**
* Format the date and time as a string.
*
* @return string The date and time as a string, with the default format.
*/
// TODO: To string for humans!
public function __toString() {
// Get the date and time as a string, return an empty string on failure
return ($result = $this->toString()) === null ? '' : $result;
}
/**
* Format the date as a string.
*
* @return string The date as a string.
*/
public function toDateString() {
return $this->format(static::DEFAULT_FORMAT_DATE);
}
/**
* Format the time as a string.
*
* @return string The time as a string.
*/
public function toTimeString() {
return $this->format(static::DEFAULT_FORMAT_TIME);
}
/**
* Convert the date and time into a string with complete formatting.
*
* @return string|null The date and time as a string, or null on failure.
*/
// TODO: Should we create a different method for this, or rename this method?
public function toCompleteString() {
return $this->toString(static::DEFAULT_FORMAT_COMPLETE);
}
}
<?php
/**
* DateTimeUtils.php
*
* A utilities class for the DateTime class.
*
* @author Tim Visee
* @website http://timvisee.com/
* @copyright Copyright (c) Carbon CMS 2015. All rights reserved.
*/
namespace carbon\core\datetime;
use carbon\core\datetime\interval\DateInterval;
use carbon\core\datetime\zone\DateTimeZone;
use Closure;
use DateTime as PHPDateTime;
use DateTimeZone as PHPDateTimeZone;
use InvalidArgumentException;
// Prevent direct requests to this set_file due to security reasons
defined('CARBON_CORE_INIT') or die('Access denied!');
/**
* A utilities class for the DateTime class.
*
* @package carbon\core\datetime
*/
class DateTimeUtils {
// TODO: Make sure all DateTime and PHPDateTime instances are correct!
/**
* Parse a date and time with an optional time zone. A new instance will be created if required.
*
* If the $dateTime parameter is a DateTime zone instance, the instance will be returned and the $timezone
* parameter is ignored. If the $dateTime parameter is anything other than a DateTime zone the date, time and the
* time zone is parsed through the constructor.
*
* This method allows better fluent syntax because it makes method chaining possible.
*
* @param DateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the time as a string, or
* null to use the now() time.
* @param DateTimeZone|PHPDateTimeZone|string|DateTime|PHPDateTime|null $timezone [optional] The time zone the
* specified time is in, or null to use the default time zone if the $time param isn't a DateTime instance. A
* DateTime or PHPDateTime instance to use it's timezone.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateTime|mixed The DateTime instance, or the default value on failure.
*
* @TODO Is this exception indeed thrown, or is it being catched?
* @throws InvalidArgumentException Throws an exception if the date and time couldn't be parsed.
*/
// TODO: Don't use exception catching!
public static function parse($dateTime = null, $timezone = null, $default = null) {
// Return the object if it's already a DateTime instance
if($dateTime instanceof DateTime)
return $dateTime;
// Parse and return the date and time, return the default value on failure
try {
return new DateTime($dateTime, $timezone);
} catch(InvalidArgumentException $ex) {
return $default;
}
}
/**
* Check whether the date and time specified by a equals b.
*
* @param DateTime|PHPDateTime|string|null $a [optional] The DateTime or PHPDateTime instance, the date and time as
* a string or null to use the now() time.
* @param DateTime|PHPDateTime|string|null $b [optional] The DateTime or PHPDateTime instance, the date and time as
* a string or null to use the now() time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool|mixed True if the date and time of a and b equals, false if not. The default value will be returned
* on failure.
*/
public static function equals($a = null, $b = null, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Compare a and b and return the result, return the default value on failure
return ($result = $a->equals($b)) === null ? $default : $result;
}
/**
* Check whether the date and time specified by a is greater than b.
*
* @param DateTime|PHPDateTime|string|null $a [optional] The DateTime or PHPDateTime instance, the date and time as
* a string or null to use the now() time.
* @param DateTime|PHPDateTime|string|null $b [optional] The DateTime or PHPDateTime instance, the date and time as
* a string or null to use the now() time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool|mixed True if the date and time of a is greater than b, false if not. The default value will be
* returned on failure.
*/
// TODO: Does this work, or should we compare the timestamps?
public static function isGreaterThan($a = null, $b = null, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Compare a and b and return the result, return the default value on failure
return ($result = $a->isGreaterThan($b)) === null ? $default : $result;
}
/**
* Check whether the date and time specified by a is greater or equal to b.
*
* @param DateTime|PHPDateTime|string|null $a [optional] The DateTime or PHPDateTime instance, the date and time as
* a string or null to use the now() time.
* @param DateTime|PHPDateTime|string|null $b [optional] The DateTime or PHPDateTime instance, the date and time as
* a string or null to use the now() time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool|mixed True if the date and time of a is greater or equal to b, false if not. The default value will
* be returned on failure.
*/
// TODO: Does this work, or should we compare the timestamps?
// TODO: Should we rename this to isGreaterThanOrEqualTo
public static function isGreaterOrEqualTo($a = null, $b = null, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Compare a and b and return the result, return the default value on failure
return ($result = $a->isGreaterOrEqualTo($b)) === null ? $default : $result;
}
/**
* Check whether the date and time specified by a is less than b.
*
* @param DateTime|PHPDateTime|string|null $a [optional] The DateTime or PHPDateTime instance, the date and time as
* a string or null to use the now() time.
* @param DateTime|PHPDateTime|string|null $b [optional] The DateTime or PHPDateTime instance, the date and time as
* a string or null to use the now() time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool|mixed True if the date and time of a is less than b, false if not. The default value will be
* returned on failure.
*/
// TODO: Does this work, or should we compare the timestamps?
public static function isLessThan($a = null, $b = null, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Compare a and b and return the result, return the default value on failure
return ($result = $a->isLessThan($b)) === null ? $default : $result;
}
/**
* Check whether the date and time specified by a is less or equal to b.
*
* @param DateTime|PHPDateTime|string|null $a [optional] The DateTime or PHPDateTime instance, the date and time as
* a string or null to use the now() time.
* @param DateTime|PHPDateTime|string|null $b [optional] The DateTime or PHPDateTime instance, the date and time as
* a string or null to use the now() time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool|mixed True if the date and time of a is less or equal b, false if not. The default value will be
* returned on failure.
*/
// TODO: Does this work, or should we compare the timestamps?
// TODO: Should we rename this to isLessThanOrEqualTo?
public static function isLessOrEqualTo($a = null, $b = null, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Compare a and b and return the result, return the default value on failure
return ($result = $a->isLessOrEqualTo($b)) === null ? $default : $result;
}
/**
* Check whether the specified date and time is between a and b.
* The $a and $b parameter may not be null at the same time or false will be returned.
*
* @param DateTime|PHPDateTime|string|null $dateTime The date and time that needs to be in between a and be as
* DateTime or PHPDateTime instance, the date and time as a string or null to use the now() value.
* @param DateTime|PHPDateTime|string|null $a The date and time as DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
* @param DateTime|PHPDateTime|string|null $b The date and time as DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
* @param bool $equals [optional] True to also return true if the date equals one of the specified date and times,
* false otherwise.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool|mixed True if the date is between the specified date and time, or if it equals one of the date and
* times while $equals is set to true, false if not. The default value will be returned on failure.
*/
public static function isBetween($dateTime = null, $a = null, $b = null, $equals = true, $default = null) {
// Parse the date and time, return the default value on failure
if(($dateTime = static::parse($dateTime)) === null)
return $default;
// Check whether the date and time is in between and return the result, return the default value on failure
return ($result = $dateTime->isBetween($a, $b, $equals)) === null ? $default : $result;
}
/**
* Get the greatest date and time of a and b. If both are equal, a will be returned.
*
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateTime|mixed The greatest DateTime instance, or the default value on failure.
*/
public static function max($a = null, $b = null, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Compare a and b and return the greatest, return the default value on failure
return ($result = $a->max($b)) === null ? $default : $result;
}
/**
* Get the lowest date and time of a and b. If both are equal, a will be returned.
*
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateTime|mixed The lowest DateTime instance, or the default value on failure.
*/
public static function min($a = null, $b = null, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Compare a and b and return the smallest, return the default value on failure
return ($result = $a->min($b)) === null ? $default : $result;
}
/**
* Check whether the specified date is a weekday (monday to friday).
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool|mixed True if this is a weekday, false if not. The default value will be returned on failure.
*/
public static function isWeekday($dateTime = null, $default = null) {
// Parse the date and time, return the default value on failure
if(($dateTime = static::parse($dateTime)) === null)
return $default;
// Check whether the specified date is a weekday, return the result
return $dateTime->isWeekday();
}
/**
* Check whether the specified date is a weekend day (saturday or sunday).
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool|mixed True if this is a weekend day, false if not. The default value on failure.
*/
public static function isWeekend($dateTime = null, $default = null) {
// Parse the date and time, return the default value on failure
if(($dateTime = static::parse($dateTime)) === null)
return $default;
// Check whether the specified date is in the weekend, return the result
return $dateTime->isWeekend();
}
/**
* Check whether the specified date is today.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool|mixed True if this is today, false if not. The default value will be returned on failure.
*/
public static function isToday($dateTime = null, $default = null) {
// Parse the date and time, return the default value on failure
if(($dateTime = static::parse($dateTime)) === null)
return $default;
// Check whether the specified date is today, return the result
return $dateTime->isToday();
}
/**
* Check whether the specified date is tomorrow.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool True if this is tomorrow, false if not. The default value will be returned on failure.
*/
public static function isTomorrow($dateTime = null, $default = null) {
// Parse the date and time, return the default value on failure
if(($dateTime = static::parse($dateTime)) === null)
return $default;
// Check whether the specified date is tomorrow, return the result
return $dateTime->isTomorrow();
}
/**
* Check whether the specified date is yesterday.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool true if this is yesterday, false if not. The default value will be returned on failure.
*/
public static function isYesterday($dateTime = null, $default = null) {
// Parse the date and time, return the default value on failure
if(($dateTime = static::parse($dateTime)) === null)
return $default;
// Check whether the specified date is yesterday, return the result
return $dateTime->isYesterday();
}
/**
* Check whether the specified date and time is in the future. If the date and time equals the now() date and time
* false is returned.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool True if this is in the future, false if not. The default value will be returned on failure.
*/
public static function isFuture($dateTime = null, $default = null) {
// Parse the date and time, return the default value on failure
if(($dateTime = static::parse($dateTime)) === null)
return $default;
// Check whether the specified date is in the future, return the result
return $dateTime->isFuture();
}
/**
* Check whether the specified date and time is in the past. If the date and time equals the now() date and time
* false is returned.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool True if this is in the past, false if not. The default value will be returned on failure.
*/
public static function isPast($dateTime = null, $default = null) {
// Parse the date and time, return the default value on failure
if(($dateTime = static::parse($dateTime)) === null)
return $default;
// Check whether the specified date is in the past, return the result
return $dateTime->isPast();
}
/**
* Check whether the specified date is a leap year.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool True if this is a leap year, false if not. The default value will be returned on failure.
*/
public static function isLeapYear($dateTime = null, $default = null) {
// Parse the date and time, return the default value on failure
if(($dateTime = static::parse($dateTime)) === null)
return $default;
// Check whether the specified date is a leap year, return the result
return $dateTime->isLeapYear();
}
/**
* Check whether the year of a and b is the same.
*
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool True if year is the same as the specified date, false otherwise. False will also be returned on
* failure.
*/
public function isSameYear($a = null, $b = null, $default = null) {
// Parse the date and time of a and b, return the default value on failure
if(($a = static::parse($a)) === null || ($b = static::parse($b)) === null)
return $default;
// Check whether the time of a and b is the same and return the result
return $a->isSameYear($b);
}
/**
* Check whether the month of a and b is the same.
*
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool True if month is the same as the specified date, false otherwise. False will also be returned on
* failure.
*/
public function isSameMonth($a = null, $b = null, $default = null) {
// Parse the date and time of a and b, return the default value on failure
if(($a = static::parse($a)) === null || ($b = static::parse($b)) === null)
return $default;
// Check whether the time of a and b is the same and return the result
return $a->isSameMonth($b);
}
/**
* Check whether the ISO-8601 week of a and b is the same.
*
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool True if the ISO-8601 week is the same as the specified date, false otherwise. False will also be
* returned on failure.
*/
public function isSameWeek($a = null, $b = null, $default = null) {
// Parse the date and time of a and b, return the default value on failure
if(($a = static::parse($a)) === null || ($b = static::parse($b)) === null)
return $default;
// Check whether the time of a and b is the same and return the result
return $a->isSameWeek($b);
}
/**
* Check whether the day of a and b is the same.
*
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool|mixed True if the date of a and b are the same, false if not. The default value will be returned on
* failure.
*/
public static function isSameDate($a = null, $b = null, $default = null) {
// Parse the date and time of a and b, return the default value on failure
if(($a = static::parse($a)) === null || ($b = static::parse($b)) === null)
return $default;
// Check whether the time of a and b is the same and return the result
return $a->isSameDate($b);
}
/**
* Check whether the hour of a and b is the same.
*
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() time.
* @param bool $checkDate [optional] True to make sure the dates are equal, false to just compare the time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool True if hour is the same as the specified date and time, false otherwise. False will also be
* returned on failure.
*/
public function isSameHour($a = null, $b = null, $checkDate = true, $default = null) {
// Parse the date and time of a and b, return the default value on failure
if(($a = static::parse($a)) === null || ($b = static::parse($b)) === null)
return $default;
// Check whether the time of a and b is the same and return the result
return $a->isSameHour($b, $checkDate);
}
/**
* Check whether the minute of a and b is the same.
*
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() time.
* @param bool $checkDate [optional] True to make sure the dates are equal, false to just compare the time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool True if minute is the same as the specified date and time, false otherwise. False will also be
* returned on failure.
*/
public function isSameMinute($a = null, $b = null, $checkDate = true, $default = null) {
// Parse the date and time of a and b, return the default value on failure
if(($a = static::parse($a)) === null || ($b = static::parse($b)) === null)
return $default;
// Check whether the time of a and b is the same and return the result
return $a->isSameMinute($b, $checkDate);
}
/**
* Check whether the time of a and b is the same.
*
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() time.
* @param bool $checkDate [optional] True to make sure the dates are equal, false to just compare the time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool True if time is the same as the specified date and time, false otherwise. False will also be
* returned on failure.
*/
public function isSameTime($a = null, $b = null, $checkDate = true, $default = null) {
// Parse the date and time of a and b, return the default value on failure
if(($a = static::parse($a)) === null || ($b = static::parse($b)) === null)
return $default;
// Check whether the time of a and b is the same and return the result
return $a->isSameTime($b, $checkDate);
}
/**
* Get the difference of a and b.
*
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param boolean $absolute [optional] Get the absolute of the difference in years.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return \DateInterval|mixed The difference of a and b, or the default value on failure.
*/
public static function diff($a = null, $b = null, $absolute = true, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// TODO: Return a Carbon CMS DateInterval instance!
// Get the difference of a and b and return the result, return the default value on failure
return ($result = $a->diff($b, $absolute)) === null ? $default : $result;
}
/**
* Get the difference of a and b by the given interval using a filter closure.
* The callback will be called for each period in the given time frame. If the callback returns true the period is
* included as difference, false should be returned otherwise.
*
* @param DateInterval $dateInterval An interval to traverse by.
* @param Closure $callback The callback function to call for each period as filter.
* @param DateTime|PHPDateTime|string|null $a [optional] The DateTime or PHPDateTime instance, the date and time as
* a string or null to use the now() date and time.
* @param DateTime|PHPDateTime|string|null $b [optional] The DateTime or PHPDateTime instance, the date and time as
* a string or null to use the now() date and time.
* @param boolean $absolute [optional] True to get the absolute difference, false otherwise.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return int|mixed The difference of the date interval in the given time frame. The default value will be
* returned on failure.
*/
public function diffFiltered($dateInterval, Closure $callback, $a = null, $b = null, $absolute = true,
$default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Call the difference filtered method on a and return the result, return the default value on failure
return ($result = $a->diffFiltered($dateInterval, $callback, $b, $absolute)) === null ? $default : $result;
}
/**
* Get the difference in years of a and b.
*
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param boolean $absolute [optional] Get the absolute of the difference in years.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return int|mixed The difference in years of a and b, or the default value on failure.
*/
public static function diffInYears($a = null, $b = null, $absolute = true, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Get the difference in years of a and b and return the result, return the default value on failure
return ($result = $a->diffInYears($b, $absolute)) === null ? $default : $result;
}
/**
* Get the difference in months of a and b.
*
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param boolean $absolute [optional] Get the absolute of the difference in months.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return int|mixed The difference in years of a and b, or the default value on failure.
*/
public static function diffInMonths($a = null, $b = null, $absolute = true, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Get the difference in months of a and b and return the result, return the default value on failure
return ($result = $a->diffInMonths($b, $absolute)) === null ? $default : $result;
}
/**
* Get the difference in weeks of a and b.
*
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param boolean $absolute [optional] Get the absolute of the difference in weeks.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return int|mixed The difference in years of a and b, or the default value on failure.
*/
public static function diffInWeeks($a = null, $b = null, $absolute = true, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Get the difference in weeks of a and b and return the result, return the default value on failure
return ($result = $a->diffInWeeks($b, $absolute)) === null ? $default : $result;
}
/**
* Get the difference in weekdays of a and b.
*
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param boolean $absolute Get the absolute of the difference.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return int The difference in weekdays, or the default value returned on failure.
*/
public function diffInWeekdays($a = null, $b = null, $absolute = true, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Get the difference in weekdays of a and b and return the result, return the default value on failure
return ($result = $a->diffInWeekdays($b, $absolute)) === null ? $default : $result;
}
/**
* Get the difference in weekend days of a and b.
*
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param boolean $absolute Get the absolute of the difference.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return int The difference in weekend days, or the default value returned on failure.
*/
public function diffInWeekendDays($a = null, $b = null, $absolute = true, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Get the difference in weekend days of a and b and return the result, return the default value on failure
return ($result = $a->diffInWeekendDays($b, $absolute)) === null ? $default : $result;
}
/**
* Get the difference in days of a and b.
*
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param boolean $absolute [optional] Get the absolute of the difference in days.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return int|mixed The difference in years of a and b, or the default value on failure.
*/
public static function diffInDays($a = null, $b = null, $absolute = true, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Get the difference in days of a and b and return the result, return the default value on failure
return ($result = $a->diffInDays($b, $absolute)) === null ? $default : $result;
}
/**
* Get the difference in days of a and b using a filter closure.
*
* @param Closure $callback The callback function to call for each day as filter.
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param boolean $absolute Get the absolute of the difference.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return int|null The difference in days. The default value will be returned on failure.
*/
public function diffInDaysFiltered(Closure $callback, $a = null, $b = null, $absolute = true, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Get the difference in days of a and b using a filter closure and return the result, return the default value on failure
return ($result = $a->diffInDaysFiltered($callback, $b, $absolute)) === null ? $default : $result;
}
/**
* Get the difference in hours of a and b.
*
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param boolean $absolute [optional] Get the absolute of the difference in hours.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return int|mixed The difference in years of a and b, or the default value on failure.
*/
public static function diffInHours($a = null, $b = null, $absolute = true, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Get the difference in hours of a and b and return the result, return the default value on failure
return ($result = $a->diffInHours($b, $absolute)) === null ? $default : $result;
}
/**
* Get the difference in hours of a and b using a filter closure.
*
* @param Closure $callback The callback function to call for each hour as filter.
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param boolean $absolute Get the absolute of the difference.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return int|null The difference in hours. The default value will be returned on failure.
*/
public function diffInHoursFiltered(Closure $callback, $a = null, $b = null, $absolute = true, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Get the difference in hours of a and b using a filter closure and return the result, return the default value on failure
return ($result = $a->diffInHoursFiltered($callback, $b, $absolute)) === null ? $default : $result;
}
/**
* Get the difference in minutes of a and b.
*
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param boolean $absolute [optional] Get the absolute of the difference in minutes.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return int|mixed The difference in years of a and b, or the default value on failure.
*/
public static function diffInMinutes($a = null, $b = null, $absolute = true, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Get the difference in minutes of a and b and return the result, return the default value on failure
return ($result = $a->diffInMinutes($b, $absolute)) === null ? $default : $result;
}
/**
* Get the difference in seconds of a and b.
*
* @param DateTime|PHPDateTime|string|null $a [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param DateTime|PHPDateTime|string|null $b [optional] A DateTime or PHPDateTime instance, the date and time as a
* string or null to use the now() date and time.
* @param boolean $absolute [optional] Get the absolute of the difference in seconds.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return int|mixed The difference in years of a and b, or the default value on failure.
*/
public static function diffInSeconds($a = null, $b = null, $absolute = true, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Get the difference in seconds of a and b and return the result, return the default value on failure
return ($result = $a->diffInSeconds($b, $absolute)) === null ? $default : $result;
}
/**
* Get the number of seconds since midnight of the specified date and time.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as string or null to use the now() date and time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return int|mixed The number of seconds or the default value on failure.
*/
public static function secondsSinceMidnight($dateTime = null, $default = null) {
// Parse the date and time, return the default value on failure
if(($dateTime = static::parse($dateTime)) === null)
return $default;
// Get and return the number of seconds since midnight
return $dateTime->secondsSinceMidnight();
}
/**
* Get the number of seconds of the specified date and time until the end of the day, which is 23:23:59.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] A DateTime or PHPDateTime instance, the date and
* time as string or null to use the now() date and time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return int|mixed The number of seconds until the end of the day, or the default value on failure.
*/
public static function secondsUntilEndOfDay($dateTime = null, $default = null) {
// Parse the date and time, return the default value on failure
if(($dateTime = static::parse($dateTime)) === null)
return $default;
// Get and return the number of seconds since midnight
return $dateTime->secondsUntilEndOfDay();
}
/**
* Get the age of the specified date and time compared to the current date and time specified by the now() method.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] The DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() date and time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return int|mixed The age of the date and time, or the default value on failure.
*/
public function getAge($dateTime = null, $default = null) {
// Parse the date and time, return the default value on failure
if(($dateTime = static::parse($dateTime)) === null)
return $default;
// Get the age, return the default value on failure
if(($age = $dateTime->getAge()) === null)
return $default;
// Return the age
return $age;
}
/**
* Check whether it's the birthday of the specified date and time. This compares the month and day of both dates.
*
* @param DateTime|PHPDateTime|string|null $dateTime [optional] The DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() date and time.
* @param DateTime|PHPDateTime|string|null $birthday [optional] The DateTime or PHPDateTime instance, the date and
* time as a string or null to use the now() date and time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return boolean True if it's the birthday, false if not. The default value will be returned on failure.
*/
public static function isBirthday($dateTime = null, $birthday = null, $default = null) {
// Parse the date and time, return the default value on failure
if(($dateTime = static::parse($dateTime)) === null)
return $default;
// Check whether it's the birthday of the specified date and time and return the result, return the default value on failure
return ($result = $dateTime->isBirthday($birthday)) === null ? $default : $result;
}
/**
* Get the average in date and time of a and b. A new DateTime instance is returned with the average date and time.
*
* @param DateTime|PHPDateTime|string|null $a [optional] The DateTime or PHPDateTime instance, the date and time as
* a string or null to use the now() date and time.
* @param DateTime|PHPDateTime|string|null $b [optional] The DateTime or PHPDateTime instance, the date and time as
* a string or null to use the now() date and time.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateTime|mixed The average as DateTime instance, or the default value on failure.
*/
public static function average($a = null, $b = null, $default = null) {
// Parse the date and time of a, return the default value on failure
if(($a = static::parse($a)) === null)
return $default;
// Get the average date and time of a and b and return the result, return the default value on failure
return ($result = $a->copy()->average($b)) === null ? $default : $result;
}
}
<?php
namespace carbon\core\datetime\interval;
use carbon\core\datetime\DateTime;
use carbon\core\datetime\interval\spec\DateIntervalSpecUtils;
use DateInterval as PHPDateInterval;
use DomainException;
use Exception;
use InvalidArgumentException;
// Prevent direct requests to this set_file due to security reasons
defined('CARBON_CORE_INIT') or die('Access denied!');
/**
* Class DateInterval
*
* @package carbon\core\datetime
*
* @TODO Update these properties below!
* @TODO Rename this to 'daysOfWeek'?
*
* property-read int $daysExcludeWeeks Total days remaining in the final week of the current instance (days % 7).
*/
class DateInterval extends PHPDateInterval {
// TODO: Should we create a DateDuration class which is similar to this class?
// TODO: Throw better exceptions!
// TODO: Create array utils!
/**
* The date interval specification prefix designator.
*
* @const string The period prefix.
*/
const PERIOD_PREFIX = 'P';
/**
* The date interval specification year designator.
*
* @const string The year prefix.
*/
const PERIOD_YEARS = 'Y';
/**
* The date interval specification month designator.
*
* @const string The month prefix.
*/
const PERIOD_MONTHS = 'M';
/**
* The date interval specification day designator.
*
* @const string The day prefix.
*/
const PERIOD_DAYS = 'D';
/**
* The date interval specification time designator.
*
* @const string The time prefix.
*/
const PERIOD_TIME_PREFIX = 'T';
/**
* The date interval specification hour designator.
*
* @const string The hour prefix.
*/
const PERIOD_HOURS = 'H';
/**
* The date interval specification minute designator.
*
* @const string The minute prefix.
*/
const PERIOD_MINUTES = 'M';
/**
* The date interval specification second designator.
*
* @const string The second prefix.
*/
const PERIOD_SECONDS = 'S';
/**
* Constructor.
*
* @param string|PHPDateInterval|PHPDateInterval|null $dateIntervalSpec [optional] A date interval specification, a
* relative date and time string, a DateInterval or PHPDateInterval instance, or null to use a zero specification.
* @param bool $inverted [optional] Defines whether the date interval specification is inverted or not, this
* parameter is ignored if a DateInterval or PHPDateInterval instance is given for the $dateIntervalSpec
* parameter.
*
* @throws Exception Throws an exception on failure.
*/
public function __construct($dateIntervalSpec, $inverted = false) {
// Try to parse the date interval specification
if(($spec = DateIntervalSpecUtils::parse($dateIntervalSpec, null)) === null)
throw new Exception('Invalid date interval specification (\'' . $dateIntervalSpec . '\' was given)');
// Copy the inverted state from DateInterval objects
if($dateIntervalSpec instanceof parent)
$inverted = $dateIntervalSpec->invert;
// Construct the parent object, and set whether the date interval is inverted
parent::__construct($spec);
$this->setInverted($inverted);
}
/**
* Parse a date interval. A new instance may be created.
*
* This method allows better fluent syntax because it makes method chaining possible.
*
* @param PHPDateInterval|PHPDateInterval|string|null $dateInterval [optional] A DateInterval or PHPDateInterval
* instance, a date interval specification, or null to use a zero specification.
*
* @return static A DateInterval instance, or null on failure.
*/
public static function parse($dateInterval) {
// Return the object if it's already a DateInterval instance
if($dateInterval instanceof self)
return $dateInterval;
// Return a zero specification if the specification is set to null
if($dateInterval === null)
return DateIntervalFactory::zero();
// Parse DateInterval objects
if($dateInterval instanceof DateInterval)
return $dateInterval;
// Parse PHPDateInterval objects
if($dateInterval instanceof PHPDateInterval)
return new static($dateInterval, $dateInterval->invert);
// Try to parse the string as date interval specification, return null on failure
if(($dateIntervalSpec = DateIntervalSpecUtils::parse($dateInterval, null)) !== null)
// Create and return a new date interval instance based on the parsed specification
return new static($dateIntervalSpec);
// Couldn't parse the date interval instance, return null
return null;
}
/**
* Create a DateInterval instance based on the relative parts of the string.
*
* @param string $dateInterval The string with the relative parts for the date interval.
*
* @return DateInterval The DateInterval instance, may be zero if the string doesn't have any relative parts.
*
* @throw DomainException Throws an exception if the date interval specification isn't a string.
*/
// TODO: Make a static version of this method in the utilities class!
// TODO: Catch errors caused by negative values!
public static function createFromDateString($dateInterval) {
// Make sure the date interval parameter is a string, throw an exception if this is not the case
if(!is_string($dateInterval)) {
/** @noinspection PhpParamsInspection */
$type = is_object($dateInterval) ? get_class($dateInterval) : gettype($dateInterval);
throw new DomainException('The date interval specification must be a string (' . $type . ' given)');
}
// Create and return a DateInterval instance
return self::parse(parent::createFromDateString($dateInterval));
}
/**
* Create a DateInterval instance from a DateInterval one. Can not instance
* DateInterval objects created from DateTime::diff() as you can't externally
* set the $days field.
*
* @param PHPDateInterval|PHPDateInterval|string $dateInterval
*
* @throws InvalidArgumentException
*
* @return static A new DateTime instance.
*/
// TODO: Update docs!
// TODO: Parse the date interval parameter?
// TODO: Support null!
public static function instance($dateInterval) {
// TODO: Is this necessary?
if(DateIntervalUtils::isCreatedFromDiff($dateInterval))
throw new InvalidArgumentException("Can not instance a DateInterval object created from DateTime::diff().");
// Parse DateInterval instances, create a new instance
if($dateInterval instanceof self)
return new static($dateInterval->toSpecString(), $dateInterval->isInverted());
// Try to parse and instantiate other specifications and return the result
return static::parse($dateInterval);
}
/**
* Create a copy of this instance.
*
* @return PHPDateInterval The DateInterval instance copy.
*/
public function copy() {
return static::instance($this);
}
/**
* Clone this instance.
*
* @return PHPDateInterval A DateInterval instance clone.
*/
public function __clone() {
return $this->copy();
}
/**
* Add the given number of years, months, weeks, days, hours, minutes and seconds to the date interval.
* The resulting values may not be a negative number, or an exception will be thrown.
*
* @param int|null $years The number of years to add to the interval. Null to ignore this value.
* @param int|null $months The number of months to add to the interval. Null to ignore this value.
* @param int|null $weeks The number of weeks to add to the interval, this is converted into and added to the
* number of days. Null to ignore this value.
* @param int|null $days The number of days to add to the interval. Null to ignore this value.
* @param int|null $hours The number of hours to add to the interval. Null to ignore this value.
* @param int|null $minutes The number of minutes to add to the interval. Null to ignore this value.
* @param int|null $seconds The number of seconds to add to the interval. Null to ignore this value.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function addDateTime($years = null, $months = null, $weeks = null, $days = null, $hours = null,
$minutes = null, $seconds = null) {
// Add the date and time part
$this->addDate($years, $months, $weeks, $days);
$this->addTime($hours, $minutes, $seconds);
// Return this instance
return $this;
}
/**
* Subtract the given number of years, months, weeks, days, hours, minutes and seconds to the date interval.
* The resulting values may not be a negative number, or an exception will be thrown.
*
* @param int|null $years The number of years to subtract to the interval. Null to ignore this value.
* @param int|null $months The number of months to subtract to the interval. Null to ignore this value.
* @param int|null $weeks The number of weeks to subtract to the interval, this is converted into and added to the
* number of days. Null to ignore this value.
* @param int|null $days The number of days to subtract to the interval. Null to ignore this value.
* @param int|null $hours The number of hours to subtract to the interval. Null to ignore this value.
* @param int|null $minutes The number of minutes to subtract to the interval. Null to ignore this value.
* @param int|null $seconds The number of seconds to subtract to the interval. Null to ignore this value.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function subDateTime($years = null, $months = null, $weeks = null, $days = null, $hours = null,
$minutes = null, $seconds = null) {
// Subtract the date and time part
$this->subDate($years, $months, $weeks, $days);
$this->subTime($hours, $minutes, $seconds);
// Return this instance
return $this;
}
/**
* Set the time part of the interval. This changes the specified hours, minutes and seconds.
*
* @param int|null $years The number of years of the interval. Null to ignore this value.
* @param int|null $months The number of months of the interval. Null to ignore this value.
* @param int|null $weeks The number of weeks of the interval, this is converted into and added to the number of
* days. Null to ignore this value.
* @param int|null $days The number of days of the interval. Null to ignore this value.
* @param int|null $hours The number of hours of the interval. Null to ignore this value.
* @param int|null $minutes The number of minutes of the interval. Null to ignore this value.
* @param int|null $seconds The number of seconds of the interval. Null to ignore this value.
*
* @return static This DateInterval instance for method chaining.
*/
public function setDateTime($years = null, $months = null, $weeks = null, $days = null, $hours = null,
$minutes = null, $seconds = null) {
// Set the date and time part
$this->setDate($years, $months, $weeks, $days);
$this->setTime($hours, $minutes, $seconds);
// Return this instance
return $this;
}
/**
* Add the given number of years, months, weeks and days to the date interval.
* The resulting values may not be a negative number, or an exception will be thrown.
*
* @param int|null $years The number of years to add to the interval. Null to ignore this value.
* @param int|null $months The number of months to add to the interval. Null to ignore this value.
* @param int|null $weeks The number of weeks to add to the interval, this is converted into and added to the
* number of days. Null to ignore this value.
* @param int|null $days The number of days to add to the interval. Null to ignore this value.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function addDate($years = null, $months = null, $weeks = null, $days = null) {
// Add the number of years and months if set
if(!empty($years))
$this->addYears($years);
if(!empty($months))
$this->addMonths($months);
// Add the number of weeks and days
$this->addWeeksAndDays($weeks, $days);
// Return this instance for method chaining
return $this;
}
/**
* Subtract the given number of years, months, weeks and days to the date interval.
* The resulting values may not be a negative number, or an exception will be thrown.
*
* @param int|null $years The number of years to subtract of the interval. Null to ignore this value.
* @param int|null $months The number of months to subtract of the interval. Null to ignore this value.
* @param int|null $weeks The number of weeks to subtract of the interval, this is converted into and added to the
* number of days. Null to ignore this value.
* @param int|null $days The number of days to subtract of the interval. Null to ignore this value.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function subDate($years = null, $months = null, $weeks = null, $days = null) {
// Subtract the number of years and months if set
if(!empty($years))
$this->subYears($years);
if(!empty($months))
$this->subMonths($months);
// Subtract the number of weeks and days
$this->subWeeksAndDays($weeks, $days);
// Return this instance for method chaining
return $this;
}
/**
* Set the date part of the interval. This changes the specified years, months and days.
*
* @param int|null $years The number of years of the interval. Null to ignore this value.
* @param int|null $months The number of months of the interval. Null to ignore this value.
* @param int|null $weeks The number of weeks of the interval, this is converted into and added to the number of
* days. Null to ignore this value.
* @param int|null $days The number of days of the interval. Null to ignore this value.
*
* @return static This DateInterval instance for method chaining.
*/
public function setDate($years = null, $months = null, $weeks = null, $days = null) {
// Set the years and months if set
if(!empty($years))
$this->setYears($years);
if(!empty($months))
$this->setMonths($months);
// Set the days
$this->setWeeksAndDays($weeks, $days);
// Return this instance
return $this;
}
/**
* Get the number of years.
*
* @return int Number of years.
*/
public function getYears() {
return $this->y;
}
/**
* Add the given number of years to the date interval.
* The resulting number of years may not be a negative number, or an exception will be thrown.
*
* @param int $years [optional] The number of years to add.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function addYears($years = 1) {
// Make sure the years parameter is an integer
if(!is_int($years))
throw new DomainException('Invalid value for years, must be an integer (\'' . $years . '\' was given)');
// Calculate the new number of years
$years = $this->getYears() + intval($years);
// Make sure the number isn't negative
if($years < 0)
throw new Exception('The resulting number of years may not be negative (' . $years . ' is negative)');
// Set the number of years
$this->setYears($years);
// Return this instance for method chaining
return $this;
}
/**
* Add one, or the given number of years to the date interval.
* The resulting number of years may not be a negative number, or an exception will be thrown.
*
* @param int $years [optional] The number of years to add.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function addYear($years = 1) {
return $this->addYears($years);
}
/**
* Subtract the given number of years to the date interval.
* The resulting number of years may not be a negative number, or an exception will be thrown.
*
* @param int $years [optional] The number of years to subtract.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function subYears($years = 1) {
// Make sure the years parameter is an integer
if(!is_int($years))
throw new \DomainException('Invalid value for years, must be an integer (\'' . $years . '\' was given)');
// Subtract the number of years, return the result
return $this->addYears($years * -1);
}
/**
* Subtract one, or the given number of years to the date interval.
* The resulting number of years may not be a negative number, or an exception will be thrown.
*
* @param int $years [optional] The number of years to subtract.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function subYear($years = 1) {
return $this->subYears($years);
}
/**
* Set the number of years.
*
* @param int $years The number of years, must be zero or a positive number.
*
* @return static The DateTime instance for method chaining.
*
* @throws \DomainException Throws an exception on failure.
*/
public function setYears($years) {
// Make sure the value is a positive number or zero
if(!is_int($years) || $years < 0)
throw new \DomainException('Invalid value for years, must be zero or a positive number (\'' . $years .
'\' was given)');
// Set the years, return this instance
$this->y = $years;
return $this;
}
/**
* Get the number of months.
*
* @return int Number of months.
*/
public function getMonths() {
return $this->m;
}
/**
* Add the given number of months to the date interval.
* The resulting number of months may not be a negative number, or an exception will be thrown.
*
* @param int $months [optional] The number of months to add.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function addMonths($months = 1) {
// Make sure the months parameter is an integer
if(!is_int($months))
throw new DomainException('Invalid value for months, must be an integer (\'' . $months . '\' was given)');
// Calculate the new number of months
$months = $this->getMonths() + intval($months);
// Make sure the number isn't negative
if($months < 0)
throw new Exception('The resulting number of months may not be negative (' . $months . ' is negative)');
// Set the number of months
$this->setMonths($months);
// Return this instance for method chaining
return $this;
}
/**
* Add one, or the given number of months to the date interval.
* The resulting number of months may not be a negative number, or an exception will be thrown.
*
* @param int $months [optional] The number of months to add.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function addMonth($months = 1) {
return $this->addMonths($months);
}
/**
* Subtract the given number of months to the date interval.
* The resulting number of months may not be a negative number, or an exception will be thrown.
*
* @param int $months [optional] The number of months to subtract.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function subMonths($months = 1) {
// Make sure the months parameter is an integer
if(!is_int($months))
throw new DomainException('Invalid value for months, must be an integer (\'' . $months . '\' was given)');
// Subtract the number of months, return the result
return $this->addMonths($months * -1);
}
/**
* Subtract one, or the given number of months to the date interval.
* The resulting number of months may not be a negative number, or an exception will be thrown.
*
* @param int $months [optional] The number of months to subtract.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function subMonth($months = 1) {
return $this->subMonths($months);
}
/**
* Set the number of months.
*
* @param int $months The number of months, must be zero or a positive number.
*
* @return static The DateTime instance for method chaining.
*
* @throws \DomainException Throws an exception on failure.
*/
public function setMonths($months) {
// Make sure the value is a positive number or zero
if(!is_int($months) || $months < 0)
throw new DomainException('Invalid value for months, must be zero or a positive number (\'' . $months .
'\' was given)');
// Set the months, return this instance
$this->m = $months;
return $this;
}
/**
* Add the given number of weeks and days to the date interval.
* The resulting number of days may not be a negative number, or an exception will be thrown.
*
* @param int|null $weeks [optional] The number of weeks to add. Null to ignore this value.
* @param int|null $days [optional] The number of days to add. Null to ignore this value.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function addWeeksAndDays($weeks = null, $days = null) {
// Calculate the total number of days
$totalDays = 0;
// Append the number of weeks if set
if(is_int($weeks))
$totalDays += intval($weeks) * DateTime::DAYS_PER_WEEK;
else if(!empty($weeks))
throw new DomainException('Invalid value for weeks (\'' . $weeks . '\' was given)');
// Append the number of days if set
if(is_int($days))
$totalDays += intval($days);
else if(!empty($days))
throw new DomainException('Invalid value for days (\'' . $days . '\' was given)');
// Set the number of days
if(!empty($totalDays)) {
// Make sure the number of days isn't negative
if(($this->getDays() + $totalDays) < 0)
throw new DomainException('The resulting number of days may not be below zero (got ' . $totalDays .
' days)');
// Add the number of days
$this->addDays($totalDays);
}
// Return this instance
return $this;
}
/**
* Subtract the given number of weeks and days to the date interval.
* The resulting number of days may not be a negative number, or an exception will be thrown.
*
* @param int|null $weeks [optional] The number of weeks to subtract. Null to ignore this value.
* @param int|null $days [optional] The number of days to subtract. Null to ignore this value.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function subWeeksAndDays($weeks = null, $days = null) {
// Calculate the total number of days
$totalDays = 0;
// Append the number of weeks if set
if(is_int($weeks))
$totalDays += intval($weeks) * DateTime::DAYS_PER_WEEK;
else if(!empty($weeks))
throw new DomainException('Invalid value for weeks (\'' . $weeks . '\' was given)');
// Append the number of days if set
if(is_int($days))
$totalDays += intval($days);
else if(!empty($days))
throw new DomainException('Invalid value for days (\'' . $days . '\' was given)');
// Set the number of days
if(!empty($totalDays)) {
// Make sure the number of days isn't negative
if(($this->getDays() + $totalDays) < 0)
throw new DomainException('The resulting number of days may not be below zero (got ' . $totalDays .
' days)');
// Subtract the number of days
$this->subDays($totalDays);
}
// Return this instance
return $this;
}
/**
* Set the number of days based ont he given number of weeks and days.
*
* @param int|null $weeks The number of weeks of the interval, this is converted into and added to the number of
* days. Null to ignore this value.
* @param int|null $days The number of days of the interval. Null to ignore this value.
*
* @return static This DateTime instance for method chaining.
*/
public function setWeeksAndDays($weeks = null, $days = null) {
// Calculate the total number of days
$totalDays = 0;
// Append the number of weeks if set
if(is_int($weeks))
$totalDays += intval($weeks) * DateTime::DAYS_PER_WEEK;
else if(!empty($weeks))
throw new DomainException('Invalid value for weeks (\'' . $weeks . '\' was given)');
// Append the number of days if set
if(is_int($days))
$totalDays += intval($days);
else if(!empty($days))
throw new DomainException('Invalid value for days (\'' . $days . '\' was given)');
// Set the number of days
if(!empty($totalDays)) {
// Make sure the number of days isn't negative
if($totalDays < 0)
throw new DomainException('The total number of days may not be below zero (' . $totalDays .
' total days)');
// Set the number of days
$this->setDays($totalDays);
}
// Return this instance
return $this;
}
/**
* Get the approximate number of weeks. This value is based on the number of days specified, and thus isn't exact.
*
* @return int The approximate number of weeks.
*/
public function getApproximateWeeks() {
return (int) ($this->getDays() / DateTime::DAYS_PER_WEEK);
}
/**
* Add the given number of days to the date interval specified as weeks.
* The resulting number of days may not be a negative number, or an exception will be thrown.
*
* @param int $weeks [optional] The number of weeks to add.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function addWeeks($weeks = 1) {
// Make sure the weeks parameter is an integer
if(!is_int($weeks))
throw new DomainException('Invalid value for weeks, must be an integer (\'' . $weeks . '\' was given)');
// Calculate the new number of days
$days = $this->getDays() + (intval($weeks) * DateTime::DAYS_PER_WEEK);
// Make sure the number isn't negative
if($days < 0)
throw new Exception('The resulting number of days may not be negative (' . $days . ' is negative)');
// Set the number of days
$this->setDays($weeks);
// Return this instance for method chaining
return $this;
}
/**
* Add one, or the given number of days to the date interval specified as weeks.
* The resulting number of days may not be a negative number, or an exception will be thrown.
*
* @param int $weeks [optional] The number of weeks to add.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function addWeek($weeks = 1) {
return $this->addWeeks($weeks);
}
/**
* Subtract the given number of days to the date interval specified as weeks.
* The resulting number of days may not be a negative number, or an exception will be thrown.
*
* @param int $weeks [optional] The number of weeks to subtract.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function subWeeks($weeks = 1) {
// Make sure the weeks parameter is an integer
if(!is_int($weeks))
throw new DomainException('Invalid value for weeks, must be an integer (\'' . $weeks . '\' was given)');
// Subtract the number of weeks, return the result
return $this->addWeeks($weeks * -1);
}
/**
* Subtract one, or the given number of days to the date interval specified as weeks.
* The resulting number of days may not be a negative number, or an exception will be thrown.
*
* @param int $weeks [optional] The number of weeks to subtract.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function subWeek($weeks = 1) {
return $this->subWeeks($weeks);
}
/**
* Set the number of days based on the given number of weeks.
* Note: This will change the number of days.
*
* @param int $weeks The number of weeks, must be zero or a positive number.
*
* @return static The DateTime instance for method chaining.
*
* @throws \DomainException Throws an exception on failure.
*/
public function setWeeks($weeks) {
// Make sure the value is a positive number or zero
if(!is_int($weeks) || $weeks < 0)
throw new DomainException('Invalid value for months, must be zero or a positive number (\'' . $weeks .
'\' was given)');
// Set the days, return this instance
$this->d = $weeks * DateTime::DAYS_PER_WEEK;
return $this;
}
/**
* Get the number of days.
*
* @return int Number of days.
*/
public function getDays() {
return $this->d;
}
/**
* Add the given number of days to the date interval.
* The resulting number of days may not be a negative number, or an exception will be thrown.
*
* @param int $days [optional] The number of days to add.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function addDays($days = 1) {
// Make sure the days parameter is an integer
if(!is_int($days))
throw new DomainException('Invalid value for days, must be an integer (\'' . $days . '\' was given)');
// Calculate the new number of days
$days = $this->getDays() + intval($days);
// Make sure the number isn't negative
if($days < 0)
throw new Exception('The resulting number of days may not be negative (' . $days . ' is negative)');
// Set the number of days
$this->setDays($days);
// Return this instance for method chaining
return $this;
}
/**
* Add one, or the given number of days to the date interval.
* The resulting number of days may not be a negative number, or an exception will be thrown.
*
* @param int $days [optional] The number of days to add.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function addDay($days = 1) {
return $this->addDays($days);
}
/**
* Subtract the given number of days to the date interval.
* The resulting number of days may not be a negative number, or an exception will be thrown.
*
* @param int $days [optional] The number of days to subtract.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function subDays($days = 1) {
// Make sure the days parameter is an integer
if(!is_int($days))
throw new DomainException('Invalid value for days, must be an integer (\'' . $days . '\' was given)');
// Subtract the number of days, return the result
return $this->addDays($days * -1);
}
/**
* Subtract one, or the given number of days to the date interval.
* The resulting number of days may not be a negative number, or an exception will be thrown.
*
* @param int $days [optional] The number of days to subtract.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function subDay($days = 1) {
return $this->subDays($days);
}
/**
* Set the number of days.
*
* @param int $days The number of days, must be zero or a positive number.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException Throws an exception on failure.
*/
public function setDays($days) {
// Make sure the value is a positive number or zero
if(!is_int($days) || $days < 0)
throw new DomainException('Invalid value for days, must be zero or a positive number (\'' . $days .
'\' was given)');
// Set the days, return this instance
$this->d = $days;
return $this;
}
/**
* Add the given number of hours, minutes and seconds to the date interval.
* The resulting values may not be a negative number, or an exception will be thrown.
*
* @param int|null $hours The number of hours to add to the interval. Null to ignore this value.
* @param int|null $minutes The number of minutes to add to the interval. Null to ignore this value.
* @param int|null $seconds The number of seconds to add to the interval. Null to ignore this value.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function addTime($hours = null, $minutes = null, $seconds = null) {
// Add the number of hours, minutes and seconds if set
if(!empty($hours))
$this->addHours($hours);
if(!empty($minutes))
$this->addMinutes($minutes);
if(!empty($seconds))
$this->addSecond($seconds);
// Return this instance for method chaining
return $this;
}
/**
* Subtract the given number of hours, minutes and seconds to the date interval.
* The resulting values may not be a negative number, or an exception will be thrown.
*
* @param int|null $hours The number of hours to subtract to the interval. Null to ignore this value.
* @param int|null $minutes The number of minutes to subtract to the interval. Null to ignore this value.
* @param int|null $seconds The number of seconds to subtract to the interval. Null to ignore this value.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function subTime($hours = null, $minutes = null, $seconds = null) {
// Subtract the number of hours, minutes and seconds if set
if(!empty($hours))
$this->subHours($hours);
if(!empty($minutes))
$this->subMinutes($minutes);
if(!empty($seconds))
$this->subSecond($seconds);
// Return this instance for method chaining
return $this;
}
/**
* Set the date and time part of the interval. This changes the specified years, months, days, hours, minutes and
* seconds.
*
* @param int|null $hours The number of hours of the interval. Null to ignore this value.
* @param int|null $minutes The number of minutes of the interval. Null to ignore this value.
* @param int|null $seconds The number of seconds of the interval. Null to ignore this value.
*
* @return static This DateInterval instance for method chaining.
*/
public function setTime($hours = null, $minutes = null, $seconds = null) {
// Set the hours, minutes and seconds
if(!empty($hours))
$this->setHours($hours);
if(!empty($minutes))
$this->setMinutes($minutes);
if(!empty($seconds))
$this->setSeconds($seconds);
// Return this instance
return $this;
}
/**
* Get the number of hours.
*
* @return int Number of hours.
*/
public function getHours() {
return $this->h;
}
/**
* Add the given number of hours to the date interval.
* The resulting number of hours may not be a negative number, or an exception will be thrown.
*
* @param int $hours [optional] The number of hours to add.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function addHours($hours = 1) {
// Make sure the hours parameter is an integer
if(!is_int($hours))
throw new DomainException('Invalid value for hours, must be an integer (\'' . $hours . '\' was given)');
// Calculate the new number of hours
$hours = $this->getHours() + intval($hours);
// Make sure the number isn't negative
if($hours < 0)
throw new Exception('The resulting number of hours may not be negative (' . $hours . ' is negative)');
// Set the number of hours
$this->setHours($hours);
// Return this instance for method chaining
return $this;
}
/**
* Add one, or the given number of hours to the date interval.
* The resulting number of hours may not be a negative number, or an exception will be thrown.
*
* @param int $hours [optional] The number of hours to add.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function addHour($hours = 1) {
return $this->addHours($hours);
}
/**
* Subtract the given number of hours to the date interval.
* The resulting number of hours may not be a negative number, or an exception will be thrown.
*
* @param int $hours [optional] The number of hours to subtract.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function subHours($hours = 1) {
// Make sure the hours parameter is an integer
if(!is_int($hours))
throw new DomainException('Invalid value for hours, must be an integer (\'' . $hours . '\' was given)');
// Subtract the number of hours, return the result
return $this->addHours($hours * -1);
}
/**
* Subtract one, or the given number of hours to the date interval.
* The resulting number of hours may not be a negative number, or an exception will be thrown.
*
* @param int $hours [optional] The number of hours to subtract.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function subHour($hours = 1) {
return $this->subHours($hours);
}
/**
* Set the number of hours.
*
* @param int $hours The number of hours, must be zero or a positive number.
*
* @return static The DateTime instance for method chaining.
*
* @throws \DomainException Throws an exception on failure.
*/
public function setHours($hours) {
// Make sure the value is a positive number or zero
if(!is_int($hours) || $hours < 0)
throw new DomainException('Invalid value for hours, must be zero or a positive number (\'' . $hours .
'\' was given)');
// Set the hours, return this instance
$this->h = $hours;
return $this;
}
/**
* Get the number of minutes.
*
* @return int Number of minutes.
*/
public function getMinutes() {
return $this->i;
}
/**
* Add the given number of minutes to the date interval.
* The resulting number of minutes may not be a negative number, or an exception will be thrown.
*
* @param int $minutes [optional] The number of minutes to add.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function addMinutes($minutes = 1) {
// Make sure the minutes parameter is an integer
if(!is_int($minutes))
throw new DomainException('Invalid value for minutes, must be an integer (\'' . $minutes . '\' was given)');
// Calculate the new number of minutes
$minutes = $this->getMinutes() + intval($minutes);
// Make sure the number isn't negative
if($minutes < 0)
throw new Exception('The resulting number of minutes may not be negative (' . $minutes . ' is negative)');
// Set the number of minutes
$this->setMinutes($minutes);
// Return this instance for method chaining
return $this;
}
/**
* Add one, or the given number of minutes to the date interval.
* The resulting number of minutes may not be a negative number, or an exception will be thrown.
*
* @param int $minutes [optional] The number of minutes to add.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function addMinute($minutes = 1) {
return $this->addMinutes($minutes);
}
/**
* Subtract the given number of minutes to the date interval.
* The resulting number of minutes may not be a negative number, or an exception will be thrown.
*
* @param int $minutes [optional] The number of minutes to subtract.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function subMinutes($minutes = 1) {
// Make sure the minutes parameter is an integer
if(!is_int($minutes))
throw new DomainException('Invalid value for minutes, must be an integer (\'' . $minutes .
'\' was given)');
// Subtract the number of minutes, return the result
return $this->addMinutes($minutes * -1);
}
/**
* Subtract one, or the given number of minutes to the date interval.
* The resulting number of minutes may not be a negative number, or an exception will be thrown.
*
* @param int $minutes [optional] The number of minutes to subtract.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function subMinute($minutes = 1) {
return $this->subMinutes($minutes);
}
/**
* Set the number of minutes.
*
* @param int $minutes The number of minutes, must be zero or a positive number.
*
* @return static The DateTime instance for method chaining.
*
* @throws \DomainException Throws an exception on failure.
*/
public function setMinutes($minutes) {
// Make sure the value is a positive number or zero
if(!is_int($minutes) || $minutes < 0)
throw new DomainException('Invalid value for minutes, must be zero or a positive number (\'' . $minutes .
'\' was given)');
// Set the minutes, return this instance
$this->i = $minutes;
return $this;
}
/**
* Get the number of seconds.
*
* @return int Number of seconds.
*/
public function getSeconds() {
return $this->s;
}
/**
* Add the given number of seconds to the date interval.
* The resulting number of seconds may not be a negative number, or an exception will be thrown.
*
* @param int $seconds [optional] The number of seconds to add.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function addSeconds($seconds = 1) {
// Make sure the seconds parameter is an integer
if(!is_int($seconds))
throw new DomainException('Invalid value for seconds, must be an integer (\'' . $seconds . '\' was given)');
// Calculate the new number of seconds
$seconds = $this->getSeconds() + intval($seconds);
// Make sure the number isn't negative
if($seconds < 0)
throw new Exception('The resulting number of seconds may not be negative (' . $seconds . ' is negative)');
// Set the number of seconds
$this->setSeconds($seconds);
// Return this instance for method chaining
return $this;
}
/**
* Add one, or the given number of seconds to the date interval.
* The resulting number of seconds may not be a negative number, or an exception will be thrown.
*
* @param int $seconds [optional] The number of seconds to add.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function addSecond($seconds = 1) {
return $this->addSeconds($seconds);
}
/**
* Subtract the given number of seconds to the date interval.
* The resulting number of seconds may not be a negative number, or an exception will be thrown.
*
* @param int $seconds [optional] The number of seconds to subtract.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function subSeconds($seconds = 1) {
// Make sure the seconds parameter is an integer
if(!is_int($seconds))
throw new DomainException('Invalid value for seconds, must be an integer (\'' . $seconds .
'\' was given)');
// Subtract the number of seconds, return the result
return $this->addSeconds($seconds * -1);
}
/**
* Subtract one, or the given number of seconds to the date interval.
* The resulting number of seconds may not be a negative number, or an exception will be thrown.
*
* @param int $seconds [optional] The number of seconds to subtract.
*
* @return static The DateTime instance for method chaining.
*
* @throws DomainException|Exception Throws an exception on failure.
*/
public function subSecond($seconds = 1) {
return $this->subSeconds($seconds);
}
/**
* Set the number of seconds.
*
* @param int $seconds The number of seconds, must be zero or a positive number.
*
* @return static The DateTime instance for method chaining.
*
* @throws \DomainException Throws an exception on failure.
*/
public function setSeconds($seconds) {
// Make sure the value is a positive number or zero
if(!is_int($seconds) || $seconds < 0)
throw new DomainException('Invalid value for seconds, must be zero or a positive number (\'' . $seconds .
'\' was given)');
// Set the seconds, return this instance
$this->s = $seconds;
return $this;
}
/**
* Check whether the date interval is inverted.
*
* @return bool True if the date interval is inverted, false if not.
*/
public function isInverted() {
return $this->invert !== 0;
}
/**
* Set whether the date interval is inverted.
*
* @param int|bool $inverted One or true if the date interval is inverted, zero or false if not.
*
* @return static This DateInterval instance.
*/
public function setInverted($inverted) {
// Parse the parameter value
$inverted = empty($inverted) ? 0 : 1;
// Set whether the interval is inverted, return this instance
$this->invert = $inverted;
return $this;
}
/**
* Get the day span of this interval. This only works for objects created with DateTime::diff().
*
* @return int|null The day span of this interval, or null on failure.
*/
public function getDaySpan() {
return $this->isCreatedFromDiff() ? $this->days : null;
}
/**
* Check whether this is a zero date interval.
*
* @return bool True if this date interval is zero, false if not.
*/
public function isZero() {
return ($this->getYears() == 0 && $this->getMonths() == 0 && $this->getDays() == 0 &&
$this->getHours() == 0 && $this->getMinutes() == 0 && $this->getSeconds() == 0);
}
/**
* Check whether this date time object was created using DateTime::diff() or PHPDateTime::diff().
*
* @return bool True if this date interval object was created by a diff() method, false if not. If the date
* interval isn't an instance of DateInterval false will also be returned.
*/
public function isCreatedFromDiff() {
return DateIntervalUtils::isCreatedFromDiff($this);
}
/**
* Add the passed interval of the current instance
*
* @param PHPDateInterval|PHPDateInterval|string|null $dateInterval The DateInterval or PHPDateInterval instance,
* the date interval specification as a string or null to use a zero specification.
*
* @return static|null This DateInterval instance for method chaining, or null on failure.
*/
public function add($dateInterval) {
// Parse the date interval, return null on failure
if(($dateInterval = static::parse($dateInterval)) === null)
return null;
// Calculate the factor to multiply each value with
$factor = $dateInterval->isInverted() ? -1 : 1;
/*if(DateIntervalUtils::isCreatedFromDiff($dateInterval))
$this->setDays($this->getDays() + ($dateInterval->getDaySpan() * $factor));
else*/
// Add the date and time
$this->addDateTime($dateInterval->getYears() * $factor, $dateInterval->getMonths() * $factor, null,
$dateInterval->getDays() * $factor, $dateInterval->getHours() * $factor,
$dateInterval->getMinutes() * $factor, $dateInterval->getSeconds() * $factor);
// Return this instance
return $this;
}
/**
* Subtract the passed interval of the current instance.
*
* @param PHPDateInterval|PHPDateInterval|string|null $dateInterval The DateInterval or PHPDateInterval instance,
* the date interval specification as a string or null to use a zero specification.
*
* @return static|null This DateInterval instance for method chaining, or null on failure.
*/
public function sub($dateInterval) {
// Parse the date interval as a new instance, return null on failure
if(($dateInterval = static::instance($dateInterval)) === null)
return null;
// Invert the date interval
$dateInterval->setInverted(!$dateInterval->isInverted());
// Subtract and return the result
return $this->add($dateInterval);
}
/**
* Create a ISO-8601 date interval specification string.
*
* @return string The date interval specification string.
*/
public function toSpecString() {
return PHPDateInterval::create($this->getYears(), $this->getMonths(), null, $this->getDays(),
$this->getHours(), $this->getMinutes(), $this->getSeconds());
}
/**
* Get the date interval as a string.
*
* @return string The date interval string.
*/
public function toString() {
return $this->toSpecString();
}
// TODO: toString() for humans!
/**
* Get the date interval as a string.
*
* @return string The date interval string.
*/
public function __toString() {
return ($result = $this->toString()) === null ? '' : $result;
}
/*
/**
* Get a date interval attribute.
*
* @param string $name The name of the attribute to get.
*
* @return int The value of the getter.
*
* @throws \InvalidArgumentException Throws an exception on failure.
* /
public function __get($name) {
// Get the number of years
if(StringUtils::equals($name, 'years', true))
return $this->getYears();
// Get the number of months
if(StringUtils::equals($name, 'months', true))
return $this->getMonths();
// Get the number of days
if(StringUtils::equals($name, 'days', true))
return $this->getDays();
// Get the number of hours
if(StringUtils::equals($name, 'hours', true))
return $this->getHours();
// Get the number of minutes
if(StringUtils::equals($name, 'minutes', true))
return $this->getMinutes();
// Get the number of seconds
if(StringUtils::equals($name, 'seconds', true))
return $this->getSeconds();
switch($name) {
case 'weeks':
return (int) floor($this->d / DateTime::DAYS_PER_WEEK);
case 'daysExcludeWeeks':
return $this->d % DateTime::DAYS_PER_WEEK;
default:
throw new \InvalidArgumentException('Unknown getter \'' . $name . '\'');
}
}
/**
* Set an attribute of the date interval object.
*
* @param string $name The name of the attribute to set.
* @param int $value The value to set the attribute to.
*
* @return static The DateTime instance.
*
* @throws \InvalidArgumentException Throw an exception on failure.
* /
public function __set($name, $value) {
// Set the number of years
if(StringUtils::equals($name, 'years', true))
return $this->setYears($value);
// Set the number of months
if(StringUtils::equals($name, 'months', true))
return $this->setMonths($value);
// Set the number of days
if(StringUtils::equals($name, 'days', true))
return $this->setDays($value);
// Set the number of hours
if(StringUtils::equals($name, 'hours', true))
return $this->setHours($value);
// Set the number of minutes
if(StringUtils::equals($name, 'minutes', true))
return $this->setMInutes($value);
// Set the number of seconds
if(StringUtils::equals($name, 'seconds', true))
return $this->setSeconds($value);
switch ($name) {
case 'weeks':
$this->d = $value * DateTime::DAYS_PER_WEEK;
break;
}
}
/**
* Allow fluent calls on the setters. CarbonInterval::years(3)->months(5)->day().
*
* Note: This is done using the magic method to allow static and instance methods to have the same names.
*
* @param string $name The name of the method being called.
* @param Array $args An array of method parameters.
*
* @return static The DateTime instance, which could be used for method chaining.
* /
public function __call($name, $args) {
// Get the delimiter value
$arg = count($args) == 0 ? 1 : $args[0];
// Handle the years setter
if(StringUtils::equals($name, Array('years', 'year'), true)) {
$this->years = $arg;
return $this;
}
// Handle the months setter
if(StringUtils::equals($name, Array('months', 'month'), true)) {
$this->months = $arg;
return $this;
}
// Handle the weeks setter
if(StringUtils::equals($name, Array('weeks', 'week'), true)) {
$this->days = $arg * DateTime::DAYS_PER_WEEK;
return $this;
}
// Handle the days setter
if(StringUtils::equals($name, Array('days', 'day'), true)) {
$this->days = $arg;
return $this;
}
// Handle the hours setter
if(StringUtils::equals($name, Array('hours', 'hour'), true)) {
$this->hours = $arg;
return $this;
}
// Handle the minutes setter
if(StringUtils::equals($name, Array('minutes', 'minute'), true)) {
$this->minutes = $arg;
return $this;
}
// Handle the seconds setter
if(StringUtils::equals($name, Array('seconds', 'second'), true)) {
$this->seconds = $arg;
return $this;
}
// Return this instance
return $this;
}
/**
* Provide static helpers to create instances.
* Allows CarbonInterval::years(3).
*
* Note: This is done using the magic method to allow static and instance methods to have the same names.
*
* @param string $name The name of the static method being called.
* @param Array $args An array of method parameters.
*
* @return static The DateInterval instance.
* /
public static function __callStatic($name, $args) {
// Get the delimiter value if any argument has been given
$delimiterValue = count($args) == 0 ? 1 : $args[0];
// Handle the years delimiter
if(StringUtils::equals($name, Array('years', 'year'), true))
return DateIntervalFactory::create($delimiterValue);
// Handle the months delimiter
if(StringUtils::equals($name, Array('months', 'month'), true))
return DateIntervalFactory::create(null, $delimiterValue);
// Handle the weeks delimiter
if(StringUtils::equals($name, Array('weeks', 'week'), true))
return DateIntervalFactory::create(null, null, $delimiterValue);
// Handle the days delimiter
if(StringUtils::equals($name, Array('days', 'day'), true))
return DateIntervalFactory::create(null, null, null, $delimiterValue);
// Handle the hours delimiter
if(StringUtils::equals($name, Array('hours', 'hour'), true))
return DateIntervalFactory::create(null, null, null, null, $delimiterValue);
// Handle the minutes delimiter
if(StringUtils::equals($name, Array('minutes', 'minute'), true))
return DateIntervalFactory::create(null, null, null, null, null, $delimiterValue);
// Handle the seconds delimiter
if(StringUtils::equals($name, Array('seconds', 'second'), true))
return DateIntervalFactory::create(null, null, null, null, null, null, $delimiterValue);
}
*/
}
<?php
namespace carbon\core\datetime\interval;
// Prevent direct requests to this set_file due to security reasons
use carbon\core\datetime\interval\spec\DateIntervalSpecFactory;
defined('CARBON_CORE_INIT') or die('Access denied!');
class DateIntervalFactory {
/**
* Create a new DateInterval instance from specific values.
*
* @param int $years [optional] The number of years, or null to ignore this value.
* @param int $months [optional] The number of months, or null to ignore this value.
* @param int $weeks [optional] The number of weeks, or null to ignore this value.
* @param int $days [optional] The number of days, or null to ignore this value.
* @param int $hours [optional] The number of hours, or null to ignore this value.
* @param int $minutes [optional] The number of minutes, or null to ignore this value.
* @param int $seconds [optional] The number of seconds, or null to ignore this value.
* @param bool $inverted [optional] Define whether the date interval is inverted or not.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateInterval|mixed A new DateInterval instance, or the default value on failure.
*/
public static function create($years = null, $months = null, $weeks = null, $days = null, $hours = null,
$minutes = null, $seconds = null, $inverted = false, $default = null) {
// Create the specification, and make sure it's valid
if(($spec = DateIntervalSpecFactory::create($years, $months, $weeks, $days, $hours, $minutes, $seconds)) === null)
return $default;
// Construct the DateInterval object
return new DateInterval($spec, $inverted);
}
/**
* Create a date interval object of zero.
*
* @return DateInterval|null The DateInterval object.
*/
public static function zero() {
return static::create();
}
/**
* Create a date interval object for one, or the given number of years.
*
* @param int $years [optional] The number of years. Null to use one year.
* @param bool $inverted [optional] True to invert the date interval, false if not.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateInterval|mixed The DateInterval instance, or the default value on failure.
*/
public static function year($years = 1, $inverted = false, $default = null) {
// Parse the year parameter, and make sure it's valid
if($years === null)
$years = 1;
// Create and return a new DateInterval instance, or return the default value on failure
return static::create(null, null, null, $years, null, null, null, $inverted, $default);
}
/**
* Alias of year();
*
* Create a date interval object for one, or the given number of years.
*
* @param int $years [optional] The number of years. Null to use one year.
* @param bool $inverted [optional] True to invert the date interval, false if not.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateInterval|mixed The DateInterval instance, or the default value on failure.
*/
public static function years($years = 1, $inverted = false, $default = null) {
return static::year($years, $inverted, $default);
}
/**
* Create a date interval object for one, or the given number of months.
*
* @param int $months [optional] The number of months. Null to use one month.
* @param bool $inverted [optional] True to invert the date interval, false if not.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateInterval|mixed The DateInterval instance, or the default value on failure.
*/
public static function month($months = 1, $inverted = false, $default = null) {
// Parse the month parameter, and make sure it's valid
if($months === null)
$months = 1;
// Create and return a new DateInterval instance, or return the default value on failure
return static::create(null, null, null, $months, null, null, null, $inverted, $default);
}
/**
* Alias of month();
*
* Create a date interval object for one, or the given number of months.
*
* @param int $months [optional] The number of months. Null to use one month.
* @param bool $inverted [optional] True to invert the date interval, false if not.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateInterval|mixed The DateInterval instance, or the default value on failure.
*/
public static function months($months = 1, $inverted = false, $default = null) {
return static::month($months, $inverted, $default);
}
/**
* Create a date interval object for one, or the given number of weeks.
*
* @param int $weeks [optional] The number of weeks. Null to use one week.
* @param bool $inverted [optional] True to invert the date interval, false if not.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateInterval|mixed The DateInterval instance, or the default value on failure.
*/
public static function week($weeks = 1, $inverted = false, $default = null) {
// Parse the week parameter, and make sure it's valid
if($weeks === null)
$weeks = 1;
// Create and return a new DateInterval instance, or return the default value on failure
return static::create(null, null, null, $weeks, null, null, null, $inverted, $default);
}
/**
* Alias of week();
*
* Create a date interval object for one, or the given number of weeks.
*
* @param int $weeks [optional] The number of weeks. Null to use one week.
* @param bool $inverted [optional] True to invert the date interval, false if not.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateInterval|mixed The DateInterval instance, or the default value on failure.
*/
public static function weeks($weeks = 1, $inverted = false, $default = null) {
return static::week($weeks, $inverted, $default);
}
/**
* Create a date interval object for one, or the given number of days.
*
* @param int $days [optional] The number of days. Null to use one day.
* @param bool $inverted [optional] True to invert the date interval, false if not.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateInterval|mixed The DateInterval instance, or the default value on failure.
*/
public static function day($days = 1, $inverted = false, $default = null) {
// Parse the day parameter, and make sure it's valid
if($days === null)
$days = 1;
// Create and return a new DateInterval instance, or return the default value on failure
return static::create(null, null, null, $days, null, null, null, $inverted, $default);
}
/**
* Alias of day();
*
* Create a date interval object for one, or the given number of days.
*
* @param int $days [optional] The number of days. Null to use one day.
* @param bool $inverted [optional] True to invert the date interval, false if not.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateInterval|mixed The DateInterval instance, or the default value on failure.
*/
public static function days($days = 1, $inverted = false, $default = null) {
return static::day($days, $inverted, $default);
}
/**
* Create a date interval object for one, or the given number of hours.
*
* @param int $hours [optional] The number of hours. Null to use one hour.
* @param bool $inverted [optional] True to invert the date interval, false if not.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateInterval|mixed The DateInterval instance, or the default value on failure.
*/
public static function hour($hours = 1, $inverted = false, $default = null) {
// Parse the hour parameter, and make sure it's valid
if($hours === null)
$hours = 1;
// Create and return a new DateInterval instance, or return the default value on failure
return static::create(null, null, null, $hours, null, null, null, $inverted, $default);
}
/**
* Alias of hour();
*
* Create a date interval object for one, or the given number of hours.
*
* @param int $hours [optional] The number of hours. Null to use one hour.
* @param bool $inverted [optional] True to invert the date interval, false if not.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateInterval|mixed The DateInterval instance, or the default value on failure.
*/
public static function hours($hours = 1, $inverted = false, $default = null) {
return static::hour($hours, $inverted, $default);
}
/**
* Create a date interval object for one, or the given number of minutes.
*
* @param int $minutes [optional] The number of minutes. Null to use one minute.
* @param bool $inverted [optional] True to invert the date interval, false if not.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateInterval|mixed The DateInterval instance, or the default value on failure.
*/
public static function minute($minutes = 1, $inverted = false, $default = null) {
// Parse the minute parameter, and make sure it's valid
if($minutes === null)
$minutes = 1;
// Create and return a new DateInterval instance, or return the default value on failure
return static::create(null, null, null, $minutes, null, null, null, $inverted, $default);
}
/**
* Alias of minute();
*
* Create a date interval object for one, or the given number of minutes.
*
* @param int $minutes [optional] The number of minutes. Null to use one minute.
* @param bool $inverted [optional] True to invert the date interval, false if not.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateInterval|mixed The DateInterval instance, or the default value on failure.
*/
public static function minutes($minutes = 1, $inverted = false, $default = null) {
return static::minute($minutes, $inverted, $default);
}
/**
* Create a date interval object for one, or the given number of seconds.
*
* @param int $seconds [optional] The number of seconds. Null to use one second.
* @param bool $inverted [optional] True to invert the date interval, false if not.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateInterval|mixed The DateInterval instance, or the default value on failure.
*/
public static function second($seconds = 1, $inverted = false, $default = null) {
// Parse the second parameter, and make sure it's valid
if($seconds === null)
$seconds = 1;
// Create and return a new DateInterval instance, or return the default value on failure
return static::create(null, null, null, $seconds, null, null, null, $inverted, $default);
}
/**
* Alias of second();
*
* Create a date interval object for one, or the given number of seconds.
*
* @param int $seconds [optional] The number of seconds. Null to use one second.
* @param bool $inverted [optional] True to invert the date interval, false if not.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateInterval|mixed The DateInterval instance, or the default value on failure.
*/
public static function seconds($seconds = 1, $inverted = false, $default = null) {
return static::second($seconds, $inverted, $default);
}
}
<?php
namespace carbon\core\datetime\interval;
// Prevent direct requests to this set_file due to security reasons
defined('CARBON_CORE_INIT') or die('Access denied!');
class DateIntervalSet {
//private $intervals = Array();
// TODO: Create this class!
}
<?php
namespace carbon\core\datetime\interval;
use DateInterval as PHPDateInterval;
// Prevent direct requests to this set_file due to security reasons
defined('CARBON_CORE_INIT') or die('Access denied!');
class DateIntervalUtils {
/**
* Before PHP 5.4.20/5.5.4 instead of false days will be set to -99999 when the interval instance was created by DateTime:diff().
*
* @const int The old PHP false value of days.
*/
const PHP_OLD_FALSE_DAYS = -99999;
/**
* Parse a date interval. A new instance may be created.
*
* This method allows better fluent syntax because it makes method chaining possible.
*
* @param DateInterval|PHPDateInterval|string|null $dateInterval [optional] A DateInterval or PHPDateInterval instance, a date interval specification, or null to use a zero specification.
* @param mixed|null $default [optional] The default value to be returned on failure.
*
* @return static|mixed A DateInterval instance, or the default value on failure.
*/
public static function parse($dateInterval, $default = null) {
return ($result = DateInterval::parse($dateInterval)) === null ? $default : $result;
}
/**
* Check whether this date time object was created using DateTime::diff() or PHPDateTime::diff().
*
* @param DateInterval|PHPDateInterval $dateInterval The DateInterval or PHPDateInterval instance.
*
* @return bool True if this date interval object was created by a diff() method, false if not. If the date interval isn't an instance of DateInterval false will also be returned.
*/
// TODO: Improve the performance of this method, just check whether it's false or -99999?
public static function isCreatedFromDiff($dateInterval) {
// Make sure the date interval isn't null
if($dateInterval == null)
return false;
// Make sure the date interval is a DateInterval or PHPDateInterval instance
if(!($dateInterval instanceof PHPDateInterval))
return false;
// Get the value to compare the days to, this differs depending on the installed PHP version
$compareTo = (
version_compare(phpversion(), '5.4.20', '<') ||
(version_compare(phpversion(), '5.0', '>=') && version_compare(phpversion(), '5.5.4', '<'))
) ? static::PHP_OLD_FALSE_DAYS : false;
// Make sure the number of days, return the result
return $dateInterval->days != $compareTo;
}
}
<?php
/**
* Created by PhpStorm.
* User: Tim
* Date: 3-5-2015
* Time: 18:09
*/
namespace carbon\core\datetime\interval\spec;
// Prevent direct requests to this set_file due to security reasons
use carbon\core\datetime\DateTime;
use carbon\core\datetime\interval\DateInterval;
defined('CARBON_CORE_INIT') or die('Access denied!');
class DateIntervalSpecFactory {
/**
* Create a date interval specification based on the given parameters.
*
* @param int|null $years [optional] The number of years, must be zero or a positive number. Null to ignore this value.
* @param int|null $months [optional] The number of months, must be zero or a positive number. Null to ignore this value.
* @param int|null $weeks [optional] The number of weeks, must be zero or a positive number. Null to ignore this value. The weeks are converted into days.
* @param int|null $days [optional] The number of days, must be zero or a positive number. Null to ignore this value.
* @param int|null $hours [optional] The number of hours, must be zero or a positive number. Null to ignore this value.
* @param int|null $minutes [optional] The number of minutes, must be zero or a positive number. Null to ignore this value.
* @param int|null $seconds [optional] The number of seconds, must be zero or a positive number. Null to ignore this value.
*
* @return string|null The date interval spec as a string, or null on failure.
*/
// TODO: Allow a default value!
public static function create($years = null, $months = null, $weeks = null, $days = null, $hours = null,
$minutes = null, $seconds = null) {
// Build the date interval specification string
$dateIntervalSpec = DateInterval::PERIOD_PREFIX;
// Check whether the weeks parameter is used, append the number of days
if(!empty($weeks))
$days += (int) ($weeks * DateTime::DAYS_PER_WEEK);
// Reading all non-zero date parts
$date = array_filter(array(
DateInterval::PERIOD_YEARS => $years,
DateInterval::PERIOD_MONTHS => $months,
DateInterval::PERIOD_DAYS => $days
));
// Reading all non-zero time parts
$time = array_filter(array(
DateInterval::PERIOD_HOURS => $hours,
DateInterval::PERIOD_MINUTES => $minutes,
DateInterval::PERIOD_SECONDS => $seconds
));
// Make sure at least one part is available
if(empty($date) && empty($time))
$date = array(DateInterval::PERIOD_YEARS => 0);
// Append each date part to the specification string
foreach($date as $key => $value)
$dateIntervalSpec .= $value . $key;
// Append each time part to the specification string if available
if(!empty($time)) {
// Prefix the time designator
$dateIntervalSpec .= DateInterval::PERIOD_TIME_PREFIX;
// Append each time part to the specification string
foreach($time as $key => $value)
$dateIntervalSpec .= $value . $key;
}
// Return the spec if it's valid, return null otherwise
return DateIntervalSpecUtils::isValid($dateIntervalSpec) ? $dateIntervalSpec : null;
}
/**
* Create a date interval specification of zero.
*
* @return string The date interval specification.
*/
public static function zero() {
return static::create();
}
/**
* Create a date interval specification for one, or the given number of years.
*
* @param int $years [optional] The number of years. Null to use one year.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return string|mixed The date interval specification, or the default value on failure.
*/
public static function year($years = 1, $default = null) {
// Parse the year parameter, and make sure it's valid
if($years === null)
$years = 1;
// Create and return a new date interval specification, or return the default value on failure
return static::create(null, null, null, $years, null, null, null, $default);
}
/**
* Alias of year();
*
* Create a date interval specification for one, or the given number of years.
*
* @param int $years [optional] The number of years. Null to use one year.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return string|mixed The date interval specification, or the default value on failure.
*/
public static function years($years = 1, $default = null) {
return static::year($years, $default);
}
/**
* Create a date interval specification for one, or the given number of months.
*
* @param int $months [optional] The number of months. Null to use one month.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return string|mixed The date interval specification, or the default value on failure.
*/
public static function month($months = 1, $default = null) {
// Parse the month parameter, and make sure it's valid
if($months === null)
$months = 1;
// Create and return a new date interval specification, or return the default value on failure
return static::create(null, null, null, $months, null, null, null, $default);
}
/**
* Alias of month();
*
* Create a date interval specification for one, or the given number of months.
*
* @param int $months [optional] The number of months. Null to use one month.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return string|mixed The date interval specification, or the default value on failure.
*/
public static function months($months = 1, $default = null) {
return static::month($months, $default);
}
/**
* Create a date interval specification for one, or the given number of weeks.
*
* @param int $weeks [optional] The number of weeks. Null to use one week.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return string|mixed The date interval specification, or the default value on failure.
*/
public static function week($weeks = 1, $default = null) {
// Parse the week parameter, and make sure it's valid
if($weeks === null)
$weeks = 1;
// Create and return a new date interval specification, or return the default value on failure
return static::create(null, null, null, $weeks, null, null, null, $default);
}
/**
* Alias of week();
*
* Create a date interval specification for one, or the given number of weeks.
*
* @param int $weeks [optional] The number of weeks. Null to use one week.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return string|mixed The date interval specification, or the default value on failure.
*/
public static function weeks($weeks = 1, $default = null) {
return static::week($weeks, $default);
}
/**
* Create a date interval specification for one, or the given number of days.
*
* @param int $days [optional] The number of days. Null to use one day.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return string|mixed The date interval specification, or the default value on failure.
*/
public static function day($days = 1, $default = null) {
// Parse the day parameter, and make sure it's valid
if($days === null)
$days = 1;
// Create and return a new date interval specification, or return the default value on failure
return static::create(null, null, null, $days, null, null, null, $default);
}
/**
* Alias of day();
*
* Create a date interval specification for one, or the given number of days.
*
* @param int $days [optional] The number of days. Null to use one day.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return string|mixed The date interval specification, or the default value on failure.
*/
public static function days($days = 1, $default = null) {
return static::day($days, $default);
}
/**
* Create a date interval specification for one, or the given number of hours.
*
* @param int $hours [optional] The number of hours. Null to use one hour.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return string|mixed The date interval specification, or the default value on failure.
*/
public static function hour($hours = 1, $default = null) {
// Parse the hour parameter, and make sure it's valid
if($hours === null)
$hours = 1;
// Create and return a new date interval specification, or return the default value on failure
return static::create(null, null, null, $hours, null, null, null, $default);
}
/**
* Alias of hour();
*
* Create a date interval specification for one, or the given number of hours.
*
* @param int $hours [optional] The number of hours. Null to use one hour.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return string|mixed The date interval specification, or the default value on failure.
*/
public static function hours($hours = 1, $default = null) {
return static::hour($hours, $default);
}
/**
* Create a date interval specification for one, or the given number of minutes.
*
* @param int $minutes [optional] The number of minutes. Null to use one minute.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return string|mixed The date interval specification, or the default value on failure.
*/
public static function minute($minutes = 1, $default = null) {
// Parse the minute parameter, and make sure it's valid
if($minutes === null)
$minutes = 1;
// Create and return a new date interval specification, or return the default value on failure
return static::create(null, null, null, $minutes, null, null, null, $default);
}
/**
* Alias of minute();
*
* Create a date interval specification for one, or the given number of minutes.
*
* @param int $minutes [optional] The number of minutes. Null to use one minute.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return string|mixed The date interval specification, or the default value on failure.
*/
public static function minutes($minutes = 1, $default = null) {
return static::minute($minutes, $default);
}
/**
* Create a date interval specification for one, or the given number of seconds.
*
* @param int $seconds [optional] The number of seconds. Null to use one second.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return string|mixed The date interval specification, or the default value on failure.
*/
public static function second($seconds = 1, $default = null) {
// Parse the second parameter, and make sure it's valid
if($seconds === null)
$seconds = 1;
// Create and return a new date interval specification, or return the default value on failure
return static::create(null, null, null, $seconds, null, null, null, $default);
}
/**
* Alias of second();
*
* Create a date interval specification for one, or the given number of seconds.
*
* @param int $seconds [optional] The number of seconds. Null to use one second.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return string|mixed The date interval specification, or the default value on failure.
*/
public static function seconds($seconds = 1, $default = null) {
return static::second($seconds, $default);
}
}
<?php
namespace carbon\core\datetime\interval\spec;
use carbon\core\datetime\DateTime;
use carbon\core\datetime\interval\DateInterval;
use DateInterval as PHPDateInterval;
use Exception;
// Prevent direct requests to this set_file due to security reasons
defined('CARBON_CORE_INIT') or die('Access denied!');
class DateIntervalSpecUtils {
/**
* Defines the regex to use to validate a date interval specification string according to ISO-8601.
*
* @const string The date interval validation regex.
*/
const DATE_INTERVAL_SPEC_REGEX = '/^\s*P((((([0-9]+Y([0-9]+M)?([0-9]+[DW])?)|([0-9]+M([0-9]+[DW])?)|([0-9]+[DW]))(T(([0-9]+H([0-9]+M)?([0-9]+S)?)|([0-9]+M([0-9]+S)?)|([0-9]+S)))?|(T(([0-9]+H([0-9]+M)?([0-9]+S)?)|([0-9]+M([0-9]+S)?)|([0-9]+S)))))|(([0-9]{4}-(0[0-9]|1[0-2])-([0-2][0-9]|3[0-1]))T(([0-1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9])))\s*$/';
/**
* Try to parse a date interval specification string.
*
* @param string|DateInterval|PHPDateInterval|null $dateIntervalSpec [optional] A date interval specification, a
* relative date and time string, a DateInterval or PHPDateInterval instance or null to create a zero
* configuration.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return string|mixed The parsed date interval specification or the default value on failure.
*/
public static function parse($dateIntervalSpec = null, $default = null) {
// Return a zero specification if the specification is set to null
if($dateIntervalSpec === null)
return DateIntervalSpecFactory::zero();
// Parse strings
if(is_string($dateIntervalSpec)) {
// Check whether the string is already a valid specification
if(static::isValid($dateIntervalSpec))
return $dateIntervalSpec;
// Check whether the string has relative keywords
if(DateTime::hasRelativeKeywords($dateIntervalSpec)) {
try {
// Try to parse the string as relative date and time
$dateInterval = DateInterval::createFromDateString($dateIntervalSpec);
// Get and return the date interval specification
return $dateInterval->toSpecString();
} catch(Exception $ex) { }
}
}
// Parse DateInterval objects
if($dateIntervalSpec instanceof DateInterval)
return $dateIntervalSpec->toSpecString();
// Parse PHPDateInterval objects
if($dateIntervalSpec instanceof PHPDateInterval)
return DateIntervalSpecFactory::create($dateIntervalSpec->y, $dateIntervalSpec->m, null, $dateIntervalSpec->d,
$dateIntervalSpec->h, $dateIntervalSpec->i, $dateIntervalSpec->s);
// Couldn't parse the string, return the default value
return $default;
}
/**
* Validate whether a date interval specification string is valid or not based on ISO-8601.
*
* @param string $dateIntervalSpec The date interval specification string to validate.
*
* @return bool True if the date interval specification is valid, false otherwise.
*/
public static function isValid($dateIntervalSpec) {
// Make sure the param is a string
if(!is_string($dateIntervalSpec))
return false;
// Check whether the specification is valid using a regular expression, return the result
return preg_match(static::DATE_INTERVAL_SPEC_REGEX, $dateIntervalSpec) > 0;
}
}
<?php
namespace carbon\core\datetime\period;
use DatePeriod as PHPDatePeriod;
// Prevent direct requests to this set_file due to security reasons
defined('CARBON_CORE_INIT') or die('Access denied!');
class DatePeriod extends PHPDatePeriod {
// TODO: Parse method!
}
<?php
namespace carbon\core\datetime\zone;
use carbon\core\datetime\DateTime;
use carbon\core\datetime\DateTimeUtils;
use carbon\core\util\StringUtils;
use DateTime as PHPDateTime;
use DateTimeZone as PHPDateTimeZone;
// Prevent direct requests to this file due to security reasons
defined('CARBON_CORE_INIT') or die('Access denied!');
class DateTimeZone extends PHPDateTimeZone {
// TODO: Make sure all DateTimeZone and PHPDateTimeZone instances are correct!
/**
* Constructor.
*
* @param string|PHPDateTimeZone|PHPDateTimeZone|null $timezone [optional] The timezone as a string, or as DateTimeZone or PHPDateTimeZone instance. Null to use the default timezone.
*
* @throws \Exception Throws an exception on failure.
*/
// TODO: Does this constructor still throw an error on failure?
public function __construct($timezone) {
// Use the default timezone if the parameter is null
if($timezone === null)
$timezone = DateTimeZoneUtils::getDefaultTimezone();
// If the timezone is already a DateTimeZone or PHPDateTimeZone instance, copy it
if($timezone instanceof parent) {
parent::__construct($timezone->getName());
return $this;
}
// Try to construct the parent object
parent::__construct($timezone);
return $this;
}
/**
* Parse a timezone. A new instance will be created if required.
*
* @param PHPDateTimeZone|PHPDateTimeZone|string|DateTime|PHPDateTime|null $timezone The timezone to parse as DateTimeZone or PHPDateTimeZone instance or as a string. A DateTime or PHPDateTime instance to use it's timezone. Null to parse as the default timezone.
*
* @return PHPDateTimeZone|null The parsed timezone as DateTimeZone instance, or null on failure.
*/
public static function parse($timezone = null) {
return DateTimeZoneUtils::parse($timezone, null);
}
/**
* Check whether this timezone equals another timezone.
*
* @param PHPDateTimeZone|PHPDateTimeZone|string|DateTime|PHPDateTime $timezone The other timezone as DateTimeZone or PHPDateTimeZone instance, or the timezone ID as a string. A DateTime or PHPDateTime instance may be supplied to use it's timezone.
*
* @return bool True if the timezones equal, false if not. False will also be returned if an error occurred.
*/
public function equals($timezone) {
// Parse the timezone
if(($timezone = static::parse($timezone)) === null)
return false;
// Compare the timezone IDs of both instances, return the result
return StringUtils::equals($this->getName(), $timezone->getName(), false);
}
/**
* Check whether a timezone is local relative to this timezone. This compares the offset of both timezones at a specific point in time.
*
* @param PHPDateTimeZone|PHPDateTimeZone|string|DateTime|PHPDateTime|null $timezone [optional] A DateTimeZone or PHPDateTimeZone instance, the timezone ID as a string, a DateTime or PHPDateTime instance to use it's timezone or null to use the defualt timezone.
* @param DateTime|PHPDateTime|string|null $dateTime [optional] The specific point in date and time to compare the offsets at. A DateTime or PHPDateTime instance, the date and time as a string or null to use the now() value.
*
* @return bool True if the timezone is local, false if not. False will also be returned on failure.
*/
public function isLocal($timezone = null, $dateTime = null) {
// Parse the timezone, return false on failure
if(($timezone = static::parse($timezone)) === null)
return false;
// Parse the date and time, return false on failure
if(($dateTime = DateTimeUtils::parse($dateTime, $timezone, null)) === null)
return false;
// Compare the offsets of both timezones at the specific point in time, return the result
return $this->getOffset($dateTime) == $timezone->getOffset($dateTime);
}
}
<?php
namespace carbon\core\datetime\zone;
use carbon\core\datetime\DateTime;
use DateTime as PHPDateTime;
use DateTimeZone as PHPDateTimeZone;
// Prevent direct requests to this file due to security reasons
defined('CARBON_CORE_INIT') or die('Access denied!');
class DateTimeZoneUtils {
// TODO: Make sure all DateTimeZone and PHPDateTimeZone instances are correct!
// TODO: TimeZone or Timezone? Use only one of the two, not both!
/**
* Parse a timezone. A new instance will be created if required.
*
* @param DateTimeZone|PHPDateTimeZone|string|DateTime|PHPDateTime|null $timezone The timezone to parse as DateTimeZone or PHPDateTimeZone instance or as a string. A DateTime or PHPDateTime instance to use it's timezone. Null to parse as the default timezone.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return DateTimeZone|mixed The parsed timezone as DateTimeZone instance, or the default value on failure.
*/
public static function parse($timezone = null, $default = null) {
// Return the timezone if it's already a DateTimeZone instance
if($timezone instanceof DateTimeZone)
return $timezone;
// Get the timezone form a DateTime object
else if($timezone instanceof DateTime)
$timezone = $timezone->getTimezone();
// Get the timezone from a PHPDateTimeZone object, and make sure it's valid
else if($timezone instanceof PHPDateTime)
if(($timezone = static::parse($timezone->getTimezone())) === null)
return $default;
// If the timezone is a string, make sure the timezone ID is valid, return the default value if not
// TODO: Should we check this for everything, or just for strings?
if(is_string($timezone))
if(!static::isValidTimezoneId($timezone))
return $default;
// Try to parse and return the timezone
try {
return new DateTimeZone($timezone);
} catch(\Exception $ex) {
// Return the default value on failure
return $default;
}
}
// TODO: equals(...); method (also to the base class)!
/**
* Get the default timezone for all date and time functions.
*
* @return DateTimeZone The default timezone.
*/
public static function getDefaultTimezone() {
return static::parse(date_default_timezone_get());
}
/**
* Set the default timezone for all date and time functions.
*
* @param DateTimeZone|PHPDateTimeZone|string|null $timezone The timezone as DateTimeZone instance, the timezone ID as a string or null to use the default timezone configured in PHPs configuration file.
*
* @return bool True if succeed, false on failure.
*/
public static function setDefaultTimezone($timezone) {
// Check whether the default timezone should be restored
if($timezone === null)
// TODO: Read the real-default timezone from other sources if possible
$timezone = ini_get('date.timezone');
// Parse the timezone and make sure it's valid
if(($timezone = static::parse($timezone, null)) === null)
return false;
// Set the default timezone
date_default_timezone_set($timezone->getName());
}
/**
* Check whether a timezone ID is valid. A timezone ID is specified by a string, see PHPs list of supported timezones.
*
* @param string $timezone The timezone ID to validate.
*
* @return bool True if the timezone ID is valid, false otherwise.
*/
// TODO: Can we improve the speed and readability of this method?
public static function isValidTimezoneId($timezone) {
// Create a list of valid timezones
$valid = array();
// Get the list of supported PHP timezones
$timezoneList = timezone_abbreviations_list();
// Create a list of valid timezones
foreach($timezoneList as $zone)
foreach($zone as $item)
$valid[$item['timezone_id']] = true;
// Remove the invalid keys
unset($valid['']);
// Check weather the timezone ID exists as a key in the array, return the result
return !!$valid[$timezone];
}
/**
* Check whether the timezones a and b are equal to each other.
*
* @param DateTimeZone|PHPDateTimeZone|string|null $a [optional] The timezone as DateTimeZone or PHPDateTimeZone instance, the timezone ID as a string or null to use the default timezone.
* @param DateTimeZone|PHPDateTimeZone|string|null $b [optional] The timezone as DateTimeZone or PHPDateTimeZone instance, the timezone ID as a string or null to use the default timezone.
* @param null|mixed $default [optional] The default value returned on failure.
*
* @return bool|mixed True if the timezones are equal, false if not. The default value will be returned on failure.
*/
public static function equals($a = null, $b = null, $default = null) {
// Parse the timezone of a, return the default value on failure
if(($a = static::parse($a, null)) === null)
return $default;
// Check whether the timezones are equal, return the result
return $a->equals($b);
}
/**
* Check whether the timezone a and b are local. This compares the offset of both timezones at a specific point in time.
*
* @param DateTimeZone|PHPDateTimeZone|string|DateTime|PHPDateTime|null $a [optional] A DateTimeZone or PHPDateTimeZone instance, the timezone ID as a string, a DateTime or PHPDateTime instance to use it's timezone or null to use the defualt timezone.
* @param DateTimeZone|PHPDateTimeZone|string|DateTime|PHPDateTime|null $b [optional] A DateTimeZone or PHPDateTimeZone instance, the timezone ID as a string, a DateTime or PHPDateTime instance to use it's timezone or null to use the defualt timezone.
* @param DateTime|PHPDateTime|string|null $dateTime [optional] The specific point in date and time to compare the offsets at. A DateTime or PHPDateTime instance, the date and time as a string or null to use the now() value.
* @param mixed|null $default [optional] The default value returned on failure.
*
* @return bool True if the timezone is local, false if not. The default value will be returned on failure.
*/
public function isLocal($a = null, $b = null, $dateTime = null, $default = null) {
// Parse the timezone of a, return false on failure
if(($a = static::parse($a)) === null)
return $default;
// Check whether the timezone of a and b are local, return the result or return the default value on failure
return ($result = $a->isLocal($b, $dateTime)) === null ? $default : $result;
}
/**
* Creates a DateTimeZone from a string or a PHPDateTimeZone.
*
* @param PHPDateTimeZone|string|null $timeZone
*
* @return PHPDateTimeZone
*
* @throws \InvalidArgumentException
*/
// TODO: Should we keep this method?
public static function safeCreateDateTimeZone($timeZone) {
// Return the default time zone if nothing was supplied
if($timeZone === null)
// Don't return null to avoid the PHP bug #52063 (< v5.3.6)
return static::getDefaultTimezone();
// Immediately return the object if it's already a time zone instance
if($timeZone instanceof PHPDateTimeZone)
return $timeZone;
// Try to parse the timezone, throw an exception on failure
if(($timeZone = static::parse($timeZone, null)) === null)
// Failed to create a time zone object, thrown an exception
throw new \InvalidArgumentException('Unknown or bad timezone ('.$timeZone.')');
return $timeZone;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment