I want to increment a value in MySQL everyday. Starting with 0 and adding +1 for each day.
I've looked at several methods but it usually involves parsing it out of the calendar and starts getting messy. Does anyone have a nice solution for how I could do this in php/mysql?
Reason:
I have a table of data and want to email 1 row each day. So row 0 will send on day one, then row 2 on day 2.
You can use difference between days to get id , so every day you got a new id
class Helper
{
public static $start=1523664000; //2018-04-13
public static function getRowOfToday(){
$now = time(); // or your date as well
$datediff = $now - Helper::$start;
$id = round($datediff / (60 * 60 * 24));
return $id;
}
}
then you can call Helper::getRowOfToday() to get the current row
Related
This is a two part problem which should be trivial but date and time handling in PHP seems to be anything but and everything I've tried so far has either given incorrect results or crashed my program
I'm trying to replicate the following two SQL Server commands in PHP
Count the days since the start of the millennium
select (cast (DATEDIFF(day,'2000-01-01',getdate()) as int)
Count the number of seconds since midnight
datediff(second,convert(date,getdate()),getdate())
I've tried all combinations of date_diff, getdate, strotime and more but nothing seems to give me a properly ISO formatted datetime or a workable method of calculating days and seconds elapsed.
I'm using PHP7 so should have all built-in functions up to date.
What am I missing?
edit: sample input data.
today's date in format '2020-11-22 16:57:10.112'
a given date in format '2000-01-01 00:00:00.000'
expected output data : 7631 days
today's date in format '2020-11-22 16:57:10.112'
previous midnight in format '2020-11-22 00:00:00.000'
expected output data : 61215 seconds
It's rather easy to do if you know your way around DateTime:
function daysSinceStartOfMillennium(DateTimeImmutable $date): int
{
$millenniumStart = new DateTimeImmutable('2000-01-01');
return $date->diff($millenniumStart)->days;
}
function secondsSinceMidnightOfDate(DateTimeImmutable $date): int
{
$midnightToday = new DateTimeImmutable('today');
$diff = $date->diff($midnightToday);
return $diff->s // seconds
+ $diff->i * 60 // minutes to seconds
+ $diff->h * 60 * 60 // hours to seconds
;
}
You could also modify the functions to take date strings as arguments and create a DateTime object inside them.
I opted to create a descriptive variable inside the millennium function to better convey the solution. The creation of this variable can be omitted if you wish and the argument passed directly into the return statement:
return $date->diff(new DateTimeImmutable('2000-01-01'))->days;
Note that if you only need to use these function for the current date, they can be simplified to take no arguments:
function daysSinceStartOfMillennium(): int
{
$millenniumStart = new DateTimeImmutable('2000-01-01');
return (new DateTimeImmutable())->diff($millenniumStart)->days;
}
function secondsSinceMidnight(): int
{
$midnightToday = new DateTimeImmutable('today');
$diff = (new DateTimeImmutable())->diff($midnightToday);
return $diff->s // seconds
+ $diff->i * 60 // minutes to seconds
+ $diff->h * 60 * 60 // hours to seconds
;
}
I would like to know if it would be possible to retrieve a value from an array and use that value for the entire day without changing the value on refresh, it will be used for a discount section. So everyday one of the random values will be taken and that value will be applied as discount % for the next 24 hours. Tomorrow (24 hours later) it will take another value and use that value for the next 24 hours.
I created a logical statement below but isn't working. Any help will be gladly appreciated to complete below function.
//TIME VALUES
date_default_timezone_set('Asia/Dubai');
$currentTime = date('H:i');
$dayStartTime = '00:01';
$dayEndTime = '23:59';
if($currentTime >= $dayStartTime && $currentTime <= $dayEndTime) {
$items = Array("10","15","20");
echo $items[array_rand($items)];
}
Thank you for you time.
Dane
I think you'll want to store a discount somewhere. This will at minimum have 2 fields: amount and expiry.
On load, check if there's a valid discount:
SELECT * FROM discounts WHERE expiry > NOW() LIMIT 1;
If a result is returned, use it. If not, create a new discount with an expiry of 24 hours and use that.
There are 3 fields in task table-> expected_start_datetime,expected_end_datetime,time_allocated
While creating a task expected start and end datetime is selected and saved in the records.
What I am trying to do is to find the difference between the two dates in hours and minutes and save the value inside the "time_allocated" while creating the task and later on the update or view page use/display the time allocated value from the records.
Trying something like this in the task controller action create
$diff = ((strtotime($model->expected_start_datetime) - strtotime($model->expected_end_datetime)) / (60 * 60 * 24));
$model->time_allocated = $model->time_allocated + $diff;
in your model you should be override beforeSave function like this:
public function beforeSave($insert) {
$diff =strtotime($this->expected_end_datetime)-strtotime($this->expected_start_datetime);
$hours= floor($diff/(60*60));
$mins= floor(($diff-($hours*60*60))/60);
$this->time_allocated=$hours.':'.sprintf("%02d",$mins);
return parent::beforeSave($insert);
}
I need to change the shiftdate variable after 05:30 AM. Since i need to generate data from past 24 hrs starting 05:31 AM to Next day 05:30 AM. I tried like this, but its giving previous day every time. Please help.
I want $shiftdate to use in my sql query;
Code:
<?php
if(date('H:i')>="00:00" || date('H:i')<"05:30"){
$shiftdate= date('Y-m-d',strtotime(date('Y-m-d'))-24*60*60);
}
else if(date('H:i')>"05:30" || date('H:i')<"00:00")
{
$shiftdate=date('Y-m-d');
}
echo $shiftdate;
?>
You can't just compare string like "05:30" as a number and hope for the best. You need to compare numerical value of the hour and then numerical value of the minute.
You have a race in between the first if and the else if
Also the else if doesn't cover it completely, so if it hit's the sweetspot, you can end up with $shiftdate being NULL.
Make it a function with protoype shiftdate_type_whatever_it_is fn_name(int hour, int minute);. This way you can simply unit test the function for different (think boundary) values of the date("H:i");
You can use the DateTime classes for this and encapsulate your check into a function:-
/**
* #param DateTime $checkTime
* #return string
*/
function getShiftDate(DateTime $checkTime)
{
$shiftDate = (new DateTime())->setTimestamp($checkTime->getTimestamp());
$hours = (int)$checkTime->format('H');
$minutes = (int)$checkTime->format('i');
$totalMins = $hours * 60 + $minutes;
if($totalMins < 330){
$shiftDate->modify('yesterday');
}
return $shiftDate->format('Y-m-d');
}
var_dump(getShiftDate(new DateTime()));
Obviously the input to the function may need to be modified as I don't know how you get your date/time, but that won't be a problem. Post a comment if you need help with that.
I have created an array with 10 timestamps each 1 day apart:
$data_points = array();
$now = time();
$one_day = 60 * 60 * 24;
for($i = 1; $i <= 10; ++$i) {
$key = $now - ($one_day * $i);
$data_points[$key] = 0;
}
print_r($data_points);
Array
(
[1328642414] => 0
[1328556014] => 0
[1328469614] => 0
[1328383214] => 0
[1328296814] => 0
[1328210414] => 0
[1328124014] => 0
[1328037614] => 0
[1327951214] => 0
[1327864814] => 0
)
Now I have a array of tasks that have started at various times in the last 10 days, I want to see which day my task fell into.
I was going to loop through each $data_point and see if the start time is greater than the current day and less than the next, then increment that data point
is there a better way to do this?
Thanks
Well, to reduce your search time you could put your data into a binary search tree rather than a simple array.
Whether or not that's worth the trouble depends on how big your data set is. Of course, you'd also have to re-balance your tree every so often as you add new dates.
I think there's a better method.
Assuming you have task starting timestamps in an array, the algorithm will be something like :
for each task starting timestamp
timestamp <- $now - timestamp // you will obtain task age in seconds
timestamp <- timestamp / (60*60*24) // you will obtain task age in days
// round resulting timestamp with a precision of 0 if you want to obtain the task age in integer days.
end for each
In this way you will loop on only one array. This will be less expensive than your method.
Obviously, if your tasks come from a SQL database, there will be a greater solution in SQL.
You can use DateTime class
$now = new DateTime();
$task = new DateTime('2012-02-20');
$interval = $taks->diff($now);
echo 'Here is the position you need:' . $interval->format('%R%a days');
** Updated to avoid use of DateTime as asked in comment **
$now = date('Ymd');
$task = date('Ymd',$tasktime);
$interval = $task - $now;
The interval is the number you expect.
I know this question is old, but since there are no accepted answers, and it seems like a fun question to answer - here we go!
Based on your question, your algorithm has the Big O of O(10n) where n is the number of tasks. This means, that it is fairly efficient compared to a lot of things. As pointed out, a binary search tree would be faster having O(log(n)), however implementing it wouldn't really be worth the saved time during processing. Though, you can make it slightly more efficient and have a resulting O(n) by using something like:
$now = time();
$oneDay = 86400; //60 * 60 * 24
foreach($tasks as $task) {
//assuming now that $task is the timestamp of the task
//extra paranthesis added for easier reading
$dif = $now - ($oneDay * ceil(($now - $task) / $oneDay));
$data_points[$dif]++;
}
The math in the diff is as follows. $now-$task is the difference between the two timestamps in seconds, we divide by $oneDay to get the number of days in the past the task occurred. Now, assuming that $now is the start of a new day, and if an event happened just 12 hours ago it was 'yesterday', we use ceil to round it to the next integer so '.5' becomes '1'. From there, we multiply by $oneDay to get the number of seconds of the days that have passed - to work with the $data_points array that you previously created. We then take that result and subtract it from $now, again to work with your $data_points array. That result gives us a time stamp that we can use that matches those in the array you created, and we use it as the 'key' for it and increment accordingly.
This will prevent you from having to loop through the entire $data_points array for each task, and thus reducing its complexity from O(10n) to O(n).
Anyways, I hope that answer helps explain why your formula isn't that inefficient, but shows how to make it ever so slightly more efficient.