Limit form entries on a per hour basis? - php

I'm currently using the Gravity Forms plugin and it's set up to limit form entries per day, week, month and year; unfortunately, I need it by hour. Here is the original code that I'm editing:
private static function get_limit_period_dates($period){
if(empty($period))
return array("start_date" => null, "end_date" => null);
switch($period){
case "day" :
return array(
"start_date" => gmdate("Y-m-d"),
"end_date" => gmdate("Y-m-d 23:59:59"));
break;
case "week" :
return array(
"start_date" => gmdate("Y-m-d", strtotime("Monday this week")),
"end_date" => gmdate("Y-m-d 23:59:59", strtotime("next Sunday")));
break;
case "month" :
$month_start = gmdate("Y-m-1");
return array(
"start_date" => $month_start,
"end_date" => gmdate("Y-m-d H:i:s", strtotime("{$month_start} +1 month -1 second")));
break;
case "year" :
return array(
"start_date" => gmdate("Y-1-1"),
"end_date" => gmdate("Y-12-31 23:59:59"));
break;
}
}
I've attempted the following code, I figured starting at 0 minutes and 0 seconds, then adding an hour would do the trick, but it isn't working:
case "hour" :
return array(
"start_date" => gmdate("H:00:00"),
"end_date" => gmdate("H:i:s", strtotime("+1 hour")));
break;
I've never used the gmdate function, so I'm eager to get a grasp on this if someone's willing to briefly explain what I'm missing. Thanks!

I think this might be what you want:
case "hour" :
$hour_start = gmdate("Y-m-d H:00:00");
return array(
"start_date" => $hour_start,
"end_date" => gmdate("Y-m-d H:i:s", strtotime("{$hour_start} +1 hour")));
break;
You have to do 1 hour after the start hour. Otherwise it takes it as 1 hour from now.

Related

How to get time slots for a specific date

Hope all are doing well. I need to print an array as time slots.
Assume that there are 2 orders for 2021.11.15 on 11:30am to 12:00pm and 2:00pm to 4:15pm.
My order needs 1h 30m to complete. Therefore time slots should be in between 8:00am and 6:00pm skipping those times for already exist orders.
My expected results should be:
array:2 [
0 => array:2 [
"start" => "08:00:00"
"end" => "9:30:00"
]
1 => array:2 [
"start" => "09:30:00"
"end" => "11:00:00"
]
2 => array:2 [
"start" => "12:00:00"
"end" => "13:30:00"
]
3 => array:2 [
"start" => "16:15:00"
"end" => "17:45:00"
]
]
Following line is used to get exist orders object with their start and end times.
$existOrders = $this->orderHasPropartnerService->getOrderExistForDateProPartner($proPartnerDefaultLocation->id, $selectedDateRecord->date);
Then I just looped it.
if ($existOrders->count() > 0) {
$dateStartTime = $selectedDateRecord->time_from;
$x = 0;
$firstEndingTime = Carbon::parse($dateStartTime)->addMinutes($totalTimeToOrder)->format('H:i:s');
foreach ($existOrders as $key1 => $existOrder1) {
if ($existOrder1->order->time_slot_from < $firstEndingTime && $existOrder1->order->time_slot_to >= $firstEndingTime) {
$timeCheckArray[$x]['start'] = $existOrder1->order->time_slot_to;
$timeCheckArray[$x]['end'] = Carbon::parse($existOrder1->order->time_slot_to)->addMinutes($totalTimeToOrder)->format('H:i:s');
} else {
$timeSlotArray[$x]['start'] = $dateStartTime;
$timeSlotArray[$x]['end'] = $firstEndingTime;
$timeCheckArray[$x]['start'] = $firstEndingTime;
$timeCheckArray[$x]['end'] = Carbon::parse($firstEndingTime)->addMinutes($totalTimeToOrder)->format('H:i:s');
}
if (isset($existOrders[$key1+1])) {
if ($existOrders[$key1+1]->order->time_slot_from < $timeCheckArray[$x]['end'] && $existOrders[$key1+1]->order->time_slot_to >= $timeCheckArray[$x]['end']) {
} else {
$timeSlotArray[$x+1]['start'] = $timeCheckArray[$x]['start'];
$timeSlotArray[$x+1]['end'] = $timeCheckArray[$x]['end'];
}
}
}
}
As for the above example $dateStartTime will be 8:00am. Value of $totalTimeToOrder will be 1h 30m.
When I try to print $timeSlotArray it'll result as follows:
array:2 [
0 => array:2 [
"start" => "08:00:00"
"end" => "09:30:00"
]
1 => array:2 [
"start" => "08:00:00"
"end" => "09:30:00"
]
]
It is really appreciated if someone point me out where I did mistakes in this logic. Thank you so much guys for your valuable time for a problem of mine.
The best approach would be to run a for loop to check that the New order does not fall between the booked times .
Try something similar to this by converting it to a PHP Date object
$NewOrder= "4:59 pm";
$start= "5:42 am";
$end= "6:26 pm";
$date1 = DateTime::createFromFormat('h:i a', $NewOrder);
$date2 = DateTime::createFromFormat('h:i a', $start);
$date3 = DateTime::createFromFormat('h:i a', $end);
if ($date1 > $date2 && $date1 < $date3)
{
echo 'Not safe to add it ';
}

How to +1 day from retrive endDate data in laravel controller?

I want to get enddate by + 1 day
$data=[
"title" =>$event->event_name,
"start" =>$event->start_date,
"end" =>new \DateTime($event->end_date.'1 day'),
"textColor" =>"white",
"backgroundColor" =>"black",
];
but the code make the fullcalendar not show any data in the view
how to make it works + 1 day?
thanks before
Try this code it's work.
<?php
$data=[
"title" => $event->event_name,
"start" => $event->start_date,
"end" => date('Y-m-d H:i:s', strtotime($event->end_date . ' +1 day')),
"textColor" => "white",
"backgroundColor" => "black",
];
?>

Failed asserting two arrays are equal but shows that the arrays are the same with no difference?

I'm trying to pass a test that involves running a query that returns a series of logins to test whether two arrays are equal in the test.
In the past I have tried changing the format of the query to make the test pass as well as editing the arrays and eventually it equalled the two arrays. Unfortunately the test still doesn't pass.
The function that performs the query to get a series of dates of logins:
public function getLogins(): array
{
return $this->createQuery()
->select('date AS datetime, COUNT(id) as total')
->orderBy('datetime', 'DESC')->groupBy('datetime')
->where('date >= -24 hours')
->getQuery()
->getResult();
}
This is the method in the test class:
public function testGetLogins()
{
$dateLogins = $this->repository->getLogins();
$this->assertCount(4, $dateLogins, "Four instances");
$this->assertEquals([
["datetime" => new \DateTime("now -3 minutes"), "total" => "1"],
["datetime" => new \DateTime("now -7 days"), "total" => "1"],
["datetime" => new \DateTime("now -1 year"), "total" => "1"],
["datetime" => new \DateTime("now -600 days"), "total" => "1"]
], $logins, "The login instances returned match the expected times");
}
I'm expecting the test to pass but instead it is displaying this:
Test Output
The expected and actual arrays are both equal so I'm unsure as to what is causing the test to fail.
\DateTime format contains information about seconds as well. new \DateTime("now -3 minutes") will return now minus 3 minutes but exact amount of seconds, which will be always different, depending on the time when you did launch the test. Apparently you want to compare dates till minutes, so you have to format your dates before comparsion, therefore you have to compare each set separately:
$expectedValues = [
["datetime" => new \DateTime("now -3 minutes"), "total" => "1"],
["datetime" => new \DateTime("now -7 days"), "total" => "1"],
["datetime" => new \DateTime("now -1 year"), "total" => "1"],
["datetime" => new \DateTime("now -600 days"), "total" => "1"]
];
for ($i = 0; $i < count($expectedValues); ++$i) {
$actualDate = (new \DateTime($logins[$i]['datetime']))->format('Y-m-d H:i');
$expectedDate = ($expectedValues[$i]['datetime'])->format('Y-m-d H:i');
$this->assertEquals($expectedDate, $actualDate);
$this->assertEquals($expectedValues[$i]['total'], $logins[$i]['total']);
}

How to override an array of overlaping timeslots

So I need to create a sort of day-per-day calendar with available times, in order for a user to be able to book a meeting with one doctor from a cabinet of multiple doctors.
I hope that this explanation is not too weird already..
Btw I use Laravel 5.5
Here's an example:
Default Schedule of the cabinet : 9:00 to 19:00
Doctor 1 says that on monday, he'll be only available from 13:00 to 15:00
Doctor 2 says that on monday, he'll be only available from 10:00 to 14:00
When I query the available timeslots :
$ids = Doctor::all()->pluck('id');
$workingSchedules = WorkingSchedule::whereIn('user_id', $ids)
->orderBy('start_date')
->whereDate('start_date', '=', $this->datetime->format('Y-m-d'))
->get();
I get:
0 => [
"start_date" => "2017-09-18 10:00:00"
"end_date" => "2017-09-18 14:00:00"
]
1 => [
"start_date" => "2017-09-18 13:00:00"
"end_date" => "2017-09-18 15:00:00"
]
And if nothing shows up from the Database then I use the default cabinet hours.
Then I use Carbon diffInMinutes() method to construct an array of 30 minutes timeslots between those date range (that the user can select).
Anyway, for my script to work correcty I need to transform the result I showed you into this:
0 => [
"start_date" => "2017-09-18 10:00:00"
"end_date" => "2017-09-18 15:00:00"
]
As I only have two timeslots in this example it might be simple a solution, but I might also get an array of 10 timeslots that overlapse one another..
Can somebody help me find a elegant solution that will cover all possible case ?
Thanks a lot in advance.
To be easier, I will suppose $workingSchedules is an array of numbers, then we can easily compare elements
$workingSchedules = [
[
'start_date' => 1,
'end_date' => 5,
],
[
'start_date' => 13,
'end_date' => 16,
],
[
'start_date' => 16,
'end_date' => 17,
],
];
$result = [$workingSchedules[0]];
$index = 0;
foreach ($workingSchedules as $row) {
if ($result[$index]['end_date'] >= $row['start_date']) {
$result[$index]['end_date'] = max($result[$index]['end_date'], $row['end_date']);
} else {
$index++;
$result[] = $row;
}
}
var_dump($result);
Above code will print:
[
[
'start_date' => 1,
'end_date' => 5,
],
[
'start_date' => 13,
'end_date' => 17,
],
]
You can custom the code to compare 2 dates instead numbers
If $workingSchedules is empty, we can simply return default schedule
To merge overlapping time-periods, you could use this code:
$result = [];
$i = -1;
foreach ($workingSchedules as $row) {
if ($i < 0 || $row["end_date"] > $result[$i]["end_date"]) {
if ($i >= 0 && $row["start_date"] <= $result[$i]["end_date"]) {
$result[$i]["end_date"] = $row["end_date"];
} else {
$result[++$i] = $row;
}
}
}
$result will then have non-overlapping periods only.
I hope this will help.
$workingSchedules=array(
0=>array(
"start_date" => "2017-09-18 10:00:00",
"end_date" => "2017-09-18 14:00:00"),
1=>array(
"start_date" => "2017-09-18 13:00:00",
"end_date" => "2017-09-18 15:00:00"
)
);
foreach ($workingSchedules as $schedule){
$start=new DateTime($schedule['start_date']);
$end=new DateTime($schedule['end_date']);
while ($start<=$end){
echo $start->format('Y-m-d H:i')."<br/>";
$start=$start->add(new DateInterval('PT'.'30'.'M'));
}
}

Finding midnight of a timezone given offset in minutes [PHP]

I have an offset from UTC stored in minutes: e.g -240
I'm trying to find the corresponding UNIX timestamp of midnight of the current day for this particular offset.
I found similar information in questions like this one: How do I get the UTC time of "midnight" for a given timezone?
However, I don't have the city name/timezone jurisdiction, just a minute offset. I think this should be fine since for my purposes I don't need to account for daylight savings, it can be off by an hour and still be fine.
Examples
Offset: -420
Midnight on 7/12/2014: 1405148400 (unix TS)
With UTC, I would have to first tell if it's the next day or same day as the TZ because it may have a different "last midnight".
While this solution looks a little ugly it does do what I think you're asking for! This example uses -180 minutes as the offset.
date_default_timezone_set('UTC');
// Work out which day the time zone is in
$day = strtotime('-180 minutes');
// Strip of the time part of the day, to give UTC midnight on the correct day
$utcMidnight = strtotime('midnight', $day);
// Now apply the offset in reverse to give the zone's midnight
$zoneMidnight = strtotime('+180 minutes', $utcMidnight);
You could use date_default_timezone_set to make all time-related functions acknowledge the shift. First thing to do is to convert those minutes into hours, since the UTC gap is 1 hour between n and n+1.
$hours = $minutes / 60;
I would also recommend that you check the minutes values first :
if($minutes % 60 == 0) // We're good.
Now, if you want to convert the UTC offset to a timezone, you can create your function :
<?php
function offsetToTimezone($offset){
$timezones = array(
"-12" => "Pacific/Kwajalein",
"-11" => "Pacific/Samoa",
"-10" => "Pacific/Honolulu",
"-9" => "America/Juneau",
"-8" => "America/Los_Angeles",
"-7" => "America/Denver",
"-6" => "America/Mexico_City",
"-5" => "America/New_York",
"-4" => "America/Caracas",
"-3.5" => "America/St_Johns",
"-3" => "America/Argentina/Buenos_Aires",
"-2" => "Atlantic/Azores",
"-1" => "Atlantic/Azores",
"0" => "Europe/London",
"1" => "Europe/Paris",
"2" => "Europe/Helsinki",
"3" => "Europe/Moscow",
"3.5" => "Asia/Tehran",
"4" => "Asia/Baku",
"4.5" => "Asia/Kabul",
"5" => "Asia/Karachi",
"5.5" => "Asia/Calcutta",
"6" => "Asia/Colombo",
"7" => "Asia/Bangkok",
"8" => "Asia/Singapore",
"9" => "Asia/Tokyo",
"9.5" => "Australia/Darwin",
"10" => "Pacific/Guam",
"11" => "Asia/Magadan",
"12" => "Asia/Kamchatka"
);
return $timezones[$offset];
}
?>
... and use if for conversion :
date_default_timezone_set(offsetToTimezone($hours));
By the way, I suggest you have a look at this answer, which provides you with a more elegant way to achieve the work of offsetToTimezone.
Now that your script if configured on the correct timezone, just ask for a timestamp :
$timestamp = mktime(0, 0, 0);
If at some time, you need to reset to timezone to default, you might need date_default_timezone_get to save it :
$timezone = date_default_timezone_get();
// Change to another timezone based on your offset.
// Get your timestamp.
date_default_timezone_set($timezone);
I had to think through it quite a bit, but I think this was the solution I was looking for. Let me know if you think this algorithm is incorrect.
function getLastMidnightForOffset( $minuteOffset ) {
$today = mktime( 0, 0, 0 );
$tomorrow = $today + 86400;
$yesterday = $today - 86400;
$offset = $minuteOffset * 60;
if ( time() + $offset >= $tomorrow ) {
$localMidnight = $tomorrow - $offset;
} elseif ( time() + $offset >= $today ) {
$localMidnight = $today - $offset;
} else {
$localMidnight = $yesterday - $offset;
}
return $localMidnight;
}

Categories