Comparison between two dates - php

I have done this function so that I have as a result the working days without counting the weekend between two dates, in the database I have the date fields as DATATIME, but at the time of executing I get this error:
A non well formed numeric value encountered
The function is as follows:
function diashabiles ($fecha_inicio, $fecha_fin) {
list ($year, $month, $day) = explode ("/", $fecha_inicio);
$ini = mktime (0, 0, 0, $month, $day, $year);
list ($yearf, $mesf, $diaf) = explode ("/", $fecha_fin);
$fin = mktime (0, 0, 0, $mesf, $diaf, $yearf);
$newArray = array ();
$r = 1; $i = 0; $dia2 = 0;
while ($ini! = $fin) {
$ini = mktime (0, 0, 0, $month, $day + $r, $year);
$newArray [$i] = $ini;
$r++; $i++;
}
for ($i = 0; $i <count($newArray); $i++) {
$day = $newArray [$i];
$date = getdate($day);
if ($date["wday"] == 0 or $date["wday"] == 6) {
$dia2++;
}
}
$rlt = count($newArray) - $dia2;
return $rlt;
}
Thank You!!

The problem is with this code:
list ($year, $month, $day) = explode ("/", $fecha_inicio);
$ini = mktime (0, 0, 0, $month, $day, $year);
list ($yearf, $mesf, $diaf) = explode ("/", $fecha_fin);
$fin = mktime (0, 0, 0, $mesf, $diaf, $yearf);
You stated that initially, the data stored was in DATE format, which means that what was coming out of the database was simply a year, month and a day. Then, you changed the data type to be DATETIME, which obviously changes what is stored in the database, and obviously changes what is retrieved.
In short, your explode function will leave you with the following:
$year = whatever year is in the database. Can be numeric.
$month = whatever month is in the database. Can be numeric.
$day = the rest, which will include day, hour, minute, second. Definitely not numeric.
When you use the above information (with the day being a string rather than a number) then mktime() fails.

Script works well if you replace
while ($ini != $fin)
with this
while ($ini <= $fin).
But i still suggest you to check this link Use DateTime, DateInterval and DatePeriod

Related

PHP Mktime shows 2 March's when I dump foreach month

I've been using the following function fine until the other day when the clocks went forward:
function months($month_format="F") {
$array = array();
for ($i = 1; $i <=12; $i++) {
$array[$i]['string'] = date($month_format, mktime(0,0,0,$i));
$array[$i]['int'] = date('m', mktime(0,0,0,$i));
}
return $array;
}
It outputs an array with:
string[]
int[]
Since the other day (like 2 days ago, when the clocks went forward in the UK), the function seems to be showing me 2 march months and 0 Februarys....
Very very strange...
I'm using rethinkdb with their eachPosTime function... not sure if this is causing it.
I tried using a different function, but still using mktime:
function months(){
$start_month = 1;
$end_month = 12;
$start_year = date("Y");
$array = array();
for($m=$start_month; $m<=12; ++$m){
echo $m.'<br>';
$array[$m]['string'] = date('F', mktime(0,0,0,$m));
$array[$m]['int'] = date('m', mktime(0,0,0,$m));
if($start_month == 12 && $m==12 && $end_month < 12)
{
$m = 0;
$start_year = $start_year+1;
}
//echo date('F Y', mktime(0, 0, 0, $m, 1, $start_year)).'<br>';
if($m == $end_month) break;
}
return $array;
}
Still, I am having no luck.
Check the image here, which shows the output of the months() function:
Output of the months() function
This is not to do with the clocks changing, but the time of the month, and the entirely unhelpful signature of the mktime function.
When you leave out parameters from a "mktime" call, they are filled in with today's date. In your case, you specified month without day or year, so when you ask for mktime(0, 0, 0, 2); it will fill in today's day and year, and look for the 29th February 2021 - a day that doesn't exist. Since the time library "overflows" dates, this becomes the 1st March.
The solution is to pass an explicit day to "mktime", as in mktime(0,0,0,$m,1) or to use a less confusing function.

data for period of months from dropdown on joomla

i have this code on joomla view php: (this code generate the months dropdown)
<form action="<?php echo JRoute::_('index.php?option=com_mycom'); ?>" method="post" name="adminForm" id="adminForm" class="modelList">
<select name="filter.search" class="inputbox" onchange="this.form.submit()">
<?php
for ($i = 0; $i <= 12; ++$i) {
$time = strtotime(sprintf('-%d months', $i));
$value = date('Y-m', $time);
$label = date('F Y', $time);
printf('<option value="%s">%s</option>', $value, $label);
}
?>
</select>
</form>
and i have a mysql table with row of "date" call "date"
so what that i am looking for is - when i am select the month all the data from this month will load on this page
so how can i get it from the sql query? i try this code on model but that give me an error:
$search = $this->getState('filter.search');
if(!empty($search))
{
if(stripos($search, 'id:') === 0)
{
$query->where('id = '.(int) substr($search, 3));
}
else
{
$search = $db->Quote('%'.$db->escape($search, true).'%');
$query->where('(date LIKE '.$search.')');
}
}
i try this code:
if(!empty($search))
{
if(stripos($search, 'id:') === 0)
{
$query->where('a.id = '.(int) substr($search, 3));
}
else
{
$searchParts = explode('-', $search);
// day 1 of selected month
$searchStartDate = date('Y-m-d', mktime(0, 0, 0, $searchParts[1], 1, $searchParts[0]));
// day 0 of next month is last day of selected month
$searchEndDate = date('Y-m-d', mktime(0, 0, 0, $searchParts[1] + 1, 0, $searchParts[0]));
$query->where("(a.date BETWEEN '$searchStartDate' AND '$searchEndDate' LIKE '.$search.')");
}
}
but it return an error:
Fatal error: Call to a member function where() on a non-object in
on this line - $query->where("(a.date BETWEEN '$searchStartDate' AND '$searchEndDate' LIKE '.$search.')");
When working with DATE fields you should do just that. You are trying to work with it as a string, which is possible but very inefficient.
Instead of asking the database to return all records WHERE date LIKE '%2013-07%' you should be asking for all records between the beginning and end of the selected month.
SELECT *
FROM tbl
WHERE `date` BETWEEN '2013-07-01' AND '2013-07-31'
You can change your PHP code to something like this -
else
{
$searchParts = explode('-', $search);
// day 1 of selected month
$searchStartDate = date('Y-m-d', mktime(0, 0, 0, $searchParts[1], 1, $searchParts[0]));
// day 0 of next month is last day of selected month
$searchEndDate = date('Y-m-d', mktime(0, 0, 0, $searchParts[1] + 1, 0, $searchParts[0]));
$query->where("(date BETWEEN '$searchStartDate' AND '$searchEndDate')");
}

calculate the dates that are between two days of the week

I need an algorithm that calculates dates that are between two days of the week!
for example i have
start date: 23-04-2012 and end date: 27-04-2012
now i want receive an array with this structure:
$arr = array(
'23-04-2012',
'24-04-2012',
'25-04-2012',
'26-04-2012',
'27-04-2012',
'28-04-2012'
);
thanks!
You could use the DateTime::Diff function (documentation here).
Pass your two dates into the function.
Get the return value as the number of days.
Add one to it (so as to include both the start and end dates).
Put together a for(int i = 0; i <= $days_difference; i++) loop.
Increment the date by one day each time and add it to the array.
$start = '23-04-2012';
$end = '27-04-2012';
$startTs = strtotime("$start 00:00:00");
$endTs = strtotime("$end 00:00:00");
$days = array();
$day = $startTs;
$i = 0;
while ($day <= $endTs) {
$days[] = date('d-m-Y', $day);
$i++;
$day = mktime(0, 0, 0, date('n', $startTs), date('j', $startTs) + $i, date('Y', $startTs));
}
var_dump($days);
This could help you.
$startdate=explode("-","23-04-2012");
$enddate=explode("-","27-04-2012");
$i;
$arr=array();
for($i=$startdate[0];$i<=$endate[0];$i++)
{
$dd=$i.'-'.$startdate[1].'-'.$startdate[2];
array_push($arr,$dd);
}
print_r($arr);

UNIX timestamp of the last time an entry was edited

In Expression Engine the {edit_date} tag would not return a UNIX timestamp like {entry_date} does. To work around that I used the approach below.
Does any one have an idea of how this could be made easier?
{exp:channel:entries channel="pieces" limit="1" track_views="three"}
<?php
$edit_date_string = {edit_date};
$edit_date = NULL;
if(!isset($edit_date_string)) {
$edit_date = {entry_date};
} else {
// Date format: 2011 05 25 00:53:44
// Raw: 20110525005344
$hour = substr($edit_date_string, -6, 2);
$minute = substr($edit_date_string, -4, 2);
$second = substr($edit_date_string, -2, 2);
$day = substr($edit_date_string, -8, 2);
$month = substr($edit_date_string, -10, 2);
$year = substr($edit_date_string, -12, 2);
$edit_date = mktime($hour, $minute, $second, $month, $day, $year);
}
echo $edit_date;
?>
{/exp:channel:entries}
As a side note it seems this is an inconsistency which makes it harder to process and compare dates. There would probably be a good reason for it. Does anyone know? Thanks
If you've got PHP 5.3, there's DateTime::createFromFormat:
$edit_date = DateTime::createFromFormat('YmdHis', $edit_date_string)->getTimestamp();
Or, even more directly, according to the Expression Engine docs:
$edit_date = {edit_date format="%U"}

Build date range

I have a start date of 20090101 and an end date of 20091130 and I'm trying to build and array of all the months in between, which would look like this:
<?php
/* ... */
$arrDates['Jan'] = 2009;
$arrDates['Feb'] = 2009;
$arrDates['Mar'] = 2009;
/* ... */
?>
How can I do this?
I don't fully understand your array structure.
But maybe this helps: When using PHP 5.3 you can use code like below to get an iterator with all months in the given range:
<?php
$db = new DateTime( '2009-01-01 00:00:00' );
$de = new DateTime( '2009-11-30 23:59:59' );
$di = DateInterval::createFromDateString( 'first day of next month' );
foreach ( $di as $dt )
{
echo $dt->format( "Y-m\n" );
}
?>
The following snippet creates such an array:
$startDate = '20090101';
$endDate = '20091130';
$arrDates = array();
$cur = strtotime($startDate);
$end = strtotime($endDate);
while ($cur < $end) {
$arrDates[date('M', $cur)] = date('Y', $cur);
$cur = mktime(0, 0, 0, date('m', $cur) + 1, 1, date('Y', $cur));
}
// If you want to add the 'end' month too...
$arrDates[date('M', $end)] = date('Y', $end);
However, note that, as danii commented, you are unclear about how you want to handle a timespan that is larger than a year. The code above will simply use the last year in the range you provide.
This code will work with pretty much any version of PHP (PHP 4+). If you want a more elegant solution and are using PHP 5.2+, I recommend the solution offered by GZipp.
I had a similar situation for a website i was building for travelagency. You need timestamps, arrays and looping. Take a look at the date function PHP provides. It gives you some interesting options to play with dates. E.g. the no. of days in a specified month.
You say "the months in between", but since your example includes the starting month, I assume you mean "the months in between plus the starting and ending months".
$dt_start = new DateTime('20090101');
$dt_end = new DateTime('20091130');
$arrDates[] = $dt_start->format('M');
while ($dt_start->modify('first day of next month') <= $dt_end) {
$arrDates[] = $dt_start->format('M'); // Or whatever you want to do with it.
}
(This is essentially johannes' solution with a little manual reading applied to adapt it for PHP 5.2.)
You can't use the month as a key, the key must be unique or if your range spans more than a year it won't work correctly.
This will return an array with Mon-Year as the key
function foo($startdate, $enddate) {
// create a timestamp for start date
if(!preg_match('/^(\d{4})(\d{2})(\d{2})$/', $startdate, $m)) die('Invalid start date format');
$start_time = mktime(0, 0, 0, $m[2], $m[3], $m[1]);
// create a timestamp for end date
if(!preg_match('/^(\d{4})(\d{2})(\d{2})$/', $enddate, $m)) die('Invalid end date format');
$end_time = mktime(23, 59, 59, $m[2], $m[3], $m[1]);
// build the array of months by incrementing $start_time by one month through each iteration
$ret = array();
while($start_time < $end_time) {
$ret[date('M-Y', $start_time)] = date('Y', $start_time);
$start_time = strtotime(date('m/d/Y', $start_time).' +1month');
}
return $ret;
}
$arrDates = foo('20090101', '20111130');
print_r($arrDates);
Array(
[Jan-2009] => 2009
[Feb-2009] => 2009
[Mar-2009] => 2009
[Apr-2009] => 2009
[May-2009] => 2009
[Jun-2009] => 2009
[Jul-2009] => 2009
[Aug-2009] => 2009
....
)
A bit convoluted but works...:
function buildDateRange($strStartDate, $strEndDate)
{
$strStartM = date('M', $strStartDate);
$strStartY = date('Y', $strStartDate);
$strEndM = date('M', $strEndDate);
$strEndY = date('Y', $strEndDate);
$intCurMN = date('m', $strStartDate);
$ii = 0;
$blnFinished = FALSE;
while(!$blnFinished)
{
$strCurM = date('M', mktime(0, 0, 0, $intCurMN , "01", $strStartY));
$strCurY = date('Y' ,mktime(0, 0, 0, $intCurMN , "01", $strStartY));
$arrSearchDates [$strCurM] = $strCurY;
$intCurMN = date('m', mktime(0, 0, 0, $intCurMN+1 , "01", $strStartY));
if($strEndM == $strCurM && $strEndY == $strCurY)
{
$blnFinished = TRUE;
}
}
Return ($arrSearchDates);
}

Categories