i have a age data:
18,25,36,20,23,21,31,
Using php how i can show like this data?
10 to 20 years = 1 people, 20 to 30 years = 4 people, 30 to 40 years = 2 people
You could try something like this. It uses array_map to divide all values in the data by 10 (thus putting them in groups), then array_count_values to count the number of people in each group.
$ages = [18,25,36,20,23,21,31];
$groups = array_count_values(array_map(function ($v) { return (int)($v / 10); }, $ages));
for ($i = 0; $i <= max(array_keys($groups)); $i++) {
echo $i*10 . " to " . ($i*10+9) . " years: " . (isset($groups[$i]) ? $groups[$i]: 0) . "\n";
}
Output:
0 to 9 years: 0
10 to 19 years: 1
20 to 29 years: 4
30 to 39 years: 2
Update
If you don't want to display groups that have no people in them, use this loop instead:
for ($i = 0; $i <= max(array_keys($groups)); $i++) {
if (isset($groups[$i])) echo $i*10 . " to " . ($i*10+9) . " years: " . $groups[$i] . "\n";
}
Output:
10 to 19 years: 1
20 to 29 years: 4
30 to 39 years: 2
Demo on 3v4l.org
There are many ways but I will prefer directly from mysql query, Something like this
SELECT IF (`age` < 10, '0 to 10 years',
IF(`age` > 10 AND `age` < 20, '10 to 20 years',
IF(`age` > 20 AND `age` < 30, '20 to 30 years', 'more than 30 years')
)
) AS age_group,
count(*) as `counts`
FROM `table_name`
Group by `age_group`
You can refer this answer to calculate age from DOB stored in database
$ages = [18,25,36,20,23,21,31];
$years = array(); // floor range
foreach ($ages as $age)
{
$m = (int)($age / 10);
(isset($years[($m*10)])) ? $years[($m*10)]++ : $years[($m*10)] = 1;
}
var_dump($years); // output: array(3) { [10]=> int(1) [20]=> int(4) [30]=> int(2) }
This code collected the birthday dates from your database and groups them for you in your desired ranges.
//Please update this section to grant access to your database
$username = 'root'; //Your Database Username
$password = ''; //Your Database Password
$database = 'test_sample'; //Your Database Name
$table_name = 'ages'; //Your Table Name
$column_name = 'date_of_birth'; // The Column where the birthday dates can be accessed
$query = 'SELECT `'.$column_name.'` FROM `'.$table_name.'`';
$db_connection = mysqli_connect('localhost', $username, $password, $database);
$result = mysqli_query($db_connection, $query);
$current_ages = [];
$now = new DateTime();
while($data = mysqli_fetch_array($result)) {
$date = new DateTime($data[$column_name]);
$interval = $now->diff($date);
$current_ages[] = $interval->y;
}
// $current_ages = [18,25,36,20,23,21,31];
$desired_range = [
[10,20], [21,30], [31,40], [41,50]
];
$result = [];
foreach($current_ages as $data) {
foreach($desired_range as $index => $range) {
if($data >= $range[0] && $data <= $range[1]) {
(isset($result[$index]))? $result[$index]++ : $result[$index] = 1;
break;
}
}
}
foreach($desired_range as $index => $range) {
$count = (isset($result[$index]))? $result[$index] : 0;
echo $range[0]." to ".$range[1]." years = ".$count.' <br/>';
}
Related
I would like to add a different Coupon Code on my Site every day. Doing this manually seems to take up a lot of unnecessary time. Is there any way i could just paste 365 Codes into a .txt File and display 1 line per day?
You could use date() to get the current day of the year and then file() to read the complete file as array.
<?php
// Fill the tmp file
define('CouponCodeFile', 'file.txt');
file_put_contents(CouponCodeFile, '');
for ($i=1; $i <= 365 ; $i++) {
file_put_contents(CouponCodeFile, sprintf("Coupon_Code_Day_%s\n", $i), FILE_APPEND);
}
// Read Coupon Code from file
$curr_day = date('z');
$CouponCodeFileLines = file(CouponCodeFile);
printf("Your Coupon Code for the day %d is: %s\n", $curr_day+1, $CouponCodeFileLines[$curr_day]);
?>
You can create a table called coupons like so
create table coupons(
id int primary key not null auto_increment,
coupon_name varchar(255),
start_date timestamp default CURRENT_TIMESTAMP ,
end_date timestamp default CURRENT_TIMESTAMP,
created_at timestamp default CURRENT_TIMESTAMP
);
Cron Script:
You can create a script like below to run on 1st day of every year:
Snippet:
<?php
$days = getDaysInTheYear(date('Y'));
$coupons = [];
$day = DateTime::createFromFormat('!Y-m-d',date('Y'). '-01-01');
for($i = 1; $i <= $days; ++$i){
$coupons[] = [
getRandomChars(4) . '_CUP' . $i,
$day->format('Y-m-d H:i:s'),
$day->format('Y-m-d'). ' 23:59:59',
date("Y-m-d H:i:s")
];
$day = $day->add(new DateInterval('P1D'));
}
function getRandomChars($len){
$chars = range('A', 'Z');
shuffle($chars);
$str = '';
for($i = 0; $i < $len; ++$i){
$str .= $chars[rand(0, count($chars) - 1)];
}
return $str;
}
function getDaysInTheYear($year){
return $year % 100 == 0 && $year % 400 == 0 ||
$year % 100 != 0 && $year % 4 == 0 ? 366 : 365;
}
print_r($coupons);
/*
mysqli DB connections etc
*/
// bulk insert all coupons at once
$coupons = array_map(fn($v) => "'".implode("','",$v). "'", $coupons);
try{
if($conn->query("insert into coupons(coupon_name, start_date, end_date, created_at) values(". implode("),(", $coupons). ")") === false){
throw new \Exception("Couldn't insert coupons: ". $conn->error);
}
}catch(\Exception $e){
// your code
}finally{
$conn->close();
}
Online Demo
Cron syntax to setup on your server would be like so:
0 0 1 1 *
Cron mnemonic
Fetching coupons:
While fetching valid coupons, it could be as simple as:
<?php
$result = $conn->query("select * from coupons where start_date >= 'your_start_date' and end_date <= 'your_end_date');
// rest of your code
so I'm trying to build a function that allows me to calculate the dates of the next x days of the week, for example, I want 5 dates from now (02/08/2022), of Tuesday and Thursday, so the output should be:
02/08/2022 - Tu
02/10/2022 - Th
02/15/2022 - Tu
02/17/2022 - Th
02/22/2022 - Tu
I'm not sure how to achieve that, since I want to be able to input various days of the week... Is there a way to do this? My current aproach is this one, but of couse, is not doing what I want, I kinda blocked right now, sorry if the answer is too obvious:
function getNextDates($start_date, $range_weeks, $how_many_dates, $days)
{
$range = 'P' . ($range_weeks * 7) . 'D';
$sd = new DateTimeImmutable($start_date);
$nd = new DateTime($start_date);
$dates_list = array();
$dates_list[0] = array('day' => $sd->format('D'), 'date' => $sd->format('d-m-Y'));
$ind = 1;
$how_many_dates--;
while ($how_many_dates > 0) {
// This in case I want a n weeks space
$nd->add(new DateInterval($range));
for ($i = 0; $i < count($days); $i++) {
if (($i + 1) < count($days)) {
if ($sd->modify($this->nextDay($days[$i])) < $sd->modify($this->nextDay($days[$i + 1]))) {
$nextDate = $nd->modify($this->nextDay($days[$i]));
$dates_list[$ind] = array('day' => $nextDate->format('D'), 'date' => $nextDate->format('d-m-Y'));
$how_many_dates--;
$ind++;
}
} else {
$nextDate = $nd->modify($this->nextDay($days[$i]));
// $sd = $nextDate;
$dates_list[$ind] = array('day' => $nextDate->format('D'), 'date' => $nextDate->format('d-m-Y'));
$how_many_dates--;
$ind++;
}
if ($how_many_dates <= 0) break;
}
}
return $dates_list;
}
Being:
$start_date: 02/08/2022
$range_weeks: 0 // Meaning every week
$how_many_dates: 5
$days: Tuesday, Thursday
I got:
02/08/2022
02/10/2022
02/17/2022
02/24/2022
03/03/2022
Sorry for my amateur code...
Starting from the start date, a day is always added and it is checked whether it is the desired day of the week.
$start = "02/08/2022";
$number = 5;
$weekDays = ['Tue','Thu'];
$dates = [];
for($date = date_create($start); $number > 0; $date->modify('+1 Day')){
$day = $date->format('D');
if(in_array($day,$weekDays)) {
$dates[] = $date->format("d/m/Y");
$number--;
}
}
Result $dates
array (
0 => "08/02/2022",
1 => "10/02/2022",
2 => "15/02/2022",
3 => "17/02/2022",
4 => "22/02/2022",
)
I have written a round robin tournament generator in PHP for an online electronic sports league, and I need to calculate the dates for each game in the tournament. Games are played every Thursday and Sunday over the course of many weeks (the number of weeks is dependent on how many teams are participating). Given the starting week and the number of weeks what would be the best way to calculate those dates?
I'm guessing it requires using some combination of DateTime, DateInterval, and DatePeriod; but I am having trouble figuring out how it would be done.
Update:
Apologies for not providing the code before. Here is the solution I had originally come up with. I didn't know if there was a simpler way of doing it. The function was called submitSchedule where the dates were generated.
<html>
<body>
<?php
function roundRobin($teams) {
$len = count($teams);
$schedule = array();
for ($i = 0; $i < $len - 1; $i++)
{
$home = array_slice($teams, 0, $len / 2);
$away = array_slice($teams, $len / 2);
$day = array();
for ($j = 0; $j < $len / 2; $j++)
{
array_push($day, array($home[$j], $away[$j]));
}
array_push($schedule, $day);
$temp = $away[0];
for ($j = 0; $j < count($away) - 1; $j++)
{
$away[$j] = $away[$j + 1];
}
$away[count($away) - 1] = $home[count($home) - 1];
for ($j = count($home) - 1; $j > 1; $j--)
{
$home[$j] = $home[$j - 1];
}
$home[1] = $temp;
$teams = array_merge($home, $away);
}
return $schedule;
}
function roundRobinBalanced($teams)
{
$schedule = roundRobin($teams);
for ($i = 1; $i < count($schedule); $i+=2)
{
$schedule[$i][0] = array_reverse($schedule[$i][0]);
}
return $schedule;
}
function doubleRoundRobinBalanced($teams)
{
$sched2 = roundRobinBalanced($teams);
for ($i = 0; $i < count($sched2); $i++)
{
$sched2[$i] = array_reverse($sched2[$i]);
}
return array_merge(roundRobinBalanced($teams), $sched2);
}
function tripleRoundRobinBalanced($teams)
{
return array_merge(doubleRoundRobinBalanced($teams), roundRobinBalanced($teams));
}
function submitSchedule($schedule, $start, $intervals, &$con)
{
mysqli_query($con, "TRUNCATE TABLE matches");
$curDate = $start;
echo "<pre>";
for ($i = 0; $i < count($schedule); $i++)
{
for ($j = 0; $j < count($schedule[$i]); $j++)
{
$temp0 = $schedule[$i][$j][0];
$temp1 = $schedule[$i][$j][1];
$temp2 = date_format($curDate, "Y-m-d");
mysqli_query($con,"INSERT INTO matches (T1ID, T2ID, gameDate) VALUES ('$temp0', '$temp1', '$temp2')");
echo "<span style=\"background:lightblue;\">( " . date_format(new DateTime(), "Y-m-d H:i:s") . " )</span>" . "> INSERT INTO matches (T1ID, T2ID, gameDate) VALUES (". $schedule[$i][$j][0] . ", " . $schedule[$i][$j][1] . ", \"" . date_format($curDate, "Y-m-d") . "\")<br>";
}
date_add($curDate, date_interval_create_from_date_string($intervals[$i % count($intervals)]));
}
echo "</pre>";
}
$teams = array();
$con=mysqli_connect("localhost:3306","root","REMOVED","schedule");
// Check connection
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
//Select all items from the 'teams' table and order them first in descending order by points, then in ascending order by 'teamName'
$result = mysqli_query($con,"SELECT * FROM teams");
while($row = mysqli_fetch_array($result))
{
array_push($teams, $row['TID']);
}
if (count($teams) % 2 == 1)
{
array_push($teams, null);
}
shuffle($teams);
$schedule = tripleRoundRobinBalanced($teams);
// echo "<pre>" . json_encode($schedule, JSON_PRETTY_PRINT, JSON_FORCE_OBJECT) . "</pre>";
echo "<pre>";
print_r($schedule);
echo "</pre>";
// ---- List of possible DateTime expressions ----
// thursday
// next thursday
// YYYY-MM-DD
// DD/MM/yy
// thursday + 1 day
$start = new DateTime("thursday"); // Indicates the date of the first game
$jump = array("3 days", "4 days"); // Indicates the time intervals of each game (e.g. If day 1 starts on thursday, day 2 starts on sunday, day 3 starts on thursday, etc.)
submitSchedule($schedule, $start, $jump, $con);
mysqli_close($con);
?>
</body>
</html>
The way to achieve this is by using PHP's DateTime classes as you guessed. They are really very useful. I would suggest a little function something like this:-
/**
* #param $startWeek ISO week number of the first week
* #param $numWeeks The number of weeks to run including the first
*
* #return \DateTime[] An array of DateTime objects
*/
function getPlayDays($startWeek, $numWeeks)
{
$numWeeks --;
$result = [];
$currYear = (int)(new \DateTime())->format('Y');
$oneDay = new \DateInterval('P1D');
// Start on the first Thursday of the given week.
$startDate = (new \DateTime())->setISODate($currYear, $startWeek, 4);
$endDate = clone $startDate;
$endDate->add(new \DateInterval("P{$numWeeks}W"));
// End on the Sunday of the last week.
$endDate->setISODate((int)$endDate->format('o'), (int)$endDate->format('W'), 7);
$period = new \DatePeriod($startDate, $oneDay, $endDate->add($oneDay));
foreach($period as $day){
if(4 === (int)$day->format('N') || 7 === (int)$day->format('N') ){
$result[] = $day;
}
}
return $result;
}
foreach(getPlayDays(1, 3) as $playDay){
var_dump($playDay->format('D m-d-Y'));
}
You didn't specify how you would identify the starting week, so I have assumed an ISO week number.
Output:-
string 'Thu 01-02-2014' (length=14)
string 'Sun 01-05-2014' (length=14)
string 'Thu 01-09-2014' (length=14)
string 'Sun 01-12-2014' (length=14)
string 'Thu 01-16-2014' (length=14)
string 'Sun 01-19-2014' (length=14)
See it working.
DateTime manual.
This function will quite happily cope with DST changes, leap years and weeks close to the start and end of the year thanks to the built in magic of the DateTime classes :)
proof or STFU.
Have a look at the strtotime function:
http://www.php.net/manual/en/function.strtotime.php
You could do something like this:
$startDate = "May 15, 2014";
$startDate = strtotime($startDate);
And you could get the start of the Sunday match by simply adding three days:
$nextDate = strtotime("+3 day", $startDate);
Your question is a bit vague, but I think this is what you were asking.
Let's say you have the timestamps of the day of starting week (06:00 AM time)...
Every other date will be 7 days (86400 seconds * 7) in the future.
Let's assume you will run this for 52 weeks (1 year)
$firstThu = 1234567890;
$firstSun = 9876543210;
$nextThus = array();
$nextSuns = array();
for($i=0; $i<52; $i++) {
$nextThus[] = date('d/m/Y', $firstThu + (86400 * 7 * $i));
$nextSuns[] = date('d/m/Y', $firstSun + (86400 * 7 * $i));
}
At the end of the loop you will have two arrays with all the 52 weeks dates.
I am searching up a database to find the past 7 days worth of data, accumulated.
It works perfectly, but I currently have seven editions of the same code - so I want to loop it somehow, however if I do that, how do I loop it correctly and name the variables. Aside from naming the variables (day_X_) I think I should be able to loop it 7 times fairly easily...
// Get the current day
$graph_day_1_date_lower = date('Y-m-d') . " 00:00";
$graph_day_1_date_upper = date('Y-m-d') . " 23:59";
$graph_day_1_name = date('D') . " (Today)";
/* Successes */
$graph_day_1 = mysqli_query($con,
"SELECT COUNT(`id`) AS num FROM `hidden`
WHERE submittedtime >= '$graph_day_1_date_lower'
AND submittedtime < '$graph_day_1_date_upper'
AND u_s_code='C001'")
or die(mysqli_error($con));
$graph_day_1_row = mysqli_fetch_assoc($graph_day_1);
$graph_day_1_count = $graph_day_1_row['num'];
$graph_total_count = $graph_day_1_count;
/* Errors */
$graph_e_day_1 = mysqli_query($con,
"SELECT COUNT(`id`) AS num FROM `hidden`
WHERE submittedtime >= '$graph_day_1_date_lower'
AND submittedtime < '$graph_day_1_date_upper'
AND u_s_code='E001'")
or die(mysqli_error($con));
$graph_e_day_1_row = mysqli_fetch_assoc($graph_e_day_1);
$graph_e_day_1_count = $graph_e_day_1_row['num'];
$graph_e_total_count = $graph_e_day_1_count;
I will then print the two total counts for each day
Here's what you would want to do:
$today = time(); // or use your upper / lower bounds
$daysToShow = 7;
$dayData = array();
for($i = 0; $i < $daysToShow; $i++){
$dateToCheck = $today + ($i * 24 * 60 * 60); // add a day each time $i goes up
$dataArray = mysql_fetch_assoc($yourDataHere); // replace with your mysqli query using $dateToCheck
$dayData[] = $dataArray; // add to array
}
foreach($dayData as $day){
echo $day['name']; // print out your info here
}
I am trying to disperse the results of 3 queries in a very specific manner across any number of days. Each result from each array represents 1 phone call, and I want a total of 18 phone calls per day.
I need a total of 18 total results per day broken down by:
8 $active_costco results
4 $inactive_costso results
3 $bashas results
3 $afs results
$active_costco returns 321 total results
$inactive_costco returns 119 total results
$bashas returns 64 total results
$afs returns 47 results
I need the total number of results to be 18 per day, so if there are no more $afs or $inactive_costco's, fill in to 18 with $active_costcos.
Here is the php I have currently (it only divides the active_costcos across 8 per day)
$active_costco = sql::results($query);
$inactive_costco = sql::results();
$bashas = sql::results("");
$afs = sql::results("");
$date = date('Y-m-d');
$str = 'INSERT pharmacy.dbo.hotlist (employee_id, store_id, follow_up_date, created_at, status, urgency)VALUES';
for ($i = 0; $i < count($active_costco); $i++)
{
if ($i%8 == 0)
{
$date = date('Y-m-d', strtotime($date . '+1 Weekday'));
}
$str .= "('0CS',". $active_costco[$i]['id'] . ", '$date', '". date('Y-m-d H:m.s') . "', 1, 3)";
$str .= ($i == count($active_costco)-1)? '': ',';
$str .= '<br />';
}
echo $str;
Any help would be appreciated.
Thanks,
Mike
After spending a little time on this, here is the solution I came up with:
$str = 'INSERT pharmacy.dbo.hotlist (employee_id, store_id, follow_up_date, created_at, status, urgency)VALUES';
do
{
$date = date('Y-m-d', strtotime($date . " +1 Weekday"));
$today = array();
for ($i = 0; $i < 3; $i ++)
{
$basha = array_pop($bashas);
$associated = array_pop($afs);
if (!empty($basha))
$today[] = $basha;
if (!empty($associated))
$today[] = $associated;
}
for ($i = 0; $i < 4; $i++)
{
$inactive = array_pop($inactive_costco);
if (!empty($inactive))
$today[] = $inactive;
}
$count = 18 - count($today);
for ($i = 0; $i < $count; $i++)
{
$active = array_pop($active_costco);
if (!empty($active))
$today[] = $active;
}
$calls_left = count($active_costco) + count($inactive_costco) + count($bashas) + count($afs);
foreach ($today as $v)
{
echo "Store ID = " . $v['id'] . " Date = " . $date . "<br />";
}
}while ($calls_left > 0);
It goes through and pops elements off each of the arrays (the number that was specified). If it the array is empty (there is nothing to pop) it doesn't add anything. Then it counts the number of calls in the today array, subtracts that from 18, and grabs the remaining calls from $active_costsco.
Thanks to everyone that put in input.