PHP giving fatal error on comparing dates - php

I have one date in database, and I want to compare it with the current date. So I write the following function:
$today = new DateTime();
$today_date = $current_date->format('Y-m-d H:i:s');
function do_diifernce($date_1, $date_2) {
$my_date = $date_1;
$createDate = new DateTime($my_date);
$strip = $createDate->format('Y-m-d');
$difference = $date_2->diff($createDate, true);
$difference->total_difference = $difference->y . "." . $difference->m;
return $difference;
}
$comparison = do_diifernce($databse_date, $today_date);
So
$databse_date = 2019-06-01 00:00:00.000000
$today_date = 2019-05-06 10:48:01
But I can't print the value of $comparison.
PHP Fatal error: Uncaught Error: Call to a member function diff() on string
How can I solve it?

You pass in $today_date to do_diifernce(), which is a string (as you have formatted it with format()). You can either pass $today in (which is an object), or include a condition that checks if its an object or not.
function do_difference($date_1, $date_2) {
// Check if the arguments were DateTime objects - if not, instantiate them as that
if (!($date_1 instanceof DateTime)) {
$date_1 = new DateTime($date_1);
}
if (!($date_2 instanceof DateTime)) {
$date_2 = new DateTime($date_2);
}
// Compare the difference and return the Y and m properties
$difference = $date_2->diff($date_1);
$difference->total = $difference->y . "." . $difference->m;
return $difference;
}
$today = new DateTime();
$comparison = do_difference($databse_date, $today);

You were playing date 2 as string which should be treated as datetime object to get the difference between two datetime objects.
function do_diifernce($date_1, $date_2)
{
$createDate1 = new DateTime($date_1);
$createDate2 = new DateTime($date_2);
$difference = $createDate2->diff($createDate1);
$sign = ($createDate1 < $createDate2 ? '-':'+');
$difference->total_difference = $difference->format("%r%a");
return $difference;
}
$databse_date = "2019-05-01 00:00:00";
$today_date = "2019-05-06 10:48:01";
$comparison = do_diifernce($databse_date, $today_date);
print_r($comparison);die;
Here is official doc.
You check that array as there is no difference of year and month as both dates belongs to same month and year so its coming 0.0

You got an error here: $difference = $date_2->diff($createDate, true);. AFAIK, the diff() function is deprecated after PHP 5.3.
If you want to calculate the difference between two dates, you can use date_diff as follows.
<?php
$date1 = date_create("2000-04-01");
$date2 = date_create("2019-04-06");
$diff = date_diff($date1, $date2);
?>

It throws an error, because you call format on date2, which returns a string, no DateTime object.
Remove the call to format, then your comparison should work.
All you have to do, is to replace the last line with the following:
$comparison=do_diifernce($databse_date, $today);

Related

PHP tell if a timestamp lies anywhere in the previousDay

Currently I am doing this to take the difference in days for two timestamps
function getDifferenceInDaysTillNow($timestamp) {
try {
$streakLastAwardedAtDateTime = DateTime::createFromFormat('U', $timestamp);
$streakLastAwardedAtDateTime->setTimezone(new DateTimeZone('Asia/Kolkata'));
$nowDateTime = new DateTime();
$nowDateTime->setTimezone(new DateTimeZone('Asia/Kolkata'));
$diff = $streakLastAwardedAtDateTime->diff($nowDateTime);
return $diff->format('%a');
}catch(Exception $e) {
throw new Exception($e);
}
}
PHP Fiddle for the above approach
This gives a difference of 1 (1day) if the timestamps have 24hours difference.
But I just want to know if a timestamp lies in the previous day.
For example it can just be a difference of 2hours or 6hours doesn't matter.
I want to return a Boolean (true or false) telling if the provided timestamp lies in the previousDay or not.
Any help is appriciated.
Thank you.
For this, you can simply check if the y or m property is greater than 0. If yes, return false. If the d difference is greater than 1, then also we need to return false since the difference is more than 1 day.
Additional check is to make sure the timestamp isn't the same day as today.
<?php
function getDifferenceInDaysTillNow($timestamp) {
try {
$streakLastAwardedAtDateTime = DateTime::createFromFormat('U', $timestamp);
$streakLastAwardedAtDateTime->setTimezone(new DateTimeZone('Asia/Kolkata'));
$nowDateTime = new DateTime();
$nowDateTime->setTimezone(new DateTimeZone('Asia/Kolkata'));
// check difference between lastStreakAward and now
$diff = $streakLastAwardedAtDateTime->diff($nowDateTime);
if($diff->y > 0 || $diff-> m > 0 || $diff->d > 1) return false;
return date("Y-m-d", $timestamp) != date("Y-m-d");
}catch(Exception $e) {
throw new Exception($e);
}
}
$timestamp = 1670211229; // Monday, 5 December 2022 09:03:49 GMT+05:30
var_dump(getDifferenceInDaysTillNow($timestamp));
Online Demo
A DateTime object is created from the timestamp, then converted to the correct time zone with setTimeZone and the time is set to 00:00. Then it can be compared directly with 'yesterday'.
$timestamp = 1670211229; //5 December 2022 09:03:49
$timeZone = new DateTimeZone('Asia/Kolkata');
$date = date_create('#'.$timestamp)
->setTimeZone($timeZone)
->setTime(0,0,0,0)
;
$isTimeStampFromYesterday = ($date == date_create('yesterday',$timeZone));

Adding 12 months to February 29

I want to add 12 months to my date. My start date is 02/29/2020 and I want to add 12 months to this.
Code:
$startdate = '02/29/2020';
date('m/d/Y', strtotime('+12 months', strtotime($startdate)));
Output:
03/01/2021
I used this code to add 12 months but the output is 03/01/2021, when the real output should be 02/28/2020.
Have a look!
function add_months($months, DateTime $dateObject)
{
$next = new DateTime($dateObject->format('Y-m-d'));
$next->modify('last day of +'.$months.' month');
if($dateObject->format('d') > $next->format('d')) {
return $dateObject->diff($next);
} else {
return new DateInterval('P'.$months.'M');
}
}
function getCalculatedDate($d1, $months)
{
$date = new DateTime($d1);
// call second function to add the months
$newDate = $date->add(add_months($months, $date));
//formats final date to m/d/Y form
$dateReturned = $newDate->format('m/d/Y');
return $dateReturned;
}
An example would be:-
$startDate = '02/29/2020';
$nMonths = 12; // choose how many months you want to add
$finalDate = getCalculatedDate($startDate, $nMonths); // output: 02/28/2021
This way you will get the output of 02/28/2021
$startdate = '02/29/2020';
$date = date('m/d/Y', strtotime($startdate . '+365 days'));
using DateTime and DateInterval objects leads to 03/01/2021
$date = new \DateTime('02/29/2020');
$date->add(new \DateInterval('P12M'));
echo $date->format('m/d/Y');
for me 03/01/2021 is not always a bad answer

A non well formed numeric value encountered in ...on Line 171

We keep getting the above error. Have tried adding a $start above 171 but same result. Here is the code :
/**
* Get all of the months since a certain date
*/
public static function getMonthsSinceDate($start) {
$key_month = date('MY', $start); (note this is Line 171)
$key = 'months_since_' . $key_month;
$months = CodonCache::read($key);
if ($months === false) {
if (!is_numeric($start)) {
$start = strtotime($start);
}
$end = date('Ym');
do {
# Get the months
$month = date('M Y', $start);
$months[$month] = $start; # Set the timestamp
$start = strtotime('+1 month +1 day', strtotime($month));
# Convert to YYYYMM to compare
$check = intval(date('Ym', $start));
} while ($check <= $end);
CodonCache::write($key, $months, 'long');
}
return $months;
}
/**
Wherever you are calling the function getMonthsSinceDate(); you are accidentally passing it something non numeric. It could be subtle like a number wrapped in quotes which would become a string, i.e
getMonthsSinceDate('111111')
PHP's date() expects to be given a date in an integer UNIX timestamp. If you are trying to pass a human-readable date as a string it will throw an error.
If you are, convert it to a timestamp using strtotime(), like this:
$start = strtotime( $start );

how to get Random date between 2 date values using php? [duplicate]

I am coding an application where i need to assign random date between two fixed timestamps
how i can achieve this using php i've searched first but only found the answer for Java not php
for example :
$string = randomdate(1262055681,1262055681);
PHP has the rand() function:
$int= rand(1262055681,1262055681);
It also has mt_rand(), which is generally purported to have better randomness in the results:
$int= mt_rand(1262055681,1262055681);
To turn a timestamp into a string, you can use date(), ie:
$string = date("Y-m-d H:i:s",$int);
If given dates are in date time format then use this easiest way of doing this is to convert both numbers to timestamps, then set these as the minimum and maximum bounds on a random number generator.
A quick PHP example would be:
// Find a randomDate between $start_date and $end_date
function randomDate($start_date, $end_date)
{
// Convert to timetamps
$min = strtotime($start_date);
$max = strtotime($end_date);
// Generate random number using above bounds
$val = rand($min, $max);
// Convert back to desired date format
return date('Y-m-d H:i:s', $val);
}
This function makes use of strtotime() as suggested by zombat to convert a datetime description into a Unix timestamp, and date() to make a valid date out of the random timestamp which has been generated.
Another solution using PHP DateTime
$start and $end are DateTime objects and we convert into Timestamp. Then we use mt_rand method to get a random Timestamp between them. Finally we recreate a DateTime object.
function randomDateInRange(DateTime $start, DateTime $end) {
$randomTimestamp = mt_rand($start->getTimestamp(), $end->getTimestamp());
$randomDate = new DateTime();
$randomDate->setTimestamp($randomTimestamp);
return $randomDate;
}
You can just use a random number to determine a random date. Get a random number between 0 and number of days between the dates. Then just add that number to the first date.
For example, to get a date a random numbers days between now and 30 days out.
echo date('Y-m-d', strtotime( '+'.mt_rand(0,30).' days'));
Here's another example:
$datestart = strtotime('2009-12-10');//you can change it to your timestamp;
$dateend = strtotime('2009-12-31');//you can change it to your timestamp;
$daystep = 86400;
$datebetween = abs(($dateend - $datestart) / $daystep);
$randomday = rand(0, $datebetween);
echo "\$randomday: $randomday\n";
echo date("Y-m-d", $datestart + ($randomday * $daystep)) . "\n";
The best way :
$timestamp = rand( strtotime("Jan 01 2015"), strtotime("Nov 01 2016") );
$random_Date = date("d.m.Y", $timestamp );
By using carbon and php rand between two dates
$startDate = Carbon::now();
$endDate = Carbon::now()->subDays(7);
$randomDate = Carbon::createFromTimestamp(rand($endDate->timestamp, $startDate->timestamp))->format('Y-m-d');
OR
$randomDate = Carbon::now()->subDays(rand(0, 7))->format('Y-m-d');
An other solution where we can use date_format :
/**
* Method to generate random date between two dates
* #param $sStartDate
* #param $sEndDate
* #param string $sFormat
* #return bool|string
*/
function randomDate($sStartDate, $sEndDate, $sFormat = 'Y-m-d H:i:s') {
// Convert the supplied date to timestamp
$fMin = strtotime($sStartDate);
$fMax = strtotime($sEndDate);
// Generate a random number from the start and end dates
$fVal = mt_rand($fMin, $fMax);
// Convert back to the specified date format
return date($sFormat, $fVal);
}
Source : https://gist.github.com/samcrosoft/6550473
You could use for example :
$date_random = randomDate('2018-07-09 00:00:00','2018-08-27 00:00:00');
The amount of strtotime in here is WAY too high.
For anyone whose interests span before 1971 and after 2038, here's a modern, flexible solution:
function random_date_in_range( $date1, $date2 ){
if (!is_a($date1, 'DateTime')) {
$date1 = new DateTime( (ctype_digit((string)$date1) ? '#' : '') . $date1);
$date2 = new DateTime( (ctype_digit((string)$date2) ? '#' : '') . $date2);
}
$random_u = random_int($date1->format('U'), $date2->format('U'));
$random_date = new DateTime();
$random_date->setTimestamp($random_u);
return $random_date->format('Y-m-d') .'<br>';
}
Call it any number of ways ...
// timestamps
echo random_date_in_range(157766400,1489686923);
// any date string
echo random_date_in_range('1492-01-01','2050-01-01');
// English textual parsing
echo random_date_in_range('last Sunday','now');
// DateTime object
$date1 = new DateTime('1000 years ago');
$date2 = new DateTime('now + 10 months');
echo random_date_in_range($date1, $date2);
As is, the function requires date1 <= date2.
i had a same situation before and none of the above answers fix my problem so i
Came with new function
function randomDate($startDate, $endDate, $count = 1 ,$dateFormat = 'Y-m-d H:i:s')
{
//inspired by
// https://gist.github.com/samcrosoft/6550473
// Convert the supplied date to timestamp
$minDateString = strtotime($startDate);
$maxDateString = strtotime($endDate);
if ($minDateString > $maxDateString)
{
throw new Exception("From Date must be lesser than to date", 1);
}
for ($ctrlVarb = 1; $ctrlVarb <= $count; $ctrlVarb++)
{
$randomDate[] = mt_rand($minDateString, $maxDateString);
}
if (sizeof($randomDate) == 1)
{
$randomDate = date($dateFormat, $randomDate[0]);
return $randomDate;
}elseif (sizeof($randomDate) > 1)
{
foreach ($randomDate as $randomDateKey => $randomDateValue)
{
$randomDatearray[] = date($dateFormat, $randomDateValue);
}
//return $randomDatearray;
return array_values(array_unique($randomDatearray));
}
}
Now the testing Part(Data may change while testing )
$fromDate = '2012-04-02';
$toDate = '2018-07-02';
print_r(randomDate($fromDate,$toDate,1));
result will be
2016-01-25 11:43:22
print_r(randomDate($fromDate,$toDate,1));
array:10 [▼
0 => "2015-08-24 18:38:26"
1 => "2018-01-13 21:12:59"
2 => "2018-06-22 00:18:40"
3 => "2016-09-14 02:38:04"
4 => "2016-03-29 17:51:30"
5 => "2018-03-30 07:28:48"
6 => "2018-06-13 17:57:47"
7 => "2017-09-24 16:00:40"
8 => "2016-12-29 17:32:33"
9 => "2013-09-05 02:56:14"
]
But after the few tests i was thinking about what if the inputs be like
$fromDate ='2018-07-02 09:20:39';
$toDate = '2018-07-02 10:20:39';
So the duplicates may occur while generating the large number of dates such as 10,000
so i have added array_unique and this will return only the non duplicates
if you use laravel then it's for you.
\Carbon\Carbon::now()->subDays(rand(0, 90))->format('Y-m-d');
Simplest of all, this small function works for me
I wrote it in a helper class datetime as a static method
/**
* Return date between two dates
*
* #param String $startDate
* #param String $endDate
* #return String
*
* #author Kuldeep Dangi <kuldeepamy#gmail.com>
*/
public static function getRandomDateTime($startDate, $endDate)
{
$randomTime = mt_rand(strtotime($startDate), strtotime($endDate));
return date(self::DATETIME_FORMAT_MYSQL, $randomTime);
}
Pretty good question; needed to generate some random sample data for an app.
You could use the following function with optional arguments to generate random dates:
function randomDate($startDate, $endDate, $format = "Y-M-d H:i:s", $timezone = "gmt", $mode = "debug")
{
return $result;
}
sample input:
echo 'UTC: ' . randomDate("1942-01-19", "2016-06-03", "Y-M-d H:i:s", "utc") . '<br>';
//1942-Jan-19 07:00:00
echo 'GMT: ' . randomDate("1942-01-19", "2016-06-03", "Y/M/d H:i A", "gmt") . '<br>';
//1942/Jan/19 00:00 AM
echo 'France: ' . randomDate("1942-01-19", "2016-06-03", "Y F", "Europe/Paris") . '<br>';
//1942 January
echo 'UTC - 4 offset time only: ' . randomDate("1942-01-19", "2016-06-03", "H:i:s", -4) . '<br>';
//20:00:00
echo 'GMT +2 offset: ' . randomDate("1942-01-19", "2016-06-03", "Y-M-d H:i:s", 2) . '<br>';
//1942-Jan-19 02:00:00
echo 'No Options: ' . randomDate("1942-01-19", "2016-06-03") . '<br>';
//1942-Jan-19 00:00:00
readers requirements could vary from app to another, in general hope this function is a handy tool where you need to generate some random dates/ sample data for your application.
Please note that the function initially in debug mode, so change it to $mood="" other than debug in production .
The function accepts:
start date
end date
format: any php accepted format for date or time
timezone: name or offset number
mode: debug, epoch, verbose epoch or verbose
the output in not debug mode is random number according to optional specifications.
tested with PHP 7.x
// Find a randomDate between $startDate and $endDate
function randomDate($startDate, $endDate)
{
// Convert to timetamps
$min = strtotime($startDate);
$max = strtotime($endDate);
// Generate random number using above bounds
$val = rand($min, $max);
// Convert back to date
return Carbon::createFromTimestamp($val);
}
dd($this->randomDate('2014-12-10', Carbon::now()->toString()));
Using carbon
$yeni_tarih = date('Y-m-d', strtotime( '+'.mt_rand(-90,0).' days'))." ".date('H', strtotime( '+'.mt_rand(0,24).' hours')).":".rand(1,59).":".rand(1,59);
Full random date and time

Comparing in PHP if today is between 2 different dates if so then print a value

I am new in php.
I have 2 dates that I am getting from 2 drupal fields and each field is saved in database with it´s own date format so the formats:
$old_format_starts -> has this date format: date('Y-m-d H:i:s'); and
$old_format_ends -> has this date format: date('jS F Y H:i:s');
So I am using the following code:
$old_format_starts = $entity->field_video_available_d[LANGUAGE_NONE][0]['value'];
$old_format_ends = $entity->field_video_until[LANGUAGE_NONE][0]['value'];
After that, I am converting those date information to this date format: date('Y-m-d'); like this:
$starts = date("Y-m-d", strtotime($old_format_starts));
$ends = date('Y-m-d', strtotime($old_format_ends));
In order later I can use that information for comparing if today is between the dates $starts and &ends, and if today is between those dates then I will print something.
So here is the total code that I am using, but I have problems with the date formats... something I am doing wrong because the page is just taking long time in load the page and in the end it does not load.... The problem is coming when I am using the WHILE bucle, because I tried just using the code before the WHILE and the page loads in a normal way. So I dont know If I am using wrong the WHILE BUCLE or the strtotime function or dates format...?
<?php
$old_format_starts = $entity->field_video_available_d[LANGUAGE_NONE][0]['value'];
$old_format_ends = $entity->field_video_until[LANGUAGE_NONE][0]['value'];
$starts = date("Y-m-d", strtotime($old_format_starts));
$ends = date('Y-m-d', strtotime($old_format_ends));
$to= date("Y-m-d", strtotime($to));
$i = date("Y-m-d", strtotime($starts));
while ($i <= $ends) {
if ($i==$to) {
print date('Y-m-d', strtotime($i));
break;
}
$i=date("Y-m-d", strtotime('+1 day', $i));
}
?>
I really have tried already many ways.. but without success.... here is the same code but using the FOR bucle... and also without success..
<?php
$old_format_starts = $entity->field_video_available_d[LANGUAGE_NONE][0]['value'];
$old_format_ends = $entity->field_video_until[LANGUAGE_NONE][0]['value'];
$starts = date("Y-m-d", strtotime($old_format_starts));
$ends = date('Y-m-d', strtotime($old_format_ends));
$to= date("Y-m-d");
for ($i = $starts; $i <= $ends; $i++) {
if ($i==$to) {
print $i;
break;
}
}
?>
PLEASE HELP!!!! Any sugestion is welcome!!! There has to be a solution... Something I am doing wrong in the bucles (While) or (FOR) because the page is not loading!!!
Thank you!!! :)
If you compared the strtotime() values directly, it would work. strtotime() returns simple integers and >/</= type comparisons will work as expected. In your code, you're converting them to strings using date(), in a least-significant-value-first ordering, so your comparisons won't work as expected.
Comparing the dates using strtotime():
$start = strtotime($old_format_starts);
$end = strtotime($old_format_ends);
$today = time();
if ($today > $start && $today < $end) {
// code
}
Comparing the dates using the DateTime class:
$start = new DateTime($old_format_starts);
$end = new DateTime($old_format_ends);
if ($today > $start && $today < $end) {
// code
}
Once the comparison is over, you can format the date strings using date() function (if you're using strtotime()) or the format() method (if you're using DateTime class).
The while loop is not necessary here
I suggest the use of the DateTime native class like this :
$old_format_starts = $entity->field_video_available_d[LANGUAGE_NONE][0]['value'];
$old_format_ends = $entity->field_video_until[LANGUAGE_NONE][0]['value'];
$starts = DateTime::createFromFormat('Y-m-d H:i:s', $old_format_starts);
$ends = DateTime::createFromFormat('jS F Y H:i:s', $old_format_ends);
$today = new DateTime() ;
if(($today > $start) && ($today < $end)){
//Do your thing
}

Categories