├── .gitignore
├── .travis.yml
├── LICENSE
├── README.rst
├── composer.json
├── src
└── FreeAgent
│ └── Bitter
│ ├── Bitter.php
│ ├── Date
│ └── DatePeriod.php
│ └── UnitOfTime
│ ├── AbstractUnitOfTime.php
│ ├── Day.php
│ ├── Hour.php
│ ├── Month.php
│ ├── UnitOfTimeInterface.php
│ ├── Week.php
│ └── Year.php
└── tests
└── units
├── Bitter.php
├── Date
└── DatePeriod.php
└── UnitOfTime
├── AbstractUnitOfTime.php
├── Day.php
├── Hour.php
├── Month.php
├── Week.php
└── Year.php
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor
2 | bin
3 | composer.lock
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 5.3
5 | - 5.4
6 |
7 | services:
8 | - redis-server
9 |
10 | before_script:
11 | # install phpredis extension.
12 | - sh -c "git clone https://github.com/nicolasff/phpredis/ && cd phpredis && phpize && ./configure && make && sudo make install " > /dev/null
13 | - echo "extension=redis.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`
14 | - pecl install bitset
15 | # composer install
16 | - wget http://getcomposer.org/composer.phar
17 | - php composer.phar install --dev
18 |
19 |
20 | script:
21 | - bin/atoum -d tests/units
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012 Jérémy Romey
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is furnished
8 | to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | Bitter Documentation
2 | ====================
3 |
4 | .. image:: https://secure.travis-ci.org/jeremyFreeAgent/Bitter.png?branch=master
5 | :target: http://travis-ci.org/jeremyFreeAgent/Bitter
6 |
7 | **1.2.0 WORK IN PROGRESS**
8 |
9 | Bitter is a simple but powerful analytics library
10 |
11 | "Use Bitter and you have time to drink a bitter beer !"
12 |
13 | -- **Jérémy Romey**
14 |
15 | Bitter can answer following questions:
16 |
17 | * Has user X been online today? This week? This month?
18 | * Has user X performed action "Y"?
19 | * How many users have been active have this month? This hour?
20 | * How many unique users have performed action "Y" this week?
21 | * How many % of users that were active last week are still active?
22 | * How many % of users that were active last month are still active this month?
23 |
24 | Bitter is very easy to use and enables you to create your own reports easily - see the `Bitter Library `_ website for more info and documentation about this project.
25 |
26 | Installation
27 | ------------
28 | Use `Composer `_ to install: ``free-agent/bitter``.
29 |
30 | In your `composer.json` you should have:
31 |
32 | .. code-block:: yaml
33 |
34 | {
35 | "require": {
36 | "free-agent/bitter": "1.1.*"
37 | }
38 | }
39 |
40 | Requirements
41 | ~~~~~~~~~~~~
42 | Bitter uses `Redis `_ with version **>=2.6**.
43 |
44 | **Note**: Every key created in Redis will be prefixed by ``bitter:``, temp keys by ``bitter_temp:``.
45 |
46 | Bitter uses `Bitset PECL extension `_ with version **=1.0.1** for the ``getIds`` method.
47 |
48 | Basic usage
49 | -----------
50 | Create a Bitter with a Redis client (Predis as example):
51 |
52 | .. code-block:: php
53 |
54 | $redisClient = new \Predis\Client();
55 | $bitter = new \FreeAgent\Bitter\Bitter($redisClient);
56 |
57 | Mark user 123 as active and has played a song:
58 |
59 | .. code-block:: php
60 |
61 | $bitter
62 | ->mark('active', 123)
63 | ->mark('song:played', 123)
64 | ;
65 |
66 | **Note**: Please don't use huge ids (e.g. 2^32 or bigger) cause this will require large amounts of memory.
67 |
68 | Pass a DateTime as third argument:
69 |
70 | .. code-block:: php
71 |
72 | $bitter->mark('song:played', 123, new \DateTime('yesterday'));
73 |
74 | Test if user 123 has played a song this week:
75 |
76 | .. code-block:: php
77 |
78 | $currentWeek = new FreeAgent\Bitter\UnitOfTime\Week('song:played');
79 |
80 | if ($bitter->in(123, $currentWeek) {
81 | echo 'User with id 123 has played a song this week.';
82 | } else {
83 | echo 'User with id 123 has not played a song this week.';
84 | }
85 |
86 | How many users were active yesterday:
87 |
88 | .. code-block:: php
89 |
90 | $yesterday = new \FreeAgent\Bitter\UnitOfTime\Day('active', new \DateTime('yesterday'));
91 |
92 | echo $bitter->count($yesterday) . ' users were active yesterday.';
93 |
94 | Using BitOp
95 | -----------
96 | How many users that were active yesterday are also active today:
97 |
98 | .. code-block:: php
99 |
100 | $today = new \FreeAgent\Bitter\UnitOfTime\Day('active');
101 | $yesterday = new \FreeAgent\Bitter\UnitOfTime\Day('active', new \DateTime('yesterday'));
102 |
103 | $count = $bitter
104 | ->bitOpAnd('bit_op_example', $today, $yesterday)
105 | ->count('bit_op_example')
106 | ;
107 | echo $count . ' users were active yesterday and today.';
108 |
109 | **Note**: The ``bit_op_example`` key will expire after 60 seconds.
110 |
111 | Test if user 123 was active yesterday and is active today:
112 |
113 | .. code-block:: php
114 |
115 | $today = new \FreeAgent\Bitter\UnitOfTime\Day('active');
116 | $yesterday = new \FreeAgent\Bitter\UnitOfTime\Day('active', new \DateTime('yesterday'));
117 |
118 | $active = $bitter
119 | ->bitOpAnd('bit_op_example', $today, $yesterday)
120 | ->in(123, 'bit_op_example')
121 | ;
122 | if ($active) {
123 | echo 'User with id 123 was active yesterday and today.';
124 | } else {
125 | echo 'User with id 123 was not active yesterday and today.';
126 | }
127 |
128 | **Note**: Please look at `Redis BITOP Command `_ for performance considerations.
129 |
130 | Custom date period stats
131 | ------------------------
132 | How many users that were active during a given date period:
133 |
134 | .. code-block:: php
135 |
136 | $from = new \DateTime('2010-14-02 20:15:30');
137 | $to = new \DateTime('2012-21-12 13:30:45');
138 |
139 | $count = $bitter
140 | ->bitDateRange('active', 'active_period_example', $from, $to)
141 | ->count('active_period_example')
142 | ;
143 | echo $count . ' users were active from "2010-14-02 20:15:30" to "2012-21-12 13:30:45".';
144 |
145 | Get Ids for a given key
146 | -----------------------
147 | Get Ids for a given date period:
148 |
149 | .. code-block:: php
150 |
151 | $from = new \DateTime('2010-14-02 20:15:30');
152 | $to = new \DateTime('2012-21-12 13:30:45');
153 |
154 | $ids = $bitter
155 | ->bitDateRange('active', 'active_period_example', $from, $to)
156 | ->getIds('active_period_example')
157 | ;
158 | echo 'Ids of users that were active from "2010-14-02 20:15:30" to "2012-21-12 13:30:45":';
159 | echo '
';
160 | echo implode(', ', $ids);
161 |
162 | Unit Tests
163 | ----------
164 |
165 | You can run tests with:
166 |
167 | .. code-block:: sh
168 |
169 | bin/atoum -d tests/units
170 |
171 | Release notes
172 | -------------
173 | 1.2.0
174 |
175 | * Added a remove method to remove a specific temp key.
176 | * Added a removeEvent method to remove all data of an event.
177 | * Renamed Event to UnitOfTime in order to be more explicit.
178 |
179 | 1.1.0
180 |
181 | * Added date period stats with bitDateRange method.
182 |
183 | Todo
184 | ----
185 | * Implements the `Redis BITOP NOT Command `_.
186 |
187 | Thanks
188 | ------
189 | This library is a port of `bitmapist `_ (Python) by `Amir Salihefendic `_.
190 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "free-agent/bitter",
3 | "description": "Bitter is a simple but powerful analytics library",
4 | "keywords": ["bitter", "analytics", "redis"],
5 | "homepage": "https://github.com/jeremyFreeAgent/Bitter",
6 | "type": "library",
7 | "license": "MIT",
8 | "authors": [
9 | {
10 | "name": "Jérémy Romey",
11 | "email": "jeremy@free-agent.fr"
12 | }
13 | ],
14 | "support": {
15 | "issues": "https://github.com/jeremyFreeAgent/Bitter/issues"
16 | },
17 | "require": {
18 | "php": ">=5.3.3",
19 | "ext-bitset": "1.0.1"
20 | },
21 | "require-dev": {
22 | "predis/predis": "0.8.*",
23 | "atoum/atoum": "dev-master"
24 | },
25 | "suggest": {
26 | "predis/predis": "0.8.*"
27 | },
28 | "autoload": {
29 | "psr-0": {
30 | "FreeAgent\\Bitter": "src/"
31 | }
32 | },
33 | "config": {
34 | "bin-dir": "bin"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/FreeAgent/Bitter/Bitter.php:
--------------------------------------------------------------------------------
1 |
17 | */
18 | class Bitter
19 | {
20 | private $redisClient;
21 | private $prefixKey;
22 | private $prefixTempKey;
23 | private $expireTimeout;
24 |
25 | public function __construct($redisClient, $prefixKey = 'bitter:', $prefixTempKey = 'bitter_temp:', $expireTimeout = 60)
26 | {
27 | $this->setRedisClient($redisClient);
28 | $this->prefixKey = $prefixKey;
29 | $this->prefixTempKey = $prefixTempKey;
30 | $this->expireTimeout = $expireTimeout;
31 | }
32 |
33 | /**
34 | * Get the Redis client
35 | *
36 | * @return The Redis client
37 | */
38 | public function getRedisClient()
39 | {
40 | return $this->redisClient;
41 | }
42 |
43 | /**
44 | * Set the Redis client
45 | *
46 | * @param object $newredisClient The Redis client
47 | */
48 | public function setRedisClient($redisClient)
49 | {
50 | $this->redisClient = $redisClient;
51 |
52 | return $this;
53 | }
54 |
55 | /**
56 | * Marks an event for hours, days, weeks and months
57 | *
58 | * @param string $eventName The name of the event, could be "active" or "new_signups"
59 | * @param integer $id An unique id, typically user id. The id should not be huge, read Redis documentation why (bitmaps)
60 | * @param DateTime $dateTime Which date should be used as a reference point, default is now
61 | */
62 | public function mark($eventName, $id, DateTime $dateTime = null)
63 | {
64 | $dateTime = is_null($dateTime) ? new DateTime : $dateTime;
65 |
66 | $eventData = array(
67 | new Year($eventName, $dateTime),
68 | new Month($eventName, $dateTime),
69 | new Week($eventName, $dateTime),
70 | new Day($eventName, $dateTime),
71 | new Hour($eventName, $dateTime),
72 | );
73 |
74 | foreach ($eventData as $event) {
75 | $key = $this->prefixKey . $event->getKey();
76 | $this->getRedisClient()->setbit($key, $id, 1);
77 | $this->getRedisClient()->sadd($this->prefixKey . 'keys', $key);
78 | }
79 |
80 | return $this;
81 | }
82 |
83 | /**
84 | * Makes it possible to see if an id has been marked
85 | *
86 | * @param integer $id An unique id
87 | * @param mixed $key The key or the event
88 | * @return boolean True if the id has been marked
89 | */
90 | public function in($id, $key)
91 | {
92 | $key = $key instanceof UnitOfTimeInterface ? $this->prefixKey . $key->getKey() : $this->prefixTempKey . $key;
93 |
94 | return (bool) $this->getRedisClient()->getbit($key, $id);
95 | }
96 |
97 | /**
98 | * Counts the number of marks
99 | *
100 | * @param mixed $key The key or the event
101 | * @return integer The value of the count result
102 | */
103 | public function count($key)
104 | {
105 | $key = $key instanceof UnitOfTimeInterface ? $this->prefixKey . $key->getKey() : $this->prefixTempKey . $key;
106 |
107 | return (int) $this->getRedisClient()->bitcount($key);
108 | }
109 |
110 | private function bitOp($op, $destKey, $keyOne, $keyTwo)
111 | {
112 | $keyOne = $keyOne instanceof UnitOfTimeInterface ? $this->prefixKey . $keyOne->getKey() : $this->prefixTempKey . $keyOne;
113 | $keyTwo = $keyTwo instanceof UnitOfTimeInterface ? $this->prefixKey . $keyTwo->getKey() : $this->prefixTempKey . $keyTwo;
114 |
115 | $this->getRedisClient()->bitop($op, $this->prefixTempKey . $destKey, $keyOne, $keyTwo);
116 | $this->getRedisClient()->sadd($this->prefixTempKey . 'keys', $destKey);
117 | $this->getRedisClient()->expire($destKey, $this->expireTimeout);
118 |
119 | return $this;
120 | }
121 |
122 | public function bitOpAnd($destKey, $keyOne, $keyTwo)
123 | {
124 | return $this->bitOp('AND', $destKey, $keyOne, $keyTwo);
125 | }
126 |
127 | public function bitOpOr($destKey, $keyOne, $keyTwo)
128 | {
129 | return $this->bitOp('OR', $destKey, $keyOne, $keyTwo);
130 | }
131 |
132 | public function bitOpXor($destKey, $keyOne, $keyTwo)
133 | {
134 | return $this->bitOp('XOR', $destKey, $keyOne, $keyTwo);
135 | }
136 |
137 | public function bitDateRange($key, $destKey, DateTime $from, DateTime $to)
138 | {
139 | if ($from > $to) {
140 | throw new Exception("DateTime from (" . $from->format('Y-m-d H:i:s') . ") must be anterior to DateTime to (" . $to->format('Y-m-d H:i:s') . ").");
141 | }
142 |
143 | $this->getRedisClient()->del($this->prefixTempKey . $destKey);
144 |
145 | // Hours
146 | $hoursFrom = DatePeriod::createForHour($from, $to, DatePeriod::CREATE_FROM);
147 | foreach ($hoursFrom as $date) {
148 | $this->bitOpOr($destKey, new Hour($key, $date), $destKey);
149 | }
150 | $hoursTo = DatePeriod::createForHour($from, $to, DatePeriod::CREATE_TO);
151 | if (array_diff($hoursTo->toArray(true), $hoursFrom->toArray(true)) !== array_diff($hoursFrom->toArray(true), $hoursTo->toArray(true))) {
152 | foreach ($hoursTo as $date) {
153 | $this->bitOpOr($destKey, new Hour($key, $date), $destKey);
154 | }
155 | }
156 |
157 | // Days
158 | $daysFrom = DatePeriod::createForDay($from, $to, DatePeriod::CREATE_FROM);
159 | foreach ($daysFrom as $date) {
160 | $this->bitOpOr($destKey, new Day($key, $date), $destKey);
161 | }
162 | $daysTo = DatePeriod::createForDay($from, $to, DatePeriod::CREATE_TO);
163 | if (array_diff($daysTo->toArray(true), $daysFrom->toArray(true)) !== array_diff($daysFrom->toArray(true), $daysTo->toArray(true))) {
164 | foreach ($daysTo as $date) {
165 | $this->bitOpOr($destKey, new Day($key, $date), $destKey);
166 | }
167 | }
168 |
169 | // Months
170 | $monthsFrom = DatePeriod::createForMonth($from, $to, DatePeriod::CREATE_FROM);
171 | foreach ($monthsFrom as $date) {
172 | $this->bitOpOr($destKey, new Month($key, $date), $destKey);
173 | }
174 | $monthsTo = DatePeriod::createForMonth($from, $to, DatePeriod::CREATE_TO);
175 | if (array_diff($monthsTo->toArray(true), $monthsFrom->toArray(true)) !== array_diff($monthsFrom->toArray(true), $monthsTo->toArray(true))) {
176 | foreach ($monthsTo as $date) {
177 | $this->bitOpOr($destKey, new Month($key, $date), $destKey);
178 | }
179 | }
180 |
181 | // Years
182 | $years = DatePeriod::createForYear($from, $to);
183 | foreach ($years as $date) {
184 | $this->bitOpOr($destKey, new Year($key, $date), $destKey);
185 | }
186 |
187 | $this->getRedisClient()->sadd($this->prefixTempKey . 'keys', $destKey);
188 | $this->getRedisClient()->expire($destKey, $this->expireTimeout);
189 |
190 | return $this;
191 | }
192 |
193 | /**
194 | * Returns the ids of an key or event
195 | *
196 | * @param mixed $key The key or the event
197 | * @return array The ids array
198 | */
199 | public function getIds($key)
200 | {
201 | $key = $key instanceof UnitOfTimeInterface ? $this->prefixKey . $key->getKey() : $this->prefixTempKey . $key;
202 |
203 | $string = $this->getRedisClient()->get($key);
204 |
205 | $data = $this->bitsetToString($string);
206 |
207 | $ids = array();
208 | while (false !== ($pos = strpos($data, '1'))) {
209 | $data[$pos] = 0;
210 | $ids[] = (int)($pos/8)*8 + abs(7-($pos%8));
211 | }
212 |
213 | sort($ids);
214 |
215 | return $ids;
216 | }
217 |
218 | protected function bitsetToString($bitset = '')
219 | {
220 | return bitset_to_string($bitset);
221 | }
222 |
223 | /**
224 | * Removes all Bitter keys
225 | */
226 | public function removeAll()
227 | {
228 | $keys_chunk = array_chunk($this->getRedisClient()->smembers($this->prefixKey . 'keys'), 100);
229 |
230 | foreach ($keys_chunk as $keys) {
231 | $this->getRedisClient()->del($keys);
232 | }
233 |
234 | return $this;
235 | }
236 |
237 | /**
238 | * Removes all Bitter temp keys
239 | */
240 | public function removeTemp()
241 | {
242 | $keys_chunk = array_chunk($this->getRedisClient()->smembers($this->prefixTempKey . 'keys'), 100);
243 |
244 | foreach ($keys_chunk as $keys) {
245 | $this->getRedisClient()->del($keys);
246 | }
247 |
248 | return $this;
249 | }
250 | }
251 |
--------------------------------------------------------------------------------
/src/FreeAgent/Bitter/Date/DatePeriod.php:
--------------------------------------------------------------------------------
1 |
10 | */
11 | class DatePeriod extends \DatePeriod
12 | {
13 | const CREATE_FROM = 'from';
14 | const CREATE_TO = 'to';
15 |
16 | public function toArray($dateToString = false)
17 | {
18 | $dates = array();
19 | foreach ($this as $date) {
20 | $dates[] = true === $dateToString ? $date->format('Y-m-d H:i:s') : $date;
21 | }
22 |
23 | return $dates;
24 | }
25 |
26 | public static function createForHour(DateTime $from, DateTime $to, $fromOrTo = self::CREATE_FROM)
27 | {
28 | if ($from->format('Y-m-d') != $to->format('Y-m-d')) {
29 | if (self::CREATE_TO !== $fromOrTo) {
30 | $from->setTime($from->format('H'), 0, 0);
31 | $to = clone($from);
32 | $to->setTime(24, 0, 0);
33 | } else {
34 | $from = clone($to);
35 | $from->setTime(0, 0, 0);
36 | $to->setTime($to->format('H'), 0, 0);
37 | }
38 | } else {
39 | $from->setTime($from->format('H'), 0, 0);
40 | $to->setTime($to->format('H'), 0, 0);
41 | }
42 |
43 | return new DatePeriod($from, new DateInterval('PT1H'), $to);
44 | }
45 |
46 | public static function createForDay(DateTime $from, DateTime $to, $fromOrTo = self::CREATE_FROM)
47 | {
48 | $mFrom = $from;
49 | $mTo = $to;
50 | if ($mFrom->format('Y-m') != $mTo->format('Y-m')) {
51 | if (self::CREATE_TO !== $fromOrTo) {
52 | $mFrom->setTime(0, 0, 0);
53 | $mFrom->setDate($mFrom->format('Y'), $mFrom->format('m'), $mFrom->format('d'));
54 | $mTo = clone($mFrom);
55 | $mTo->setDate($mFrom->format('Y'), $mFrom->format('m') + 1, 1);
56 | } else {
57 | $mTo->setTime(0, 0, 0);
58 | $mFrom = clone($mTo);
59 | $mFrom->setDate($mFrom->format('Y'), $mFrom->format('m'), 1);
60 | $mTo->setDate($mTo->format('Y'), $mTo->format('m'), $mTo->format('d'));
61 | }
62 | } else {
63 | $mFrom->setTime(0, 0, 0);
64 | $mTo->setTime(0, 0, 0);
65 | }
66 |
67 | return new DatePeriod($mFrom, new DateInterval('P1D'), $mTo, self::CREATE_TO !== $fromOrTo || $from->format('Y-m') == $to->format('Y-m') ? self::EXCLUDE_START_DATE : null);
68 | }
69 |
70 | public static function createForMonth(DateTime $from, DateTime $to, $fromOrTo = self::CREATE_FROM)
71 | {
72 | $mFrom = $from;
73 | $mTo = $to;
74 | if ($mFrom->format('Y') != $to->format('Y')) {
75 | if (self::CREATE_TO !== $fromOrTo) {
76 | $mFrom->setTime(0, 0, 0);
77 | $mFrom->setDate($mFrom->format('Y'), $mFrom->format('m'), 1);
78 | $mTo = clone($mFrom);
79 | $mTo->setDate($mFrom->format('Y'), 13, 1);
80 | } else {
81 | $mTo->setTime(0, 0, 0);
82 | $mFrom = clone($mTo);
83 | $mFrom->setDate($mFrom->format('Y'), 1, 1);
84 | $mTo->setDate($mTo->format('Y'), $mTo->format('m'), 1);
85 | }
86 | } else {
87 | $mFrom->setDate($mFrom->format('Y'), $mFrom->format('m'), 1);
88 | $mFrom->setTime(0, 0, 0);
89 | $mTo->setDate($mTo->format('Y'), $mTo->format('m'), 1);
90 | $mTo->setTime(0, 0, 0);
91 | }
92 |
93 | return new DatePeriod($mFrom, new DateInterval('P1M'), $mTo, self::CREATE_TO !== $fromOrTo || $from->format('Y') == $to->format('Y') ? self::EXCLUDE_START_DATE : null);
94 | }
95 |
96 | public static function createForYear(DateTime $from, DateTime $to)
97 | {
98 | $from->setDate($from->format('Y'), 1, 1);
99 | $from->setTime(0, 0, 0);
100 | $to->setDate($to->format('Y'), 1, 1);
101 | $to->setTime(0, 0, 0);
102 |
103 | return new DatePeriod($from, new DateInterval('P1Y'), $to, self::EXCLUDE_START_DATE);
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/FreeAgent/Bitter/UnitOfTime/AbstractUnitOfTime.php:
--------------------------------------------------------------------------------
1 |
9 | */
10 | abstract class AbstractUnitOfTime
11 | {
12 | protected $eventName;
13 | protected $dateTime;
14 |
15 | public function __construct($eventName, DateTime $dateTime = null)
16 | {
17 | $this->eventName = $eventName;
18 | $this->dateTime = is_null($dateTime) ? new DateTime : $dateTime;
19 | }
20 |
21 | public function getUnitOfTimeName()
22 | {
23 | return $this->eventName;
24 | }
25 |
26 | public function getDateTime()
27 | {
28 | return $this->dateTime;
29 | }
30 |
31 | abstract public function getDateTimeFormated();
32 |
33 | public function getKey()
34 | {
35 | return sprintf('%s:%s', $this->getUnitOfTimeName(), $this->getDateTimeFormated());
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/FreeAgent/Bitter/UnitOfTime/Day.php:
--------------------------------------------------------------------------------
1 |
7 | */
8 | class Day extends AbstractUnitOfTime implements UnitOfTimeInterface
9 | {
10 | public function getDateTimeFormated()
11 | {
12 | return sprintf('%s-%s-%s', $this->getDateTime()->format('Y'), $this->getDateTime()->format('m'), $this->getDateTime()->format('d'));
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/FreeAgent/Bitter/UnitOfTime/Hour.php:
--------------------------------------------------------------------------------
1 |
7 | */
8 | class Hour extends AbstractUnitOfTime implements UnitOfTimeInterface
9 | {
10 | public function getDateTimeFormated()
11 | {
12 | return sprintf('%s-%s-%s-%s', $this->getDateTime()->format('Y'), $this->getDateTime()->format('m'), $this->getDateTime()->format('d'), $this->getDateTime()->format('H'));
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/FreeAgent/Bitter/UnitOfTime/Month.php:
--------------------------------------------------------------------------------
1 |
7 | */
8 | class Month extends AbstractUnitOfTime implements UnitOfTimeInterface
9 | {
10 | public function getDateTimeFormated()
11 | {
12 | return sprintf('%s-%s', $this->getDateTime()->format('Y'), $this->getDateTime()->format('m'));
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/FreeAgent/Bitter/UnitOfTime/UnitOfTimeInterface.php:
--------------------------------------------------------------------------------
1 |
7 | */
8 | interface UnitOfTimeInterface
9 | {
10 | public function __construct($eventName, \DateTime $dateTime);
11 | public function getUnitOfTimeName();
12 | public function getDateTime();
13 | public function getDateTimeFormated();
14 | public function getKey();
15 | }
16 |
--------------------------------------------------------------------------------
/src/FreeAgent/Bitter/UnitOfTime/Week.php:
--------------------------------------------------------------------------------
1 |
7 | */
8 | class Week extends AbstractUnitOfTime implements UnitOfTimeInterface
9 | {
10 | public function getDateTimeFormated()
11 | {
12 | return sprintf('%s-W%s', $this->getDateTime()->format('Y'), $this->getDateTime()->format('W'));
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/FreeAgent/Bitter/UnitOfTime/Year.php:
--------------------------------------------------------------------------------
1 |
7 | */
8 | class Year extends AbstractUnitOfTime implements UnitOfTimeInterface
9 | {
10 | public function getDateTimeFormated()
11 | {
12 | return sprintf('%s', $this->getDateTime()->format('Y'));
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/tests/units/Bitter.php:
--------------------------------------------------------------------------------
1 |
15 | */
16 | class Bitter extends atoum\test
17 | {
18 | public function dataProviderTestedClients()
19 | {
20 | $clients = array(
21 | new \Predis\Client(),
22 | );
23 |
24 | if (class_exists('\Redis')) {
25 | $conn = new \Redis();
26 | $conn->connect('127.0.0.1');
27 |
28 | $clients[] = $conn;
29 | }
30 |
31 | return $clients;
32 | }
33 |
34 | private function getPrefixKey()
35 | {
36 | return 'test_bitter:';
37 | }
38 |
39 | private function getPrefixTempKey()
40 | {
41 | return 'test_bitter_temp:';
42 | }
43 |
44 | private function removeAll($redisClient)
45 | {
46 | $keys_chunk = array_chunk($redisClient->keys($this->getPrefixKey() . '*'), 100);
47 |
48 | foreach ($keys_chunk as $keys) {
49 | $redisClient->del($keys);
50 | }
51 |
52 | $keys_chunk = array_chunk($redisClient->keys($this->getPrefixTempKey() . '*'), 100);
53 |
54 | foreach ($keys_chunk as $keys) {
55 | $redisClient->del($keys);
56 | }
57 | }
58 |
59 | /**
60 | * @dataProvider dataProviderTestedClients
61 | */
62 | public function testConstruct($redisClient)
63 | {
64 | $bitter = new TestedBitter($redisClient, $this->getPrefixKey(), $this->getPrefixTempKey());
65 |
66 | $this
67 | ->object($bitter->getRedisClient())
68 | ->isIdenticalTo($redisClient)
69 | ;
70 | }
71 |
72 | /**
73 | * @dataProvider dataProviderTestedClients
74 | */
75 | public function testMarkUnitOfTime($redisClient)
76 | {
77 | $bitter = new TestedBitter($redisClient, $this->getPrefixKey(), $this->getPrefixTempKey());
78 |
79 | $this->removeAll($redisClient);
80 |
81 | $dateTime = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-06 15:30:45');
82 |
83 | $day = new Day('drink_a_bitter_beer', $dateTime);
84 |
85 | $this
86 | ->integer($bitter->count($day))
87 | ->isIdenticalTo(0)
88 | ;
89 | $this
90 | ->boolean($bitter->in(404, $day))
91 | ->isFalse()
92 | ;
93 |
94 | $this
95 | ->object($bitter->mark('drink_a_bitter_beer', 404, $dateTime))
96 | ->isIdenticalTo($bitter)
97 | ;
98 |
99 | $this
100 | ->integer($bitter->count($day))
101 | ->isIdenticalTo(1)
102 | ;
103 | $this
104 | ->boolean($bitter->in(404, $day))
105 | ->isTrue()
106 | ;
107 |
108 | // Adding it a second time with the same dateTime !
109 | $bitter->mark('drink_a_bitter_beer', 404, $dateTime);
110 |
111 | $this
112 | ->integer($bitter->count($day))
113 | ->isIdenticalTo(1)
114 | ;
115 | $this
116 | ->boolean($bitter->in(404, $day))
117 | ->isTrue()
118 | ;
119 |
120 | $this->removeAll($redisClient);
121 |
122 | $day = new Day('drink_a_bitter_beer', new DateTime());
123 | $this
124 | ->boolean($bitter->in(13, $day))
125 | ->isFalse()
126 | ;
127 | $bitter->mark('drink_a_bitter_beer', 13);
128 | $this
129 | ->boolean($bitter->in(13, $day))
130 | ->isTrue()
131 | ;
132 |
133 | $this->removeAll($redisClient);
134 | }
135 |
136 | /**
137 | * @dataProvider dataProviderTestedClients
138 | */
139 | public function testbitOpAnd($redisClient)
140 | {
141 | $bitter = new TestedBitter($redisClient, $this->getPrefixKey(), $this->getPrefixTempKey());
142 |
143 | $this->removeAll($redisClient);
144 |
145 | $yesterday = new Day('drink_a_bitter_beer', new DateTime('yesterday'));
146 | $today = new Day('drink_a_bitter_beer', new DateTime('today'));
147 |
148 | $bitter->mark('drink_a_bitter_beer', 13, new DateTime('today'));
149 | $bitter->mark('drink_a_bitter_beer', 13, new DateTime('yesterday'));
150 | $bitter->mark('drink_a_bitter_beer', 404, new DateTime('yesterday'));
151 |
152 | $this
153 | ->object($bitter->bitOpAnd('test_a', $today, $yesterday))
154 | ->isIdenticalTo($bitter)
155 | ;
156 |
157 | $this
158 | ->boolean($bitter->bitOpAnd('test_b', $today, $yesterday)->in(13, 'test_b'))
159 | ->isTrue()
160 | ;
161 |
162 | $this
163 | ->boolean($bitter->bitOpAnd('test_c', $today, $yesterday)->in(404, 'test_c'))
164 | ->isFalse()
165 | ;
166 |
167 | $this->removeAll($redisClient);
168 | }
169 |
170 | /**
171 | * @dataProvider dataProviderTestedClients
172 | */
173 | public function testbitOpOr($redisClient)
174 | {
175 | $bitter = new TestedBitter($redisClient, $this->getPrefixKey(), $this->getPrefixTempKey());
176 |
177 | $this->removeAll($redisClient);
178 |
179 | $twoDaysAgo = new Day('drink_a_bitter_beer', new DateTime('2 days ago'));
180 | $yesterday = new Day('drink_a_bitter_beer', new DateTime('yesterday'));
181 | $today = new Day('drink_a_bitter_beer', new DateTime('today'));
182 |
183 | $bitter->mark('drink_a_bitter_beer', 13, new DateTime('today'));
184 | $bitter->mark('drink_a_bitter_beer', 13, new DateTime('yesterday'));
185 | $bitter->mark('drink_a_bitter_beer', 404, new DateTime('yesterday'));
186 |
187 | $this
188 | ->object($bitter->bitOpOr('test_a', $today, $yesterday))
189 | ->isIdenticalTo($bitter)
190 | ;
191 |
192 | $this
193 | ->boolean($bitter->bitOpOr('test_b', $today, $yesterday)->in(13, 'test_b'))
194 | ->isTrue()
195 | ;
196 |
197 | $this
198 | ->boolean($bitter->bitOpOr('test_c', $today, $twoDaysAgo)->in(13, 'test_c'))
199 | ->isTrue()
200 | ;
201 |
202 | $this
203 | ->boolean($bitter->bitOpOr('test_d', $today, $twoDaysAgo)->in(404, 'test_d'))
204 | ->isFalse()
205 | ;
206 |
207 | $this->removeAll($redisClient);
208 | }
209 |
210 | /**
211 | * @dataProvider dataProviderTestedClients
212 | */
213 | public function testbitOpXor($redisClient)
214 | {
215 | $bitter = new TestedBitter($redisClient, $this->getPrefixKey(), $this->getPrefixTempKey());
216 |
217 | $this->removeAll($redisClient);
218 |
219 | $yesterday = new Day('drink_a_bitter_beer', new DateTime('yesterday'));
220 | $today = new Day('drink_a_bitter_beer', new DateTime('today'));
221 |
222 | $bitter->mark('drink_a_bitter_beer', 13, new DateTime('today'));
223 | $bitter->mark('drink_a_bitter_beer', 13, new DateTime('yesterday'));
224 | $bitter->mark('drink_a_bitter_beer', 404, new DateTime('yesterday'));
225 |
226 | $this
227 | ->object($bitter->bitOpXor('test_a', $today, $yesterday))
228 | ->isIdenticalTo($bitter)
229 | ;
230 |
231 | $this
232 | ->boolean($bitter->bitOpXor('test_b', $today, $yesterday)->in(13, 'test_b'))
233 | ->isFalse()
234 | ;
235 |
236 | $this
237 | ->boolean($bitter->bitOpXor('test_c', $today, $yesterday)->in(404, 'test_c'))
238 | ->isTrue()
239 | ;
240 |
241 | $this->removeAll($redisClient);
242 | }
243 |
244 | /**
245 | * @dataProvider dataProviderTestedClients
246 | */
247 | public function testBitDateRange($redisClient)
248 | {
249 | $bitter = new TestedBitter($redisClient, $this->getPrefixKey(), $this->getPrefixTempKey());
250 |
251 | $this->removeAll($redisClient);
252 |
253 | $dateTime = DateTime::createFromFormat('Y-m-d H:i:s', '2011-11-06 15:30:45');
254 | $bitter->mark('drink_a_bitter_beer', 1, $dateTime);
255 | $dateTime = DateTime::createFromFormat('Y-m-d H:i:s', '2012-10-12 15:30:45');
256 | $bitter->mark('drink_a_bitter_beer', 2, $dateTime);
257 |
258 | $this
259 | ->if($from = DateTime::createFromFormat('Y-m-d H:i:s', '2012-10-05 15:30:45'))
260 | ->and($to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-12-07 15:30:45'))
261 | ->and($bitter->bitDateRange('drink_a_bitter_beer', 'test_create_date_period', $from, $to))
262 | ->then()
263 | ->object($bitter->bitDateRange('drink_a_bitter_beer', 'test_create_date_period', $from, $to))
264 | ->isIdenticalTo($bitter)
265 | ;
266 |
267 | $this
268 | ->if($prefixKey = $this->getPrefixKey())
269 | ->and($prefixTempKey = $this->getPrefixTempKey())
270 | ->exception(
271 | function() use ($redisClient, $prefixKey, $prefixTempKey) {
272 | $bitter = new TestedBitter($redisClient, $prefixKey, $prefixTempKey);
273 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2012-12-07 15:30:45');
274 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-12-07 14:30:45');
275 | $bitter->bitDateRange('drink_a_bitter_beer', 'test_create_date_period', $from, $to);
276 | }
277 | )
278 | ->hasMessage("DateTime from (2012-12-07 15:30:45) must be anterior to DateTime to (2012-12-07 14:30:45).")
279 | ;
280 |
281 | $this
282 | ->if($from = DateTime::createFromFormat('Y-m-d H:i:s', '2010-10-05 20:30:45'))
283 | ->and($to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-12-07 12:30:45'))
284 | ->and($bitter->bitDateRange('drink_a_bitter_beer', 'test_create_date_period', $from, $to))
285 | ->then()
286 | ->boolean($bitter->in(1, 'test_create_date_period'))
287 | ->isTrue()
288 | ->boolean($bitter->in(2, 'test_create_date_period'))
289 | ->isTrue()
290 | ->integer($bitter->count('test_create_date_period'))
291 | ->isEqualTo(2)
292 | ;
293 |
294 | $this
295 | ->if($from = DateTime::createFromFormat('Y-m-d H:i:s', '2012-09-05 20:30:45'))
296 | ->and($to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-12-07 12:30:45'))
297 | ->and($bitter->bitDateRange('drink_a_bitter_beer', 'test_create_date_period', $from, $to))
298 | ->then()
299 | ->boolean($bitter->in(1, 'test_create_date_period'))
300 | ->isFalse()
301 | ->boolean($bitter->in(2, 'test_create_date_period'))
302 | ->isTrue()
303 | ->integer($bitter->count('test_create_date_period'))
304 | ->isEqualTo(1)
305 | ;
306 |
307 | $this->removeAll($redisClient);
308 | }
309 |
310 | /**
311 | * @dataProvider dataProviderTestedClients
312 | */
313 | public function testGetIds($redisClient)
314 | {
315 | $bitter = new TestedBitter($redisClient, $this->getPrefixKey(), $this->getPrefixTempKey());
316 |
317 | $this->removeAll($redisClient);
318 |
319 | $eventKey = 'liloo_multipass';
320 | $dateTime = new DateTime('2012-10-12 15:30:45');
321 | $event = new Day($eventKey, $dateTime);
322 | $ids = array(1, 13, 404, 2, 12700042, 13003, 99);
323 |
324 | foreach ($ids as $id) {
325 | $bitter->mark($eventKey, $id, $dateTime);
326 | }
327 | sort($ids);
328 |
329 | $this
330 | ->array($bitter->getIds($event))
331 | ->isIdenticalTo($ids)
332 | ;
333 |
334 | $this->removeAll($redisClient);
335 | }
336 |
337 | /**
338 | * @dataProvider dataProviderTestedClients
339 | */
340 | public function testRemoveAll($redisClient)
341 | {
342 | $this->removeAll($redisClient);
343 |
344 | $this
345 | ->array($redisClient->keys($this->getPrefixKey() . '*'))
346 | ->isEmpty()
347 | ;
348 |
349 | $bitter = new TestedBitter($redisClient, $this->getPrefixKey(), $this->getPrefixTempKey());
350 |
351 | $yesterday = new Day('drink_a_bitter_beer', new DateTime('yesterday'));
352 | $today = new Day('drink_a_bitter_beer', new DateTime('today'));
353 |
354 | $bitter->mark('drink_a_bitter_beer', 13, new DateTime('today'));
355 | $bitter->mark('drink_a_bitter_beer', 13, new DateTime('yesterday'));
356 | $bitter->mark('drink_a_bitter_beer', 404, new DateTime('yesterday'));
357 |
358 | $this
359 | ->array($redisClient->keys($this->getPrefixKey() . '*'))
360 | ->isNotEmpty()
361 | ;
362 |
363 | $this
364 | ->object($bitter->removeAll())
365 | ->isIdenticalTo($bitter)
366 | ;
367 |
368 | $this
369 | ->array($redisClient->keys($this->getPrefixKey() . '*'))
370 | ->strictlyContains($this->getPrefixKey() . 'keys')
371 | ;
372 |
373 |
374 | $this->removeAll($redisClient);
375 | }
376 |
377 | /**
378 | * @dataProvider dataProviderTestedClients
379 | */
380 | public function testRemoveTemp($redisClient)
381 | {
382 | $keys_chunk = array_chunk($redisClient->keys($this->getPrefixKey() . '*'), 100);
383 |
384 | foreach ($keys_chunk as $keys) {
385 | $redisClient->del($keys);
386 | }
387 |
388 | $this
389 | ->array($redisClient->keys($this->getPrefixKey() . '*'))
390 | ->isEmpty()
391 | ;
392 |
393 | $bitter = new TestedBitter($redisClient, $this->getPrefixKey(), $this->getPrefixTempKey());
394 |
395 | $yesterday = new Day('drink_a_bitter_beer', new DateTime('yesterday'));
396 | $today = new Day('drink_a_bitter_beer', new DateTime('today'));
397 |
398 | $bitter->mark('drink_a_bitter_beer', 13, new DateTime('today'));
399 | $bitter->mark('drink_a_bitter_beer', 13, new DateTime('yesterday'));
400 | $bitter->mark('drink_a_bitter_beer', 404, new DateTime('yesterday'));
401 |
402 | $bitter->bitOpOr('test_b', $today, $yesterday);
403 |
404 | $this
405 | ->array($redisClient->keys($this->getPrefixKey() . '*'))
406 | ->isNotEmpty()
407 | ;
408 |
409 | $this
410 | ->array($redisClient->keys($this->getPrefixTempKey() . '*'))
411 | ->isNotEmpty()
412 | ;
413 |
414 | $this
415 | ->object($bitter->removeTemp())
416 | ->isIdenticalTo($bitter)
417 | ;
418 |
419 | $this
420 | ->array($redisClient->keys($this->getPrefixTempKey() . '*'))
421 | ->strictlyContains($this->getPrefixTempKey() . 'keys')
422 | ;
423 |
424 | $this
425 | ->array($redisClient->keys($this->getPrefixKey() . '*'))
426 | ->isNotEmpty()
427 | ;
428 |
429 | // Expire timeout
430 | $this->removeAll($redisClient);
431 |
432 | $bitter = new TestedBitter($redisClient, $this->getPrefixKey(), $this->getPrefixTempKey(), 2);
433 | $bitter->mark('drink_a_bitter_beer', 13, new DateTime('today'));
434 | $bitter->mark('drink_a_bitter_beer', 13, new DateTime('yesterday'));
435 | $bitter->mark('drink_a_bitter_beer', 404, new DateTime('yesterday'));
436 |
437 | $bitter->bitOpOr('test_b', $today, $yesterday);
438 |
439 | $this
440 | ->array($redisClient->keys($this->getPrefixTempKey() . '*'))
441 | ->isNotEmpty()
442 | ;
443 |
444 | sleep(3);
445 |
446 | $this
447 | ->array($redisClient->keys($this->getPrefixTempKey() . '*'))
448 | ->strictlyContains($this->getPrefixTempKey() . 'keys')
449 | ;
450 |
451 | $this->removeAll($redisClient);
452 | }
453 | }
454 |
--------------------------------------------------------------------------------
/tests/units/Date/DatePeriod.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | class DatePeriod extends atoum\test
16 | {
17 | public function testToArray()
18 | {
19 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-13 15:30:45');
20 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-20 15:30:45');
21 |
22 | $datePeriodArray = array(
23 | '2012-11-14 15:30:45',
24 | '2012-11-15 15:30:45',
25 | '2012-11-16 15:30:45',
26 | '2012-11-17 15:30:45',
27 | '2012-11-18 15:30:45',
28 | '2012-11-19 15:30:45',
29 | );
30 |
31 | $this
32 | ->if($datePeriod = new TestedDatePeriod($from, new DateInterval('P1D'), $to, TestedDatePeriod::EXCLUDE_START_DATE))
33 | ->array($datePeriod->toArray(true))
34 | ->isEqualTo($datePeriodArray)
35 | ;
36 | }
37 |
38 | public function testCreateForHour()
39 | {
40 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-15 10:30:45');
41 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-15 15:30:45');
42 |
43 | $datePeriodFromArray = $datePeriodToArray = array(
44 | '2012-11-15 10:00:00',
45 | '2012-11-15 11:00:00',
46 | '2012-11-15 12:00:00',
47 | '2012-11-15 13:00:00',
48 | '2012-11-15 14:00:00',
49 | );
50 |
51 | $this
52 | ->if($datePeriod = TestedDatePeriod::createForHour($from, $to, TestedDatePeriod::CREATE_FROM))
53 | ->array($datePeriod->toArray(true))
54 | ->isEqualTo($datePeriodFromArray)
55 | ->if($datePeriod = TestedDatePeriod::createForHour($from, $to, TestedDatePeriod::CREATE_TO))
56 | ->array($datePeriod->toArray(true))
57 | ->isEqualTo($datePeriodToArray)
58 | ;
59 |
60 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-13 15:30:45');
61 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-15 10:30:45');
62 |
63 | $datePeriodFromArray = array(
64 | '2012-11-13 15:00:00',
65 | '2012-11-13 16:00:00',
66 | '2012-11-13 17:00:00',
67 | '2012-11-13 18:00:00',
68 | '2012-11-13 19:00:00',
69 | '2012-11-13 20:00:00',
70 | '2012-11-13 21:00:00',
71 | '2012-11-13 22:00:00',
72 | '2012-11-13 23:00:00',
73 | );
74 |
75 | $datePeriodToArray = array(
76 | '2012-11-15 00:00:00',
77 | '2012-11-15 01:00:00',
78 | '2012-11-15 02:00:00',
79 | '2012-11-15 03:00:00',
80 | '2012-11-15 04:00:00',
81 | '2012-11-15 05:00:00',
82 | '2012-11-15 06:00:00',
83 | '2012-11-15 07:00:00',
84 | '2012-11-15 08:00:00',
85 | '2012-11-15 09:00:00',
86 | );
87 |
88 | $this
89 | ->if($datePeriod = TestedDatePeriod::createForHour($from, $to, TestedDatePeriod::CREATE_FROM))
90 | ->array($datePeriod->toArray(true))
91 | ->isEqualTo($datePeriodFromArray)
92 | ->if($datePeriod = TestedDatePeriod::createForHour($from, $to, TestedDatePeriod::CREATE_TO))
93 | ->array($datePeriod->toArray(true))
94 | ->isEqualTo($datePeriodToArray)
95 | ;
96 | }
97 |
98 | public function testCreateForDay()
99 | {
100 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-13 10:30:45');
101 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-13 15:30:45');
102 |
103 | $datePeriodFromArray = $datePeriodToArray = array();
104 |
105 | $this
106 | ->if($datePeriod = TestedDatePeriod::createForDay($from, $to, TestedDatePeriod::CREATE_FROM))
107 | ->array($datePeriod->toArray(true))
108 | ->isEqualTo($datePeriodFromArray)
109 | ->if($datePeriod = TestedDatePeriod::createForDay($from, $to, TestedDatePeriod::CREATE_TO))
110 | ->array($datePeriod->toArray(true))
111 | ->isEqualTo($datePeriodToArray)
112 | ;
113 |
114 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-10 15:30:45');
115 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-15 10:30:45');
116 |
117 | $datePeriodFromArray = $datePeriodToArray = array(
118 | '2012-11-11 00:00:00',
119 | '2012-11-12 00:00:00',
120 | '2012-11-13 00:00:00',
121 | '2012-11-14 00:00:00',
122 | );
123 |
124 | $this
125 | ->if($datePeriod = TestedDatePeriod::createForDay($from, $to, TestedDatePeriod::CREATE_FROM))
126 | ->array($datePeriod->toArray(true))
127 | ->isEqualTo($datePeriodFromArray)
128 | ->if($datePeriod = TestedDatePeriod::createForDay($from, $to, TestedDatePeriod::CREATE_TO))
129 | ->array($datePeriod->toArray(true))
130 | ->isEqualTo($datePeriodToArray)
131 | ;
132 |
133 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2012-08-20 15:30:45');
134 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-10 10:30:45');
135 |
136 | $datePeriodFromArray = array(
137 | '2012-08-21 00:00:00',
138 | '2012-08-22 00:00:00',
139 | '2012-08-23 00:00:00',
140 | '2012-08-24 00:00:00',
141 | '2012-08-25 00:00:00',
142 | '2012-08-26 00:00:00',
143 | '2012-08-27 00:00:00',
144 | '2012-08-28 00:00:00',
145 | '2012-08-29 00:00:00',
146 | '2012-08-30 00:00:00',
147 | '2012-08-31 00:00:00',
148 | );
149 |
150 | $datePeriodToArray = array(
151 | '2012-11-01 00:00:00',
152 | '2012-11-02 00:00:00',
153 | '2012-11-03 00:00:00',
154 | '2012-11-04 00:00:00',
155 | '2012-11-05 00:00:00',
156 | '2012-11-06 00:00:00',
157 | '2012-11-07 00:00:00',
158 | '2012-11-08 00:00:00',
159 | '2012-11-09 00:00:00',
160 | );
161 |
162 | $this
163 | ->if($datePeriod = TestedDatePeriod::createForDay($from, $to, TestedDatePeriod::CREATE_FROM))
164 | ->array($datePeriod->toArray(true))
165 | ->isEqualTo($datePeriodFromArray)
166 | ->if($datePeriod = TestedDatePeriod::createForDay($from, $to, TestedDatePeriod::CREATE_TO))
167 | ->array($datePeriod->toArray(true))
168 | ->isEqualTo($datePeriodToArray)
169 | ;
170 | }
171 |
172 | public function testCreateForMonth()
173 | {
174 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-13 10:30:45');
175 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-13 15:30:45');
176 |
177 | $datePeriodFromArray = $datePeriodToArray = array();
178 |
179 | $this
180 | ->if($datePeriod = TestedDatePeriod::createForMonth($from, $to, TestedDatePeriod::CREATE_FROM))
181 | ->array($datePeriod->toArray(true))
182 | ->isEqualTo($datePeriodFromArray)
183 | ->if($datePeriod = TestedDatePeriod::createForMonth($from, $to, TestedDatePeriod::CREATE_TO))
184 | ->array($datePeriod->toArray(true))
185 | ->isEqualTo($datePeriodToArray)
186 | ;
187 |
188 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-10 10:30:45');
189 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-13 15:30:45');
190 |
191 | $datePeriodFromArray = $datePeriodToArray = array();
192 |
193 | $this
194 | ->if($datePeriod = TestedDatePeriod::createForMonth($from, $to, TestedDatePeriod::CREATE_FROM))
195 | ->array($datePeriod->toArray(true))
196 | ->isEqualTo($datePeriodFromArray)
197 | ->if($datePeriod = TestedDatePeriod::createForMonth($from, $to, TestedDatePeriod::CREATE_TO))
198 | ->array($datePeriod->toArray(true))
199 | ->isEqualTo($datePeriodToArray)
200 | ;
201 |
202 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2012-10-10 15:30:45');
203 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-15 10:30:45');
204 |
205 | $datePeriodFromArray = $datePeriodToArray = array();
206 |
207 | $this
208 | ->if($datePeriod = TestedDatePeriod::createForMonth($from, $to, TestedDatePeriod::CREATE_FROM))
209 | ->array($datePeriod->toArray(true))
210 | ->isEqualTo($datePeriodFromArray)
211 | ->if($datePeriod = TestedDatePeriod::createForMonth($from, $to, TestedDatePeriod::CREATE_TO))
212 | ->array($datePeriod->toArray(true))
213 | ->isEqualTo($datePeriodToArray)
214 | ;
215 |
216 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2012-09-10 15:30:45');
217 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-15 10:30:45');
218 |
219 | $datePeriodFromArray = $datePeriodToArray = array(
220 | '2012-10-01 00:00:00',
221 | );
222 |
223 | $this
224 | ->if($datePeriod = TestedDatePeriod::createForMonth($from, $to, TestedDatePeriod::CREATE_FROM))
225 | ->array($datePeriod->toArray(true))
226 | ->isEqualTo($datePeriodFromArray)
227 | ->if($datePeriod = TestedDatePeriod::createForMonth($from, $to, TestedDatePeriod::CREATE_TO))
228 | ->array($datePeriod->toArray(true))
229 | ->isEqualTo($datePeriodToArray)
230 | ;
231 |
232 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2012-08-20 15:30:45');
233 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-10 10:30:45');
234 |
235 | $datePeriodFromArray = $datePeriodToArray = array(
236 | '2012-09-01 00:00:00',
237 | '2012-10-01 00:00:00',
238 | );
239 |
240 | $this
241 | ->if($datePeriod = TestedDatePeriod::createForMonth($from, $to, TestedDatePeriod::CREATE_FROM))
242 | ->array($datePeriod->toArray(true))
243 | ->isEqualTo($datePeriodFromArray)
244 | ->if($datePeriod = TestedDatePeriod::createForMonth($from, $to, TestedDatePeriod::CREATE_TO))
245 | ->array($datePeriod->toArray(true))
246 | ->isEqualTo($datePeriodToArray)
247 | ;
248 |
249 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2010-08-20 15:30:45');
250 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-10 10:30:45');
251 |
252 | $datePeriodFromArray = array(
253 | '2010-09-01 00:00:00',
254 | '2010-10-01 00:00:00',
255 | '2010-11-01 00:00:00',
256 | '2010-12-01 00:00:00',
257 | );
258 |
259 | $datePeriodToArray = array(
260 | '2012-01-01 00:00:00',
261 | '2012-02-01 00:00:00',
262 | '2012-03-01 00:00:00',
263 | '2012-04-01 00:00:00',
264 | '2012-05-01 00:00:00',
265 | '2012-06-01 00:00:00',
266 | '2012-07-01 00:00:00',
267 | '2012-08-01 00:00:00',
268 | '2012-09-01 00:00:00',
269 | '2012-10-01 00:00:00',
270 | );
271 |
272 | $this
273 | ->if($datePeriod = TestedDatePeriod::createForMonth($from, $to, TestedDatePeriod::CREATE_FROM))
274 | ->array($datePeriod->toArray(true))
275 | ->isEqualTo($datePeriodFromArray)
276 | ->if($datePeriod = TestedDatePeriod::createForMonth($from, $to, TestedDatePeriod::CREATE_TO))
277 | ->array($datePeriod->toArray(true))
278 | ->isEqualTo($datePeriodToArray)
279 | ;
280 | }
281 |
282 | public function testCreateForYear()
283 | {
284 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-13 10:30:45');
285 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-13 15:30:45');
286 |
287 | $datePeriodArray = array();
288 |
289 | $this
290 | ->if($datePeriod = TestedDatePeriod::createForYear($from, $to))
291 | ->array($datePeriod->toArray(true))
292 | ->isEqualTo($datePeriodArray)
293 | ;
294 |
295 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-10 10:30:45');
296 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-13 15:30:45');
297 |
298 | $datePeriodArray = array();
299 |
300 | $this
301 | ->if($datePeriod = TestedDatePeriod::createForYear($from, $to))
302 | ->array($datePeriod->toArray(true))
303 | ->isEqualTo($datePeriodArray)
304 | ;
305 |
306 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2012-10-10 15:30:45');
307 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-15 10:30:45');
308 |
309 | $datePeriodArray = array();
310 |
311 | $this
312 | ->if($datePeriod = TestedDatePeriod::createForYear($from, $to))
313 | ->array($datePeriod->toArray(true))
314 | ->isEqualTo($datePeriodArray)
315 | ;
316 |
317 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2012-09-10 15:30:45');
318 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-15 10:30:45');
319 |
320 | $datePeriodArray = array();
321 |
322 | $this
323 | ->if($datePeriod = TestedDatePeriod::createForYear($from, $to))
324 | ->array($datePeriod->toArray(true))
325 | ->isEqualTo($datePeriodArray)
326 | ;
327 |
328 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2012-08-20 15:30:45');
329 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-10 10:30:45');
330 |
331 | $datePeriodArray = array();
332 |
333 | $this
334 | ->if($datePeriod = TestedDatePeriod::createForYear($from, $to))
335 | ->array($datePeriod->toArray(true))
336 | ->isEqualTo($datePeriodArray)
337 | ;
338 |
339 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2011-08-20 15:30:45');
340 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-10 10:30:45');
341 |
342 | $datePeriodArray = array();
343 |
344 | $this
345 | ->if($datePeriod = TestedDatePeriod::createForYear($from, $to))
346 | ->array($datePeriod->toArray(true))
347 | ->isEqualTo($datePeriodArray)
348 | ;
349 |
350 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2010-08-20 15:30:45');
351 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-10 10:30:45');
352 |
353 | $datePeriodArray = array(
354 | '2011-01-01 00:00:00',
355 | );
356 |
357 | $this
358 | ->if($datePeriod = TestedDatePeriod::createForYear($from, $to))
359 | ->array($datePeriod->toArray(true))
360 | ->isEqualTo($datePeriodArray)
361 | ;
362 |
363 | $from = DateTime::createFromFormat('Y-m-d H:i:s', '2009-08-20 15:30:45');
364 | $to = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-10 10:30:45');
365 |
366 | $datePeriodArray = array(
367 | '2010-01-01 00:00:00',
368 | '2011-01-01 00:00:00',
369 | );
370 |
371 | $this
372 | ->if($datePeriod = TestedDatePeriod::createForYear($from, $to))
373 | ->array($datePeriod->toArray(true))
374 | ->isEqualTo($datePeriodArray)
375 | ;
376 | }
377 | }
378 |
--------------------------------------------------------------------------------
/tests/units/UnitOfTime/AbstractUnitOfTime.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | class AbstractUnitOfTime extends atoum\test
15 | {
16 | public function testConstruct()
17 | {
18 | $dateTime = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-06 15:30:45');
19 |
20 | $event = new \mock\FreeAgent\Bitter\UnitOfTime\AbstractUnitOfTime('drink_a_bitter_beer', $dateTime);
21 |
22 | $this
23 | ->variable($event->getDateTime())
24 | ->isIdenticalTo($dateTime)
25 | ;
26 | $this
27 | ->variable($event->getUnitOfTimeName())
28 | ->isIdenticalTo('drink_a_bitter_beer')
29 | ;
30 | }
31 |
32 | public function testGetKey()
33 | {
34 | $dateTime = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-06 15:30:45');
35 |
36 | $event = new \mock\FreeAgent\Bitter\UnitOfTime\AbstractUnitOfTime('drink_a_bitter_beer', $dateTime);
37 |
38 | $event->getMockController()->getDateTimeFormated = '2012-11-06';
39 |
40 | $this
41 | ->string($event->getKey())
42 | ->isEqualTo('drink_a_bitter_beer:2012-11-06')
43 | ;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/tests/units/UnitOfTime/Day.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | class Day extends atoum\test
15 | {
16 | public function testConstruct()
17 | {
18 | $day = new TestedDay('drink_a_bitter_beer', new DateTime());
19 |
20 | $this
21 | ->object($day)
22 | ->isInstanceOf('FreeAgent\Bitter\UnitOfTime\AbstractUnitOfTime')
23 | ->isInstanceOf('FreeAgent\Bitter\UnitOfTime\UnitOfTimeInterface')
24 | ;
25 | }
26 |
27 | public function testGetDateTimeFormated()
28 | {
29 | $dateTime = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-06 15:30:45');
30 |
31 | $day = new TestedDay('drink_a_bitter_beer', $dateTime);
32 |
33 | $this
34 | ->string($day->getDateTimeFormated())
35 | ->isEqualTo('2012-11-06')
36 | ;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/tests/units/UnitOfTime/Hour.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | class Hour extends atoum\test
15 | {
16 | public function testConstruct()
17 | {
18 | $hour = new TestedHour('drink_a_bitter_beer', new DateTime());
19 |
20 | $this
21 | ->object($hour)
22 | ->isInstanceOf('FreeAgent\Bitter\UnitOfTime\AbstractUnitOfTime')
23 | ->isInstanceOf('FreeAgent\Bitter\UnitOfTime\UnitOfTimeInterface')
24 | ;
25 | }
26 |
27 | public function testGetDateTimeFormated()
28 | {
29 | $dateTime = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-06 15:30:45');
30 |
31 | $hour = new TestedHour('drink_a_bitter_beer', $dateTime);
32 |
33 | $this
34 | ->string($hour->getDateTimeFormated())
35 | ->isEqualTo('2012-11-06-15')
36 | ;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/tests/units/UnitOfTime/Month.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | class Month extends atoum\test
15 | {
16 | public function testConstruct()
17 | {
18 | $month = new TestedMonth('drink_a_bitter_beer', new DateTime());
19 |
20 | $this
21 | ->object($month)
22 | ->isInstanceOf('FreeAgent\Bitter\UnitOfTime\AbstractUnitOfTime')
23 | ->isInstanceOf('FreeAgent\Bitter\UnitOfTime\UnitOfTimeInterface')
24 | ;
25 | }
26 |
27 | public function testGetDateTimeFormated()
28 | {
29 | $dateTime = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-06 15:30:45');
30 |
31 | $month = new TestedMonth('drink_a_bitter_beer', $dateTime);
32 |
33 | $this
34 | ->string($month->getDateTimeFormated())
35 | ->isEqualTo('2012-11')
36 | ;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/tests/units/UnitOfTime/Week.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | class Week extends atoum\test
15 | {
16 | public function testConstruct()
17 | {
18 | $week = new TestedWeek('drink_a_bitter_beer', new DateTime());
19 |
20 | $this
21 | ->object($week)
22 | ->isInstanceOf('FreeAgent\Bitter\UnitOfTime\AbstractUnitOfTime')
23 | ->isInstanceOf('FreeAgent\Bitter\UnitOfTime\UnitOfTimeInterface')
24 | ;
25 | }
26 |
27 | public function testGetDateTimeFormated()
28 | {
29 | $dateTime = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-06 15:30:45');
30 |
31 | $week = new TestedWeek('drink_a_bitter_beer', $dateTime);
32 |
33 | $this
34 | ->string($week->getDateTimeFormated())
35 | ->isEqualTo('2012-W45')
36 | ;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/tests/units/UnitOfTime/Year.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | class Year extends atoum\test
15 | {
16 | public function testConstruct()
17 | {
18 | $month = new TestedYear('drink_a_bitter_beer', new DateTime());
19 |
20 | $this
21 | ->object($month)
22 | ->isInstanceOf('FreeAgent\Bitter\UnitOfTime\AbstractUnitOfTime')
23 | ->isInstanceOf('FreeAgent\Bitter\UnitOfTime\UnitOfTimeInterface')
24 | ;
25 | }
26 |
27 | public function testGetDateTimeFormated()
28 | {
29 | $dateTime = DateTime::createFromFormat('Y-m-d H:i:s', '2012-11-06 15:30:45');
30 |
31 | $month = new TestedYear('drink_a_bitter_beer', $dateTime);
32 |
33 | $this
34 | ->string($month->getDateTimeFormated())
35 | ->isEqualTo('2012')
36 | ;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------