I am trying to get the values from timespan() function in Code Igniter. I have one problem, how can I know whether each of the date format is displayed? For example in regards with the codes below, one timespan might be 2 Months, 6 Days, 13 Hours, 14 Minutes which would have 4 elements but another might be 2 Months, 1 Week, 3 Days, 4 Hours, 39 Minutes which has 5 elements. If do the preg_replace then I won't know which are the months or weeks or days etc.
So how do I find out if it is the week or days or hours etc? Because I want to convert the values into cycles like 39mins/1440mins would be 0.0270833 days, then I will calculate for the hours days weeks months and years and add all of them together
// Hold Cycle Time Conversion
foreach($results as $key => $values)
{
// Convert mysql timestamp to unix
$remove = array('-', ':', ' ');
$hold_timestamp = mysql_to_unix( str_replace( $remove, '', $values['hold_date'] ) );
// Get timespan
$hold_timestamp = timespan($hold_timestamp);
// Explode into arrays
$timestamp_format = explode(',', $hold_timestamp);
// Check each array to get value
foreach($timestamp_format as $ts)
{
$separated_stamp = preg_replace('/[^0-9]/', '', $ts);
/*** Stuck here, incomplete ***/
}
}
I've decided to abandon that logic and use PHP's Date Time class instead. Got some help from this post as well. Not sure if it's the best way but it's what I've found.
// Hold Cycle Time Conversion
foreach($results as $key => $values)
{
// Declare timestamps
$last = new DateTime( $values['hold_date'] );
$now = new DateTime( date( 'Y-m-d h:i:s', time() )) ;
// Find difference
$interval = $last->diff($now);
// Store in variable to be used for calculation etc
$years = (int)$interval->format('%Y');
$months = (int)$interval->format('%m');
$days = (int)$interval->format('%d');
$hours = (int)$interval->format('%H');
$minutes = (int)$interval->format('%i');
}
Related
I have comma separated days(1,3,5,6) and i want to count number of days between two days.
I have done this as below.
$days=$model->days; // comma saperated days
$days=explode(',',$days); // converting days into array
$count=0;
$start_date = $model->activity_start_date; // i.e. 2018-03-27
$end_date = date('Y-m-d');
while(strtotime($start_date) <= strtotime($end_date)){
if(in_array(date("N",strtotime($start_date)),$days)){ // check for day no
$count++;
}
$start_date = date ("Y-m-d", strtotime("+1 day", strtotime($start_date)));
}
This code is working fine. But the problem is if difference between two date will be year or more than a year than it loop 365 times or more.
Is there any way to reduce execution time to count days. Or it is possible to get counts of days using mysql query.
Real Scenario : I have one event which have start date and it occurs multiple in week(i.e. Monday and Wednesday ) and i want to find how many times event occur from start date to now. If start date is 2018-04-9 and today is 2018-05-9 than count will be 9
This requires no looping.
I find how many weeks between start and end and multiply full weeks (in your example 16,17,18) with count of days.
Then I find how many days there is in first week (15) that is higher than or equal to daynumber of startday.
Then the opposit for week 19.
$days="1,3"; // comma saperated days
$days=explode(',',$days); // converting days into array
$count=0;
$start_date = "2018-04-09";
$end_date = "2018-05-09";
// calculate number of weeks between start and end date
$yearW = floor(((strtotime($end_date) - strtotime($start_date)) / 86400)/7);
if($yearW >0) $count = ($yearW -1)*count($days); //full weeks multiplied with count of event days
$startday = date("N", strtotime($start_date));
$endday = date("N", strtotime($end_date));
//find numer of event days in first week (less than or equal to $startday)
$count += count(array_filter($days,function ($value) use($startday) {return ($value >= $startday);}));
//find numer of event days in last week (less than $endday)
$count += count(array_filter($days,function ($value) use($endday) {return ($value < $endday);}));
echo $count; // 9
https://3v4l.org/9kupt
Added $yearW to hold year weeks
Here, I have a code I have used previously in a project. It is used to find the distance between date from today.
public function diffFromToday($date){
$today = date('jS F, Y');
$today = str_replace(',','',$today);
$today=date_create($today);
$today = date_format($today,"Y-m-j");
$date = str_replace(',','',$date);
$date=date_create($date);
$date = date_format($date,"Y-m-j");
$today=date_create($today);
$date=date_create($date);
$diff=date_diff($today,$date);
$result = $diff->format("%R%a");
$result = str_replace('+','',$result);
return $result;
}
You can use this function according to your requirement. Date format used in this function is 'jS F, Y' DO not be confused and use your own format to convert.
$start_date = date_create('2018-03-27');
$end_date = date_create('2018-04-27');
$t = ceil(abs($endDate- $start_date) / 86400);
echo date_diff($start_date, $end_date)->format('%a');
Output with like this
396
Could you not use the date->diff function to get the values you can directly use like -5 or 5?
$diffInDays = (int)$dDiff->format("%r%a");
Here is something for format parameter descriptions if it could be helpful to you.
You may use tplaner/when library for this:
$days = str_replace(
['1', '2', '3', '4', '5', '6', '0', '7'],
['mo', 'tu', 'sa', 'th', 'fr', 'sa', 'su', 'su'],
'1,3'
);
$when = new When();
$when->rangeLimit = 1000;
$occurrences = $when->startDate(new DateTime('2018-04-9'))
->freq('daily')
->byday('mo,we')
->getOccurrencesBetween(new DateTime('2018-04-9'), new DateTime('2018-05-9'));
echo count($occurrences);
I have a function like this:
function time_elapsed_string($ptime)
{
$date_time = strtotime("1348-10-10 04:30:01") + $ptime;
$year = date("Y",$date_time);
$month = date("m",$date_time);
$day = date("d",$date_time);
$time = date("H:i:s",$date_time);
$etime = time() - $ptime + 1;
$a = array( 31536000 => 'year',
2592000 => 'month',
86400 => 'day',
3600 => 'hour',
60 => 'minute',
1 => 'second'
);
foreach ($a as $secs => $str)
{
$d = $etime / $secs;
if ($d >= 1)
{
$r = round($d);
// EX:
return array('date' => $day.'-'.$month.'-'.$year, // 2016-02-20
'time' => $time, // 03:30:04
'difference' => $r . ' ' . $str . ' ago' // 2 month ago
);
}
}
}
And I use it like this:
$ptime = 1470692661;
$html = '<span title="date: '.time_elapsed_string($ptime)['date'].' time: '.time_elapsed_string($ptime)['time'].'">in '.time_elapsed_string($ptime)['difference'].'<span>';
As you see, I'm using of that function's result like this:
time_elapsed_string($ptime)['date']
ime_elapsed_string($ptime)['time']
time_elapsed_string($ptime)['difference']
In fact I'm calling that function every time I need one of its results. Is that right? Or should I call it once and store it into an array?
Note: My code works as well.
Counting time elapsed since some date/time like this is mauvais ton.
DateTime has been available since PHP 5.2.0 and tonns of people underestimate it. Why don't you use this instead of loops and ifs?
$create_time = "2016-08-02 12:35:04";
$current_time="2016-08-02 16:16:02";
$dtCurrent = DateTime::createFromFormat('Y-m-d H:i:s', $current_time);
// to use current timestamp, use the following:
//$dtCurrent = new DateTime();
$dtCreate = DateTime::createFromFormat('Y-m-d H:i:s', $create_time);
$diff = $dtCurrent->diff($dtCreate);
Now, you can format the result however you want:
$interval = $diff->format("%h hours %i minutes %s seconds");
This will give a clean 3 hours 40 minutes 58 seconds without any arrays, which is better.
UPDATE
There is a general solution to get hours / minutes / seconds via regex:
$interval = $diff->format("%y years %m months %d days %h hours %i minutes %s seconds");
// now remove zero values
$interval = preg_replace('/(^0| 0) (years|months|days|hours|minutes|seconds)/', '', $interval);
UPDATE 2
As of your comment:
Look, I want to use your approach .. but I really cannot implement it .. Actually I need three things: time, date, difference ..! But your approach doesn't give me them..
Well, we already know how to get the difference, it's the $interval variable described above.
To get time and date, you can get it from the $dtCreate variable by, again, using format:
$time = $dtCreate->format('H:i:s');
$date = $dtCreate->format('d-m-Y');
This is a no brainer.
Yes - store the function call result of time_elapsed_string($ptime) in an array, then use that to access your results. You're wasting CPU cycles otherwise!
// call it once
$result = time_elapsed_string($ptime);
// then use:
$result['date'];
$result['time'];
$result['difference'];
The timestamp in my database is 2015-03-03 00:25:39 (Take note that the type = timestamp and the correct current timestamp in my end is 2015-03-02 01:31:00. The difference should be around 23 hours. But now the problem is that the answers provided in the net will give me 30 hours instead of 23 hours. Some of the codes that I have tried are the following:
$target is the target date
CODE 1:
$then = strtotime($target);
$diff = $then - time();
echo sprintf("%s days and %s hours left", date('z', $diff), date('G', $diff));
But it gives me 1 days and 6 hours left. So 30 hours
CODE2:
$seconds = strtotime("$target") - time();
echo $seconds; exit();
$days = floor($seconds / 86400);
$seconds %= 86400;
$hours = floor($seconds / 3600);
echo $hours;
It gives me something like 107388 = 30 hours.
CODE 3:
//Convert to date
$datestr= $target;//Your date
$date=strtotime($datestr);//Converted to a PHP date (a second count)
//Calculate difference
$diff=$date-time();//time returns current time in seconds
$days=floor($diff/(60*60*24));//seconds/minute*minutes/hour*hours/day)
$hours=round(($diff-$days*60*60*24)/(60*60));
It gives me 6 hours
I don't know what I'm doing wrong, more like I have no idea how to do it.
This is now my last resort since I can't find the solution that will help me.
Hoping for your fast responses.
PHP's DateTime() (and DateInterval()) are much better for date math and returns the correct results:
$date = new DateTime('2015-03-03 00:25:39');
$now = new DateTime('2015-03-02 01:31:00');
$diff = $date->diff($now);
echo $diff->h, ' hours ', $diff->i, ' minutes';
Demo
This is a very late answer, but your question is a good one that will likely be searched for in the future.
Here is an online demo.
// this doesn't appreciate any timezone declarations, you'll need to add this if necessary
$target="2015-03-03 00:25:39"; // declare your input
$then=new DateTime($target); // feed input to DateTime
$now=new DateTime(); // get DateTime for Now
$diff=(array)$then->diff($now); // calculate difference & cast as array
$labels=array("y"=>"year","m"=>"month","d"=>"day","h"=>"hour","i"=>"minute","s"=>"second");
$readable=""; // declare as empty string
// filter the $diff array to only include the desired elements and loop
foreach(array_intersect_key($diff,$labels) as $k=>$v){
if($v>0){ // only add non-zero values to $readable
$readable.=($readable!=""?", ":"")."$v {$labels[$k]}".($v>1?"s":"");
// use comma-space as glue | show value | show unit | pluralize when necessary
}
}
echo "$readable";
// e.g. 2 years, 20 days, 1 hour, 10 minutes, 40 seconds
I have two Zend_Date that represent an interval :
$start = new Zend_Date($punch->getStart());
$end = new Zend_Date($punch->getEnd());
$nbHours = $start->sub($end , Zend_Date::HOUR);
$nbMinutes = $start->sub($end , Zend_Date::MINUTE);
$hoursTotal = $nbHours->get(Zend_Date::HOUR);
$minutesTotal = $nbMinutes->get(Zend_Date::MINUTE);
Is there an simple way to split the interval by day of the week with Zend_Date when the interval > 24 hours?
For example, if I have an interval from Monday 8am to Tuesday 4:30pm, I would like to have an array containing monday = 16h and tuesday = 16:30.
You don't need to use Zend_Date for this, in fact it is probably better not to. You should use the date/time classes in PHP instead.
If I understand your question correctly you want an array of days and the hours worked for those days.
I first created a mock class to reflect your code example, I have assumed it is returning timestamps:-
class Punch
{
public function getStart()
{
return time();
}
public function getEnd()
{
return strtotime('+36 hours 45 minutes');
}
}
Then we set up the DateTime objects-
$Punch = new Punch();
$start = new DateTime();
$start->setTimestamp($Punch->getStart());
$end = new DateTime();
$end->setTimestamp($Punch->getEnd());
Then we use a DateInterval object to generate our iterable DatePeriod:-
$interval = new DateInterval('PT1M');
$minutes = new DatePeriod($start, $interval, $end);
Then we simply iterate over it counting the minutes worked in each day:-
$format = 'l';
foreach($minutes as $minute){
if(!isset($result[$minute->format($format)])) $result[$minute->format($format)] = 0;
$result[$minute->format($format)]++;
}
See the manual page for acceptable formats.
We now have the number of minutes worked in each day, converting them to hours is trivial:-
foreach($result as $key => $r){
$result[$key] = $r/60;
}
var_dump($result);
Output (Obviously, you will get a different result running it at a different time) :-
array
'Monday' => float 17.483333333333
'Tuesday' => float 19.266666666667
So on Monday 17.48 hours were worked and 19.27 on Tuesday.
Alternatively:-
foreach($result as $key => $r){
$result[$key] = floor($r/60) . ':' . $r % 60;
}
Would give the following output if that is closer to what you want:-
array
'Monday' => string "17:29"
'Tuesday' => string "19:16"
That's the simplest way I can think of doing it.
I want to calculate the number of years between two dates. One of them is retrieved from the database while the other is taken from user input in date format.
I used this code to get the date from the user:
$today = $_POST['to-day'];
$tomonth = $_POST['to-month'];
$toyaer = $_POST['to-year'];
$dateto = date("$toyaer-$tomonth-$today");
And here is how I calculated it with the one retrieved from the database,
$start = $leaveresult['date']; // i took from database
$end = strtotime($dateto);
$difference = abs($end - $start);
$years = floor($difference / (60*60*24*365));
The problem is that the result I get is always 0.
I tried different methods but all of them resulted with 0 and one of them resulted with a huge number.
This is untested but I think something like this will work:
$today = $_POST['to-day'];
$tomonth = $_POST['to-month'];
$toyear = $_POST['to-year'];
$dateto = "$toyear-$tomonth-$today";
$start = $leaveresult['date'];// i took from database
$end = strtotime($dateto);
$difference = abs($end - $start);
$years = floor($difference / (60*60*24*365));
I am assuming $leaveresult['date'] is unix timestamp
Also please note that I fixed the post variable names.
If the start date is not in unix timestamp then use
$start = strtotime($leaveresult['date']);// i took from database
The DateTime class simplifies all this by giving you a diff method. This will return a DateInterval object which you can get the values you're looking for.
Assuming $_POST looks like this:
$_POST = array(
'to-year' => 2010,
'to-month' => 8,
'to-day' => 22
);
And $leaveresult['date'] looks like this:
$leaveresult = array(
'date' => date('Y-m-d H:i:s', strtotime('-5 years')));
You can do something like this...
$input_date = new DateTime(sprintf("%d-%d-%d", $_POST['to-year'], $_POST['to-month'], $_POST['to-day']));
$database_date = new DateTime($leaveresult['date']);
$diff = $database_date->diff($input_date);
echo $diff->format('%r%y years') . PHP_EOL;
echo $diff->format('%r%m months') . PHP_EOL;
echo $diff->format('%r%d days') . PHP_EOL;
$years = $diff->y;
Which will yield
3 years
1 months
5 days
And $years will equal 3
you need in both cases a timestamp - the one you formatted ( as date object ) and the one you get from the database...
so I think you'r approach wasn't wrong, if your getting timestamps in both cases... but finally you've tried to round the number with floor... and of course this will result in 0, if it's less than a year.
test it without rounding first, and test your timestamps, maybe something is wrong there, too?