Imagine we have the day (of week) and the time of an event ( that is in the future ) :
$day = "Wednesday";
$time = "13:00";
And we want to create a Carbon date for that, but it has to be relative to current time :
$carbon = new Carbon();
For example if $carbon is Tuesday, 2017-01-17 09:00,
the $event date that we create should be Wednesday, 2017-01-18 13:00
In other words, the $event is a date that is taking place in the next 7 days. We don't have it's year, month and other data, but we do know it's day of week and the time.
you should be able to use something like:
Carbon::parse('next ' . $day)
and you can also throw the $time part in there somewhere too but can't remember exactly how right now.
Related
If the date is the last day of the month, I want to get the last day of the next month. I don't want the time to change.
Original date -> 2022-31-01 14:00:00
I need -> 2022-28-02 14:00:00
Original date -> 2022-28-02 14:00:00
I need -> 2022-31-03 14:00:00
$date->lastOfMonth() returns the last day of $date's month.
$date->isLastOfMonth() returns true if $date is the last day of the month.
Assuming $date is a Carbon instance, then it's just a matter of using a few functions and a ternary operator.
$result = $date->isLastOfMonth()
? $date->addDays(1)->lastOfMonth()
: $date;
To keep the time part of the date, you'll need to create an interval first and add it later.
$interval = $date->diffAsCarbonInterval($date->startOfDay());
$result = $date->isLastOfMonth()
? $date->addDays(1)->lastOfMonth()->add($interval)
: $date;
#IGP answer's is correct, but;
$date->startOfDay() -> changes your original date.
you should use $date->copy()->startOfDay()
Carbon is an extension of DateTime. However, Carbon is not needed here as there is a very simple solution using DateTime. It only has to be checked whether the day of the date (d) matches the last day of the month (t). if so, then it is modified to the last day of the next month. Time remains unaffected.
$dt = new DateTime('2022-01-31 14:00:00');
if($dt->format('d') == $dt->format('t')){
$dt->modify('last Day of next month');
}
//test output
echo $dt->format('Y-m-d H:i:s')."\n";
Try self.
I have a website where we show next delivery date, eg for a weekly delivery each Tuesday -- although the actual day that deliveries go out needs to be manually changed sometimes. I need to update it to (eg) Tuesday and Friday deliveries, and I'm struggling to find a good method.
Here's how I've got it set up currently:
<?php
$start_date = '2020-05-05'; // Date in the past to start counting from: YYYY-MM-DD
$date_interval = new DateInterval('P7D'); // DELIVERY EVERY x DAYS: PxD (usually P7D)
// create a DateTime object that represents start of sequence
$start_datetime = DateTime::createFromFormat('Y-m-d', $start_date);
// create a DateTime object representing the current date
$current_datetime = new DateTime('today');
// determine end date for DatePeriod object that will later be used.
// This is no further out than current date plus the interval.
$end_datetime = new DateTime('tomorrow');
$end_datetime->add($date_interval);
$date_period = new DatePeriod($start_datetime, $date_interval, $end_datetime);
// iterate until the last date in the set
foreach($date_period as $dp) {
$next_delivery = $dp;
}
echo $next_delivery->format('l, M j, Y');
?>
The dateperiod class says that it accepts ISO 8601 time periods, but as far as I can tell there's no way to set it to "next Tuesday or Friday, whichever is closer".
One hacky method I've thought of that would work is to run this function twice, once for Tuesday and once for Friday, compare with today's date, and display whichever is sooner in the future. But surely there's a more elegant way?
That's a very long winded way to find the next available Tuesday or Friday. One way to do it is check to see what day of the week it is and dynamically set the day based on that:
$day = (in_array((int) date('w'), [0,1,5,6], true)) ? 'Tuesday' : 'Friday';
echo (new DateTime("next {$day}"))->format('l, M j, Y');
output:
Tuesday, May 12, 2020
The code above checks to see if the day is Sunday, Monday, Friday, Or Saturday. If so, set the next day to "Tuesday". Otherwise, set it to "Friday". Then you can use a relative datetime value to set your date.
If you want a more human readable version of this you can spell out the days:
$day = (in_array(date('l'), ['Sunday', 'Monday', 'Friday', 'Saturday'], true)) ? 'Tuesday' : 'Friday';
It is not very difficult to find the next available Tuesday or Friday.
It is the smaller date of both.
echo min(date_create('next Tuesday'),date_create('next Friday'))->format('l, M j, Y');
Alternatively with a PHP extension for DateTime API called dt. You can find it here.
This class supports date calculations with crontab expressions. The days of the week start with 0 for Sunday. If you want to calculate the next Tuesday or Friday at 14:00 as an example, you only have to do this:
$cron = "0 14 * * 2,5"; //next Tuesday or Friday 14:00
$next_delivery = dt::create('today')->nextCron($cron); //today is 2020-05-10
echo $next_delivery->format('l, M j, Y, H:i');
//Tuesday, May 12, 2020, 14:00
I have this:
$previousMonth = new DateTime('2019-12-31');
$previousMonth->modify('-1 month');
My understanding is '-1 month' should modify the object regardless of number of days in that month, or?
Naturally what should I get or expect to get is end of Nov(2019-11-30) but what I get is first of December(the same month).
BTW if I change the date to '2019-12-30'(one day prior) then it will be end of Nov.
If my initial assumption is not correct, then what is the best alternative to reliably calculate the previous month?
Any thoughts?
The simplest and easiest way to get the last month in php is
$previousMonth = date("Y-n-j", strtotime("last day of previous month"));
Same as been suggested on other thread Getting last month's date in php
$date = "2019-12-31 00:00:00";
echo date('Y-m-d', strtotime($date . '-1month'));
This prints out 2019-12-01 as the 31/11 does not exist.
The following doesn't answer your question but may help in the future. I like to use Carbon when working with dates. Your issue could be resolved quite simply with this.
https://carbon.nesbot.com/
It has many functions and is extremely simple to use, and it can be installed with Composer.
To get the last day of the previous month, you can get the first day of the current month and substract 1 second or 1 day :
$previousMonth = new DateTime('2019-12-31');
$previousMonth->modify($previousMonth->format('Y-m-01')); // date is 2019-12-01 00:00:00
$previousMonth->modify('-1 sec');
echo $previousMonth->format('Y-m-d H:i:s') . PHP_EOL; // Outputs 2019-11-30 23:59:59
$previousMonth->modify('+1 sec'); // set back the original date 2019-12-01 00:00:00
$previousMonth->modify('-1 day');
echo $previousMonth->format('Y-m-d H:i:s'); // Outputs 2019-11-30 00:00:00
I have Carbon date variable.
Carbon::parse("2018-08-01") //tuesday
I want to add days until next monday ("2018-08-07").
Is there command like
Carbon->addDaysUntil("monday"); ->addMonthUntil("september")
and so on.
So i want to change current date to begining of next week, month, year
Old question but there's a nice way of doing this at the moment.
$date = Carbon::parse('2018-08-01')->next('Monday');
Additionally, if you want to check if your date is monday first, you could do something like this:
$date = Carbon::parse(...);
// If $date is Monday, return $date. Otherwise, add days until next Monday.
$date = $date->is('Monday') ? $date : $date->next('Monday');
Or using the Carbon constants as suggested by #smknstd in the comment below:
$date = Carbon::parse(...);
// If $date is Monday, return $date. Otherwise, add days until next Monday.
$date = $date->is(Carbon::MONDAY) ? $date : $date->next(Carbon::MONDAY);
What you can do is determine the current date, get the start of the week (Monday) and add a week to get the next week.
$date = Carbon::create(2017, 8, 30);
$monday = $date->startOfWeek();
$mondayOneWeekLater = $date->addWeeks(1); // $date->addWeek();
Rinse and repeat for months and years but as Maritim suggests it's in the docs. ;-)
Source: http://carbon.nesbot.com/docs/
There are a lot of SO questions showing you how to check if a date-time is within a range, but there is not much to help when you want to do recurrently and the date range spans more than one day.
As an example, how do you check if its between 22:00 on a Tuesday and 07:30 on the following Thrusday? And how do you do that week in week out?
The constructor for PHP's DataTime class accepts the relative argument this xxxday, which can be used to give you the next 'xxxday' relative to the current time.
So for example, new DateTime('next friday') will give you a datetime object representing 00:00:00 on the next Friday relative to the current day. If the current day is Friday, then that is the date which will be returned.
So if you define
$end = new DateTime(next thursday 07:30);
then $end is a DateTime object representing 22:00 on the next Tuesday from the current time, or 20:00 for today if today is a Tuesday. Then you can take the interval off the end to get the start with
$start = clone $end;
$start = $end->sub(new DateInterval('P1DT9H30M'));
which gives you a DateTime object 1day, 9hours and 30 minutes prior to 07:30 on the next Thursday from the current time, or 22:00 on the Tuesday before the next Thursday from the current time.
Then you can get the current date time and see if its between the start and end date times:
$now = new DateTime();
if( $now >= $start && $now <= $end ) {
//In interval
}