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

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

Related

Display the item nearest to current time

I have a list of dates/times items in PHP array that are formatted like this:
2019-03-19 00:00:00
2019-03-19 02:30:00
2019-03-19 05:00:00
2019-03-19 14:30:00
2019-03-19 23:59:59
etc.
I'm sure this is easy, I just can't wrap my head around it. What equation do I use to display the item that is closest to the current time without going over.
So if current time is 22:00:00, I would want to display item 14:30:00, rather than 23:59:59.
Since your times are in Y-m-d H:i:s you can just compare them as strings and use a simple foreach loop to get your result:
$dates = array('2019-03-19 00:00:00',
'2019-03-19 02:30:00',
'2019-03-19 05:00:00',
'2019-03-19 14:30:00',
'2019-03-19 23:59:59');
$now = date('Y-m-d H:i:s');
$latest = '';
// add sort($dates) here if they are not already sorted.
foreach ($dates as $date) {
if ($date > $now) break;
$latest = $date;
}
echo $latest;
Demo on 3v4l.org
Note this code assumes your dates are already sorted, if not, add sort($dates) before the foreach loop.
First of all convert all the Dates to this format
$changed_date_1 = date('YmdHis', strtotime($orignaldate_1));
$changed_date_2 = date('YmdHis', strtotime($orignaldate_2));
$changed_date_3 = date('YmdHis', strtotime($orignaldate)_3);
so 2019-03-19 00:00:00 will become 20190319000000, and so on, now they can be compared easily.
than run a foreach loop in which iterate through all these date
$closestdate= date('Y-m-d H:i:s');//intaily set it to current date
$closest_difference= 99999999999999999;//intaily set a big value, more than 15 digits
foreach($datesArray as $item){
$difference = $item - date('YmdHis');
if($difference < $closest_difference){
$closes_difference = $difference;
$closestdate = $item;//this item is closest one. in next iteration this may change
}
}
echo $Closesdate;
/**
* Gets the nearest moment of the same day as $today.
*
* #param string[] $dates - A list of dates (needed format: "Y-m-d H:i:s")
* #param string|null $today - The date used for comparaison. (default is current date)
* #return string|bool - Returns the nearest date, or false.
*/
function getNearestDate(array $dates, ?string $today = null) {
if (!$today) {
$today = date('Y-m-d H:i:s');
}
$fnDT = function($d) {
return DateTime::createFromFormat('Y-m-d H:i:s', $d);
};
usort($dates, function($a, $b) use ($fnDT, $today) {
$da = abs($fnDT($today)->getTimestamp() - $fnDT($a)->getTimestamp());
$db = abs($fnDT($today)->getTimestamp() - $fnDT($b)->getTimestamp());
return $da - $db;
});
$nearest = $dates[0];
if ($fnDT($nearest)->format('Y-m-d') !== $fnDT($today)->format('Y-m-d')) {
print_r('No date of the same day.');
return false;
}
return $nearest;
}
Test it on 3v4l.org

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 );

Random time and date between 2 date values

I'm trying to write a php script (or line of code) to echo a random time and date between 2 dates, eg
2012-12-24 13:03
which would be between my chosen dates of 1st October 2012 and 1st Jan 2013.
Any ideas how best to do this? Thanks in advance.
Easy :) Just choose 2 random dates, convert to EPOCH, and random between these 2 values :)
EPOCH - The time since 1/1/1970, in seconds.
You can use the strtotime() function to make date-strings turn into epoch time, and the date() function to make it the other way back.
function rand_date($min_date, $max_date) {
/* Gets 2 dates as string, earlier and later date.
Returns date in between them.
*/
$min_epoch = strtotime($min_date);
$max_epoch = strtotime($max_date);
$rand_epoch = rand($min_epoch, $max_epoch);
return date('Y-m-d H:i:s', $rand_epoch);
}
You probably want to define a resolution, for example one minute, or three minutes or 15 seconds or one and a half day or what not. The randomness should be applied on the whole period, I've choosen one minute here for exemplary purposes (there are 132480 minutes in your period).
$start = new Datetime('1st October 2012');
$end = new Datetime('1st Jan 2013');
$interval = new DateInterval('PT1M'); // Resolution: 1 Minute
$period = new DatePeriod($start, $interval, $end);
$random = new RandomIterator($period);
list($result) = iterator_to_array($random, false) ? : [null];
This for example gives:
class DateTime#7 (3) {
public $date =>
string(19) "2012-10-16 02:06:00"
public $timezone_type =>
int(3)
public $timezone =>
string(13) "Europe/Berlin"
}
You can find the RandomIterator here. Without it, it will take a little longer (ca. 1.5 the number of iterations compared to the example above) using:
$count = iterator_count($period);
$random = rand(1, $count);
$limited = new LimitIterator(new IteratorIterator($period), $random - 1, 1);
$limited->rewind();
$result = $limited->current();
I also tried with seconds, but that would take quite long. You probably want first to find a random day (92 days), and then some random time in it.
Also I've run some tests and I could not find any benefit in using DatePeriod so far as long as you're on common resolutions like seconds:
$start = new Datetime('1st October 2012');
$end = new Datetime('1st Jan 2013');
$random = new DateTime('#' . mt_rand($start->getTimestamp(), $end->getTimestamp()));
or minutes:
/**
* #param DateTime $start
* #param DateTime $end
* #param int|DateInterval $resolution in Seconds or as DateInterval
* #return DateTime
*/
$randomTime = function (DateTime $start, DateTime $end, $resolution = 1) {
if ($resolution instanceof DateInterval) {
$interval = $resolution;
$resolution = ($interval->m * 2.62974e6 + $interval->d) * 86400 + $interval->h * 60 + $interval->s;
}
$startValue = floor($start->getTimestamp() / $resolution);
$endValue = ceil($end->getTimestamp() / $resolution);
$random = mt_rand($startValue, $endValue) * $resolution;
return new DateTime('#' . $random);
};
$random = $randomTime($start, $end, 60);
Assuming you want to include October 1st, but not include Jan 1st...
$start = strtotime("2012-10-01 00:00:00");
$end = strtotime("2012-12-31 23:59:59");
$randomDate = date("Y-m-d H:i:s", rand($start, $end));
echo $randomDate;
so crazy it just may worK
function randomDate($start_date, $end_date)
{
//make timetamps
$min = strtotime($start_date);
$max = strtotime($end_date);
//random date
$rand_date = rand($min, $max);
//format it
return date('Y-m-d H:i:s', $rand_date);
}
Here's some code to accomplish this:
$randDate=date('Y-m-d', mt_rand(strtotime('2012-10-01'), strtotime('2013-01-01')));
Okay, here's something
$date_start = strtotime('1 October 2012');
$date_end = strtotime('1 January 2013');
$rand_date = rand($date_start, $date_end);
echo(date('d.m.Y H:i', $rand_date));

Changing date and time between timezones

I have been trying to convert between timezones a given date and time.
Code speaks more than words, so here it is:
/**
* Returns the date and time in the new timezone.
*
* #param string $datetime:
* the date and time to change between timezones
* #param string $input_tz:
* the input timezone
* #param string $output_tz:
* the output timezone
* #return string The new date and time
*/
public function changeDateTime($datetime, $input_tz, $output_tz) {
if($input_tz == $output_tz) return $datetime;
/*
* We calculate the hour and minute offset from GMT
*/
date_default_timezone_set($output_tz);
$out_dst = date('I', $datetime) ? 1 : 0;
$out_hour_offset = intval(substr(date('O', $datetime), 1, 3)) + $out_dst;
$out_minute_offset = intval(substr(date('O', $datetime)), - 2);
date_default_timezone_set($input_tz);
$in_dst = date('I', $datetime) ? 1 : 0;
$in_hour_offset = intval(substr(date('O', $datetime), 1, 3)) + $in_dst;
$in_minute_offset = intval(substr(date('O', $datetime)), - 2);
/*
* We subtract hour and minute offsets to come up with total difference
*/
$hour_offset = $out_hour_offset - $in_hour_offset;
$minute_offset = $out_minute_offset - $in_minute_offset;
/*
* Now we must take care of changing the day/month/year if necessary, as
* well as the hour/minute for $datetime, and return that value.
*/
$date = new DateTime($datetime);
if($hour_offset > 0) {
$date->add(date_interval_create_from_date_string($hour_offset . ' hours'));
if($minute_offset > 0) $date->add(date_interval_create_from_date_string($minute_offset . ' minutes'));
} else if($hour_offset < 0) {
$date->sub(date_interval_create_from_date_string($hour_offset . ' hours'));
if($minute_offset > 0) $date->sub(date_interval_create_from_date_string($minute_offset . ' minutes'));
}
return $date->format('Y-m-d H:i:s');
}
However, it does not seem to work well. This is the code I am running to test whether it works or not:
$newdatetime = $gato->changeDateTime("2012-08-10 11:33:33", 'Europe/London', 'Europe/Madrid');
echo $newdatetime;
And this is my expected output: 2012-08-10 12:33:33
But this is my actual output: 2012-08-10 11:33:33, which means there is no change in time.
OK, try this instead:
function changeDateTime($datetime, $input_tz, $output_tz) {
// Return original string if in and out are the same
if($input_tz == $output_tz) {
return $datetime;
}
// Save current timezone setting and set to input timezone
$original_tz = date_default_timezone_get();
date_default_timezone_set($input_tz);
// Get Unix timestamp based on input time zone
$time = strtotime($datetime);
// Start working in output timezone
date_default_timezone_set($output_tz);
// Calculate result
$result = date('Y-m-d H:i:s', $time);
// Set timezone correct again
date_default_timezone_set($original_tz);
// Return result
return $result;
}
$out = changeDateTime("2012-08-10 11:33:33", 'Europe/London', 'Europe/Madrid');
var_dump($out);
Rather than messing about doing all that complicated maths, just let PHP do all the hard work for you ;-)
See it working
If your stumbling on this, it can be done cleaner now with the DateTime Object.
public function convertTZ($dateTimeString, $inputTZ, $outputTZ){
$datetime =
\DateTime::createFromFormat('Y-m-d H:i:s', //input format - iso8601
$dateTimeString,
new \DateTimeZone($inputTZ))
->setTimezone(new \DateTimeZone('$outputTZ'));
//outputs a string, if you want the dateTime obj - remove ->format
return $datetime->format('Y-m-d H:i:s'); //output format
}

Format date whose timestamp exceeds the int limit

So, we have the following code:
date("Y-m-d",time()+60*365*24*60*60);
The ideea is that I have to make a prognosis and I have the result in number of days which I have to add to the current date. The prognosis is for the year 2060 or past it...in an 64bit environment that works, but on 32bit not so much :)
any ideeas?
10x.
LE:
Ok so I've tried :
$date = new DateTime();
// for PHP 5.3
$date->add(new DateInterval('P20000D'));
// for PHP 5.2
$date->modify('+20000day');
echo $date->format('Y-m-d') . "\n";
and it works
this is working on my 32bit system:
$date = new DateTime("2071-05-26");
echo $date->format('Y-m-d H:i:s');
//i saw this in this question
See this:
http://www.infernodevelopment.com/forum/Thread-Solution-2038-PHP-Date-Bug-Y2-038K-UNIX-TIMESTAMP-BUG
<?php
// Specified date/time in your computer's time zone.
$date = new DateTime('9999-04-05');
echo $date->format('Y-M-j') ."";
// Specified date/time in the specified time zone.
$date = new DateTime('2040-09-08', new DateTimeZone('America/New_York'));
echo $date->format('n / j / Y') . "";
// INPUT UNIX TIMESTAMP as float or bigint from database
// Notice the result is in the UTC time zone.
$r = mysql_query("SELECT date FROM test_table");
$obj = mysql_fetch_object($r);
$date = new DateTime('#'.$obj->date); // a bigint(8) or FLOAT
echo $date->format('Y-m-d H:i: sP') ."";
// OR a constant greater than 2038:
$date = new DateTime('#2894354000'); // 2061-09-19
echo $date->format('Y-m-d H:i: sP') ."";
?>
If you are adding full years/days/months, I suppose you could use simple arithmetic on them individually and then use checkdate() (it claims to work up to year 32767) to validate the result
$date = array('Y' => date('Y'), 'm' => date('n'), 'd' => date('j'));
// +60 years
$date['Y'] += 60;
if (checkdate($date['m'], $date['d'], $date['Y'])) {
$fulldate = implode('-', $date);
}
<?php
// A dirty hack
function bigdate_to_string($t_64bit)
{
$t_base = strtotime('2038-01-01 00:00:00 +0000');
$t_32bit = $t_64bit - $t_base;
return date("Y", $t_32bit) + 68 . date("-m-d H:i:s", $t_32bit);
}
$t_64bit = 130 * 365 * 86400; // November 30, 2099 UTC
echo bigdate_to_string($t_64bit) . "\n";
?>
Output:
susam#swift:~$ php datehack.php
2099-11-30 05:30:00
I am subtracting 68 years from the time and adding it back again while printing the formatted output.

Categories