How to divide datetime period into separate days in PHP - php

I need to divide time period for example from:
2015-11-22 11:22:33 to 2015-11-24 02:02:04
into something like this:
2015-11-22 11:22:33 - 2015-11-22 23:59:59
2015-11-23 00:00:00 - 2015-11-23 23:59:59
2015-11-24 00:00:00 - 2015-11-24 02:02:04.
It has to work also for periods shorter than 24h, so for
2015-11-22 11:22:33 to 2015-11-23 02:02:04
I need this:
2015-11-22 11:22:33 - 2015-11-22 23:59:59
2015-11-23 00:00:00 - 2015-11-23 02:02:04.
I found almost perfect piece of code, but it only works for periods longer than 24h and I don't know how to tune it.
<?php
$start_date = '27:04:2013';
$start_time = '16:30';
$end_date = '29:04:2013';
$end_time = '22:30';
// Date input strings and generate a suitable DatePeriod
$start = DateTime::createFromFormat("d:m:Y H:i", "$start_date $start_time");
$end = DateTime::createFromFormat("d:m:Y H:i", "$end_date $end_time");
$interval = new DateInterval('P1D');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $date) {
// Get midnight at start of current day
$date_start = clone $date;
$date_start->modify('midnight');
// Get 23:59:59, end of current day
// (moving to midnight of next day might be good too)
$date_end = clone $date;
$date_end->modify('23:59:59');
// Take care of partial days
$date_start = max($start, $date_start);
$date_end = min($end, $date_end);
// Here you would construct your array of
// DateTime pairs, or DateIntervals, as you want.
printf(
"%s -> %s \n",
$date_start->format('Y-m-d H:i'),
$date_end->format('Y-m-d H:i')
);
}
?>

Try this:
$date1 = '2015-11-22 11:22:33';
$date2 = '2015-11-23 12:22:34';
$f1 = strtotime($date1);
$f2 = strtotime(substr($date1, 0, 10) . " 23:59:59");
while($f2 < strtotime($date2)) {
print(date('Y-m-d H:i:s',$f1) .' - ' .date('Y-m-d H:i:s',$f2).'<br>');
$f1 = strtotime(date('Y-m-d H:i:s', $f2) .' +1 second');
$f2 = strtotime(date('Y-m-d H:i:s', $f2) .' +1 day');
}
print(date('Y-m-d H:i:s',$f1) .' - ' .$date2.'<br>');

See here: http://sandbox.onlinephpfunctions.com/code/77eaae15fdd7c0d2ca1f02a2d225c17199218819
$datetime1 = new DateTime('2015-11-22 11:22:33');
$datetime2 = new DateTime('2015-11-23 02:02:04');
$interval = $datetime1->diff($datetime2);
var_dump($interval->format('%y-%m-%d %h:%i:%s'));
// RESULT: string(14) "0-0-0 14:39:31"
References:
http://php.net/manual/de/datetime.diff.php
http://php.net/manual/de/class.dateinterval.php
http://php.net/manual/de/dateinterval.format.php

Related

Carbon custom start and end of the week by timestamp

I have a list of records with $clocked_in timestamps. I want to display its week start and end date, so I came up with this:
$timesheetWeekStartDate = Carbon::parse($clocked_in)->startOfWeek()->setTimezone($timezone)->addHours(12)->addMinute()->format('Y-m-d H:i');
$timesheetWeekEndDate = Carbon::parse($clocked_in)->endOfWeek()->setTimezone($timezone)->addHours(12)->addMinute()->format('Y-m-d H:i');
$timesheet->period = $timesheetsWeekStartDate . ' - ' . $timesheetWeekEndDate;
It seems to be working, but I would like to have customized start and end of week - add 12 hours ahead. So next week would start/end on 2022-05-23 12:01 - 2022-05-29 12:00, not 2022-05-23 23:59 - 2022-05-29 00:00.
For example, if $clocked_in is starts on Monday 05:00 I want it to display the previous week, not current(because its not 12:01 yet).
How I can achieve that by utilising Carbon?
Didn't find a solution in Carbon, so made it in plain DateTime, here is solution:
$timesheet->clocked_in = '2022-05-21 21:20:04';
$start = date('Y-m-d', strtotime('-2 week', strtotime($timesheet->clocked_in)));
$end = date('Y-m-d', strtotime('+2 week', strtotime($timesheet->clocked_in)));
$period = new DatePeriod(
new DateTime($start),
new DateInterval('P1W'),
new DateTime($end)
);
$periods = [];
foreach ($period as $periodDate) {
$start = $periodDate;
$end = clone $periodDate;
$periods[] = [
'start' => $start->setTimezone(new DateTimeZone($user->account->timezone))->add(new DateInterval('PT12H'))->add(new DateInterval('PT1M'))->format('Y-m-d H:i'),
'end' => $end->setTimezone(new DateTimeZone($user->account->timezone))->add(new DateInterval('P7D'))->add(new DateInterval('PT12H'))->format('Y-m-d H:i'),
];
}
foreach ($periods as $period) {
if (($timesheet->clocked_in >= $period['start']) && ($timesheet->clocked_in <= $period['end'])) {
$timesheets[$timesheetKey]->period = date('m/d/Y', strtotime($period['start'])) . ' - ' . date('m/d/Y', strtotime($period['end']));
}
}

PHP confusion over reversing a DatePeriod iterator

I'm trying to work out how to invert my date period without pushing the data into an array and reversing it.
Say I would like a list of the last 5 Saturdays the following code will produce:
$begin = new DateTime( date('Y-m-d', strtotime("last Saturday")));
$begin->modify("- 4 weeks");
$end = new DateTime( date('Y-m-d', strtotime("last Saturday")));
$end = $end->modify( '+1 day' );
$interval = new DateInterval('P1W');
$periods = new DatePeriod($begin, $interval ,$end);
foreach($periods as $date){
echo $date->format("Y-m-d") . "\n";
}
2021-07-31
2021-08-07
2021-08-14
2021-08-21
2021-08-28
I would like this list reversed. So I figured I could make use of the DatePeriod invert property. Both the start and end of the DatePeriod look correct, with a result showing in the current element. However, interating over $period returns nothing:
$begin = new DateTime( date('Y-m-d', strtotime("last Saturday")));
$begin = $begin->modify( '+1 day' );
$end = new DateTime( date('Y-m-d', strtotime("last Saturday")));
$end->modify("- 4 weeks");
$interval = new DateInterval('P1W');
$interval->invert = 1;
$periods = new DatePeriod($begin, $interval ,$end);
foreach($periods as $date){
echo $date->format("Y-m-d") . "\n";
}
Update
So I've found a solution that calculates a diff of days and passes that to the end param in the DatePeriod constructor. It's not ideal but is working. Note the diff->days had to be divided by the days interval to prevent additional dates pulling through.
$start = new \DateTime( date('Y-m-d', strtotime("last Saturday")));
$end = new DateTime( date('Y-m-d', strtotime("last Saturday")));
$end->modify("- 4 weeks");
$diff = $end->diff($start);
$interval = new \DateInterval('PT0S'); //0 duration
$interval->d = -7; //negative value
$period = new \DatePeriod($start, $interval, $diff->days / 7);
foreach ($period as $date) {
echo $date->format('Y-m-d') . PHP_EOL;
}

Days between two dates doesn't work in PHP

I need to compute the days between two dates (format YYYYMMDD)
I used two test dates, 2020-01-20 and 2020-02-20
$enddate = "20200220";
$startdate = "20200120";
$s = new DateTime($enddate);
$e = new DateTime($startdate);
$diff = $s->diff($e);
echo "days: ".$diff->d;
the result is 0 instead of being a month worth of days
days: 0
I understand that dates as strings might be ambiguous, so I also tried to specify the format, by doing:
$enddate = "20200220";
$startdate = "20200120";
$s = DateTime::createFromFormat('Ymd', $startdate);
$e = DateTime::createFromFormat('Ymd', $enddate);
$diff = $s->diff($e);
echo "days: ".$diff->d;
Still got 0
days: 0
You can use strtotime
<?php
// strtotime converts any string date format to unix time
$date1 = "2020-01-20";
$date2 = "2020-02-20";
$seconds_in_a_day = 86400;
$diff = (strtotime($date2) - strtotime($date1))/$seconds_in_a_day;
echo $diff; // output 31

php - match day of week in date() / time()

I'm trying to reschedule recurring events based on the recurring method: daily, weekly or monthly.
So assuming I have this data:
$now = time();
$start_date = '01/01/2011 14:00';
$end_date = '01/01/2011 14:20';
$start_time = date('H:i', $start_date);
$end_time = date('H:i', $end_date);
$period = $end_date - $start_date; // in this case, 20 minutes
This event rescheduled daily would be:
$new_time_start = strtotime(date("m/d/Y {$start_time}", $now));
$new_time_end = $new_time_start + $period;
And monthly:
$start_day = date('d', $start_date);
$new_time_start = strtotime(date("m/{$start_day}/Y {$start_time}", $now));
$new_time_end = $new_time_start + $period;
It seems to be working, but I don't know how to do the same for weekly events :(
For example '01/01/2011' is Saturday, so I want to reschedule the event to run every Saturday (day 6 of the week according to PHP).
Any ideas?
Give this a try...
$today = date('w');
$day = date('w', $start_date);
$diff = abs(7 - ($today - $day));
$new_time_start = strtotime('+'.$diff.'days', strtotime(date("m/d/Y {$start_time}")));
$new_time_end = $new_time_start + ($end_date - $start_date);
It seems as though you're missing some strtotime( ) wrappers around your $start_date and $end_date values. I'm assuming your storing your start and end date variables as unix timestamps, so I didn't include them in my code either.
Also, just as a side note, you don't have to enter time( ) in date( ) as the second argument. If the time value is missing, it will use the current time. So you can remove all your $now instances and it will still work.
I'm not too sure I understand your question, but can't you do this?
$time = '2011-01-31';
$weekLater = date('Y-m-d', strtotime('+7 days ' . $time));
echo $time . ' -> ' . $weekLater;
Output : 2011-01-31 -> 2011-02-07
Whatever date you give it, it will give you a date 7 days in the future. Is this what you need?

Get timestamp of today and yesterday in php

How can I get the timestamp of 12 o'clock of today, yesterday and the day before yesterday by using strtotime() function in php?
12 o'clock is a variable and would be changed by user.
$hour = 12;
$today = strtotime($hour . ':00:00');
$yesterday = strtotime('-1 day', $today);
$dayBeforeYesterday = strtotime('-1 day', $yesterday);
strtotime supports a number of interesting modifiers that can be used:
$hour = 12;
$today = strtotime("today $hour:00");
$yesterday = strtotime("yesterday $hour:00");
$dayBeforeYesterday = strtotime("yesterday -1 day $hour:00");
echo date("Y-m-d H:i:s\n", $today);
echo date("Y-m-d H:i:s\n", $yesterday);
echo date("Y-m-d H:i:s\n", $dayBeforeYesterday);
It works as predicted:
2011-01-24 12:00:00
2011-01-23 12:00:00
2011-01-22 12:00:00
OO Equivalent
$iHour = 12;
$oToday = new DateTime();
$oToday->setTime($iHour, 0);
$oYesterday = clone $oToday;
$oYesterday->modify('-1 day');
$oDayBefore = clone $oYesterday;
$oDayBefore->modify('-1 day');
$iToday = $oToday->getTimestamp();
$iYesterday = $oYesterday->getTimestamp();
$iDayBefore = $oDayBefore->getTimestamp();
echo "Today: $iToday\n";
echo "Yesterday: $iYesterday\n";
echo "Day Before: $iDayBefore\n";
You can easily find out any date using DateTime object, It is so flexible
$yesterday = new DateTime('yesterday');
echo $yesterday->format('Y-m-d');
$firstModayOfApril = new DateTime('first monday of april');
echo $firstModayOfApril->format('Y-m-d');
$nextMonday = new DateTime('next monday');
echo $nextMonday->format('Y-m-d');
to get start of day yesterday
$oDate = new DateTime();
$oDate->modify('-1 day');
echo $oDate->format('Y-m-d 00:00:00');
result
2014-11-05 00:00:00
All the answers here are too long and bloated, everyone loves one-lines ;)
$yesterday = Date('Y-m-d', strtotime('-1 day'));
(Or if you are American you can randomize the date unit order to m/d/y (or whatever you use) and use Cups, galloons, feet and horses as units...)
As of PHP 7 you can write something like this:
$today = new \DateTime();
$yesterday = (clone $today)->modify('-1 day');
$dayBefore = (clone $yesterday)->modify('-1 day');
// Then call ->format('Y-m-d 00:00:00'); on each objects
you can also use new DateTime("now") for today new DateTime("1 day ago") for yesterday or all can be parse by strtotime php function.
Then format as you want.
$timeStamp = time();
// $timeStamp = time() - 86400;
if (date('d.m.Y', $timeStamp) == date('d.m.Y')) {
echo 'Today';
} elseif (date('d.m.Y', $time) == date('d.m.Y', strtotime('-1 day'))) {
echo 'Yesterday';
}

Categories