├── README.md ├── composer.json ├── LICENSE.md ├── .gitignore ├── tests └── CarbonPeriodTest.php └── src └── CarbonPeriod.php /README.md: -------------------------------------------------------------------------------- 1 | carbon-period 2 | ================= 3 | 4 | [![SensioLabsInsight](https://insight.sensiolabs.com/projects/0096f692-a40f-49c6-9a47-589e469e8357/small.png)](https://insight.sensiolabs.com/projects/0096f692-a40f-49c6-9a47-589e469e8357) 5 | 6 | Extension of nesbot/carbon plugin, to work with date period 7 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "advmaker/carbon-period", 3 | "type": "library", 4 | "description": "Extension of nesbot/carbon plugin, to work with date period", 5 | "keywords": [ 6 | "date", 7 | "time", 8 | "DateTime", 9 | "Period" 10 | ], 11 | "license": "MIT", 12 | "authors": [ 13 | { 14 | "name": "Stanislav A. Karabanov" 15 | } 16 | ], 17 | "autoload": { 18 | "psr-4": { 19 | "Advmaker\\": "src" 20 | } 21 | }, 22 | "require": { 23 | "php": ">=5.3.0", 24 | "nesbot/carbon": ">=1.14" 25 | }, 26 | "require-dev": { 27 | "phpunit/phpunit": ">=4.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 AdvMaker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io 2 | 3 | ### Windows ### 4 | # Windows image file caches 5 | Thumbs.db 6 | ehthumbs.db 7 | 8 | # Folder config file 9 | Desktop.ini 10 | 11 | # Recycle Bin used on file shares 12 | $RECYCLE.BIN/ 13 | 14 | # Windows Installer files 15 | *.cab 16 | *.msi 17 | *.msm 18 | *.msp 19 | 20 | # Windows shortcuts 21 | *.lnk 22 | 23 | 24 | ### OSX ### 25 | .AppleDouble 26 | .LSOverride 27 | 28 | # Icon must end with two \r 29 | Icon 30 | 31 | 32 | # Thumbnails 33 | ._* 34 | 35 | # Files that might appear in the root of a volume 36 | .DocumentRevisions-V100 37 | .fseventsd 38 | .Spotlight-V100 39 | .TemporaryItems 40 | .Trashes 41 | .VolumeIcon.icns 42 | 43 | # Directories potentially created on remote AFP share 44 | .AppleDB 45 | .AppleDesktop 46 | Network Trash Folder 47 | Temporary Items 48 | .apdisk 49 | 50 | 51 | ### Linux ### 52 | *~ 53 | 54 | # KDE directory preferences 55 | .directory 56 | 57 | # Linux trash folder which might appear on any partition or disk 58 | .Trash-* 59 | 60 | 61 | ### PhpStorm ### 62 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 63 | 64 | ## Directory-based project format: 65 | .idea/ 66 | # if you remove the above rule, at least ignore the following: 67 | 68 | # User-specific stuff: 69 | # .idea/workspace.xml 70 | # .idea/tasks.xml 71 | # .idea/dictionaries 72 | 73 | # Sensitive or high-churn files: 74 | # .idea/dataSources.ids 75 | # .idea/dataSources.xml 76 | # .idea/sqlDataSources.xml 77 | # .idea/dynamic.xml 78 | # .idea/uiDesigner.xml 79 | 80 | # Gradle: 81 | # .idea/gradle.xml 82 | # .idea/libraries 83 | 84 | # Mongo Explorer plugin: 85 | # .idea/mongoSettings.xml 86 | 87 | ## File-based project format: 88 | *.ipr 89 | *.iws 90 | 91 | ## Plugin-specific files: 92 | 93 | # IntelliJ 94 | out/ 95 | 96 | # mpeltonen/sbt-idea plugin 97 | .idea_modules/ 98 | 99 | # JIRA plugin 100 | atlassian-ide-plugin.xml 101 | 102 | # Crashlytics plugin (for Android Studio and IntelliJ) 103 | com_crashlytics_export_strings.xml 104 | crashlytics.properties 105 | crashlytics-build.properties 106 | 107 | composer.lock 108 | vendor/ 109 | -------------------------------------------------------------------------------- /tests/CarbonPeriodTest.php: -------------------------------------------------------------------------------- 1 | assertEquals(Carbon::now(), $period->start()); 13 | $this->assertEquals(Carbon::parse('+1 month'), $period->end()); 14 | 15 | $period = CarbonPeriod::instance(Carbon::now(), Carbon::parse('+1 month')); 16 | 17 | $this->assertEquals(Carbon::now(), $period->start()); 18 | $this->assertEquals(Carbon::parse('+1 month'), $period->end()); 19 | } 20 | 21 | public function testToday() 22 | { 23 | $period = CarbonPeriod::today(); 24 | 25 | $this->assertEquals(Carbon::today(), $period->start()); 26 | $this->assertEquals(Carbon::now(), $period->end()); 27 | } 28 | 29 | public function testThisDay() 30 | { 31 | $period = CarbonPeriod::thisDay(); 32 | 33 | $this->assertEquals(Carbon::today(), $period->start()); 34 | $this->assertEquals(Carbon::now()->endOfDay(), $period->end()); 35 | } 36 | 37 | public function testLengthInYears() 38 | { 39 | $period = CarbonPeriod::instance(Carbon::now(), Carbon::parse('+1 year')); 40 | 41 | $this->assertEquals(1, $period->lengthInYears()); 42 | } 43 | 44 | public function testLengthInMonths() 45 | { 46 | $period = CarbonPeriod::instance(Carbon::now(), Carbon::parse('+15 months')); 47 | 48 | $this->assertEquals(15, $period->lengthInMonths()); 49 | } 50 | 51 | public function testLengthInWeeks() 52 | { 53 | $period = CarbonPeriod::instance(Carbon::now(), Carbon::parse('+4 weeks')); 54 | 55 | $this->assertEquals(4, $period->lengthInWeeks()); 56 | } 57 | 58 | public function testLengthInDays() 59 | { 60 | $period = CarbonPeriod::instance(Carbon::now(), Carbon::parse('+20 days')); 61 | 62 | $this->assertEquals(20, $period->lengthInDays()); 63 | } 64 | 65 | public function testLengthInHours() 66 | { 67 | $period = CarbonPeriod::instance(Carbon::now(), Carbon::parse('+19 hours')); 68 | 69 | $this->assertEquals(19, $period->lengthInHours()); 70 | } 71 | 72 | public function testLengthInMinutes() 73 | { 74 | $period = CarbonPeriod::instance(Carbon::now(), Carbon::parse('+110 minutes')); 75 | 76 | $this->assertEquals(110, $period->lengthInMinutes()); 77 | } 78 | 79 | public function testLengthInSeconds() 80 | { 81 | $period = CarbonPeriod::instance(Carbon::now(), Carbon::parse('+1000 seconds')); 82 | 83 | $this->assertEquals(1000, $period->lengthInSeconds()); 84 | } 85 | 86 | public function testLastWeek() 87 | { 88 | $period = CarbonPeriod::lastWeek(); 89 | 90 | $date = Carbon::parse('last week')->startOfDay(); 91 | 92 | $this->assertEquals($period->start(), $date); 93 | 94 | $this->assertEquals($period->end(), $date->addWeek()); 95 | } 96 | 97 | public function testLastMonth() 98 | { 99 | $period = CarbonPeriod::lastMonth(); 100 | 101 | $date = Carbon::parse('first day of last month')->startOfDay(); 102 | 103 | $this->assertEquals($period->start(), $date); 104 | 105 | $this->assertEquals($period->end(), $date->addMonth()); 106 | } 107 | 108 | public function testThisWeek() 109 | { 110 | $period = CarbonPeriod::thisWeek(); 111 | 112 | $start = Carbon::today(); 113 | $end = Carbon::tomorrow(); 114 | if ($start->dayOfWeek !== Carbon::MONDAY) { 115 | $start->modify('last monday'); 116 | } 117 | 118 | 119 | $this->assertEquals($start, $period->start()); 120 | $this->assertEquals($end, $period->end()); 121 | } 122 | 123 | public function testThisMonth() 124 | { 125 | $period = CarbonPeriod::thisMonth(); 126 | 127 | $date = Carbon::parse('first day of today'); 128 | 129 | $this->assertEquals($date, $period->start()); 130 | $this->assertEquals($date->tomorrow(), $period->end()); 131 | } 132 | 133 | public function testThisYear() 134 | { 135 | $period = CarbonPeriod::thisYear(); 136 | 137 | $date = Carbon::parse('1 January'); 138 | 139 | $this->assertEquals($date, $period->start()); 140 | $this->assertEquals($date->tomorrow(), $period->end()); 141 | } 142 | 143 | public function testParse() 144 | { 145 | try { 146 | CarbonPeriod::parse('wtf', 'lol'); 147 | } catch(Exception $e) { 148 | $this->assertEquals( 149 | 'DateTime::__construct(): Failed to parse time string (wtf) at position 0 (w): The timezone could not be found in the database', 150 | $e->getMessage() 151 | ); 152 | } 153 | 154 | $period = CarbonPeriod::parse('+1 day', '+1 year'); 155 | 156 | $this->assertEquals(Carbon::parse('+1 day'), $period->start()); 157 | $this->assertEquals(Carbon::parse('+1 year'), $period->end()); 158 | } 159 | 160 | /** 161 | * Test the date between start and end dates in the instance 162 | */ 163 | public function testContains() 164 | { 165 | $period = CarbonPeriod::lastWeek(); 166 | $date = Carbon::parse('last week +1 day'); 167 | 168 | $this->assertTrue($period->contains($date)); 169 | } 170 | 171 | /** 172 | * Test the iterator for each weekday 173 | */ 174 | public function testEachDayOfWeek() 175 | { 176 | $period = CarbonPeriod::lastMonth(); 177 | 178 | $dayOfWeek = Carbon::FRIDAY; 179 | 180 | $date = $period->start(); 181 | if ($dayOfWeek !== $date->dayOfWeek) { 182 | $date->next($dayOfWeek); 183 | } 184 | 185 | $period->eachDayOfWeek($dayOfWeek, function (CarbonPeriod $period) use ($date, $dayOfWeek) { 186 | /** Check dates */ 187 | $this->assertEquals($period->start(), $date); 188 | 189 | /** Check days of week */ 190 | $this->assertEquals($period->start()->dayOfWeek, $dayOfWeek); 191 | 192 | /** Check end day from the period */ 193 | $this->assertEquals( 194 | $period->end(), $period->start()->addDay(), 195 | 'Крайняя дата периода, в итераторе по дню недели, должна ровняться началу следующего дня, "startDate->addDay()->startOfDay()"' 196 | ); 197 | 198 | $date->next($dayOfWeek); 199 | }); 200 | } 201 | 202 | public function testAddYears() 203 | { 204 | $addValue = 2; 205 | 206 | $start = Carbon::today(); 207 | $end = Carbon::today()->addYears(2); 208 | 209 | $period = new CarbonPeriod($start, $end); 210 | 211 | $period->addYears($addValue); 212 | 213 | $start->addYears($addValue); 214 | $end->addYears($addValue); 215 | 216 | $this->assertEquals($period->start(), $start); 217 | 218 | $this->assertEquals($period->end(), $end); 219 | } 220 | 221 | public function testSubYears() 222 | { 223 | $subValue = 2; 224 | 225 | $start = Carbon::today()->subYears(2); 226 | $end = Carbon::today(); 227 | 228 | $period = new CarbonPeriod($start, $end); 229 | 230 | $period->subYears($subValue); 231 | 232 | $start->subYears($subValue); 233 | $end->subYears($subValue); 234 | 235 | $this->assertEquals($period->start(), $start); 236 | 237 | $this->assertEquals($period->end(), $end); 238 | } 239 | 240 | public function testAddMonths() 241 | { 242 | $addValue = 12; 243 | 244 | $start = Carbon::today(); 245 | $end = Carbon::today()->addMonths(12); 246 | 247 | $period = new CarbonPeriod($start, $end); 248 | 249 | $period->addMonths($addValue); 250 | 251 | $start->addMonths($addValue); 252 | $end->addMonths($addValue); 253 | 254 | $this->assertEquals($period->start(), $start); 255 | 256 | $this->assertEquals($period->end(), $end); 257 | } 258 | 259 | public function testSubMonths() 260 | { 261 | $subValue = 12; 262 | 263 | $start = Carbon::today()->subMonths(12); 264 | $end = Carbon::today(); 265 | 266 | $period = new CarbonPeriod($start, $end); 267 | 268 | $period->subMonths($subValue); 269 | 270 | $start->subMonths($subValue); 271 | $end->subMonths($subValue); 272 | 273 | $this->assertEquals($period->start(), $start); 274 | 275 | $this->assertEquals($period->end(), $end); 276 | } 277 | 278 | public function testAddDays() 279 | { 280 | $addValue = 4; 281 | 282 | $start = Carbon::today(); 283 | $end = Carbon::today()->addWeek(); 284 | 285 | $period = new CarbonPeriod($start, $end); 286 | 287 | $period->addDays($addValue); 288 | 289 | $start->addDays($addValue); 290 | $end->addDays($addValue); 291 | 292 | $this->assertEquals($period->start(), $start); 293 | 294 | $this->assertEquals($period->end(), $end); 295 | } 296 | 297 | public function testSubDays() 298 | { 299 | $subValue = 4; 300 | 301 | $start = Carbon::today()->subWeek(); 302 | $end = Carbon::today(); 303 | 304 | $period = new CarbonPeriod($start, $end); 305 | 306 | $period->subDays($subValue); 307 | 308 | $start->subDays($subValue); 309 | $end->subDays($subValue); 310 | 311 | $this->assertEquals($period->start(), $start); 312 | 313 | $this->assertEquals($period->end(), $end); 314 | } 315 | 316 | public function testIterateDates() 317 | { 318 | $totalDays = mt_rand(7, 14); 319 | $start = Carbon::today()->subDays($totalDays); 320 | $end = Carbon::today(); 321 | $period = CarbonPeriod::instance($start, $end); 322 | $count = 0; 323 | $period->iterateDates(function (Carbon $day) use (&$count) { 324 | $count++; 325 | }); 326 | $this->assertEquals($count, $totalDays); 327 | } 328 | } 329 | -------------------------------------------------------------------------------- /src/CarbonPeriod.php: -------------------------------------------------------------------------------- 1 | startDate > $this->endDate) { 29 | $tmp = clone $this->startDate; 30 | $this->startDate = clone $this->endDate; 31 | $this->endDate = clone $tmp; 32 | unset($tmp); 33 | } 34 | 35 | return $this; 36 | } 37 | 38 | /** 39 | * Create a new CarbonPeriod instance. 40 | * 41 | * @param \DateTime $startDate 42 | * @param \DateTime $endDate 43 | */ 44 | public function __construct(\DateTime $startDate = null, \DateTime $endDate = null) 45 | { 46 | $this->startDate = new CarbonDate($startDate); 47 | 48 | $this->endDate = $endDate 49 | ? CarbonDate::instance($endDate) 50 | : $this->startDate->copy()->addDay()->startOfDay(); 51 | 52 | $this->order(); 53 | 54 | return $this; 55 | } 56 | 57 | /** 58 | * This is an alias for the constructor 59 | * that allows better fluent syntax as it allows you to do 60 | * CarbonPeriod::instance()->fn() rather than 61 | * (new CarbonPeriod())->fn() 62 | * 63 | * @param \DateTime $startDate 64 | * @param \DateTime $endDate 65 | * @return static 66 | */ 67 | public static function instance(\DateTime $startDate = null, \DateTime $endDate = null) 68 | { 69 | return new static($startDate, $endDate); 70 | } 71 | 72 | /** 73 | * Create a CarbonPeriod from start of this day to current time. 74 | * 75 | * @return static 76 | */ 77 | public static function today() 78 | { 79 | return new static(CarbonDate::today(), CarbonDate::now()); 80 | } 81 | 82 | /** 83 | * Create a CarbonPeriod from start of this day to end of this day. 84 | * 85 | * @return static 86 | */ 87 | public static function thisDay() 88 | { 89 | return new static(CarbonDate::today(), CarbonDate::now()->endOfDay()); 90 | } 91 | 92 | /** 93 | * Create a CarbonPeriod of last full week. 94 | * 95 | * @return static 96 | */ 97 | public static function lastWeek() 98 | { 99 | $start = CarbonDate::parse('last week'); 100 | 101 | return new static( 102 | $start->startOfDay(), 103 | $start->copy()->addWeek() 104 | ); 105 | } 106 | 107 | /** 108 | * Create a CarbonPeriod of last full month. 109 | * 110 | * @return static 111 | */ 112 | public static function lastMonth() 113 | { 114 | $start = CarbonDate::parse('first day of last month'); 115 | 116 | return new static( 117 | $start->startOfDay(), 118 | $start->copy()->addMonth() 119 | ); 120 | } 121 | 122 | /** 123 | * Create a CarbonPeriod from closest monday to today. 124 | * 125 | * @return static 126 | */ 127 | public static function thisWeek() 128 | { 129 | $start = CarbonDate::today(); 130 | $end = CarbonDate::tomorrow(); 131 | if ($start->dayOfWeek !== CarbonDate::MONDAY) { 132 | $start->modify('last monday'); 133 | } 134 | 135 | return new static($start, $end); 136 | } 137 | 138 | /** 139 | * Create a CarbonPeriod instance from first day of current month to current date. 140 | * 141 | * @return static 142 | */ 143 | public static function thisMonth() 144 | { 145 | $start = CarbonDate::parse('first day of now'); 146 | return new static($start->startOfDay(), $start->copy()->tomorrow()); 147 | } 148 | 149 | /** 150 | * Create a CarbonPeriod instance from 1 January of current year to current date. 151 | * 152 | * @return static 153 | */ 154 | public static function thisYear() 155 | { 156 | $start = CarbonDate::parse('1 January'); 157 | return new static($start, $start->copy()->tomorrow()); 158 | } 159 | 160 | /** 161 | * Create a CarbonPeriod instance from two strings. 162 | * 163 | * @param string $startDate 164 | * @param string $endDate 165 | * @return static 166 | */ 167 | public static function parse($startDate, $endDate) 168 | { 169 | return new static( 170 | CarbonDate::parse($startDate), 171 | CarbonDate::parse($endDate) 172 | ); 173 | } 174 | 175 | /** 176 | * Get the start date from the instance. 177 | * 178 | * @return CarbonDate 179 | */ 180 | public function start() 181 | { 182 | return $this->startDate->copy(); 183 | } 184 | 185 | /** 186 | * Get the end date from the instance. 187 | * 188 | * @return CarbonDate|null 189 | */ 190 | public function end() 191 | { 192 | return $this->endDate->copy(); 193 | } 194 | 195 | /** 196 | * Set the internal iterator with interval for the instance. 197 | * 198 | * @param \DateInterval $interval 199 | * @param \Closure $callback 200 | * @return CarbonDate|$this 201 | */ 202 | public function each(\DateInterval $interval, \Closure $callback) 203 | { 204 | $period = new static($this->start(), $this->start()->add($interval)); 205 | 206 | do { 207 | $callback(new static( 208 | $period->start(), 209 | $period->end() > $this->endDate ? $this->endDate : $period->end() 210 | )); 211 | } while ($period->add($interval)->start() < $this->endDate); 212 | 213 | return $this; 214 | } 215 | 216 | /** 217 | * Set the internal iterator with day interval for the instance. 218 | * 219 | * @param int $days 220 | * @param callable $callback 221 | * @return CarbonDate|$this 222 | */ 223 | public function eachDays($days = 1, \Closure $callback) 224 | { 225 | return $this->each(new \DateInterval("P{$days}D"), $callback); 226 | } 227 | 228 | /** 229 | * Set the internal iterator with week interval for the instance. 230 | * 231 | * @param int $weeks 232 | * @param callable $callback 233 | * @param bool $onlyFullWeek 234 | * @return CarbonDate|$this 235 | */ 236 | public function eachWeeks($weeks = 1, \Closure $callback, $onlyFullWeek = false) 237 | { 238 | if ($this->lengthInWeeks() > 0) { 239 | return $this->each( 240 | new \DateInterval("P{$weeks}W"), 241 | function (CarbonPeriod $period) use ($weeks, $callback, $onlyFullWeek) { 242 | if (!$onlyFullWeek || $period->lengthInWeeks() === $weeks) { 243 | call_user_func_array($callback, func_get_args()); 244 | } 245 | } 246 | ); 247 | } 248 | 249 | return $this; 250 | } 251 | 252 | /** 253 | * Set the internal iterator with month interval for the instance. 254 | * 255 | * @param int $months 256 | * @param callable $callback 257 | * @param bool $onlyFullMonth 258 | * @return CarbonDate|$this 259 | */ 260 | public function eachMonths($months = 1, \Closure $callback, $onlyFullMonth = false) 261 | { 262 | if ($this->lengthInMonths() > 0) { 263 | return $this->each( 264 | new \DateInterval("P{$months}M"), 265 | function (CarbonPeriod $period) use ($months, $callback, $onlyFullMonth) { 266 | if (!$onlyFullMonth || $period->lengthInMonths() === $months) { 267 | call_user_func_array($callback, func_get_args()); 268 | } 269 | } 270 | ); 271 | } 272 | 273 | return $this; 274 | } 275 | 276 | /** 277 | * Set the internal iterator for day of week for the instance. 278 | * 279 | * @param $dayOfWeek 280 | * @param callable $callback 281 | * @return $this 282 | */ 283 | public function eachDayOfWeek($dayOfWeek, \Closure $callback) 284 | { 285 | $start = $this->startDate->copy(); 286 | if ($start->dayOfWeek !== $dayOfWeek) { 287 | $start->next($dayOfWeek); 288 | } 289 | 290 | if ($start < $this->endDate) { 291 | $period = new static($start, $this->endDate); 292 | 293 | $period->eachDays(CarbonDate::DAYS_PER_WEEK, function (CarbonPeriod $period) use ($callback) { 294 | $callback(new static($period->start(), $period->start()->addDay())); 295 | }); 296 | } 297 | 298 | return $this; 299 | } 300 | 301 | /** 302 | * Get the difference between start and end dates of the period in years. 303 | * 304 | * @return int 305 | */ 306 | public function lengthInYears() 307 | { 308 | return $this->startDate->diffInYears($this->endDate); 309 | } 310 | 311 | /** 312 | * Get the difference between start and end dates of the period in months. 313 | * 314 | * @return int 315 | */ 316 | public function lengthInMonths() 317 | { 318 | return $this->startDate->diffInMonths($this->endDate); 319 | } 320 | 321 | /** 322 | * Get the difference between start and end dates of the period in weeks. 323 | * 324 | * @return int 325 | */ 326 | public function lengthInWeeks() 327 | { 328 | return $this->startDate->diffInWeeks($this->endDate); 329 | } 330 | 331 | /** 332 | * Get the difference between start and end dates of the period in days. 333 | * 334 | * @return int 335 | */ 336 | public function lengthInDays() 337 | { 338 | return $this->startDate->diffInDays($this->endDate); 339 | } 340 | 341 | /** 342 | * Get the difference between start and end dates of the period in hours. 343 | * 344 | * @return int 345 | */ 346 | public function lengthInHours() 347 | { 348 | return $this->startDate->diffInHours($this->endDate); 349 | } 350 | 351 | /** 352 | * Get the difference between start and end dates of the period in minutes. 353 | * 354 | * @return int 355 | */ 356 | public function lengthInMinutes() 357 | { 358 | return $this->startDate->diffInMinutes($this->endDate); 359 | } 360 | 361 | /** 362 | * Get the difference between start and end dates of the period in seconds. 363 | * 364 | * @return int 365 | */ 366 | public function lengthInSeconds() 367 | { 368 | return $this->startDate->diffInSeconds($this->endDate); 369 | } 370 | 371 | /** 372 | * Add \DateInterval to the instance. 373 | * 374 | * @param \DateInterval $interval 375 | * @return $this 376 | */ 377 | public function add(\DateInterval $interval) 378 | { 379 | $this->startDate->add($interval); 380 | $this->endDate->add($interval); 381 | 382 | return $this; 383 | } 384 | 385 | /** 386 | * Sub \DateInterval from the instance. 387 | * 388 | * @param \DateInterval $interval 389 | * @return $this 390 | */ 391 | public function sub(\DateInterval $interval) 392 | { 393 | $this->startDate->sub($interval); 394 | $this->endDate->sub($interval); 395 | 396 | return $this; 397 | } 398 | 399 | /** 400 | * Add years to the period. 401 | * 402 | * @param $value 403 | * @return CarbonPeriod 404 | */ 405 | public function addYears($value) 406 | { 407 | return $this->add(new \DateInterval("P{$value}Y")); 408 | } 409 | 410 | /** 411 | * Remove years from the period. 412 | * 413 | * @param $value 414 | * @return CarbonPeriod 415 | */ 416 | public function subYears($value) 417 | { 418 | return $this->sub(new \DateInterval("P{$value}Y")); 419 | } 420 | 421 | /** 422 | * Add months to the period. 423 | * 424 | * @param $value 425 | * @return CarbonPeriod 426 | */ 427 | public function addMonths($value) 428 | { 429 | return $this->add(new \DateInterval("P{$value}M")); 430 | } 431 | 432 | /** 433 | * Remove months from the period. 434 | * 435 | * @param $value 436 | * @return CarbonPeriod 437 | */ 438 | public function subMonths($value) 439 | { 440 | return $this->sub(new \DateInterval("P{$value}M")); 441 | } 442 | 443 | /** 444 | * Add days to the period. 445 | * 446 | * @param $value 447 | * @return CarbonPeriod 448 | */ 449 | public function addDays($value) 450 | { 451 | return $this->add(new \DateInterval("P{$value}D")); 452 | } 453 | 454 | /** 455 | * Remove days from the period. 456 | * 457 | * @param $value 458 | * @return CarbonPeriod 459 | */ 460 | public function subDays($value) 461 | { 462 | return $this->sub(new \DateInterval("P{$value}D")); 463 | } 464 | 465 | /** 466 | * Determines if the instances contains a date. 467 | * 468 | * @see \Carbon\Carbon::between 469 | * @param CarbonDate $date 470 | * @param bool $equal Indicates if a > and < comparison should be used or <= or >= 471 | * @return bool 472 | */ 473 | public function contains(CarbonDate $date, $equal = true) 474 | { 475 | return $date->between($this->startDate, $this->endDate, $equal); 476 | } 477 | 478 | /** 479 | * Iterate period over each day 480 | * 481 | * @param \Closure $callback 482 | * 483 | * @return CarbonPeriod 484 | */ 485 | public function iterateDates(\Closure $callback) 486 | { 487 | $interval = new \DateInterval('P1D'); 488 | 489 | $period = new \DatePeriod($this->start()->copy()->startOfDay(), $interval, $this->end()->copy()->startOfDay()); 490 | 491 | foreach ($period as $date) { 492 | $callback($date); 493 | } 494 | 495 | return $this; 496 | } 497 | } 498 | --------------------------------------------------------------------------------