Compare and find the closest datetime to given ending datetime - php

I have a list of data that I've retrieved and is ordered from previous to more recent datetime. I'm trying to loop backwards in this list based on a time and date I specify, however the date and time in the list won't necessarily be equal to the datetime I specify so I want it to find the closest datetime in the list then iterate backwards. Here's an example:
I want 2016-08-27 23:30:00 PM.
List:
2016-08-27 22:30:00 PM
2016-08-27 22:30:20 PM
2016-08-27 23:29:40 PM
2016-08-27 23:29:59 PM
2016-08-27 23:29:58 PM
How can I do this with PHP?

Push dates into array and sort it.
$array = ['2016-08-27 23:29:58 PM', '2016-08-27 23:29:59 PM'];
function sortbydate( $a, $b ) {
return strtotime($a) - strtotime($b);
}
usort($array, "sortbydate");
var_dump($data);
If you want remove newer dates
function new($var)
{
return strtotime($a) < strtotime('2016-08-27 23:29:59');
}
array_filter($data, "new");

Related

How to apply date filters in reports php

How to apply date range filters to get rows of exact date
Below is my sql table
id name created
1 abc 2018-07-06 10:30:45
2 test 2018-07-01 10:30:45
3 raj 2018-07-05 10:30:45
4 zyz 2018-07-08 10:30:45
But when i select date 2018/07/01 - 2018/07/01 it returns empty rows,
and when i select date 2018/07/01 - 2018/07/02 then it will shows below single row
2 test 2018-07-01 10:30:45
My query is, how to apply date filter if i need record of selected date in from and to date range filter
Below is my php code
public function clientReport(){
if ($this->request->is('post')) {
$daterng = $this->request->data['daterange'];
if(!empty($daterng)){
$dates = explode("-", $daterng);
$frmDate = date("Y-m-d", strtotime($dates[0]));
$toDate = date("Y-m-d", strtotime($dates[1]));
}
$conditions = [];
if(!empty($frmDate)){
$conditions['Orders.created >='] = $frmDate;
}
if(!empty($toDate)){
$conditions['Orders.created <='] = $toDate;
}
$orders = $order
->find()
->where($conditions);
$orders->enableHydration(false); // You can retrieve basic arrays by disabling hydration
if(!empty($orders)){
$this->set('clientlist', $orders);
}
}
}
You have to add time also in query
if(!empty($frmDate)){
$conditions['Orders.created >='] = $frmDate.' 00:00:00';
}
if(!empty($toDate)){
$conditions['Orders.created <='] = $toDate.' 23:59:59';
}
You need to "round up" the end date to 23:59:59 hours. You're actually working with timestamps, so a date will be converted to a date/time. 2018/07/01 probably becomes midnight 00:00:00 on that day. When searching from 2018/07/01 to 2018/07/01, what you actually want is to search from 2018/07/01 00:00:00 to 2018/07/01 23:59:59.
To filter your data base on a date range you can use this
SELECT * FROM your_table WHERE DATE(created) BETWEEN '2018-07-01' AND '2018-07-01'

how to find the next closest date (month/day/time) without specifying year

I have a script that a user can setup a frequency as to when they want it to run.
They specify
The month they want it to run
The day of the month
The time (24 hour format)
They do not specify the year, the script needs to find the next closest date that matches.
PHP
The way I propigate the dates is through an array of months the user chooses and I can output all the dates into a nice array
$scheduler_months = unserialize($row['scheduler_months']);
foreach ($scheduler_months as $scheduler_month) {
$next_date[] = $scheduler_month."/".$row['scheduler_date']." ".$row['scheduler_time'];
}
which will out put
Array ( [0] => 2/28 12:00 [1] => 4/28 12:00 [2] => 12/28 12:00 )
So now at this point I need to figure out what the next closest date based on today as the starting point will be, obviously if the next closest date is in the next year it needs to be smart enough to figure that out. I just have no idea how to find the next closest date based on the dates in the array.
It's quite easy to figure out the year of the dates - if you were to convert them to unix time using strtotime you can determine if this year's date was in the past or not and if it were, you can assign that date next year.
$scheduler_months = unserialize($row['scheduler_months']);
$now = strtotime("now"); # get the unix time in seconds 'now'
foreach ($scheduler_months as $scheduler_month) {
# $tmp will be holding the date in the form of YYYY-MM-DD HH:MM
$tmp = date("Y")."-".$scheduler_month."-".$row['scheduler_date']." ".$row['scheduler_time'];
if(strtotime($tmp) - $now < 0) # if date is in the past, assign it to the next year
$tmp = (date("Y")+1)."-".$scheduler_month."-".$row['scheduler_date']." ".$row['scheduler_time'];
$next_date[] = $tmp;
}
# Initialize $smallest and $smallest_key
$smallest = strtotime($next_date[0])-$now;
$smallest_key = 0;
foreach($next_date as $key => $val) {
$time_diff = strtotime($val) - $now;
if($time_diff < $smallest) {
$smallest_key = $key;
$smallest = $time_diff;
}
}
In the first part, I've modified your foreach loop to determine the correct year based on unix time. I've changed the date format to YYYY-MM-DD HH:MM. If the date's unixtime is less than the current unix time, then the next closest date is next year.
In the second part I initilize two variables - $smallest, which holds the smallest time in seconds relative to now and $smallest_key, which holds the array key for the smallest time.
Then I loop over $next_date and I look for the smallest time in seconds from now to either of the dates.

I want to remove one date between three dates by function

function get_date_diff1($from,$to,$remove_dates,$check=0){
$cDays = dateDiff($from,$to);
$tmp=$from;
$i=0;$o=0;$p=0;
while($i<$cDays){
if(in_array($tmp,$remove_dates)){
$p=$p+1;
}
$tmp=strtotime($tmp)+(($i>0)?86400:0);
$twd = strtolower(date("l",$tmp));
if($twd=='sunday' || $twd=='saturday') $o=$o+1;
$tmp = date("Y-m-d",$tmp);
$i=$i+1;
}
if($check==0){
return abs($cDays-$o-$p);
}else{
return abs($cDays-$p);
}
}
echo get_date_diff1("14 April, 2014","16 April, 2014",array('14 April, 2014'));
I'm sorry for my grammar mistakes. I want to make a function which is remove the FROM or TO date between three dates and give the result of due dates. In this function when I removing the 14 April, 2014 then function work good and give the due dates (result = 2 (which I want)) but when I removing the 15 April, 2014 then function give the three due dates (result = 3) while function should be return two dates (result = 2) can someone help me where I am wrong? Thanks in Advance
You're passing in dates in 14 April, 2014 format, which corresponds to the PHP date() format code of d F, Y. You then build dates internally in your code in Y-m-d format. That means your in_array() call is literally trying to do
if ('14 April, 2014' == '2014-04-14`) { ... }
which will NEVER be true. You and I know they're the same dates. PHP has NO idea they're dates. They're just strings, and as strings they're NOT equal.

Check for consecutive dates within a set and return as range

I have arrays of dates Y-m-d format that may be any combination of ten set dates that are one day apart.
e.g. Here is the full set:
2011-01-01, 2011-01-02, 2011-01-03, 2011-01-04, 2011-01-05, 2011-01-06, 2011-01-07, 2011-01-08, 2011-01-09, 2011-01-10
The arrays that are created from that set can be any combination of dates— all of them, one of them, some consecutive, all consecutive, etc.
I currently have them printing pretty much as they're returned. e.g. here's a possible result:
2011-01-02
2011-01-03
2011-01-04
2011-01-08
(what's actually printed is more like "Friday, Jan. 2…", but we'll stick with the simple date string)
I'd like to condense it so that if there are three or more consecutive days, those become a range, e.g the above example would become:
2011-01-02 to 2011-01-04
2011-01-08
which would eventually become:
Sunday, Jan. 2 - Tuesday, Jan. 4
Saturday Jan. 8
Is there a way to loop through and check the time difference, create a start time and end time for the range(s), and then gather up the stragglers?
Bit of a quick answer so sorry about the lack of implementation but assuming you are using 5.3 and the dates are ordered chronologically, you could convert each date to a DateTime object (if they aren't already) and then iterate over the array using DateTime::diff() to generate a DateInterval object which you could use to compare the current date in the iteration with the last. You could group your consecutive dates into sub arrays and use shift() and pop() to get the first and last days in that sub array.
EDIT
I had a think about this. Pretty rough and ready implementation follows, but it should work:
// assuming a chronologically
// ordered array of DateTime objects
$dates = array(
new DateTime('2010-12-30'),
new DateTime('2011-01-01'),
new DateTime('2011-01-02'),
new DateTime('2011-01-03'),
new DateTime('2011-01-06'),
new DateTime('2011-01-07'),
new DateTime('2011-01-10'),
);
// process the array
$lastDate = null;
$ranges = array();
$currentRange = array();
foreach ($dates as $date) {
if (null === $lastDate) {
$currentRange[] = $date;
} else {
// get the DateInterval object
$interval = $date->diff($lastDate);
// DateInterval has properties for
// days, weeks. months etc. You should
// implement some more robust conditions here to
// make sure all you're not getting false matches
// for diffs like a month and a day, a year and
// a day and so on...
if ($interval->days === 1) {
// add this date to the current range
$currentRange[] = $date;
} else {
// store the old range and start anew
$ranges[] = $currentRange;
$currentRange = array($date);
}
}
// end of iteration...
// this date is now the last date
$lastDate = $date;
}
// messy...
$ranges[] = $currentRange;
// print dates
foreach ($ranges as $range) {
// there'll always be one array element, so
// shift that off and create a string from the date object
$startDate = array_shift($range);
$str = sprintf('%s', $startDate->format('D j M'));
// if there are still elements in $range
// then this is a range. pop off the last
// element, do the same as above and concatenate
if (count($range)) {
$endDate = array_pop($range);
$str .= sprintf(' to %s', $endDate->format('D j M'));
}
echo "<p>$str</p>";
}
Outputs:
Thu 30 Dec
Sat 1 Jan to Mon 3 Jan
Thu 6 Jan to Fri 7 Jan
Mon 10 Jan

Need help sorting multi array

I see a lot of examples here, but it's not working for me.
I have a list of sorted events retrieved from my DB:
16.08.2010 12:00:00 - 21.08.2010 20:00:00
16.08.2010 20:00:00 - 21.08.2010 23:00:00
18.08.2010 17:00:00 - 18.08.2010 19:00:00
As you can see, the first event is from 16.08 to 21.08.
I need to "chop this up" so that I get one entry foreach day.
This is my function:
function fullList( $data ) {
$ev = $data['events'];
$events = array();
// Loop through each event. If event spans over several days, add each day in to new event list
foreach($ev as $e) :
$endDate = strtotime(date('Y-m-d 23:59:59', strtotime($e->endTime)));
$current = strtotime($e->startTime);
// Copy event so data is not overwritten
$newEv = $e;
while ($current <= $endDate) {
//Set start date of event to new date
$newEv->startTime = date('d.m.Y H:i:s', $current);
// Add events to new event list
array_push($events,$newEv);
//Go to next date
$current = strtotime('+1 day', $current);
}
endforeach;
// Need to sort $events here
}
Now $events contains all events, but it's not sorted by date. I've tried uasort, but I can't use uasort($array, 'cmp');.
How can I go about sorting this array by date?
Have you tried natural sorting algorithm?
As Nazariy mentioned, you would be better off pre-sorting the events at the source (assuming they come from a DB).
If you must sort the array in code, you should be able to use usort. I'm assuming you want to sort by startTime
usort($events, function($a, $b) {
return strtotime($a->startTime) - strtotime($b->startTime);
});

Categories