I have a user in a database with a creation_date. This user can run a job in my app UI, but he is limited by a number of job to run in one year.
This user has been created in 2014. I would like to do something like :
function runJob($user){
$nbRemainingJob = findReminingJobs($user);
if ($nbRemainingJob > 0){
runJob($user);
}
else {
die("no more credits";)
}
}
findReminingJobs($user){
$dateRangeStart = ?; //start date to use
$endRangeStart = ?; //end date to use
$sql = "SELECT count(*) FROM jobs WHERE user_id=?";
$sql .= "AND job_created_at BETWEEN ($dateRangeStart AND $endRangeStart)";
$res = $pdo->execute($sql, [$user->id]);
$done = $res->fetchOne();
return ($user->max_jobs - $done);
}
Every user's creation birthday, the $user->max_jobs is reset.
The question is how to find starting/ending date ? in other words, I would like to get a range of date starting from the user's creation date.
For example, if the user was created on 2014-04-12, my start_date should be 2018-04-12 and my end_date = 2019-04-11.
Any idea ?
First get the user register date from db and split it into Year, Month and Day like
$register= explode('-', $userCridate);
$month = $register[0];
$day = $register[1];
$year = $register[2];
Then get the current year like
$year = date("Y");
$dateRangeStart = $year."-".$month."-".$day; //start date to use
Now, check if this date is greater then today date, then use last year as starting date
$previousyear = $year -1;
$dateRangeStart = $previousyear ."-".$month."-".$day; //start date to use
$endRangeStart = date("Y-m-d", strtotime(date("Y-m-d", strtotime($dateRangeStart))
. " + 365 day"));
It is a idea, check if it work for you.
function getRange($registrationDate) {
$range = array();
// Split registration date components
list($registrationYear, $registrationMonth, $registrationDay) = explode('-', $registrationDate);
// Define range start year
$currentYear = date('Y');
$startYear = $registrationYear < $currentYear ? $currentYear : $registrationYear;
// Define range boudaries
$range['start'] = "$startYear-$registrationMonth-$registrationDay";
$range['end'] = date("Y-m-d", strtotime($range['start'] . ' + 364 day'));
return $range;
}
And for your example:
print_r(getRange('2014-04-12'));
Array
(
[start] => 2018-04-12
[end] => 2019-04-11
)
print_r(getRange('2014-09-13'));
Array
(
[start] => 2018-09-13
[end] => 2019-09-12
)
$created='2025-04-12';
$date=explode('-',$created);
if($date[0]<date("Y")){
$newDate=date('Y').'-'.$date[1].'-'.$date[2];
$dateEnding = strtotime($newDate);
$dateEnding = date('Y-m-d',strtotime("+1 year",$dateEnding));
}
else{
$newDate=$created;
$dateEnding = strtotime($newDate);
$dateEnding = date('Y-m-d',strtotime("+1 year",$dateEnding));
}
echo 'starting date is: '.$newDate;
echo '</br>';
echo 'ending date is: '.$dateEnding;
This code will get the date you have and match it with the current year. If the year of the date you provided is equal or above the current year the start date will be your date and end date will be current date +1 year. Otherwise if the year is below our current year (2014) it will replace it with the current year and add 1 year for the end date. Some example outputs:
For input
$created='2014-04-12';
The output is :
starting date is: 2018-04-12
ending date is: 2019-04-12
But for input
$created='2025-04-12';
The outpus is :
starting date is: 2025-04-12
ending date is: 2026-04-12
The solution that match my need :
$now = new DateTime();
$created_user = date_create($created);
$diff = $now->diff($created_user)->format('%R%a');
$diff = abs(intval($diff));
$year = intval($diff / 365);
if ($year == 0){
$startDate=$created_user->format("Y-m-d");
}else{
$startDate=$created_user->add(new DateInterval("P".$year."Y"))->format("Y-m-d");
}
The problem was to define the starting date that is comprised in the one year range max from the current date and starting from the user's creation date.
So if the user's creation_date is older than one year, than I do +1 year, if not, take this date. the starting date must not be greater than the current date_time
thanks to all for your help
Related
I have a job that runs every 28 days. and I want to assign it a cycle number based on a starting reference date.
e.g
1st cycle is 01/27/22. and that cycle number would be 2201.
subsequently I want to calculate the cycle number based on the current date. but for each year there could be either 13 or 14 cycles.
I've managed to figure out the number of cycles since the reference date to figure out the latest cycle date (see below)
const REF_ZERO_DATE = '01/27/2022';
const REF_ZERO_CYCLE_YEAR = "22";
const REF_ZERO_CYCLE_NUM = "01";
$today = new \DateTime("2023/12/29");
echo ("Today = ".$today->format("Y/m/d")."\n");
$ref_zero = new \DateTime(self::REF_ZERO_DATE);
echo ("ref_zero = ".$ref_zero->format("Y/m/d")."\n");
$number_of_days_since_ref_zero = $today->diff($ref_zero)->format("%a");
echo ("Number of days since ref zero = ".$number_of_days_since_ref_zero."\n");
$number_of_cycles_since_ref_zero = floor($number_of_days_since_ref_zero/28);
echo ("Number of cycles since ref zero = ".$number_of_cycles_since_ref_zero."\n");
$interval = 'P' . $number_of_cycles_since_ref_zero*28 . 'D';
echo ("Interval = ".$interval);
$date_of_lastest_cycle = date_add($ref_zero,new \DateInterval($interval));
echo ("last Cycle Date = ".$date_of_lastest_cycle->format("Y/m/d")."\n");
But my math for the cycle adjustment is missing coping with 12 or 13 cycle in a specific year.
It is not explicitly stated whether the cycle of the previous year continues into the next or not.
The scenario in which the cycles can overlap between years is more complicated, so this is assumed.
The interval count code was extracted to the following function:
function calculateIntervalCount($startDate, $endDate, $interval) {
$start = new \DateTime($startDate);
$end = new \DateTime($endDate);
$interval = new \DateInterval($interval);
$periodDays = intval($end->diff($start)->format('%a'));
$intervalDays = intval($interval->format('%d'));
return floor($periodDays / $intervalDays);
}
There are two cases when calculating the interval count of a particular year:
year of start and end are the same year
year of end is after year of start
In the first case the interval count is the same as the interval count of the whole period.
In the second case the interval count of a particular year can be calculated from the difference between the interval counts of the whole period and the period before the end year.
The following function returns the cycle number:
function calculateCycleNumber($startDate, $endDate, $interval) {
$totalCycles = calculateIntervalCount($startDate,$endDate,$interval);
$startYear = intval((new \DateTime($startDate))->format('Y'));
$endYear = intval((new \DateTime($endDate))->format('Y'));
if($startYear < $endYear) {
$endOfLastYearDate = (new \DateTime($endDate))->modify('last day of December last year')->format('Y-m-d');
$cyclesSinceEndOfLastYear = calculateIntervalCount($endOfLastYearDate, $endDate, $interval);
$yearCycle = $totalCycles - $cyclesSinceEndOfLastYear + 1;
} else {
$yearCycle = $totalCycles;
}
$yearCode = substr($endYear,-2);
$yearCycleCode = sprintf('%02d', $yearCycle);
return $yearCode . $yearCycleCode;
}
A cycle number of 2314 was obtained with the inputs provided.
echo calculateCycleNumber('01/27/2022','2023/12/29','P28D');
Note that 14 is possible in case of overlapping cycles.
You can use timestamp, where you add 28 days each time so you get the next date and so on.
Get the next timestamp
$next_date = strtotime('+28 day', $timestamp);
Convert to readable date
echo date('m/d/Y', $next_date);
I need to extract only the day number of a user's registration date.
And extract only the day number of the current date.
Simply in an if loop, say if the day number the user registered is equal to the day number of the current date, do this, or do that.
Code:
$manager = "Manager";
$managerPRO = "ManagerPRO";
$q = $connessione->prepare("
SELECT * FROM collaboratori
WHERE cat_professionisti = ?
OR cat_professionisti = ?
");
$q->bind_param('ss', $manager,$managerPRO);
$q->execute();
$r = $q->get_result();
while($rr = mysqli_fetch_assoc($r)){
/*REGISTRATION DATE*/
$registrazione = $rr['data_registrazione'];
$timestamp = strtotime($registrazione);
echo date("d", $timestamp) .'=' ;
/*CURRENT DATE*/
$data_corrente = date('Y-m-d');
$timestamp_uno = strtotime($data_corrente);
echo date("d", $timestamp_uno);
/*CONTROL*/
if ($timestamp == $timestamp_uno){
echo "yes".'<br>';
}else{
echo "no".'<br>';
}
}
Result:
18=18no
17=18no
16=18no
16=18no
Why in the first case if 18 = 18 gives me false?
However, if I change the date of the user's registration and therefore the first 18, from 2020/11/18 to 2020/12/18, then the current month gives me yes!
I need that regardless of the month, just by checking the day if it is the same, tell me yes, where am I wrong?
You are comparing timestamps, which are measured in seconds. What you are doing is effectively comparing two different points in time, not the days of the month.
You really should be using DateTime. If you want to compare only the day part then you can do something like this.
$dt1 = new DateTime($registrazione);
$dt2 = new DateTime(); // defaults to now
if($dt1->format('d') === $dt2->format('d')) {
echo "Yes, it's the same day of the month";
} else {
echo 'no!';
}
I have date in this form - - 20160428000000 (28th April 2016) i.e yyyymmdd...
I need that if some days(eg. 3) are added to this date - it should add them but not exceed the month(04) - expected output - 20160430000000 - 30th April
Similarly, 20160226000000 + 5days should return 20160229000000 i.e leap year Feb. That means, it should not jump to another month.
Any hints/Ideas ?
Another alternative would be to use DateTime classes to check it out:
First of course create your object thru the input. Then, set the ending day of the month object.
After that, make the addition then check if it exceeds the ending day. If yes, set it to the end, if not, then get the result of the addition:
$day = 5; // days to be added
$date = '20160226000000'; // input date
$dt = DateTime::createFromFormat('YmdHis', $date); // create the input date
$end = clone $dt; // clone / copy the input
$end->modify('last day of this month'); // and set it to last day
$dt->add(DateInterval::createFromDateString("+{$day} days")); // add x days
// make comparision
$final_date = ($dt > $end) ? $end->format('YmdHis') : $dt->format('YmdHis');
echo $final_date;
For this you can try like this:
$given_date = 20160428000000;
$no_of_day = 3;
if(date('m',strtotime($given_date)) < date('m',strtotime($given_date ." +".$no_of_day."days"))){
echo "Exceeded to next month <br/>";
echo "Last date of month should be: ".date("t M Y", strtotime($given_date));
}
else {
echo "Next date will be after ".$no_of_day." day(s)<br/>";
echo date('d M Y',strtotime($given_date ." +".$no_of_day."days"));
}
If month will jump to next month then it will show the current month last date.
other wise it will show date after number of days extended.
If the added date exceeds last day, will select the last day as the new date.
<?php
$date_orig = 20160226000000;
$add_day = 5; # No. of days to add
$added_date = strtotime($date_orig. ' + '.$add_day.' days'); // Add $add_day to $date_orig
$last_date = strtotime(date("YmtHis", strtotime($date_orig))); // Last day of $date_orig
$new_date = ($added_date > $last_date) ? $last_date : $added_date; // check the added date exceeds the last date
$new_date_format = date("YmdHis", $new_date); // Format Date
echo $new_date_format;
?>
<?php
$month_end = date('t-m-Y'); // Gets the last day of the month; e.g 31-07-2019
echo $month_end;
?>
I have got strange issue with dates of events and I have tried hard to get it fixed but unable to do it.
I am attaching a screenshot of how I want to display the dates on the page :
In the picture the first event Deine Energie in Aktion! is a combination of 5 events with each event having its start date and end date.
The first part of the event is 1 day event which starts on 4th April and ends on 4th April. Similarly the second part is on 7th April, 3rd part on 9th April and 4th part on 20th April
The last part starts on 5th May and ends on 10th May.
The dates are stored in database in this format :
I am showing the dates for last part of event.
Event Start Date : 2013-05-05 00:00:00
Event End Date : 2013-05-10 00:00:00
So I want to display dates in the format shown in the picture.
There are multiple cases:
First is if all the dates are coming within a single month then we display the month name at the end only once.
Second is if months are changed then the month name will be shown after the date when the month is changed.
I am getting events dates in a while loop, so how do I compare the current event date with the coming event date in a loop.
This is the code I have used so far to get the dates from the database..
$nid = $row->nid;
$get_product_id = "SELECT product_id from {uc_product_kits} where nid='$nid'";
$res = db_query($get_product_id);
while ($get_product_id_array_value = db_fetch_array($res)) {
$prductid = $get_product_id_array_value['product_id'];
$start_date = db_query("select event_start,event_end from {event} where nid=%d",$prductid);
$start_date_value = db_fetch_object($start_date);
$end_value = $start_date_value->event_start;
$event_end_date = $start_date_value->event_end;
$TotalStart = date("d M Y", strtotime($end_value));
$TotalEnd = date("d M Y", strtotime($event_end_date));
$onlyMonthStart = date("M", strtotime($end_value));
$onlyMonthEnd = date("M", strtotime($event_end_date));
//$groupMonth = db_query("select event_start,event_end, month from {event} where nid=%d group by ",$prductid);
if($TotalStart == $TotalEnd ){
$startDay = date("d", strtotime($end_value));
$startMonth = date("M", strtotime($end_value));
if(in_array($startMonth,$newMonth)) {
echo $onlstartdate;
}
else {
$onlstartdate = date("d", strtotime($end_value));
echo $onlstartdate;
$tempStorage[] = $startMonth
}
//$newMonth[] = $startMonth;
}
}
Easiest would be to first collect all data from your query into e.g. array.
Only then iterate over the array. Having all data together will allow you to compare two consecutive date ranges to decide level of details you need to print for each.
Commented example:
// collect data from SQL query into structure like this:
$events = array(
array("event_start" => "2013-4-4", "event_end" => "2013-4-4"),
array("event_start" => "2013-4-7", "event_end" => "2013-4-7"),
array("event_start" => "2013-4-9", "event_end" => "2013-4-9"),
array("event_start" => "2013-4-20", "event_end" => "2013-4-20"),
array("event_start" => "2013-5-5", "event_end" => "2013-5-10"),
array("event_start" => "2014-1-1", "event_end" => "2014-1-2"),
);
// the actual code for range list generation:
for ($i = 0; $i < count($events); $i++)
{
// parse start and end of this range
$this_event = $events[$i];
$this_start_date = strtotime($this_event["event_start"]);
$this_end_date = strtotime($this_event["event_end"]);
// extract months and years
$this_start_month = date("M", $this_start_date);
$this_end_month = date("M", $this_end_date);
$this_start_year = date("Y", $this_start_date);
$this_end_year = date("Y", $this_end_date);
$last = ($i == count($events) - 1);
// parse start and end of next range, if any
if (!$last)
{
$next_event = $events[$i + 1];
$next_start_date = strtotime($next_event["event_start"]);
$next_end_date = strtotime($next_event["event_end"]);
$next_start_month = date("M", $next_start_date);
$next_end_month = date("M", $next_end_date);
$next_start_year = date("Y", $next_start_date);
$next_end_year = date("Y", $next_end_date);
}
// ranges with different starting and ending months always go
// on their own line
if (($this_start_month != $this_end_month) ||
($this_start_year != $this_end_year))
{
echo date("j M", $this_start_date);
// print starting year only if it differs from ending year
if ($this_start_year != $this_end_year)
{
echo " ".date("Y", $this_start_date);
}
echo "-".date("j M Y", $this_end_year)." <br/>\n";
}
else
{
// this is range starting and ending in the same month
echo date("j", $this_start_date);
// different starting and ending day
if ($this_start_date != $this_end_date)
{
echo "-".date("j", $this_end_date);
}
$newline = false;
// print month for the last range;
// and for any range that starts(=ends) in different month
// than the next range ends
if ($last ||
($this_start_month != $next_end_month))
{
echo " ".date("M", $this_start_date);
$newline = true;
}
// print year for the last range;
// and for any range that starts(=ends) in different year
// than next range ends
if ($last ||
($this_start_year != $next_end_year) ||
($next_start_month != $next_end_month))
{
echo " ".date("Y", $this_start_date);
$newline = true;
}
if ($newline)
{
echo " <br/>\n";
}
else
{
// month (and year) will be printed for some future range
// on the same line
echo ", ";
}
}
}
This outputs:
4, 7, 9, 20 Apr <br/>
5-10 May 2013 <br/>
1-2 Jan 2014 <br/>
A possibility to check if you need to print the month for the current date item is actually to check in the next item. Let me try to explain with pseudocode:
<?php
$month = 0; // Initialize $month variable to unset
// Loop over all your events
foreach($dates as $date) {
// Convert $date to a timestamp
// If the 'month' of the current $timestamp is unequal to $month
// it means we switch months and we have to print the $month first
if(date('m', $timestamp) != $month) {
echo $month; // Of course format how you want it to be displayed
// Set $month to the new month
$month = date('m', $timestamp);
}
// Print the rest of the event, like day numbers here
}
?>
Well, since you need to compare value from one loop to another, you won't be able to use echo directly.
You need to use temp variables. So with the first loop for the start date, you store $tmp_day_1 and $tmp_month_1 then with the end date loop you can compare both months and check if they are diferents. Then you can use echo. I hope I make my point :)
Ok, I've got a logistical question here more so than coding one, but a code example/solution might answer both, so here goes...
If I have a form that I pass in PHP with start_date and end_date (full on m/d/Y format) and I need to print out a table of all entries in mysql database that fall in that range (so from m1/d1/Y1 to m2/d2/Y2) grouped by month, how would I even go about doing that in an elegant way?
For example, if I pass start_date = 5/20/2012, end_date = 7/31/2012, I need the resulting table to show results in this format:
May 2012 | June 2012 | July 2012
.... | .... | .....
where the first column for May 2012 would show results from an mysql query like
SELECT ... WHERE signup_date >= 5/20/2012 AND signup_date <= 5/31/2012
and June 2012 would similarly show:
SELECT ... WHERE signup_date >= 6/1/2012 AND signup_date <= 6/30/2012
etc
So I am looking for a way to parse the start and end date into an array of dates properly arranged from the starting day of the month until the last day of the month, and if the end_date is a few months later then cover all the other months in-between in full (from 1st til last of that month), so that I can cycle through them in a for/while loop? So something like:
[0]['start'] => '5/20/2012'
[0]['end'] => '5/31/2012'
[1]['start'] => '6/1/2012'
[1]['end'] => '6/30/2012'
[2]['start'] => '7/1/2012'
[2]['end'] => '7/31/2012'
Any ideas?
You should be do achieve this with mktime() . Sample code below.
<?php
$startDate = '05/20/2012';
$endDate = '07/31/2012';
$curMonth = date("m", strtotime($endDate)); //End Month
$curYear = date("Y", strtotime($endDate)); //End Year
$months = array();
$months[] = array('start' => "$curMonth/01/$curYear", 'end' => $endDate);
while ("$curMonth/01/$curYear" > $startDate) {
$monthEnd = date("m/d/Y", mktime(0, 0, 0, $curMonth, 0, $curYear));
$curMonth = date('m', strtotime($monthEnd));
$curYear = date('Y', strtotime($monthEnd));
$monthStart = ($curMonth/01/$curYear > $startDate) ? $startDate : "$curMonth/01/$curYear";
$months[] = array('start' => $monthStart, 'end' => $monthEnd);
}
print_r(($months));
?>
try this:
$date = '5/20/2012';
$dateStart = date("m/01/y", strtotime($date));
$start = date("Y-m-d", strtotime($dateStart));
$end = date("Y-m-d", strtotime($dateStart. '+ 1 month - 1 day') );
echo $start;
echo $end;
See my comments first for mysql db date format.
written a bit in pseudo language
$sql="SELECT * FROM ... WHERE `signup_date`>='2012-5-20' AND `signup_date`<'2012-5-31' ORDER BY `signup_date`";
$result=mysql_query($sql);
$month_year=array() //3-dimensional array $month_year[year][month][primary_key];
$month_index=-1;
while($row=mysql_fetch_assoc($result)){
// find $month_of_the_date AND $year_of_the_date
//find different months ,corresponding years, and db primary key and keep track in the $month_year array
}
for( all the years in the array ){
for(all the corresponding months of the year in the array){
//**EDIT:** you MIGHT need other loops and arrays to collect distinct years and corresponding months together
// show the records with the primary keys corresponding to that month and year
}
}