How to create CarbonPeriod without knowing end date? - laravel

I need help with CarbonPeriod. I'm creating reminder to take medicine from one date to another in hours interval like this:
$startDate = Carbon::parse($this->data->get('date'))->setTimezone($timezone);
$endDate = Carbon::parse($this->data->get('endDate'))->addDay()->setTimezone($timezone);
$interval = $this->data->get('interval');
$period = new DatePeriod($startDate, CarbonInterval::hours($interval), $endDate);
but now I need to create CarbonPeriod knowing only $startDate and $interval in days and not the $endDate. Like I want to take my tablet every day in 12 o'clock until I turn off this reminder myself. Can somebody help me with this?

Typically when doing this, I would simply set the end date a very long way in the future (10 years or 20 years or 30 years ... you get the idea) and also (if you think it will ever get close to that date) have a mechanism when checking the date to extend it when it gets close (i.e. a rolling end date as such).

You can do the following:
$date = Carbon::now();
$period = $date->toPeriod(null, 3, 'days');
$period->setRecurrences(INF);
This will create a never-ending period that jumps 3 days at a time.
Examples directly from the documentation:
CarbonPeriod::create('now', '2 days', INF); // infinite iteration
CarbonPeriod::create('now', '2 days', INF)->calculateEnd()->isEndOfTime(); // true
CarbonPeriod::create('now', CarbonInterval::days(-2), INF)->calculateEnd()->isStartOfTime(); // true
https://carbon.nesbot.com/docs/#api-period

Related

Carbon: comparing date instances is giving unexpected result

This problem is driving me crazy.
Here is my Carbon instance:
$carbonTemp = CarbonImmutable::createFromFormat('Y-m-d', $date);
What I want to do is just to understand if the date here is the last day of the week.
$carbonTemp->equalTo($carbonTemp->endOfWeek())
If $date = '2021-08-08' which is the last day of this week, the result above must be true, right?
It is giving me FALSE !!
Even though $carbonTemp->endOfWeek()->format('Y-m-d') is giving me '2021-08-08'.
endOfWeek() returns last day of week and time 23:59:59.999999. Therefore it is necessary to use endOfDay() method when creating date.
$carbonTemp = CarbonImmutable::createFromFormat('Y-m-d', $date)->endOfDay();
that's because you created CarbonImmutable object, so endOfWeek will not work.
Create a normal Carbon date:
$carbonTemp = Carbon::createFromFormat('Y-m-d', $date);

Laravel Carbon get passed years relative to current time

I need to show the passed years like 5.6 years with a given date $model->created_at
What I tried so far is
$dt = Carbon::now();
echo $dt->diffForHumans($model->created_at); 1 month ago
how to show date only like 5.6 years
you can use Carbon::floatDiffInRealYears to get exactly the different,
and Carbon::diffInYears to get the rounded result of the previous method
$dt = Carbon::now();
echo $dt->floatDiffInRealYears($model->created_at);

Can't get monthy CarbonPeriod to behave as desired

In the project I'm working on I have a daily command that basically checks the date of the last record in the database and tries to fetch data from an API from the day after and then each month after that (the data is published monthly).
Basically, the last record's date is 2019-08-30. I'm mocking as if I were running the task on 2019-09-01 with
$test = Carbon::create(2019,9,1,4);
Carbon::setTestNow($test);
I then create a monthly period between the next day of the last record's date and the last day of the current month like so:
$period = CarbonPeriod::create($last_record_date->addDay(), '1 month', $last_day_of_current_month);
Successfully generating a period with start_date = 2019-08-31 and end_date = 2019-09-30. Which I use in a simple foreach.
What I expected to happen is that it runs twice, once for August and once for September, but it's running only once for the start date. It's probably adding a month and going past the end date, but I don't know how to force the behaviour I'm looking for.
TL;DR:
$period = CarbonPeriod::create('2019-08-31', '1 month', '2019-09-30');
foreach ($period as $dt) {
echo $dt->format("Y-m") . "<br>\n";
}
This will print just 2019-08, while I expect 2019-08 and 2019-09. What's the best way to achieve that?
Solution :-
You can store actual date in $actual_day and current date for occurring monthly in $current_day. Put a check on comparing both dates, if not matched then make it on the same day it will skip 30,31 case in case of February month.
$current_date = $current_date->addMonths(1);
if($current_date->day != $actual_day){
$date = Carbon::parse($date->year."-".$date->month."-".$actual_day);
}
Your start date is 2019-08-31. Adding a month takes you to 2019-09-31. 2019-09-31 doesn't exist so instead you get 2019-10-01, which is after your end date. To avoid this I'd suggest you use a more regular interval such as 30 days.
Otherwise you're going to have to rigorously define what you mean by "a month later". If the start date is 31st Jan is the next date 28th February? Is the month after 28th or 31st March? How do leap years affect things?

Get First day of last month timestamp with Carbon

I want to get the timestamp in milliseconds for first day of last month and last day of last month using Carbon in laravel.
I have tried to do it with carbon::parse, which is achieved. But I want to instantiate the Carbon class simply to achieve the same.
This is the code that works fine with Carbon::parse
Carbon::parse('first day of last month',$timezone)->timestamp
But I want to achieve the same using something like below.
$start = new Carbon('first day of last month');
$end = new Carbon('last day of last month');
The output should be timestamp in milliseconds. Like 1555704794000
You may try the below code
$previous_month_start = Carbon::now()->subMonth()->startOfMonth()->format('x');
$previous_month_end = Carbon::now()->subMonth()->endOfMonth()->format('x');

Get a Specific WeekDay date after a date

I am trying to implement a delivery process that occurs at specific days of week for each region. So, in a Region that delivers on Tuesdays and Thursdays I need to be able to get next eligible date based on the date the product will be available. So, if I will have it read on the 5th, O need to get the date for the next Tuesday or Thursday.
I started implementing it on Carbon, but I and creating a lot of loops through dates, testing dates and checking if its valid. something of getting product availability date and checking each day after it if its a monday Tuesday or Thursday ... etc ///I am sure, using Carbon, will have a better way to do it.
Any hint on how to do that ?
Thanks for any help!
Define a date:
$date = Carbon::now();
Now you have to get the day:
$day = $date->dayOfWeekIso
If $date is monday, then you will get a integer and that would be 1. That is because: 1 (monday), 2 (Tuesday), ..., 7 (sunday).
Now that you have this number you just need to apply some simple logic.
If the number you get is a 2 (Tuesday) then you will need to add two days to your $date in order to get the delivery date:
$delivery_date = $date->addDays(2);
If your day is equal 4 (Thursday), then you need to add 6 days to your $date so that would give you the next Tuesday:
$delivery_date = $date->addDays(6);
I think that's what you want! I hope it helps!

Resources