I would like to create a serial number the following way.
The serial number should go back to 01 with the start of each month.
$stockno=dofetch(doquery("Select count(id) from vehicle",$dblink));
$stock_no= date("Ymd")."-".$stockno=$stockno["count(id)"]+1;
output is
20150424-01
20150424-02
20150424-03
...
20150430-120
20150501-121
20150501-122
20150502-122
but need Result below format, when new month start serials will be reset
20150424-01
20150424-02
20150424-03
...
20150430-120
20150501-01
20150501-02
20150502-03
new month start again reset to 1
20150601-01
etc.
Here you go,
you just need to get last inserted serial value.
$dateString = "20150424-03"; // get Last entry's date from database. ( date("Ymd"). Ex. 20150424-03
$dtData = split('-',$dateString); // $dtData[0] = date part, $dtData[1] = Prefix part
$month1 = date("m",strtotime($dtData[0])); //Get the month of retrived date
//$date2 = date("Ymd"); // Get current date
// OR
$date2 = date("Ymd", strtotime("+1 day", strtotime($dtData[0]))); // OR Increment last-date by one day
$month2 = date("m",strtotime($date2)); // Get updated date's month
// now calculate month difference between dates. if months are same, prefix will be increased else prefix will be reset to 1
$prefix = (($month2-$month1) == 0) ? str_pad(++$dtData[1], 2, '0', STR_PAD_LEFT) : str_pad(1, 2, '0', STR_PAD_LEFT);
echo $date2. '-'. $prefix;
Simple and doesn't need any changes in database
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 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
I have comma separated days(1,3,5,6) and i want to count number of days between two days.
I have done this as below.
$days=$model->days; // comma saperated days
$days=explode(',',$days); // converting days into array
$count=0;
$start_date = $model->activity_start_date; // i.e. 2018-03-27
$end_date = date('Y-m-d');
while(strtotime($start_date) <= strtotime($end_date)){
if(in_array(date("N",strtotime($start_date)),$days)){ // check for day no
$count++;
}
$start_date = date ("Y-m-d", strtotime("+1 day", strtotime($start_date)));
}
This code is working fine. But the problem is if difference between two date will be year or more than a year than it loop 365 times or more.
Is there any way to reduce execution time to count days. Or it is possible to get counts of days using mysql query.
Real Scenario : I have one event which have start date and it occurs multiple in week(i.e. Monday and Wednesday ) and i want to find how many times event occur from start date to now. If start date is 2018-04-9 and today is 2018-05-9 than count will be 9
This requires no looping.
I find how many weeks between start and end and multiply full weeks (in your example 16,17,18) with count of days.
Then I find how many days there is in first week (15) that is higher than or equal to daynumber of startday.
Then the opposit for week 19.
$days="1,3"; // comma saperated days
$days=explode(',',$days); // converting days into array
$count=0;
$start_date = "2018-04-09";
$end_date = "2018-05-09";
// calculate number of weeks between start and end date
$yearW = floor(((strtotime($end_date) - strtotime($start_date)) / 86400)/7);
if($yearW >0) $count = ($yearW -1)*count($days); //full weeks multiplied with count of event days
$startday = date("N", strtotime($start_date));
$endday = date("N", strtotime($end_date));
//find numer of event days in first week (less than or equal to $startday)
$count += count(array_filter($days,function ($value) use($startday) {return ($value >= $startday);}));
//find numer of event days in last week (less than $endday)
$count += count(array_filter($days,function ($value) use($endday) {return ($value < $endday);}));
echo $count; // 9
https://3v4l.org/9kupt
Added $yearW to hold year weeks
Here, I have a code I have used previously in a project. It is used to find the distance between date from today.
public function diffFromToday($date){
$today = date('jS F, Y');
$today = str_replace(',','',$today);
$today=date_create($today);
$today = date_format($today,"Y-m-j");
$date = str_replace(',','',$date);
$date=date_create($date);
$date = date_format($date,"Y-m-j");
$today=date_create($today);
$date=date_create($date);
$diff=date_diff($today,$date);
$result = $diff->format("%R%a");
$result = str_replace('+','',$result);
return $result;
}
You can use this function according to your requirement. Date format used in this function is 'jS F, Y' DO not be confused and use your own format to convert.
$start_date = date_create('2018-03-27');
$end_date = date_create('2018-04-27');
$t = ceil(abs($endDate- $start_date) / 86400);
echo date_diff($start_date, $end_date)->format('%a');
Output with like this
396
Could you not use the date->diff function to get the values you can directly use like -5 or 5?
$diffInDays = (int)$dDiff->format("%r%a");
Here is something for format parameter descriptions if it could be helpful to you.
You may use tplaner/when library for this:
$days = str_replace(
['1', '2', '3', '4', '5', '6', '0', '7'],
['mo', 'tu', 'sa', 'th', 'fr', 'sa', 'su', 'su'],
'1,3'
);
$when = new When();
$when->rangeLimit = 1000;
$occurrences = $when->startDate(new DateTime('2018-04-9'))
->freq('daily')
->byday('mo,we')
->getOccurrencesBetween(new DateTime('2018-04-9'), new DateTime('2018-05-9'));
echo count($occurrences);
I am trying make the interval dynamic based on the date range.
Consider this dataset:
$data = [
"2016-06-01": 2,
"2016-06-01": 2,
"2016-06-02": 2,
"2016-06-02": 2,
"2016-06-03": 2,
"2016-06-03": 2,
"2016-06-04": 2,
"2016-06-04": 2,
...
];
I want to sum the values based on date range intervals.
So for eg:
$start_date = "2016-06-01";
$end_date = "2016-07-01";
// some function that returns interval dates based on range
$interval_dates = [
"2016-06-01",
"2016-06-05",
"2016-06-10,
...
];
Based on that I iterate through the $data array and get the sums for intervals.
The caveat is however that the interval dates should be based on the date range:
for eg:
if $end_date was next year, the interval dates would look like this:
$interval_dates = [
"2016-06-01",
"2016-08-01",
"2016-10-01"
];
So the interval is based on the difference between start and end date. The bigger the difference the bigger the intervals.
So far:
public function getIntervalDates($start_date, $end_date, $interval = 5)
{
$start_date = new \DateTime($start_date);
$end_date = new \DateTime($end_date);
// get the difference in days
$diff_object = $start_date->diff($end_date);
$diff_days = $diff_object->days;
// set the interval days based on difference in days
// and the interval
$interval_days = round(intval($diff_days) / $interval);
// set the first date to given start date
$interval_dates[] = $start_date->format("Y-m-d");
$current_date = $start_date;
for($i=0; $i < $interval; $i++) {
// set interval dates by incrementing
// by interval days
$current_date->add(new \DateInterval("P".$interval_days."D"));
// Dont go beyond end date
if($current_date < $end_date) {
array_push($interval_dates, $current_date->format("Y-m-d"));
}
}
// add end date
$interval_dates[] = $end_date->format("Y-m-d");
return $interval_dates;
}
This solution kinda works but is not reliable.
for eg: if choosing a big range eg: 2016-06-10 TO 2020-06-10, it only returns 2 dates.
I think there must be a mathematical formula that was made to solve precisely this kind of a problem.
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;
?>