Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'core/Date.php')
-rw-r--r--core/Date.php425
1 files changed, 302 insertions, 123 deletions
diff --git a/core/Date.php b/core/Date.php
index f6aefce606..87fd5d55a0 100644
--- a/core/Date.php
+++ b/core/Date.php
@@ -18,66 +18,192 @@
class Piwik_Date
{
/**
+ * Builds a Piwik_Date object
+ *
+ * @param int timestamp
+ */
+ protected function __construct( $timestamp, $timezone = 'UTC')
+ {
+ if(!is_int( $timestamp ))
+ {
+ throw new Exception("Piwik_Date is expecting a unix timestamp");
+ }
+ $this->timezone = $timezone;
+ $this->timestamp = $timestamp ;
+ }
+
+
+ /**
* Returns a Piwik_Date objects.
- * Accepts strings 'today' 'yesterday' or any YYYY-MM-DD or timestamp
*
- * @param string $strDate
- * @return Piwik_Date
+ * @param string $strDate 'today' 'yesterday' or any YYYY-MM-DD or timestamp
+ * @param string $timezone if specified, the dateString will be relative to this $timezone.
+ * For example, today in UTC+12 will be a timestamp in the future for UTC.
+ * This is different from using ->setTimezone()
+ * @return Piwik_Date
*/
- static public function factory($dateString)
+ static public function factory($dateString, $timezone = null)
{
- if($dateString == 'today')
+ if($dateString == 'now')
+ {
+ $date = self::now();
+ }
+ elseif($dateString == 'today')
{
- return self::today();
+ $date = self::today();
}
- if($dateString == 'yesterday')
+ elseif($dateString == 'yesterday')
{
- return self::yesterday();
+ $date = self::yesterday();
}
- if (!is_int($dateString)
+ elseif($dateString == 'yesterdaySameTime')
+ {
+ $date = self::yesterdaySameTime();
+ }
+ elseif (!is_int($dateString)
&& ($dateString = strtotime($dateString)) === false)
{
- throw new Exception("Date format must be: YYYY-MM-DD, or 'today' or 'yesterday' or any keyword supported by the strtotime function (see http://php.net/strtotime for more information)");
+ throw new Exception(Piwik_TranslateException('General_ExceptionInvalidDateFormat', array("YYYY-MM-DD, or 'today' or 'yesterday'", "strtotime", "http://php.net/strtotime")));
+ }
+ else
+ {
+ $date = new Piwik_Date($dateString);
+ }
+ if(is_null($timezone))
+ {
+ return $date;
+ }
+
+ // manually adjust for UTC timezones
+ $utcOffset = self::extractUtcOffset($timezone);
+ if($utcOffset !== false)
+ {
+ return $date->addHour($utcOffset);
}
- return new Piwik_Date($dateString);
+
+ date_default_timezone_set($timezone);
+ $datetime = $date->getDatetime();
+ date_default_timezone_set('UTC');
+
+ $date = Piwik_Date::factory(strtotime($datetime));
+
+ return $date;
}
+ /*
+ * The stored timestamp is always UTC based.
+ * The returned timestamp via getTimestamp() will have the conversion applied
+ */
protected $timestamp = null;
+
+ /*
+ * Timezone the current date object is set to.
+ * Timezone will only affect the returned timestamp via getTimestamp()
+ */
+ protected $timezone = 'UTC';
+
+ const DATE_TIME_FORMAT = 'Y-m-d H:i:s';
+
+ /**
+ * Returns the datetime start in UTC
+ *
+ * @return string
+ */
+ function getDateStartUTC()
+ {
+ $dateStartUTC = date('Y-m-d', $this->timestamp);
+ $date = Piwik_Date::factory($dateStartUTC)->setTimezone($this->timezone);
+ return $date->toString(self::DATE_TIME_FORMAT);
+ }
+ /**
+ * Returns the datetime of the current timestamp
+ *
+ * @return string
+ */
+ function getDatetime()
+ {
+ return $this->toString(self::DATE_TIME_FORMAT);
+ }
+
+ /**
+ * Returns the datetime end in UTC
+ *
+ * @return string
+ */
+ function getDateEndUTC()
+ {
+ $dateEndUTC = date('Y-m-d 23:59:59', $this->timestamp);
+ $date = Piwik_Date::factory($dateEndUTC)->setTimezone($this->timezone);
+ return $date->toString(self::DATE_TIME_FORMAT);
+ }
+
/**
- * Returns the unix timestamp of the date
- *
- * @return int
+ * Returns a new date object, copy of $this, with the timezone set
+ * This timezone is used to offset the UTC timestamp returned by @see getTimestamp()
+ * Doesn't modify $this
+ *
+ * @param string $timezone 'UTC', 'Europe/London', ...
*/
- public function getTimestamp()
+ public function setTimezone($timezone)
{
- return $this->timestamp;
+ return new Piwik_Date($this->timestamp, $timezone);
}
/**
- * Builds a Piwik_Date object
+ * Helper function that returns the offset in the timezone string 'UTC+14'
+ * Returns false if the timezone is not UTC+X or UTC-X
*
- * @param int timestamp
+ * @param $timezone
+ * @return int or false
*/
- protected function __construct( $date )
+ static protected function extractUtcOffset($timezone)
{
- if(!is_int( $date ))
+ if($timezone == 'UTC')
{
- throw new Exception("Piwik_Date is expecting a unix timestamp");
+ return 0;
+ }
+ $start = substr($timezone, 0, 4);
+ if($start != 'UTC-'
+ && $start != 'UTC+')
+ {
+ return false;
}
- $this->timestamp = $date ;
+ $offset = (float)substr($timezone, 4);
+ if($start == 'UTC-') {
+ $offset = -$offset;
+ }
+ return $offset;
}
/**
- * Sets the time part of the date
- * Doesn't modify $this
- *
- * @param string $time HH:MM:SS
- * @return Piwik_Date The new date with the time part set
+ * Returns the unix timestamp of the date in UTC,
+ * converted from the date timezone
+ *
+ * @return int
*/
- public function setTime($time)
+ public function getTimestamp()
{
- return new Piwik_Date( strtotime( $this->get("j F Y") . " $time"));
+ $utcOffset = self::extractUtcOffset($this->timezone);
+ if($utcOffset !== false) {
+ return (int)($this->timestamp - $utcOffset * 3600);
+ }
+ // @fixme
+ // The following code seems clunky - I thought the DateTime php class would allow to return timestamps
+ // after applying the timezone offset. Instead, the underlying timestamp is not changed.
+ // I decided to get the date without the timezone information, and create the timestamp from the truncated string.
+ // Unit tests pass (@see Date.test.php) but I'm pretty sure this is not the right way to do it
+ date_default_timezone_set($this->timezone);
+ $dtzone = timezone_open('UTC');
+ $time = date('r', $this->timestamp);
+ $dtime = date_create($time);
+ date_timezone_set($dtime, $dtzone);
+ $dateWithTimezone = date_format($dtime, 'r');
+ $dateWithoutTimezone = substr($dateWithTimezone, 0, -6);
+ $timestamp = strtotime($dateWithoutTimezone);
+ date_default_timezone_set('UTC');
+
+ return (int)$timestamp;
}
/**
@@ -113,7 +239,7 @@ class Piwik_Date
{
return date($part, $this->getTimestamp());
}
-
+
/**
* @see toString()
*
@@ -125,6 +251,114 @@ class Piwik_Date
}
/**
+ * Compares the week of the current date against the given $date
+ * Returns 0 if equal, -1 if current week is earlier or 1 if current week is later
+ * Example: 09.Jan.2007 13:07:25 -> compareWeek(2); -> 0
+ *
+ * @param Piwik_Date $date
+ * @return integer 0 = equal, 1 = later, -1 = earlier
+ */
+ public function compareWeek(Piwik_Date $date)
+ {
+ $currentWeek = date('W', $this->getTimestamp());
+ $toCompareWeek = date('W', $date->getTimestamp());
+ if( $currentWeek == $toCompareWeek)
+ {
+ return 0;
+ }
+ if( $currentWeek < $toCompareWeek)
+ {
+ return -1;
+ }
+ return 1;
+ }
+
+ /**
+ * Compares the month of the current date against the given $date month
+ * Returns 0 if equal, -1 if current month is earlier or 1 if current month is later
+ * For example: 10.03.2000 -> 15.03.1950 -> 0
+ *
+ * @param Piwik_Date $month Month to compare
+ * @return integer 0 = equal, 1 = later, -1 = earlier
+ */
+ function compareMonth( Piwik_Date $date )
+ {
+ $currentMonth = date('n', $this->getTimestamp());
+ $toCompareMonth = date('n', $date->getTimestamp());
+ if( $currentMonth == $toCompareMonth)
+ {
+ return 0;
+ }
+ if( $currentMonth < $toCompareMonth)
+ {
+ return -1;
+ }
+ return 1;
+ }
+
+ /**
+ * Returns true if current date is today
+ *
+ * @return bool
+ */
+ public function isToday()
+ {
+ return $this->toString('Y-m-d') === Piwik_Date::factory('today', $this->timezone)->toString('Y-m-d');
+ }
+
+ /**
+ * Returns a date object set to now (same as today, except that the time is also set)
+ *
+ * @return Piwik_Date
+ */
+ static public function now()
+ {
+ return new Piwik_date(time());
+ }
+
+ /**
+ * Returns a date object set to today midnight
+ *
+ * @return Piwik_Date
+ */
+ static public function today()
+ {
+ return new Piwik_Date(strtotime(date("Y-m-d 00:00:00")));
+ }
+
+ /**
+ * Returns a date object set to yesterday midnight
+ *
+ * @return Piwik_Date
+ */
+ static public function yesterday()
+ {
+ return new Piwik_Date(strtotime("yesterday"));
+ }
+
+ /**
+ * Returns a date object set to yesterday same time of day
+ *
+ * @return Piwik_Date
+ */
+ static public function yesterdaySameTime()
+ {
+ return new Piwik_Date(strtotime("yesterday ".date('H:i:s')));
+ }
+
+ /**
+ * Sets the time part of the date
+ * Doesn't modify $this
+ *
+ * @param string $time HH:MM:SS
+ * @return Piwik_Date The new date with the time part set
+ */
+ public function setTime($time)
+ {
+ return new Piwik_Date( strtotime( date("Y-m-d", $this->timestamp) . " $time"), $this->timezone);
+ }
+
+ /**
* Sets a new day
* Returned is the new date object
* Doesn't modify $this
@@ -134,7 +368,7 @@ class Piwik_Date
*/
public function setDay( $day )
{
- $ts = $this->getTimestamp();
+ $ts = $this->timestamp;
$result = mktime(
date('H', $ts),
date('i', $ts),
@@ -143,7 +377,7 @@ class Piwik_Date
1,
date('Y', $ts)
);
- return new Piwik_Date( $result );
+ return new Piwik_Date( $result, $this->timezone );
}
/**
@@ -156,7 +390,7 @@ class Piwik_Date
*/
public function setYear( $year )
{
- $ts = $this->getTimestamp();
+ $ts = $this->timestamp;
$result = mktime(
date('H', $ts),
date('i', $ts),
@@ -165,11 +399,9 @@ class Piwik_Date
date('j', $ts),
$year
);
- return new Piwik_Date( $result );
+ return new Piwik_Date( $result, $this->timezone );
}
-
-
/**
* Subtracts days from the existing date object and returns a new Piwik_Date object
* Returned is the new date object
@@ -183,8 +415,8 @@ class Piwik_Date
{
return clone $this;
}
- $ts = strtotime("-$n day", $this->getTimestamp());
- return new Piwik_Date( $ts );
+ $ts = strtotime("-$n day", $this->timestamp);
+ return new Piwik_Date( $ts, $this->timezone );
}
/**
@@ -200,7 +432,7 @@ class Piwik_Date
{
return clone $this;
}
- $ts = $this->getTimestamp();
+ $ts = $this->timestamp;
$result = mktime(
date('H', $ts),
date('i', $ts),
@@ -209,23 +441,8 @@ class Piwik_Date
1, // we set the day to 1
date('Y', $ts)
);
- return new Piwik_Date( $result );
+ return new Piwik_Date( $result, $this->timezone );
}
-
- /**
- * Returns a representation of a date or datepart
- *
- * @param string OPTIONAL Part of the date to return, if null the timestamp is returned
- * @return integer|string date or datepart
- */
- public function get($part = null)
- {
- if(is_null($part))
- {
- return $this->getTimestamp();
- }
- return date($part, $this->getTimestamp());
- }
/**
* Returns a localized date string, given a template.
@@ -247,12 +464,12 @@ class Piwik_Date
"%longDay%" => Piwik_Translate('General_LongDay_'.$dayOfWeek),
"%longYear%" => $this->toString('Y'),
"%shortYear%" => $this->toString('y'),
- "%time%" => $this->toString('H:i:s T')
+ "%time%" => $this->toString('H:i:s')
);
$out = str_replace(array_keys($patternToValue), array_values($patternToValue), $template);
return $out;
}
-
+
/**
* Adds days to the existing date object.
* Returned is the new date object
@@ -263,82 +480,44 @@ class Piwik_Date
*/
public function addDay( $n )
{
- $ts = strtotime("+$n day", $this->getTimestamp());
- return new Piwik_Date( $ts );
+ $ts = strtotime("+$n day", $this->timestamp);
+ return new Piwik_Date( $ts, $this->timezone );
}
-
- /**
- * Compares the week of the current date against the given $date
- * Returns 0 if equal, -1 if current week is earlier or 1 if current week is later
- * Example: 09.Jan.2007 13:07:25 -> compareWeek(2); -> 0
- *
- * @param Piwik_Date $date
- * @return integer 0 = equal, 1 = later, -1 = earlier
- */
- public function compareWeek(Piwik_Date $date)
- {
- $currentWeek = date('W', $this->getTimestamp());
- $toCompareWeek = date('W', $date->getTimestamp());
- if( $currentWeek == $toCompareWeek)
- {
- return 0;
- }
- if( $currentWeek < $toCompareWeek)
- {
- return -1;
- }
- return 1;
- }
+
/**
- * Compares the month of the current date against the given $date month
- * Returns 0 if equal, -1 if current month is earlier or 1 if current month is later
- * For example: 10.03.2000 -> 15.03.1950 -> 0
- *
- * @param Piwik_Date $month Month to compare
- * @return integer 0 = equal, 1 = later, -1 = earlier
+ * Adds hours to the existing date object.
+ * Returned is the new date object
+ * Doesn't modify $this
+ *
+ * @param int Number of hours to add
+ * @return Piwik_Date new date
*/
- function compareMonth( Piwik_Date $date )
+ public function addHour( $n )
{
- $currentMonth = date('n', $this->getTimestamp());
- $toCompareMonth = date('n', $date->getTimestamp());
- if( $currentMonth == $toCompareMonth)
+ $minutes = 0;
+ if($n != round($n))
{
- return 0;
+ $minutes = abs($n - floor($n)) * 60;
+ $n = floor($n);
}
- if( $currentMonth < $toCompareMonth)
+ if($n > 0 )
{
- return -1;
+ $n = '+'.$n;
}
- return 1;
+ $ts = strtotime("$n hour $minutes minutes", $this->timestamp);
+ return new Piwik_Date( $ts, $this->timezone );
}
-
- /**
- * Returns true if current date is today
- *
- * @return bool
- */
- public function isToday()
- {
- return $this->get('Y-m-d') === date('Y-m-d', time());
- }
-
- /**
- * Returns a date object set to today midnight
- *
- * @return Piwik_Date
- */
- static public function today()
- {
- return new Piwik_Date(strtotime(date("Y-m-d 00:00:00")));
- }
-
+
/**
- * Returns a date object set to yesterday midnight
- *
- * @return Piwik_Date
- */
- static public function yesterday()
+ * Substract hour to the existing date object.
+ * Returned is the new date object
+ * Doesn't modify $this
+ *
+ * @param int Number of hours to substract
+ * @return Piwik_Date new date
+ */
+ public function subHour( $n )
{
- return new Piwik_Date(strtotime("yesterday"));
+ return $this->addHour(-$n);
}
}