When creating event I need to set event start and event end in datetime format (0000-00-00 00:00:00)
Then I have option to set weekly repeating of that event until specific date (0000-00-00)
But I can't insert repeating events properly in database. Here is what I have:
$startDateTime = '2015-04-30 10:30:00';
$endDateTime = '2015-04-30 11:30:00';
$repeatEndDate = '2015-06-01';
$timestamp = strtotime($startDateTime);
$day_of_week = date('l', $timestamp);
$step = 1;
$unit = 'W';
$repeatStart = new DateTime($startDateTime);
$repeatEnd = new DateTime($repeatEndDate);
$repeatStart->modify($day_of_week);
$interval = new DateInterval("P{$step}{$unit}");
$period = new DatePeriod($repeatStart, $interval, $repeatEnd);
foreach ($period as $key => $date ) {
$repeatQuery = 'INSERT INTO event(start,end,status,repeats) VALUES ("'.$startDateTime.'","'.$endDateTime.'","'.$status.'","'.$repeatEndDate.'")';
$repeatResult = mysqli_query($db, $repeatQuery) or die (mysqli_error($db));
}
When I do print_r($date); it looks like this, no actual time just 00:00:00
DateTime Object
(
[date] => 2015-04-30 00:00:00
[timezone_type] => 3
[timezone] => Europe/Berlin
)
I know that I can't insert values like that but I don't know how to get correct values from objects.
So in this example I need to insert events that begin in 10:30:00 and end in 11:30:00(events always end same day) every Thursday starting at 2015-04-30 and ending at 2015-06-01. How can this be achieved?
Thank you
The problem is you're calling DateTime::modify with a day name (currently 'Thursday'). This value is calculated from the $startDateTime variable, and then used to modify that variable, so the only effect it has, is resetting the Time portion of that DateTime instance back to 0:00:00.
The following gives me the results I would expect:
(I've commented out the parts you need to remove from yours, to make it easier to see the difference)
date_default_timezone_set('Etc/UTC');
$startDateTime = '2015-04-30 10:30:00';
$endDateTime = '2015-04-30 11:30:00';
$repeatEndDate = '2015-06-01';
#$timestamp = strtotime($startDateTime);
#$day_of_week = date('l', $timestamp);
$step = 1;
$unit = 'W';
$repeatStart = new DateTime($startDateTime);
$repeatEnd = new DateTime($repeatEndDate);
#$repeatStart->modify($day_of_week);
$interval = new DateInterval("P{$step}{$unit}");
$period = new DatePeriod($repeatStart, $interval, $repeatEnd);
foreach ($period as $key => $date ) {
echo($date->format('Y-m-d H:i:s')) . PHP_EOL;
}
The result from running the above is:
2015-04-30 10:30:00
2015-05-07 10:30:00
2015-05-14 10:30:00
2015-05-21 10:30:00
2015-05-28 10:30:00
When you modify your $repeatStart using the modify() method you are using the l format character which, according to the docs, returns
A full textual representation of the day of the week
by changing the $day_of_week format string to
$day_of_week = date('Y-m-d H:i:s', $timestamp);
I get the following output
DateTime Object
(
[date] => 2015-04-30 10:30:00
[timezone_type] => 3
[timezone] => Europe/London
)
DateTime Object
(
[date] => 2015-05-07 10:30:00
[timezone_type] => 3
[timezone] => Europe/London
)
DateTime Object
(
[date] => 2015-05-14 10:30:00
[timezone_type] => 3
[timezone] => Europe/London
)
DateTime Object
(
[date] => 2015-05-21 10:30:00
[timezone_type] => 3
[timezone] => Europe/London
)
DateTime Object
(
[date] => 2015-05-28 10:30:00
[timezone_type] => 3
[timezone] => Europe/London
)
Although, the modification is not actually necessary and the following code should achieve what you are looking for.
<?php
$startDateTime = '2015-04-30 10:30:00';
$endDateTime = '2015-04-30 11:30:00';
$repeatEndDate = '2015-06-01';
$step = 1;
$unit = 'W';
$repeatStart = new DateTime($startDateTime);
$repeatEnd = new DateTime($repeatEndDate);
$interval = new DateInterval("P{$step}{$unit}");
$period = new DatePeriod($repeatStart, $interval, $repeatEnd);
foreach ($period as $key => $date ) {
$repeatQuery = 'INSERT INTO event(start,end,status,repeats) VALUES ("'.$startDateTime.'","'.$endDateTime.'","'.$status.'","'.$repeatEndDate.'")';
$repeatResult = mysqli_query($db, $repeatQuery) or die (mysqli_error($db));
print_r($date);
}
Related
I am trying to write a program to dynamically add interval and find datetime between two dates in php.
I am getting Startdatetime, Enddatetime, Interval from the user.
If the
Start date is 2020-02-17 00:00:00, end date is 2020-02-17 08:00:00, and interval to be added to is 2hrs,
then I am trying to print all datetime ranges like
Array(
[0] => 2020-02-17 00:00:00
[1] => 2020-02-17 02:00:00
[2] => 2020-02-17 04:00:00
[3] => 2020-02-17 06:00:00
[4] => 2020-02-17 08:00:00
)
I tried with dateperiod, but doesn't work as it gives only start & end date
$period = new DatePeriod(
new DateTime($from_datetime),
new DateInterval('PT$hoursH'),
new DateTime($to_datetime)
);
Please help me to get all datetime ranges.
Using this:
<?php
$begin = new DateTime('2020-02-17 00:00:00');
$end = new DateTime('2020-02-17 08:00:01');
$interval = DateInterval::createFromDateString('2 hours');
$period = new DatePeriod($begin, $interval, $end);
$myDates = [];
foreach ($period as $dt) {
$myDates[] = $dt->format("Y-m-d H:i:s");
}
Now executing:
print_r($myDates);
gives you
Array (
[0] => 2020-02-17 00:00:00
[1] => 2020-02-17 02:00:00
[2] => 2020-02-17 04:00:00
[3] => 2020-02-17 06:00:00
[4] => 2020-02-17 08:00:00
)
You can use the date parser of PHP, its pretty intelligent.
$startDate = new DateTime('2020-02-17 00:00:00');
$endDate = new DateTime('2020-02-17 08:00:00');
$intervalInHrs = 2;
while ($startDate <= $endDate) {
$output[] = $startDate->format("Y-m-d H:i:s");
$startDate->modify("+$intervalInHrs Hours");
}
Output:
Array
(
[0] => 2020-02-17 00:00:00
[1] => 2020-02-17 02:00:00
[2] => 2020-02-17 04:00:00
[3] => 2020-02-17 06:00:00
[4] => 2020-02-17 08:00:00
)
$from_datetime = new DateTime('2020-02-17 00:00:00');
$to_datetime = new DateTime('2020-02-17 08:00:00');
$hours = 2;
$interval = new DateInterval('PT'.$hours.'H');
$period = new DatePeriod($from_datetime, $interval, $to_datetime);
$dateArray = [];
foreach ($period as $dt) {
$dateArray[] = $dt->format("Y-m-d H:i:s");
}
print_r($dateArray);exit;
Above code gave me the expected output as
Array
(
[0] => 2021-02-17 00:00:00
[1] => 2021-02-17 02:00:00
[2] => 2021-02-17 04:00:00
[3] => 2021-02-17 06:00:00
[4] => 2021-02-17 08:00:00
)
Am trying to get hours from midnight from the current time
that is suppose now it's 02:34 then I expect to get
02:34 - 02:00,
01:00 - 02:00,
00:00 - 01:00
as an array
so I have tried
function getFromMidnight(){
$durations = [];
$currentTime = strtotime("now");
$iStartOfHour = $currentTime - ($currentTime % 3600);
$midnight = strtotime('today midnight');
$hours = floor(($iStartOfHour - $midnight)/3600);
array_push($durations,["from"=>$currentTime, "to"=>$iStartOfHour]);
if(floor(($iStartOfHour - $midnight)/3600) > 0){
for ($val = 1;$val <= $hours;$val++){
$newval = $val +=1;
array_push($durations, ["from"=>strtotime('- '.$val.' hours',$iStartOfHour),"to"=>strtotime('- '.$newval.' hours',$iStartOfHour)]);
}
}
return $durations;
}
For the first array has the correct durations e.g. from the above example 02:34-02:00 but the next arrays are messed up giving me wrong values with constant timestamps eg: 01:00 - 01:00
I suspect its my for loop with an error, what could be wrong?
I would not use that code, instead of working things out just use DateInterval inverted and work backwards. Then sub() the hour in the loop to get the offset.
<?php
date_default_timezone_set('UTC');
$begin = new DateTime('today midnight');
$end = new DateTime();
$interval = new DateInterval('PT60M');
$interval->invert = 1;
$daterange = new DatePeriod($begin, $interval, $end);
$range = [];
foreach ($daterange as $date){
$range[] = [
'from' => $date->format("H:i"),
'to' => $date->sub($interval)->format("H:i")
];
}
print_r($range);
https://3v4l.org/BMSbI
Result:
Array
(
[0] => Array
(
[from] => 00:00
[to] => 01:00
)
[1] => Array
(
[from] => 01:00
[to] => 02:00
)
[2] => Array
(
[from] => 02:00
[to] => 03:00
)
[3] => Array
(
[from] => 03:00
[to] => 04:00
)
)
My understanding is that you cant access start and current date from date period object. My current php is 5.5, is there a workaround, since I cant upgrade to php 5.6 or php 7, and I need to get those dates.
DatePeriod Object
(
[start] => DateTime Object
(
[date] => 2016-04-03 00:00:00
[timezone_type] => 3
[timezone] => UTC
)
[current] => DateTime Object
(
[date] => 2016-04-10 00:00:00
[timezone_type] => 3
[timezone] => UTC
)
)
DatePeriod is a Traversable interface implementation. It supports only foreach loop.
You can obtain start and current elements only converting it to an array:
$start = new DateTime( '2016-03-01' );
$end = new DateTime( '2016-03-31' );
$interval = new DateInterval( 'P1D' );
$period = new DatePeriod( $start, $interval ,$end );
$arPeriod = iterator_to_array( $period );
$startDate = $arPeriod[0];
next( $arPeriod );
$currentDate = current( $arPeriod );
so my problem is rather simple but the solution keeps evading me. i am trying to get a list of future dates at a set interval that respects week nr in month and day nr in week. for example i need to make a list of dates of the 2nd mondays at 3 months apart.
i have a form where user specifies 2 dates and the interval.
so what i have is something like:
$start_date = "2015-01-07";
$end_date = "2016-01-07";
$period = "+1 month";
then, using this function from this link stackoverflow i get what weeknr my start_date is: (ie: "first monday")
function literalDate($timestamp) {
$timestamp = is_numeric($timestamp) ? $timestamp : strtotime($timestamp);
$weekday = date('l', $timestamp);
$month = date('M', $timestamp);
$ord = 1;
while(date('M', ($timestamp = strtotime('-1 week', $timestamp))) == $month) {
$ord++;
}
$lit = array(null, 'first', 'second', 'third', 'fourth', 'fifth');
return $lit[$ord].' '.$weekday;
}
$day_number = literalDate($start_date);
$list=array();
then. i'm trying to do this
while(strtotime($start_date) <= strtotime($end_date))
{
$list[]=$start_date;
$start_date=date('Y-m-d', strtotime("$start_date $period"));
$month = date('F', strtotime($start_date));
$start_date = date('Y-m-d', strtotime($day_number.' of '.$month)); //this always returns 1970-01-01
}
print_r($list);
as asked in comment my expected output is something like
array(
[0] => 2015-01-07
[1] => 2015-02-04
[2] => 2015-03-04
[3] => 2015-04-01
[4] => 2015-05-06
[5] => 2015-06-03
[6] => 2015-07-01
[7] => 2015-08-05
[8] => 2015-09-02
[9] => 2015-10-07
[10] => 2015-11-04
[11] => 2015-12-02
)
From what I understand, DateInterval should get you what you need:
$start = new DateTime('2015-01-07');
$start->modify('first day of this month');
$end = new DateTime('2016-01-07');
$end->modify('first day of this month');
$interval = DateInterval::createFromDateString('first wednesday');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
$d = $dt->format("d");
if($d <= 7){
echo $dt->format("Y-m-d") . "\n";
}
}
will display:
2015-01-07
2015-02-04
2015-03-04
2015-04-01
2015-05-06
2015-06-03
2015-07-01
2015-08-05
2015-09-02
2015-10-07
2015-11-04
2015-12-02
2016-01-06
strtotime() which works in reference of today.
strtotime("+x days");
strtotime
if you need something in relation to another date...
date("Y-m-d", strtotime($yourdate) + 86400 * $days);
$start_date = "2013-05-01";
$last_date = "2013-08-30";
How can I get dates of tuesdays and thursdays between these two dates?
<?php
$start = new DateTime('2013-05-01');
$end = new DateTime('2013-08-30');
$interval = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
if ($dt->format("N") == 2 || $dt->format("N") == 4) {
echo $dt->format("l Y-m-d") . "<br>\n";
}
}
See it in action
What this code does:
Creates a starting date object using DateTime.
Creates a starting date object using DateTime.
Creates a DateInterval object to represent our interval of time to iterate through. In this case 1 day.
Creates a DatePeriod object to manage these objects.
Using DatePeriod, it iterates through the date starting with the starting date and ending at the end date. We use DateTime::format() with the N parameter to get the day number of the week. If the day number of the week is 2 (Tuesday) or 4 (Thursday) echo out it's value.
Some PHP-Fu
$start_date = '2013-05-01';
$last_date = '2013-08-30';
$dates = range(strtotime($start_date), strtotime($last_date),86400);
$days = array('tuesday' => array(), 'thursday' => array());
array_map(function($v)use(&$days){
if(date('D', $v) == 'Tue'){
$days['tuesday'][] = date('Y-m-d', $v);
}elseif(date('D', $v) == 'Thu'){
$days['thursday'][] = date('Y-m-d', $v);
}
}, $dates); // Requires PHP 5.3+
print_r($days);
Output
Array
(
[tuesday] => Array
(
[0] => 2013-05-07
[1] => 2013-05-14
[2] => 2013-05-21
[3] => 2013-05-28
[4] => 2013-06-04
[5] => 2013-06-11
[6] => 2013-06-18
[7] => 2013-06-25
[8] => 2013-07-02
[9] => 2013-07-09
[10] => 2013-07-16
[11] => 2013-07-23
[12] => 2013-07-30
[13] => 2013-08-06
[14] => 2013-08-13
[15] => 2013-08-20
[16] => 2013-08-27
)
[thursday] => Array
(
[0] => 2013-05-02
[1] => 2013-05-09
[2] => 2013-05-16
[3] => 2013-05-23
[4] => 2013-05-30
[5] => 2013-06-06
[6] => 2013-06-13
[7] => 2013-06-20
[8] => 2013-06-27
[9] => 2013-07-04
[10] => 2013-07-11
[11] => 2013-07-18
[12] => 2013-07-25
[13] => 2013-08-01
[14] => 2013-08-08
[15] => 2013-08-15
[16] => 2013-08-22
[17] => 2013-08-29
)
)
Online demo
$start_date = strtotime("2013-05-01");
$last_date = strtotime("2013-08-30");
while ($start_date <= $last_date) {
$start_date = strtotime('+1 day', $start_date);
if (date('N',$start_date) == 2 || date('N',$start_date) == 4){
echo date('Y-m-d', $start_date).PHP_EOL;
}
}
<?php echo date('Y-m-d', strtotime('next thursday', strtotime($start_date)));
Also for tuesday ofcourse
Please use the following function for your solution,
function daycount($day, $startdate, $lastdate, $counter=0)
{
if($startdate >= $lastdate)
{
return $counter;
}
else
{
return daycount($day, strtotime("next ".$day, $startdate), ++$counter);
}
}
$start_date = "2013-05-01";
$last_date = "2013-08-30";
echo "Tuesday Count - ".daycount("tuesday", strtotime($start_date), strtotime($last_date));
echo "<br/>";
echo "Thursday Count - ".daycount("thursday", strtotime($start_date), strtotime($last_date));
Try with this
$startDate = strtotime($start_date);
$endDate = strtotime($last_date);
while ($startDate < $endDate) {
echo date('Y-m-d', $startDate ). "\n";
// Give the condition to find last Tuesday
$startDate = strtotime( 'next Tuesday', $startDate );
}
With DateTime:
$start_date = "2013-05-01";
$last_date = "2013-08-30";
$start = new DateTime($start_date);
$clone = clone $start;
$start->modify('next thursday');
$thursday=$start->format('Y-m-d');
$clone->modify('next tuesday');
$tuesday=$clone->format('Y-m-d');
echo $thursday; //2013-05-02
echo $tuesday; //2013-05-07
We need to objects because if in interval tuesday is before thursday we will have next tuesday. But you can modify little code to use one object.
With the help of few php date functions this can be solved easily..
<?php
// Create the from and to date
$start_date = strtotime("2013-05-01");
$last_date = strtotime("2013-08-30");
// Get the time interval to get the tue and Thurs days
$no_of_days = ($last_date - $start_date) / 86400; //the diff will be in timestamp hence dividing by timestamp for one day = 86400
$get_tue_thu_days = array();
// Loop upto the $no_of_days
for($i = 0; $i < $no_of_days; $i++) {
$temp = date("D", $start_date);
if($temp == "Tue" || $temp == "Thu") {
$get_tue_thu_days[] = date("D/M/Y", $start_date); //formating date in Thu/May/2013 formate.
}
$start_date += 86400;
}
print_r($get_tue_thu_days);
if you have a reference date which you know is a tuesday/thursday you can find days which are a multiple of 7 days from your reference date, these days will always be the same day of the week.