Check if date is in the next 3 days PHP - php

I have a date stored in my DB (due_date)
I am wanting to write a script that checks if the due_date is in the next 3 days
From checking online (google) i have found some code but it doesnt seem to work, see below
if (time() - filemtime($due_date) >= 3 * 86400)
{
echo" Invoice $id is due in the next 3 days<br />";
}
else
{
echo" Invoice $id not due in the next 3 days </br>";
}
$due_date contains a date in the format 01/01/2015
Please can someone help with this? P.s I am a newbie!
Thanks

Use strtotime() to convert the date string to a unix timestamp, and edit your if statement accordingly:
$seconds_to_expire = strtotime($due_date) - time();
if ($seconds_to_expire < 3*86400) {
...
Note that dates in the m/d/y or d/m/y formats are disambiguated by looking at the separator between the various components: if the separator is a slash (/), then the American m/d/y is assumed; whereas if the separator is a dash (-) or a dot (.), then the European d-m-y format is assumed (see this). You may want to convert your date to a Y-m-d format instead:
$due_date_ymd = date('Y-m-d', strtotime(str_replace('/', '-', $due_date));
$seconds_to_expire = strtotime($due_date_ymd) - time();
if ($seconds_to_expire < 3*86400) {
...

Change
filemtime($due_date)
to
strtotime(str_replace('/', '-', $due_date))
you have to change / to - if the day comes first, otherwise php will assume that first is month!

if (strtotime($due_date)+60*60*24*3 =< time()+60*60*24*3) {
echo "Is due in the next 3 days"
} else {
echo "Is not due in the next 3 days"
}

You could translate the DB date value (which is in the format 'yyyy-mm-dd') to a DateTime object and then compare:
$d = DateTime::createFromFormat('Y-m-d', $due_date);
$d->modify('-3 days'); // subtract 3 days from due date
if ($d < new DateTime()) {
echo 'date is due within 3 days';
}
Notes:
new DateTime() will give you the current date.
I assume that $due_date is a string in the format 'yyyy-mm-dd', as you should get if it is a Date column in the database.
Since you commented that $due_date is "A date in the format 01/01/2015", you can easily ajust the code: change the format specifier in the createFromFormat function from 'Y-m-d' into 'd/m/Y'.

Related

why strtotime isn't working on php

I'm trying to compare between two date but unfortunately this isn't working by converting this into UNIX format with strtotime. I'm trying to compare a date to another date.
However this format is working:
if(strtotime("22-04-17") < strtotime("25-05-17")){
echo 'Date One is smaller than date two';
}
But Many times it's failing. I've seen a lot of examples on the web but I can't figure out anything good!
if(strtotime("22-04-17") < strtotime("04-05-17")){ //passing still the
// bigger on but not working
echo 'Date One is smaller than date two';
}
From the manual (make special note of the part I've put in bold):
"Dates in the m/d/y or d-m-y formats are disambiguated by looking at the separator between the various components: if the separator is a slash (/), then the American m/d/y is assumed; whereas if the separator is a dash (-) or a dot (.), then the European d-m-y format is assumed. If, however, the year is given in a two digit format and the separator is a dash (-, the date string is parsed as y-m-d."
So here's what you're doing, with the dates PHP is interpreting your strings as in comments:
// Is 17 April 2022 earlier than 17 May 2025? Yes.
if(strtotime("22-04-17") < strtotime("25-05-17")){
echo 'Date One is smaller than date two';
}
// Is 17 April 2022 earlier than 17 May 2004? No.
if(strtotime("22-04-17") < strtotime("04-05-17")){ //passing still the
// bigger on but not working
echo 'Date One is smaller than date two';
}
I hope this makes the problem you're having clear.
As it also says in the manual, use DateTime::createFromFormat/date_create_from_format if you want to avoid ambiguity:
$date = date_create_from_format('d-m-y', '04-05-17'); // 4 May 2017
your comparsion is not working because strtotime("22-04-17") actually results to timestamp for this date: 17th April 2022;
Do the following and you will see what I mean. the following code will output '2022-May-17`
$date = "22-05-17";
echo date ("Y-M-d ",strtotime($date))."<br>";
Try this
$date1 = date('d-m-y',strtotime("22-04-17"));
$date2 = date('d-m-y',strtotime("04-05-17"));;
if((int)strtotime($date1) < (int)strtotime($date2)){ //passing still the
echo 'Date One is smaller than date two';
}
Your year format 17 causing the problem in strtotime function
I know this isn't what you're looking for but have you tried doing this to showing if date greater / smaller?
// Dates
$Date1 = strtotime("22-04-17 GMT");
$Date2 = strtotime("04-05-17 GMT");
// Diff between dates
$Diff = (int)floor(($Date1 - $Date2) / (60*60*24));
if ($Diff < 0) {
echo "The Diff is negative";
}
Then the other way is like this answer: LINK
$date1 = strtotime("22-04-17 GMT");
$date2 = strtotime("04-05-17 GMT");
if((int)strtotime($date1) < (int)strtotime($date2)){ //passing still the
echo 'Date One is smaller than date two';
}
I wrote a function that takes your datestring and properly return timestmp. Please note that I followed PHP's convention of treating 2 digit years, i.e. 00-69 are mapped to 2000-2069 and 70-99 to 1970-1999
/* functon takes dateString of format dd-dd-yy and return proper timestamp */
function getTimestamp($dateString)
{
$res = preg_match('/^([0-9]{2})\-([0-9]{2})-([0-9]{2})/', $dateString, $matches);
if(!$res)
return 0;
//00-69 are mapped to 2000-2069 and 70-99 to 1970-1999
if($matches[3]>=70 && $matches[3]<=99 )
$year = "19".$matches[3];
else
$year = "20".$matches[3];
$formatted_dat_string = $year."-".$matches[2]."-".$matches[1];
return strtotime($formatted_dat_string);
}
getTimestamp("22-04-99");
So you can now use this function instead of strtotime for comparison.
Finally, I got the solution. The strtotime() isn't any good to handle this case. You should go for dateTime object instead.
//First you need to pass the original format then you will need to pass new
//Format to get this working properly. Hope this will help you guy's
$myDateTimestart = DateTime::createFromFormat('d-m-Y', $dateString);
$startDate = $myDateTimestart->format('m-d-Y');
//with Simply that you can format your date properly
I just Messed my times with this thing it was really bad

php - uniformize date strings with different formats

I have an array with many different formats of dates. All strings.
I want to uniformize this into an array with dates(). Something like this:
function uniformize($str){
$date = strtotime($str);
return $date;
}
$arr = array(
'07/29/1975',
'20/01/1981',
'1983-05-24',
'10 /8 /1995'
);
print_r( array_map('uniformize', $arr) );
But this only works with one format:
Array (
[0] =>
[1] =>
[2] => 454215600
[3] =>
)
Is there any way I can do it for all formats?
You can use this function for that. Fiddle here
Notice it's supposed to have always the days before than the months. Otherwise it's impossible to know whether first part of the date is a day or a month (unless the day is more than 12.. and can't cover all the cases).
function date2time($date)
{
$date = str_replace(' ','',$date);
if(strpos($date,'-')!==false)
$date_array = explode('-',$date);
if(strpos($date,'/')!==false)
$date_array = explode('/',$date);
//add more delimiters if needed
$day = $month = $year = '';
foreach($date_array as $date_elem)
{
if(strlen($date_elem) < 3)
{
if(empty($day))
$day = $date_elem;
else
$month = $date_elem;
}else
$year = $date_elem;
}
$time = mktime(0,0,0,$month,$day,$year);
return $time;
}
$arr = array(
'07/29/1975',
'20/01/1981',
'1983-05-24',
'10 /8 /1995'
);
print_r( array_map('date2time', $arr) );
Unfortunately, I think you have to detect yourself the format and then convert it into the format you wish...
The real problem is about months and days...
some use 31-12-2014, other countries use 12-31-2014...
so you HAVE to define which is the month and the day in a string like 05-06-2015...
EDIT :
You have many regex to do...
I'm using this for 2015-12-31 format :
if(preg_match("/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/", $yourDate, $split)) && (checkdate($split[2],$split[3],$split[1]))) {
// do stuff where $split[1] is years, split[2] is month, and split[3] is day
}
Then you may adapt it to every formats you encounter changing order...
checkdate checks if it is a valide date (2015-52-38 is not a valid date)
You may also find some on google with "date pattern regex" for instance...
The first two strings use / as component separator. The function strtotime consider them to be formatted according to the American format: month/day/year. Because 24 and 20 are invalid month numbers they cannot be parsed correctly.
The last string ('10 /8 /1995') looks like a short date format but the spaces inside the components also render it invalid.
As it is explained in a note in the documentation of function strtotime():
Note:
Dates in the m/d/y or d-m-y formats are disambiguated by looking at the separator between the various components: if the separator is a slash (/), then the American m/d/y is assumed; whereas if the separator is a dash (-) or a dot (.), then the European d-m-y format is assumed.
What can you do
If you know the order of components in your dates you can use str_replace() to always use / for m/d/y (the American format) and - for d-m-y (the European format). Also, you should strip the spaces.
Another option is to write your own date parser to identify the date components then use mktime() or DateTime::setDate() to get the date. However, if the date have both the day and the month in 1..12, the format cannot be detected and it have to be assumed (from the separator).

PHP date conversion from user input

I am trying to convert a user inputted date so I can use it to search in MySQL. This is my code -
<form name="date_form" action="" method="POST"">
<input type="text" name="start_date" value="<?php echo date('d/m/Y');?>"/>
<input type="submit" name="submit_start" value="Submit" />
<?php
if(isset($_POST["submit_start"]))
{
$date_1 = mysqli_real_escape_string($dbc, trim($_POST['start_date']));//checking that I am getting something from the input
$newDate = date("Y-m-d", strtotime($_POST['start_date']));//converting date from the input to SQL format
echo '<br>date 1 = '.$date_1.'<br>';
echo 'date 2 = '.$newDate.'<br>';
$start_date = '2013-12-13';
echo 'date 3 = '.$start_date.'<br>';//Just to compare formats
$report = create_user_report($dbc, $start_date);
}
and this is the output
date 1 = 14/12/2013
date 2 = 1970-01-01
date 3 = 2013-12-13
2013-12-13
I was expecting date 2 to be 2013-12-13, the format appears to be ok but the value isnt. I have played with many different ways of getting the value, all have been wrong!
So I have two questions please
1. How can I get the correct value in the code above?
2. I want to use this value to search a MySQL table and return a count of dates that match it. Once the above is working, is that the best way to do it - or is there a better way?
Many thanks
From the strtotime manual:
Dates in the m/d/y or d-m-y formats are disambiguated by looking at the separator between
the various components: if the separator is a slash (/), then the American m/d/y is
assumed; whereas if the separator is a dash (-) or a dot (.), then the European d-m-y
format is assumed.
So:
$newDate = date("Y-m-d", strtotime($_POST['start_date']))
is asking for the 12th day of the 14th month.
Try replacing the / with -
$date = str_replace ( '/' , '-' , $_POST['start_date'])
The problem is caused because when confronted with /, strtotime assumes the time to be in the American format of m/d/Y (instead of d/m/Y). Read the manual on strtotime (especially the Notes) for more information.
And because 14/12/2013 is not valid in the American format, you'll get the default time (aka UNIX timestamp 0).
Since this is user input and you cannot be sure if he really means to use the American format or is misusing it, you could do a check before the conversion like this
//check if input is a date in the American format
if (preg_match("#^(\d+)/(\d+)/(\d+)$#", $_POST['start_date'], $matches)) {
if ($matches[1] > $matches[2]) {
$day = $matches[1];
$month = $matches[2];
} else {
$day = $matches[2];
$month = $matches[1];
}
$start_date = $month.'/'.$day.'/'.$matches[3];
}
However if a user inputs e.g. 04/05/2013 this will be interpreted in the American format, although the user could have meant it in d/m/Y.
"Explode" seems to be commonly used in situations like this.
$mydate = $_POST["submit_start"];
list ($y, $m, $d) = explode('/', $mydate);
$mydate = sprintf("%02d-%02d-%04d", $m, $d, $y);
strtotime requires the English date format as input - HERE.
strtotime() PHP Manual
Take a look over there, it reports
The function expects to be given a string containing an English date format
And that's why your function doesn't work as you expect. In fact, d/m/Y is NOT an american date format. Here, take a look, I made you some examples to let you see how to make it work: Click here - eval.in
<?php
echo strtotime(date('m/d/Y'));
echo strtotime(date('d/m/Y'));
echo strtotime(date('d-m-Y'));
echo strtotime(date('d/m/Y'));
echo strtotime(date('Y-m-d'));
echo strtotime(date('Y/m/d'));
?>
Produces
1386979200
FALSE
1386979200
FALSE
1386979200
1386979200
Since you'll never know what kind of date format (or if it's actually a date at all) an user may input, I suggest you to use a date picker plugin on your input, that'll be very useful, or you may want to use a regular expression that other user suggested.
For the mysql part you can easly compare two dates with the MySQL Date Function
Since I don't know your query I'll just provide you the part you need for the comparsion in the query:
... WHERE DATE(some_date) = DATE(some_other_date) ...
Where some_date and some_other_date are two valid date formats as written above.

Not sure what's wrong with my code

I'm passing a date input using php $_GET
<form action="trigger_date.php" method="get">
Enter Project Turnover date (mm/dd/yy): <input type="string" name="date"> <input type="submit">
In the trigger_date.php takes this as
<?php $turnover_date = $_GET['date']; ?>
I do some math to compare it to today's date
<?php
$project_turnover = strtotime($turnover_date);
$project_turnover = date ("m/d/y", $project_turnover);
?>
<?php
$datetime1 = date_create($today);
$datetime2 = date_create($project_turnover);
$wks_to_turnover = date_diff($datetime1, $datetime2); // taking the difference between today and project turnover date
$wks_to_turnover = $wks_to_turnover->format('%R%a');
$wks_to_turnover = ($wks_to_turnover/7);
$wks_to_turnover = round($wks_to_turnover,1); //with input of 5/1/14 this should be roughly 24 wks
?>
Here's where I'm stumped, my styling is:
<?php
if ($wks_to_turnover > 2) {
echo $date_green; // colors the background green
} elseif (2 > $wks_to_turnover && $wks_to_turnover > 0) {
echo $date_yellow; // colors the background yellow
} elseif (0 >= $wks_to_turnover) {
echo $date_red; //colors the background red
} ?>;
But even if (24 > 2) it's still coloring as red
Note that <input type="string" /> is not valid HTML -- you're looking for type="text"
date_create accepts several different formats of dates. The m/d/y format, which you're using on the input date, is bad form because it is ambiguous. Per the manual:
Note:
Dates in the m/d/y or d-m-y formats are disambiguated by looking at
the separator between the various components: if the separator is a
slash (/), then the American m/d/y is assumed; whereas if the
separator is a dash (-) or a dot (.), then the European d-m-y format
is assumed.
To avoid potential ambiguity, it's best to use ISO 8601 (YYYY-MM-DD)
dates or DateTime::createFromFormat() when possible.
Use a standardized date format that is supported by the Date object. It may not be the cause of your issue, but it is good to be unambiguous in code.
I'm not completely sure why you turn the input into a UNIX timestamp and then back to a formatted date. You could simply use the formatted date you get from input, which appears to be in a supported format, and deal with any errors that may generate.
Finally, your math produces a negative number. That's one reason why your logic fails to act as you expect. You can reverse the order of arguments passed to date_diff, OR use abs to get the absolute distance between the two dates. I went with abs, which makes the code not care if the 2 weeks is in the past or in the future. I don't know what you're doing here -- maybe the sign matters. If so, reverse the order of arguments passed to date_diff
(edit: OP clarified abs would not suite his need, adjusted accordingly)
Putting it together, I would suggest something like this:
$datetime1 = date_create('now');
$datetime2 = date_create(
array_key_exists(
'date',
$_GET
) ? $_GET['date'] : 'invalid'
);
if (!$datetime2)
die('invalid date');
$wks_to_turnover = date_diff($datetime2, $datetime1);
$wks_to_turnover = $wks_to_turnover->format('%R%a');
$wks_to_turnover = ($wks_to_turnover/7);
$wks_to_turnover = round($wks_to_turnover,1);be roughly 24 wks
if ($wks_to_turnover <= 0) {
echo 'green';
} elseif ($wks_to_turnover < 2 && $wks_to_turnover > 0) {
echo 'yellow';
} else {
echo 'red';
}
I also adjusted the final block of ifs -- if weeks is less than or equal to zero, green, if less than two but greater than 0 yellow, otherwise red.
Try it: http://codepad.viper-7.com/kLN5jk
Documentation
strtotime - http://www.php.net/manual/en/function.strtotime.php
DateTime::__construct - http://www.php.net/manual/en/datetime.construct.php
Date formats - http://www.php.net/manual/en/datetime.formats.date.php
date (documents format strings) - http://php.net/manual/en/function.date.php
abs - http://www.php.net/manual/en/function.abs.php
I tried your code and it return red when i pass "non numerical value" so , i tried
echo (int)$wks_to_turnover;
and it returned '0' , the reason because the date not returned as integer yet.
a quick fix for that using your approach
replace that line :
$wks_to_turnover = date_diff($datetime1, $datetime2);
with that :
$wks_to_turnover = strtotime($datetime1)-strtotime($datetime2);
it'll return the difference in seconds , you can handle it from here

How to use PHP's strtotime

I'm new to PHP and kind of struggling with the basics, please excuse the horrible code to come.
What I'm trying to do is parse a date retrieved from an XML file, and see if that date falls on a Monday/Tuesday/etc.
I can't seem to get it right, any help is much appreciated.
<?php
foreach ($xml as $x)
{
$time = strtotime($x->Start);
echo $time;
if(date('D', $time) === 'Mon')
echo "Booking for Monday";
else if(date('D', $time) === 'Tue')
echo "Booking for Tuesday";
else if(date('D', $time) === 'Wed')
echo "Booking for Wednesday";
else if(date('D', $time) === 'Thu')
echo "Booking for Thursday";
else if(date('D', $time) === 'Fri')
echo "Booking for Friday";
}
?>
$time isn't outputting anything, and the only result coming back is "Booking for Thursday" for each XML record (x5) despite only two of the records falling on a Thursday.
If I output the results by:
echo $x->Start;
That works fine and outputs "15/07/2013 9:30:00 a.m.".
Cheers!
The date looks like European format d-m-y and uses American format m/d/y seperator.
Note:
Dates in the m/d/y or d-m-y formats are disambiguated by looking at
the separator between the various components: if the separator is a
slash (/), then the American m/d/y is assumed; whereas if the
separator is a dash (-) or a dot (.), then the European d-m-y format
is assumed.
Instead of
$time = strtotime($x->Start);
Try
$time = strtotime(str_replace('/','-',$x->Start));
Additional Info :PHP Manual
you have to convert your time string($x->Start) to one of the Supported Formats before passing it to the strtotime.
Replacing / with . would change your date to a support format. but double check to be sure.
$time = strtotime(str_replace('/', '.',$x->Start));
I see you already have an accepted answer, but I would strongly recommend that you take a look at PHP's DateTime classes. They are extremely useful and can make seemingly complex date operations trivial.
In your particular case, I would replace:-
$time = strtotime($x->Start);
with:-
$time = \DateTime::createFromFormat('d/m/Y H:i:s a', $x->Start);
You can then format the date as you wish using the \DateTime::format() method.

Categories