php issue with date_diff - php

I'm trying to figure out the number of months between two dates, the dates hypothetically lets say are between 2018-08-27 and 2018-10-10. What i want is a function based on those dates to return a difference of 3 months, 08,09,10. I have the following function, but it only seems to output 1 month;
public function getGraphMonthsCount(){
$now = '2018-08-27';
$then = '2018-10-10';
$newNow = new DateTime($now);
$newThen = new DateTime($then);
$result = $newNow->diff($newThen)->m;
return $result;
}
this return a value of 1.
this is what the diff function outputs without the ->m param
object(DateInterval)#157 (15) {
["y"]=>
int(0)
["m"]=>
int(1)
["d"]=>
int(13)
["h"]=>
int(0)
["i"]=>
int(0)
["s"]=>
int(0)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
int(44)
["special_type"]=>
int(0)
["special_amount"]=>
int(0)
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
I don't know why it's providing only 13 'd' and 1 'm', but if you look further into the obj you can see it does have the correct amount of 'days'
Is there a better way of doing this?

What i want is a function based on those dates to return a difference of 3 months
You can try something like this:
$newNow = new DateTime($now);
$newNow = $newNow->modify('first day of this month');
$newThen = new DateTime($then);
$newThen = $newThen->modify('first day of next month');
$result = $newNow->diff($newThen)->m;
Test results:
$now = '2018-08-27';
$then = '2018-10-10';
// 3
$now = '2018-08-10';
$then = '2018-08-27';
// 1

Related

I need help about getting list of days from a week number with PHP

I want to create a function to get a list of days from a week number and a year as parameters.
I've tried to write this following function, which only works when my week number is greater than 10.
public function getDaysofWeek(int $year, int $week){
// ...
$days = array();
for($d=1; $d<8; $d++) {
$days[] = date('d/m/Y', strtotime($year."W". $week .$d));
}
var_dump($days);
// ...
For the week 37 of 2019 (week of today), i got this (actually the correct result) :
array(7) { [0]=> string(10) "09/09/2019"
[1]=> string(10) "10/09/2019"
[2]=> string(10) "11/09/2019"
[3]=> string(10) "12/09/2019"
[4]=> string(10) "13/09/2019"
[5]=> string(10) "14/09/2019"
[6]=> string(10) "15/09/2019" }
But when my week number is less than 10, i got this (here, week 05 of 2019):
array(7) { [0]=> string(10) "16/12/2019"
[1]=> string(10) "23/12/2019"
[2]=> string(10) "30/12/2019"
[3]=> string(10) "01/01/1970"
[4]=> string(10) "01/01/1970"
[5]=> string(10) "01/01/1970"
[6]=> string(10) "01/01/1970" }
I can't understand why this problem is happening, does someone have an
explanation or solution ?
The problem is that as you are using an integer for the week, when you build this into the date in
$days[] = date('d/m/Y', strtotime($year."W". $week .$d));
You end up with an error as the date isn't formed correctly (2019W5), you need to make sure you have a 2 digit week.
This just formats the week to ensure it comes out as 2019W05...
$days[] = date('d/m/Y', strtotime($year."W".
sprintf("%02d", $week) .$d));

PHP Date + days

I got something like this in MyBB and I want add 5 days to date ($datetime1) with one should be stored in $nowPlus5D.
Moreover display in $leeft variable how much days, hours, minutes left. difference between (day bought + 5days ) - datenow
define("IN_MYBB", 1);
require_once "global.php";
$data_zakupu = $db->query("
SELECT timestamp
FROM ".TABLE_PREFIX."subs
WHERE txn_id <> '' AND uid=".$mybb->user['uid']." ORDER BY lid DESC LIMIT 1;
");
$dat = $db->fetch_field($data_zakupu,"timestamp");
$date_buy = date('d-m-Y H:i:s', $dat); // added h:i:s
// Total bought
echo '<br><hr>';
echo 'Bought date - ' . $date_buy;
echo '<br>';
$datetime2 = new DateTime('now');
$datetime1 = new DateTime($date_buy);
$interval = $datetime1->diff($datetime2);
$nowPlus5D = $datetime1->add(new DateInterval('P5D'));
echo '<hr><br>';
echo 'Expiration date - ' . $nowPlus5D->format('%a days, %h hours, %i, minutes');
echo '<br>';
$leeft = $nowPlus5D->diff($datetime1);
var_dump($leeft);
echo '<br>';
echo $left->format('%a days, %h hours, %i, minutes');
and I got that
Bought date - 20-12-2018 18:20:48
Expiration date - %pm 25pm1848, %06 062018000000Tue, 25 Dec 2018 18:20:48 +010048, %20, 12201200000031Europe/Warsaw48
object(DateInterval)#14 (15) { ["y"]=> int(0) ["m"]=> int(0) ["d"]=> int(0) ["h"]=> int(0) ["i"]=> int(0) ["s"]=> int(0) ["weekday"]=> int(0) ["weekday_behavior"]=> int(0) ["first_last_day_of"]=> int(0) ["invert"]=> int(0) ["days"]=> int(0) ["special_type"]=> int(0) ["special_amount"]=> int(0) ["have_weekday_relative"]=> int(0) ["have_special_relative"]=> int(0) }
Fatal error: Call to a member function format() on integer in /stackoverflow.php on line 42
Your main issue is you are confusing a couple objects. Specifically DateInterval with DateTime. Formatting is one thing that differs.
<?php
$date_buy = '2018-12-15 10:05:22';
$datetime2 = new DateTime('now');
$datetime1 = new DateTime($date_buy);
$interval = $datetime1->diff($datetime2);
$nowPlus5D = $datetime1->add(new DateInterval('P5D'));
//THIS IS A DATETIME OBJECT, NOT AN INTERVAL! NOTE FORMAT `Y-m-d H:i:s`
echo 'Expiration date - ' . $nowPlus5D->format('d \d\a\y\s, H \h\o\u\r\s, i \m\i\n\u\t\e\s');
var_dump($nowPlus5D);
var_dump($datetime1);
// ^ Notice those are the same? A result of `$nowPlus5D = $datetime1->add(new DateInterval('P5D'));`
// and Intervals then are of course zeros...
$left = $nowPlus5D->diff($datetime1);
echo '<br>';
echo $left->format('%a days, %h hours, %i, minutes');
// could do this...
$left = $nowPlus5D->diff(new \DateTime);
echo $left->format('%a days, %h hours, %i, minutes');
Anyway, think your main confusion was over the two object types. Imagine you can take it from here.

Increment the day value from current day

For example, in my case, i already has this value of array.....
array(1) {
[1]=>
array(1120) {
["2006-02-25"]=>
array(1) {
[0]=>
int(33)
}
["2006-02-20"]=>
array(1) {
[0]=>
int(38)
}
["2006-02-28"]=>
array(1) {
[0]=>
int(46)
}
that result I've got this code
$explodeEndDate = explode(" ",$adEndDate);
$explodeStartDate = explode(" ", $adStartDate);
$StartDate = $explodeStartDate[0];
$NewStartDate = strtotime("$explodeStartDate[0]");
$NewEndDate = strtotime("$explodeEndDate[0]");
$timeDiff = abs($NewEndDate - $NewStartDate);
// 86400 seconds in one day
$NumberDays = $timeDiff/86400;
//convert into int
$NumberDays = intval($NumberDays);
if(array_key_exists($NumberDays, $array[$itemType]) == false){
$array[$itemType][$StartDate] =[$NumberDays];
}
}
what I wanted to achieve is, in the "$StartDate" value which is for example ["2006-02-28"] , I wanted to plus it with the value of it. If we referring back to the figure above for example is
["2006-02-25"]=>
array(1) {
[0]=>
int(33)
so 2006-02-25 is the plus by 33 and the result is 2006-04-01. and after that, i wanted to make the date within that range
If you want to add date so here you go:
Months:
<?php
$date = date('Y-m-d', strtotime("+33 months", strtotime('2006-02-25')));
var_dump($date)
?>
Demo.
Days:
<?php
$date = date('Y-m-d', strtotime("+33 days", strtotime('2006-02-25')));
var_dump($date)
?>
Demo

How to account for GMT offset when converting date timestamp to relative time

I have timestamps in the following format: 2013-10-19 18:47:30
I am using this to convert to relative (x minutes, hours, days ago) time but it returns nothing for the most recent users, I assume because my system time is GMT -3 hours so it is interpreting it as a time in the future. If that is the case, how can I take the users GMT offset into account in the result?
$time = strtotime('2013-04-28 17:25:43');
echo 'event happened '.humanTiming($time).' ago';
function humanTiming ($time)
{
$time = time() - $time; // to get the time since that moment
$tokens = array (
31536000 => 'year',
2592000 => 'month',
604800 => 'week',
86400 => 'day',
3600 => 'hour',
60 => 'minute',
1 => 'second'
);
foreach ($tokens as $unit => $text) {
if ($time < $unit) continue;
$numberOfUnits = floor($time / $unit);
return $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':'');
}
}
$eventTimeString = '2013-04-28 17:25:43';
$timezone = new DateTimeZone("Etc/GMT+3"); // Same as GMT-3, here you should use the users's timezone
$eventTime = new DateTime($eventTimeString , $timezone);
$diff = $eventTime->diff(new DateTime()); // Compare with
The $diff variable now has number of seconds, months, days etc. since $eventTime
object(DateInterval)#4 (15) {
["y"]=>
int(0)
["m"]=>
int(7)
["d"]=>
int(18)
["h"]=>
int(17)
["i"]=>
int(35)
["s"]=>
int(38)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
int(232)
["special_type"]=>
int(0)
["special_amount"]=>
int(0)
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
Here is a rewrite of your method that will be more reliable/accurate:
function humanTiming($time){
$timezone=new DateTimeZone("Australia/Melbourne"); // declare whatever your user's timezone is
$time=new DateTime($time,$timezone); // input your datetime
$now=new DateTime("now",$timezone); // get current datetime
if($time>$now){
return "event hasn't happened yet";
}elseif($time==$now){
return "event is happening";
}
$diff=(array)$time->diff($now); // get time between now and $time, 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 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
}
}
return "event happened $readable ago";
}
echo humanTiming('2013-04-28 17:25:43');
// event happened 3 years, 10 months, 23 days, 8 hours, 33 minutes, 59 seconds ago

Months from 2 unixtimestamps

I have 2 timestamps from 2 dates: 01/2012 and 02/2013. The difference between these timestamps is 31795200. The function i've used is:
function unixTimeStampInMonths($timestamp){
$elapsed_minutes = ($timestamp / 60);
$elapsed_hours = ($elapsed_minutes / 60);
$elapsed_days = ($elapsed_hours / 24);
$elapsed_months = floor($elapsed_days / 30);
return $elapsed_months;
}
But there is a problem, the months are rounded to 30 days. What's the best way of calculating the months difference between them?
LE:
The solution suggested by a friend is:
// arguments format: 05/2010
function monthDifferenceBetween2Dates($first, $second){
$expl1 = explode('/', $first);
$expl2 = explode('/', $second);
$months_in_years = ($expl2[1] - $expl1[1] - 1) * 12;
$first_months = 12 - $expl1[0];
$second_months = $expl2[0];
return $months_in_years + $first_months + $second_months;
}
i'm gonna use this. thanks #nickb
Use PHP's DateTime class instead of UNIX timestamps:
$start = DateTime::createFromFormat( 'm/d/Y', '01/01/2012');
$end = DateTime::createFromFormat( 'm/d/Y', '02/01/2013');
$diff = $start->diff( $end);
var_dump( $diff);
Will output:
object(DateInterval)#3 (8) {
["y"]=>
int(1)
["m"]=>
int(1)
["d"]=>
int(0)
["h"]=>
int(0)
["i"]=>
int(0)
["s"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
int(397)
}
So, to calculate total months, we can do:
$months = $diff->y * 12 + $diff->m;
Which will print 13. Demo

Categories