php function to get dates of last 7 weeks - php

I am trying to build a php function that would return an array with the start date and end date of the last n number of weeks. this would include the current week. It would look something like this:
function lastnweeks(n)
{
//the code. I am not asking for the code itself but ideas on how to accomplish this
return $array;
}
$lastnweeks =lastnweeks(2);
print_r($lastnweeks);
this would print:
Array (
[0] => Array (
[0] => 2010/09/20
[1] => 2010/09/26
)[1] => Array (
[0] => 2010/09/13
[1] => 2010/09/19
))

I wouldn't use an absolute number of seconds because of daylight savings time and leapyears/leapseconds. You can let PHP's strtotime() function take care of this for you by using relative dates. Each iteration through a loop you can simply tell the function to find "Last Monday", and then use that result as your starting point for the next iteration.
The code:
$past_weeks = 7;
$relative_time = time();
$weeks = array();
for($week_count=0;$week_count<$past_weeks;$week_count++) {
$monday = strtotime("last Monday", $relative_time);
$sunday = strtotime("Sunday", $monday);
$weeks[] = array(
date("Y-m-d", $monday),
date("Y-m-d", $sunday),
);
$relative_time = $monday;
}
var_dump($weeks);
The output:
array
0 =>
array
0 => string '2010-09-20' (length=10)
1 => string '2010-09-26' (length=10)
1 =>
array
0 => string '2010-09-13' (length=10)
1 => string '2010-09-19' (length=10)
2 =>
array
0 => string '2010-09-06' (length=10)
1 => string '2010-09-12' (length=10)
3 =>
array
0 => string '2010-08-30' (length=10)
1 => string '2010-09-05' (length=10)
4 =>
array
0 => string '2010-08-23' (length=10)
1 => string '2010-08-29' (length=10)
5 =>
array
0 => string '2010-08-16' (length=10)
1 => string '2010-08-22' (length=10)
6 =>
array
0 => string '2010-08-09' (length=10)
1 => string '2010-08-15' (length=10)

Use strtotime to get the monday and then subtract the number of seconds for each week:
function lastnweeks($n) {
$time = strtotime('Monday 00:00:00+0000');
$arr = array();
while ($n-- > 0) {
$arr[] = array_reverse(array(
date('Y/m/d', $time-=86400), // sunday
date('Y/m/d', $time-=6*86400) // monday
));
}
return $arr;
}
array_reverse is used to reverse the array as the calculation walks backwards.

Take your pick
$last_week = strtotime('last Week');
echo "Last Week ".date("Y/m/d", $last_week)."<br />\n";
or
$last_week = mktime(0,0,0,date("m"),date("d")-7,date("Y"));
echo "Last Week ".date("Y/m/d", $last_week)."<br />\n";

Related

Creating an associative multidimensional array in PHP

I'm trying to create an array where the Month is the key and each key contains one or more dates within them. I start with an array that looks like $arr below. Sidenote: I do not control how the original array is structured as it comes from an API. I merely added the below $arr to illustrate and make it easier for people to understand and debug.
$arr = array(
0 => array(
'date' => '2020-12-07'
),
1 => array(
'date' => '2020-12-19'
),
2 => array(
'date' => '2021-01-03'
),
3 => array(
'date' => '2020-01-18'
)
);
Because I need to display the dates differently than this, I need to construct an array which contains the Month name and a formated date:
$sorted = array(); // This is the array I will return later.
foreach ( $arr as $day ) {
setlocale(LC_TIME, 'sv_SE');
$month = strftime( '%B', strtotime( $day['date'] ) );
$display_date = trim( strftime( '%e %b', strtotime( $day['date'] ) ) );
}
Everything I've tried doing here so far has failed. I can't even remember all methods to be honest. The last I tried was this (within the foreach()):
array_push($sorted, array(
$month => $display_date
));
The var_dump() of that, generated an enumerated array:
array (size=4)
0 =>
array (size=1)
'December' => string '7 Dec' (length=5)
1 =>
array (size=1)
'December' => string '19 Dec' (length=6)
2 =>
array (size=1)
'Januari' => string '3 Jan' (length=5)
3 =>
array (size=1)
'Januari' => string '18 Jan' (length=6)
What I'm trying to achieve is this:
All $display_date's should sit under its $month key. The $month key must be unique and contain all dates for that month.
Thankful for any help that gets me in the right direction here because I feel like I'm doing something fundamentally wrong.
You are appending new array with month and date every loop, replace array_push() with $sorted[$month][] = $display_date;
foreach ( $arr as $day ) {
setlocale(LC_TIME, 'sv_SE');
$month = strftime( '%B', strtotime( $day['date'] ) );
$display_date = trim( strftime( '%e %b', strtotime( $day['date'] ) ) );
$sorted[$month][] = $display_date;
}
print_r($sorted);
Output:
Array
(
[december] => Array
(
[0] => 7 dec
[1] => 19 dec
)
[januari] => Array
(
[0] => 3 jan
[1] => 18 jan
)
)

Search Array for Best Match based on Day & Time

I'm trying to work out how to the the correct Site base on the current Day and Time from an array. The examples array just shows Monday, the real array will contain 7 days of the week with multiple values for each day.
This is the example array :
$arr = array (
array( 'Day' => 'Monday',
'Start' => '0830',
'End' => '1730',
'Site' => 'NW1'),
array( 'Day' => 'Monday',
'Start' => '1200',
'End' => '1300',
'Site' => 'PL1'),
array( 'Day' => 'Monday',
'Start' =>'1730',
'End' => '2130',
'Site' => 'RE1')
);
So Monday at 1100 I should get NW1, at 1800 I should get RE1, but between 1200-1300 I should get PL1
So far this is the code I have:
$today = 'Monday'; // Full day name
$time = '1205';
echo "<br/>Day: $today";
echo "<br/>Time: $time <br/><br/>";
$arr = array (
array( 'Day' => 'Monday',
'Start' => '0830',
'End' => '1730',
'Site' => 'NW1'),
array( 'Day' => 'Monday',
'Start' => '1200',
'End' => '1300',
'Site' => 'PL1'),
array( 'Day' => 'Monday',
'Start' =>'1730',
'End' => '2130',
'Site' => 'RE1')
);
usort($arr, function($a, $b) {
return (date("N", strtotime($a['Day'])) <=> date("N", strtotime($b['Day']))) * 100 +
($a['Start'] <=> $b['Start']) * 10 +
($a['End'] <=> $b['End']);
});
foreach ($arr as $i => $values) {
if ($today != $values['Day']) continue;
if ($time >= $values['Start'] && $time <= $values['End']) {
$site = $values['Site'];
break;
}
}
echo "$today # $time Site => $site";
This works for times between 0830-1730 & 1730-2130, but not if the time is 1200-1300.
I'm assuming I need to search the array for the Day match, then the Start time and check the end time, but I'm not sure how to do this ?
Can anyone point me in the right direction.
Thanks
**** UPDATE ****
New example array with additional entries
Array
(
[0] => Array
(
[Day] => Monday
[Start] => 0830
[End] => 1730
[Site] => NW1
)
[1] => Array
(
[Day] => Monday
[Start] => 0930
[End] => 0945
[Site] => PK1
)
[2] => Array
(
[Day] => Monday
[Start] => 1200
[End] => 2100
[Site] => PL1
)
[3] => Array
(
[Day] => Monday
[Start] => 1230
[End] => 1245
[Site] => EM1
)
[4] => Array
(
[Day] => Monday
[Start] => 1730
[End] => 2130
[Site] => RE1
)
}
The expected results are:
0940 = PK1
1430 = PL1
0920 = NW1
The aim is 0830 to 1730 NW1 is correct unless something else overrides this, ie 1200-2100 PL1 would be correct, after 2100 to 2130 RE1 etc.
Thanks
All you need to do is reverse the sorting based on start time
usort($arr, function($a, $b) {
return (date("N", strtotime($a['Day'])) <=> date("N", strtotime($b['Day']))) * 100 +
($b['Start'] <=> $a['Start']) * 10 +
($a['End'] <=> $b['End']);
});
This way, we will loop through the array starting with the latest start time (for each day) and once we find a match, we break the loop, using the site value for the match.
I'm still not really sure of the purpose of the multiplication in your usort, but it doesn't seem to be causing any problems, so I'm going to leave it in.
DEMO
As far as I can see as soon as you find a $time between the "start" and "end" you assign the value to $site and then "break" straight away without looking through the rest of the array.
But if the time is 1230 on a Monday which entry in the array should take precedence?
If it is the last one, then maybe hang on to a variable until you search the entire array like so:
$lastCorrectEntry;
foreach ($arr as $i => $values) {
if ($today != $values['Day']) continue;
if ($time >= $values['Start'] && $time <= $values['End']) {
$lastCorrectEntry = $values['Site'];
}
}
$site = $lastCorrectEntry;

Php mysql - get the values of last days and total of entries

I have to get the total values of last days into an array.
First, i have an array to get the last days:
$today = date('Y-m-d');
$ldays = [];
$db = 6;
for($i=-$db; $i<=0; $i++) {
array_push($ldays, date('Y-m-d', strtotime("$i days")));
}
//this will produce an array like this:
array (size=7)
0 => string '2018-12-21' (length=10)
1 => string '2018-12-22' (length=10)
2 => string '2018-12-23' (length=10)
3 => string '2018-12-24' (length=10)
4 => string '2018-12-25' (length=10)
5 => string '2018-12-26' (length=10)
6 => string '2018-12-27' (length=10)
And now, i pull the total of values of each days from the database.
SELECT COUNT(id) as total, data FROM users WHERE data >= '2018-12-21' GROUP BY data ORDER BY data ASC
The output will be an array like this:
array (size=2)
0 =>
array (size=2)
'total' => int 1
'data' => string '2018-12-21' (length=10)
1 =>
array (size=2)
'total' => int 1
'data' => string '2018-12-24' (length=10)
As you can see, the array is missing some days, so i need to cross the 2 arrays and see if a day exists in the 2 arrays:
$response = [];
for($i=0; $i<count($ldays); $i++) {
if(in_array($ldays[$i], array_column($rows_d, 'data'))) {
$response[$ldays[$i]] = 'yes';
}
else {
$response[$ldays[$i]] = 'no';
}
}
//this will make an array like so:
array (size=7)
'2018-12-21' => string 'yes' (length=3)
'2018-12-22' => string 'no' (length=2)
'2018-12-23' => string 'no' (length=2)
'2018-12-24' => string 'yes' (length=3)
'2018-12-25' => string 'no' (length=2)
'2018-12-26' => string 'no' (length=2)
'2018-12-27' => string 'no' (length=2)
But, insted of 'yes' and 'no', i want the array to be something like
array(size=7)
'2018-12-21' => int 1
'2018-12-22' => int 0
'2018-12-23' => int 0
'2018-12-24' => int 1
'2018-12-25' => int 0
'2018-12-26' => int 0
'2018-12-27' => int 0
and i keep getting an error if i do this :
if(in_array($ldays[$i], array_column($rows_d, 'data'))) {
$response[$ldays[$i]] = $rows[$i]['total'];
}
else {
$response[$ldays[$i]] = 0;
}
I guess this is because the rows array has only 2 entrys and the days array has 7. So, how can i obtain this? tks.
Rather than using in_array, use array_search combined with array_column to find the appropriate index into the $rows array instead:
if (($k = array_search($ldays[$i], array_column($rows_d, 'data'))) !== false) {
$response[$ldays[$i]] = $rows_d[$k]['total'];
}
else {
$response[$ldays[$i]] = 0;
}
Note that you have used both $rows and $rows_d in your code, I'm assuming it is supposed to be $rows_d in both cases.
It can looks prettier
$today = date('Y-m-d');
$ldays = [];
$db = 6;
for($i=-$db; $i<=0; $i++) {
$ldays[date('Y-m-d', strtotime("$i days"))] = 0;
}
$dbResult = [['total' => 1,'data' => '2018-12-21'],['total' => 2,'data' => '2018-12-24']]
foreach ($dbResult as $v) {
$ldays[$v['data']] = $v['total'];
}
var_dump($ldays);

Assign maximum temperature to a specific day in multidimensional array

I'm sure that the title is a bit of vague, but i hope that the example will explain the issue better.
So, I have an array that contains a list of 40 results. In each of the results, there is a timestamp, which i translate to a specific day, like "monday" and a temperature. The thing is that, there can be up to 8 time periods in one day. And a temperature for each period. I somehow have to determine how to asign a maximum temperature for a specific day based on all of the temperatures related to that day.
So, the array looks something like this:
array (size=40)
0 =>
'dt' => int 1530802800
'main' =>
'temp' => float 29.14
1 =>
'dt' => int 1530813600
'main' =>
'temp' => float 25.63
...
And what i would like to achieve something like this:
array
monday => 27.65
tuesday => 24.65
...
I'm able to create two separate arrays that hold all the days and all of the temperatures, but i'm not sure how to bind all of the temperatures related to a specific day, since i can have the same day appear in that array up to 8 times, and then calculate the highest temperature for that day.
I have something like:
0 => monday
1 => monday
2 => monday
3 => tuesday
and another array is:
0 => 23.56
1 => 34.66
2 => 12.44
3 => 34.44
What i would like is to at least have something like this
monday => array(
0 => 23.56
1 => 34.66
2 => 12.44
),
tueasday => array(
0 => 34.56
1 => 34.66
2 => 13.44
)
...
Hope that was clear enough.
Any help is appreciated.
Thanks.
Starting from your original array (not the two separate ones). Get the day from the timestamp and assign that as the key of the result. Check if the current value is less and if so replace with the new one:
foreach($array as $values) {
$day = strtolower(date('l', $values['dt']));
if(!isset($result[$day]) || $result[$day] < $values['main']['temp']) {
$result[$day] = $values['main']['temp'];
}
}
You could also create an array keyed by the day with all temperatures:
foreach($array as $values) {
$day = strtolower(date('l', $values['dt']));
$result[$day][] = $values['main']['temp'];
}
Then compute the maximums for each day:
$max = array_map('max', $result);
It looks like the concept you're missing to accomplish this is dynamically constructing an array from keys.
If you iterate your original array, convert the timestamp to a day. You've said you already know how to do that. Then use that day as the key to construct your result array.
foreach ($data as $measurement) {
$day = however_you_convert($measurement['dt']);
// ↓ defines the group
$result[$day][] = $measurement['main']['temp'];
// ↑ adds the value to an array under that group
}
That will convert your data to the grouped structure shown in the last code block in your question. From there, you can use sort or max to get the highest value.
If you don't need the sets of values, you can just keep track of the max value as you go, like this other answer shows.
now that you have this:
$days = ["0" => "monday",
"1" => "monday",
"2" => "monday",
"3" => "tuesday"];
$temps = [
0 => 23.56,
1 => 34.66,
2 => 12.44,
3 => 34.44
];
you can do this:
$result = [];
foreach($days as $key => $day){
if(!isset($result[$day]))
$result[$day] = $temps[$key];
if($temps[$key] > $result[$day])
$result[$day] = $temps[$key];
}
var_dump($result);
output:
array(2) {
["monday"]=>
float(34.66)
["tuesday"]=>
float(34.44)
}
Hope it helps you arrive at a optimal solution.
Based of what you show us :
$days = array(
0 => 'monday',
1 => 'monday',
2 => 'monday',
3 => 'tuesday'
);
$temp = array(
0 => 23.56,
1 => 34.66,
2 => 12.44,
3 => 34.44
);
If you are sure that you have 2 array with the same size :
$new_array = array();
foreach ($days as $key=> $day) {
$new_array[$day][] = $temp[$key];
}
var_dump($new_array);
The output is :
array (size=2)
'monday' => array (size=3)
0 => float 23.56
1 => float 34.66
2 => float 12.44
'tuesday' => array (size=1)
0 => float 34.44
Now if you want an array with the day and the max temp of each day :
$result = array();
foreach($new_array as $day => $temp_array) {
$result[$day] = max($new_array[$day]);
}
var_dump($result);
The output is :
array (size=2)
'monday' => float 34.66
'tuesday' => float 34.44
There is maybe a better way to achieve it but according to your question and what you ask for it should do the job, I hope it helps !

Explode using two delimeters from date string

I have a string
$string="2012-1-12 51:00:00.5";
How can i explode this to date,month,year,hour,minutes,second without using date function.
I was trying like this please let me know the feasible solution for this,
My try:
$string="2012-1-12 51:00:00.5";
$pieces = explode(" ", $date);
$pieces = explode("-", $date);
$pieces = explode(":", $date);
Out Put:
Array
(
[0] => Array
(
[0] => 2012-1-12
[1] => 51:00:00.5
)
[1] => Array
(
[0] => 2012
[1] => 1
[2] => 12 51:00:00.5
)
[2] => Array
(
[0] => 2012-1-12 51
[1] => 00
[2] => 00.5
)
)
You can use preg_split since you need to explode on 3 parameters, This works -
$string="2012-1-12 51:00:00.5";
$pieces = preg_split("/[-: ]/", $string);
var_dump($pieces);
/*
array
0 => string '2012' (length=4)
1 => string '1' (length=1)
2 => string '12' (length=2)
3 => string '51' (length=2)
4 => string '00' (length=2)
5 => string '00.5' (length=4)
*/
As mentioned in the comment to your query three explodes would be needed:
list($date, $time) = explode(" ", $string);
list($year, $month, $day) = explode("-", $date);
list($hours, $mins, $sec) = explode(":", $time);
/*print the values of $year, $date and so on*/
Hope this helps. Of course this would work assuming all date-time values in your application are in the above format.

Categories