I'm having an issue with some code that someone else has previously worked on.
The goal is to iterate through a directory and push any files that are within a certain date range to an array (files are in mmddyyy.txt format).
The (terribly named, not by my own doing) variables in the code represent the following:
$aYear - A given year, read in from a text file. This variable changes during every iteration of the loop. The same goes for $aMonth and $aDay.
$sYear1 - Start year. $sMonth1 and $sDay1 are used in respect to $sYear1.
$sYear2 - End year. $sMonth2 and $sDay2 are used in respect to $sYear2.
$isGood - File will be added to the array.
$isGood = false;
if($aYear >= $sYear1 && $aYear <= $sYear2)
{
if($aYear == $sYear1)
{
if($aMonth == $sMonth1)
{
if($aDay >= $sDay1 && $aDay <= $sDay2)
{
$isGood = true;
}
}
else
{
if($aMonth >= $sMonth1 && $aMonth <= $sMonth2)
{
$isGood = true;
}
}
}
else if($aYear == $sYear2)
{
if($aMonth == $sMonth2)
{
if($aDay <= $sDay2)
{
$isGood = true;
}
}
else
{
if($aMonth <= $sMonth2)
{
$isGood = true;
}
}
}
else
{
$isGood = true;
}
}
if($isGood)
{
//echo "Found good article";
$a = $a . "===" . $file;
array_push($result, $a);
}
I'm not getting the results that I expected. I'm looking for some help as to how I can simplify this code and get it working properly. I do need to keep this solution in PHP.
Thank you in advance.
It seems to me Month statement if($aMonth >= $sMonth1 && $aMonth <= $sMonth2) needs work
eg start date- 03 Aug 2013 end date- 04 Sep 2016 and check date say 08 Nov 2013
would make isGood=false whereas it should be true.
Removing && $aDay <= $sDay2 and && $aMonth <= $sMonth2 should work.
As #Sandeep pointed out you're issues are with:
if ($aMonth >= $sMonth1 && $aMonth <= $sMonth2)
and
if ($aDay >= $sDay1 && $aDay <= $sDay2)
as you don't need to be comparing the date with end dates as well.
That being said you can clear up your code completely by doing something like:
$date = (new DateTime)->setDate($aYear, $aMonth, $aDay);
$start = (new DateTime)->setDate($sYear1, $sMonth1, $sDay1);
$end = (new DateTime)->setDate($sYear2, $sMonth2, $sDay2);
if ($start <= $date && $date <= $end) {
//echo "Found good article";
$a = $a . "===" . $file;
array_push($result, $a);
}
Hope this helps!
Related
I am setting some vars from GET
$start = $_GET['start'];
$end = $_GET['end'];
From which I get:
start=1-11-2018&end=30-11-2018
And then I am doing:
if((!$start) && (!$end)) {
if (($dateFormat >= $start) && ($dateFormat <= $end)) {
} else {
echo "no dates";
}
And to close it
if((!$start) && (!$end)) {
}
}
But this isn't happening
if((!$start) && (!$end)) {
UPDATE
Now this is working but it doesn't go in else if no GET
if((!empty($_GET['start'])) && (!empty($_GET['end']))) {
if (($dateFormat >= $start) && ($dateFormat <= $end)) {
} else {
echo "No dates";
}
Check via isset()
if you are calling : http://example.com?start=1-11-2018&end=30-11-2018
1. The isset() is checking query string "start"/"end" is having or not.
2. The empty() is checking query string "start"/"end" is empty/blank or not
if( isset($_GET['start']) && isset($_GET['end']) ){ // check the GET method is set or not
if((!empty($_GET['start'])) && (!empty($_GET['end']))) {
if (($dateFormat >= $start) && ($dateFormat <= $end)) {
}
else {
echo "Empty dates";
}
}
else{
echo "Start / End date query string is missing...";
}
This is how I resolved it:
if((!empty($start)) && (!empty($end))) {
if (($dateFormat >= $start) && ($dateFormat <= $end)) {
}
// here the content which
// in case those vars are not empty,
// would get filtered by that logic.
if((empty($start)) && (empty($end))) {
// Close the condition for second if when not empty
} else {
echo "No dates";
}
I have the following if statement:
$current=date('d/m/Y');
$next_year=date('y')+1;
$q1a='01/04/'.date('Y');
$q1b='30/06/'.date('Y');
$q2a='01/07/'.date('Y');
$q2b='30/09/'.date('Y');
$q3a='01/09/'.date('Y');
$q3b='31/12/'.date('Y');
$q4a='01/01/20'.$next_year;
$q4b='31/03/20'.$next_year;
if (($current > $q1a) && ($current < $q1b))
{
$currentquarter='Q1';
}
elseif (($current > $q2a) && ($current < $q2b))
{
$currentquarter='Q2';
}
elseif (($current > $q3a) && ($current < $q3b))
{
$currentquarter='Q3';
}
elseif (($current > $q4a) && ($current < $q4b))
{
$currentquarter='Q4';
}
echo $currentquarter;
BUT its returning Q1 even though it should be Q3 as todays date falls between 01/09/2017 and 31/12/2017
You're not comparing dates, you're lexically comparing strings. E.g.:
'21/03/2017' > '01/04/2017'
2 is larger than 0, so this will be true. Character by character the first string sorts "larger than" the second. Again, it's a lexical comparison, not a numeric comparison.
At the very least you need to reverse the endianness to Y/m/d to get the correct result; but you should really construct DateTime objects or UNIX timestamps to do actual date/numeric comparisons properly.
For date comparison in PHP you can use strtotime() function
$date1 = '07/28/2018';
$date2 = '07/28/2017';
if(strtotime($date1) < strtotime($date2))
{
echo 'Date2 is greater then date1';
}
else
{
echo 'Date1 is greater then date2';
}
This would help you simplify the comparison to retrieve the current quarter.
function CurrentQuarter(){
$n = date('n');
if($n < 4){
return "1";
} elseif($n > 3 && $n <7){
return "2";
} elseif($n >6 && $n < 10){
return "3";
} elseif($n >9){
return "4";
}
}
Code Source
I'm using Laravel 5.2 for a project I'm working on. Does anyone have any tips regarding how I can leverage Laravel to make this loop run more quickly?
foreach ($purchaseYears as $purchaseYear){
$totalInventory = \App\Inventory::where('purchase_year', $purchaseYear)->count();
if ($purchaseYear < 1960) { $purchaseYear = 'Pre 1960'; }
else if ($purchaseYear >= 1960 && $purchaseYear < 1965) { $purchaseYear = '1960-64'; }
else if ($purchaseYear >= 1965 && $purchaseYear < 1970) { $purchaseYear = '1965-69'; }
else if ($purchaseYear >= 1970 && $purchaseYear < 1975) { $purchaseYear = '1970-74'; }
else if ($purchaseYear >= 1975 && $purchaseYear < 1980) { $purchaseYear = '1975-79'; }
else if ($purchaseYear >= 1980 && $purchaseYear < 1985) { $purchaseYear = '1980-84'; }
else if ($purchaseYear >= 1985 && $purchaseYear < 1990) { $purchaseYear = '1985-89'; }
else if ($purchaseYear >= 1990 && $purchaseYear < 1995) { $purchaseYear = '1990-94'; }
else if ($purchaseYear >= 1995 && $purchaseYear < 2000) { $purchaseYear = '1995-99'; }
else if ($purchaseYear >= 2000 && $purchaseYear < 2005) { $purchaseYear = '2000-04'; }
else if ($purchaseYear >= 2005 && $purchaseYear < 2010) { $purchaseYear = '2005-09'; }
else if ($purchaseYear >= 2010 && $purchaseYear < 2015) { $purchaseYear = '2010-14'; }
else if ($purchaseYear >= 2015 && $purchaseYear < 2019) { $purchaseYear = '2015-19'; }
if (isset($chartData[$purchaseYear])) {
$prev = $chartData[$purchaseYear];
$chartData[$purchaseYear] = $totalInventory + $prev;
$prev = null;
} else {
$chartData[$purchaseYear] = $totalInventory;
}
}
I believe the most time consuming part should be executing the query. If you use whereIn, then I think you can execute the query only once, and then loop over the results. I haven't tested it, but it should be something like this:
$purchasesByYear = \App\Inventory::select('purchase_year',
DB::raw('count(*) as purchase_count'))
->whereIn('purchase_year', $purchaseYears)
->groupBy('purchase_year')->get();
I think reducing the number of query executions will be the main opportunity to keep this from running slowly. Also, I think adding an index to purchase_year should be helpful if you have not already done so.
Instead of a lot of elseif conditions to handle grouping the years, you could use some math. This might actually be slightly slower, but the code would be a little less repetitive, and I believe anything you do to this part will be a micro-optimization compared to what you can do with the query part. My suggestion:
foreach ($purchasesByYear as $purchaseYear) {
$year = $purchaseYear->purchase_year;
if ($year < 1960) {
$yearRange = 'Pre 1960';
} else {
// subtract one until the year is a multiple of five
while ($year % 5) { $year--; }
// then construct the range string using the starting number
$yearRange = $year.'-'.($year+4);
}
if (isset($chartData[$yearRange])) {
$chartData[$yearRange] += $purchaseYear->purchase_count;
} else {
$chartData[$yearRange] = $purchaseYear->purchase_count;
}
}
I think you can break the dates into a pattern, rather than just testting for each decade, something like this:
if ($purchaseYear < 1960) {
$purchaseYear = 'Pre 1960';
} else {
$prefix = substr($purchaseYear,0,2);
$decade = substr($purchaseYear,1,1);
$suffix = substr($purchaseYear,-1);
$purchYear = $prefix . $decade
if ($suffix<5) {
$purchYear .= '0-' . $decade . '4';
} else {
$purchYear .= '5-' . $decade . '9'
}
Haven't tested this, but I think it will do what you'd like.
This seems simple but I don't know why it doe snot work.
I need to write an if statement that
first, checks if it is numeric
second, if it is not between 1 and 10, issue errorA
third, if it is not between 20 and 30, issue errorB
fourth, it is not a number, issue errorC
If is not numeric and satisfies all the ranges, added to the database.
anyways, I am not sure about the if and while combination to satisfy this....
So far I have,
if numeric and satisfies ranges, add to database
else, issue errorC
How can I filter for error A and B?
if ( isset [some code...]) {
$a = ...;
$b = ...);
$c = ...;
if (preg_match('/^\d+$/',$b) && preg_match('/^\d+$/',$c) &&
((1 <= $b && 10 >= $b)) && ((20 <= $c && 30 >= $c))) {
$sql = "INSERT [some code...]
mysql_query($sql);
$_SESSION['success'] = $_POST['success'];
header('Location: index.php') ;
return;
} else {
$_SESSION['error'] = $_POST['error'];
header('Location: index.php') ;
return;
}
}
if (preg_match('/^\d+$/',$b) && preg_match('/^\d+$/',$c)) {
if (($b >= 1 && $b <= 10) && ($c >= 20 && $c <= 30)) {
echo "OK";
} else {
echo "not in range";
}
} else {
echo "not a number";
}
im not sure this is a good question to post but here is my issue. I have an if statement that is getting way too long and i was wondering if there is some other kind of syntax to shorten it out:
if (($time1 <= $one_day)&&
($time2 <= $one_day)&&
($time3 <= $one_day)&&
($time4 <= $one_day)&&
($time5 <= $one_day)&&
($time1 != NULL)&&
($time2 != NULL)&&
($time3 != NULL)&&
($time4 != NULL)&&
($time5 != NULL)){
//do sometihng
}
this is one example but i have a similar one that goes up to ..&&($time15 <= $one_day).
the statement is pretty self explanatory, $time1, $time2, etc can come back empty so i have to check if they are NULL or not
any ideas?
thanks
You can put the common stuff in a function:
function validate_time($time, $one_day) {
return $time <= $one_day && $time != NULL;
}
if (validate_time($time1, $one_day) &&
validate_time($time2, $one_day) &&
validate_time($time3, $one_day) &&
validate_time($time4, $one_day) &&
validate_time($time5, $one_day)) {
// do something
}
You may want to refactor code and eliminate the need for copying & pasting those checks. Another way to get the job done:
while (true) {
foreach (array($time1, $time2, $time3, $time4, $time5) as $time) {
if ($time > $one_day || $time == NULL) {
break 2;
}
}
// do something
break;
}
The above could be put in a function as well which would make the while-loop and break keyword redundant. Replace break 2 by return then.
Using an array for you variables would help. The you can iterate over them and check.
Put the times in an array and have a for loop to do the checking.
Instead of using 15 similar but different variables, consider using an array.
If you must (or want to) keep the original variable names and not use an array here is the good solution (for $time1 to $time5):
$ok = true;
for ($i = 1; $i <= 5; $i++)
{
$var =& ${'time'.$i};
if ( ! ($var <= $one_day && $var != NULL))
{
$ok = false;
}
}
if ($ok)
{
//do something
}
You can set all the values into an Array and compare it using an For Loop.
A functionised version which should help with your reuse. This is similar to Lekensteyns code.
$times = array(
'time',
'time',
'time',
'time',
'time',
);
function validateTime($checks, $limit)
{
foreach($checks as $check) {
if($check == null || $check > $limit) {
return false;
}
}
return true;
}
if(validateTime($times,$one_day) == true) {
//codey code.
}