Year value error from PHP date() [duplicate] - php

This question already has answers here:
Display all the week numbers between two dates in PHP [duplicate]
(3 answers)
Closed 8 years ago.
Given a start and end date, I need to generate an array with year and week values.
For example:
Start Date: 2013-01-01
End Date: 2013-02-23
Generated Array:
Array ( [0] => Array ( [week] => 01 [year] => 2013 )
[1] => Array ( [week] => 02 [year] => 2013 )
[2] => Array ( [week] => 03 [year] => 2013 )
[3] => Array ( [week] => 04 [year] => 2013 )
[4] => Array ( [week] => 05 [year] => 2013 )
[5] => Array ( [week] => 06 [year] => 2013 )
[6] => Array ( [week] => 07 [year] => 2013 )
[7] => Array ( [week] => 08 [year] => 2013 ) )
Here is the code I'm using to generate this:
public static function getYearWeekRange($startdate, $enddate) {
$array = array();
$starttime = strtotime($startdate);
$endtime = strtotime($enddate);
while ($starttime <= $endtime) {
$year = date('Y', $starttime);
$week = date('W', $starttime);
$array[] = array('week' => $week, 'year' => $year);
$starttime = strtotime('+1 week', $starttime);
}
return $array;
}
My problem is that when I generate certain date ranges, I don't get the correct year value at the start of the 2013 year. For example:
Start Date: 2012-01-01
End Date: 2013-02-23
In this case, where it should have an subarray with year = 2013 and week = 01, it actually has it's year value equal to 2012.
If I were to switch the start date to 2013-01-05 for example, then there is no problem.
Can anyone offer a solution that would guarantee that my year and week values are always correct?

I was able to fix my problem using the following:
public static function getWeekRange($startdate, $enddate) {
$array = array();
$p = new DatePeriod(
new DateTime($startdate),
new DateInterval('P1W'),
new DateTime($enddate)
);
foreach ($p as $w) {
$array[] = array('year' => $w->format('o'), 'week' => $w->format('W'));
}
return $array;
}

Related

Generate month & year array from two dates in PHP [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Generate month & year array from two dates in PHP
i have two MM/YYYY from form
ex:
$start = "2/2016";
$end = "11/2017"
i need the output in all array of months And year
like this in php
$monthArray = Array (
[0] => 2
[1] => 3
[2] => 4
[3] => 5
[4] => 6
[5] => 7
[6] => 8
[7] => 9
[8] => 10
[9] => 11
[10] => 12
[11] => 1
[12] => 2
[13] => 3
[14] => 4
[15] => 5
[16] => 6
[17] => 7
[18] => 8
[19] => 9
[20] => 10
[21] => 11
);
$yearArray = Array (
[0] => 2016
[1] => 2016
[2] => 2016
[3] => 2016
[4] => 2016
[5] => 2016
[6] => 2016
[7] => 2016
[8] => 2016
[9] => 2016
[10] => 2016
[11] => 2017
[12] => 2017
[13] => 2017
[14] => 2017
[15] => 2017
[16] => 2017
[17] => 2017
[18] => 2017
[19] => 2017
[20] => 2017
[21] => 2017
);
Function would be better. Please help. Thanks in advance
If you want to use datetime you can do:
<?php
$start = date_create_from_format("m/Y","2/2016")->modify("first day of this month");
$end = date_create_from_format("m/Y","11/2017")->modify("first day of this month");
$timespan = date_interval_create_from_date_string("1 month");
$months = [];
$years = [];
while ($start <= $end) {
$months[] = $start->format("m");
$years[] = $start->format("Y");
$start = $start->add($timespan);
}
print_r([ $months, $years ]);
Example: http://sandbox.onlinephpfunctions.com/code/8bfa8cc9481aa8a13d83f62d9c1c6c7927654842
<?php
$start = "2/2016";
$end = "11/2017";
$start = explode('/', $start);
$end = explode('/', $end);
$d1 = strtotime($start[1] . '-' . $start[0] . '-01');
$d2 = strtotime($end[1] . '-' . $end[0] . '-01');
$min_date = min($d1, $d2);
$max_date = max($d1, $d2);
$month = [];
$year = [];
while (($min_date = strtotime("+1 MONTH", $min_date)) <= $max_date) {
$month[] = date('m',$min_date);
$year[] = date('Y',$min_date);
}
print_r($month);
print_r($year);
This should work faster and use less memory than the existing answers because it doesn't rely on creation and manipulation of date objects (especially parsing strings into date objects):
/**
* Takes start and end date string in format 'mm/yyyy' along with a $months and $years
* arrays; modifies the arrays in place to add all months and years between the dates
*/
function listMonthsAndYears($start, $end, &$months, &$years) {
list($startM, $startY) = array_map('intval', explode('/',$start));
list($endM, $endY) = array_map('intval', explode('/',$end));
$m = $startM;
$y = $startY;
while($endY > $y || ($endY === $y && $endM >= $m) ){
$months[]= $m;
$years[] = $y;
$m++;
if($m > 12){ // loop to the next year
$m = 1;
$y++;
}
}
}
Usage:
$start = '2/2016';
$end = '11/2017';
listMonthsAndYears($start, $end, $months, $years);
Live demo

Issue with DatePeriod Class Output

I'm using DatePeriod to get date difference between two dates but it creates issue when I need to get data Year based format. Following is my work
$start_date = '2016-08-29 21:47:33';
$end_date = '2018-04-28 17:30:55';
function getDateRange($start_date, $end_date, $type, $format = 'Y-m-d')
{
$period = new DatePeriod(
new DateTime($start_date),
new DateInterval("P1{$type}"),
new DateTime($end_date)
);
$dates = [];
foreach($period as $dt)
{
$dates[] = $dt->format("$format");
}
return $dates;
}
print_r(getDateRange($start_date, $end_date, 'Y', 'Y'));
According to my function it should return
Array
(
[0] => 2016
[1] => 2017
[2] => 2018
)
But its been outputting only two of them
Array
(
[0] => 2016
[1] => 2017
)
If I'm using output format with Month & Year i.e. M Y with interval of Month then it works fine output for that
print_r(getDateRange($start_date, $end_date, 'M', 'M Y'));
Array
(
[0] => Aug 2016
[1] => Sep 2016
[2] => Oct 2016
[3] => Nov 2016
[4] => Dec 2016
[5] => Jan 2017
[6] => Mar 2017
[7] => Apr 2017
[8] => May 2017
[9] => Jun 2017
[10] => Jul 2017
[11] => Aug 2017
[12] => Sep 2017
[13] => Oct 2017
[14] => Nov 2017
[15] => Dec 2017
[16] => Jan 2018
[17] => Feb 2018
[18] => Mar 2018
[19] => Apr 2018
)
I have modified changes as per documentation link,
Here is the code,
function getDateRange($start_date, $end_date, $type, $format = 'Y-m-d')
{
$start_date = date_create_from_format("Y-m-d H:i:s", $start_date);
$end_date = date_create_from_format("Y-m-d H:i:s", $end_date);
$endDateInt = new DateInterval( "P1Y" );
$end_date->add( $endDateInt );
$period = new DatePeriod(
$start_date,
new DateInterval("P1{$type}"),
$end_date
);
$dates = [];
foreach($period as $dt)
{
$dates[] = $dt->format("$format");
}
return $dates;
}
$start_date = '2016-08-29 21:47:33';
$end_date = '2018-04-28 17:30:55';
print_r(getDateRange($start_date, $end_date, 'Y', 'Y'));
Here is working link.
You can see the reason why in your second output. The last date goes only until April, and the first one is in August. So it's indeed not two full years, and your first result is correct. If you want to make it be the number of "years involved", without regard for actual difference, you could simulate this by setting the second date to the same day and month as the first one, if $type is Y:
<?php
$start_date = '2016-08-29 23:47:33';
$end_date = '2018-09-28 17:30:55';
function getDateRange($start_date, $end_date, $type, $format = 'Y-m-d')
{
$start = new DateTime($start_date);
$end = new DateTime($end_date);
if ($type === "Y") {
$start->setTime(0, 0, 0);
$end->setDate($end->format("Y"), $start->format("m"), $start->format("d"));
$end->setTime(0, 0, 1);
}
$period = new DatePeriod(
$start,
new DateInterval("P1{$type}"),
$end
);
$dates = [];
foreach($period as $dt)
{
$dates[] = $dt->format("$format");
}
return $dates;
}
print_r(getDateRange($start_date, $end_date, 'Y', 'Y'));
Demo

PHP: print all days between a given day and end of month

I don't want to return DATE (Y-m-d).
I need to print all days until end of month from a given day independently of the month or year.
I tried both [$array as $i] - [$array as $key] and didn't work.
$myday (for example = 19)
return $days
would result:
Array
[0] => 20
[1] => 21
[2] => 22
[3] => 23
...
[31] => 31 || [30] => 30 || [28] => 28
I would need each value for $days to compare each to another field.
Didn't try to use $myday as regular number instead of treating as date. And not use strtotime, mktime....
EDITING
Need something very simple like this one:
$output = array();
for ($i=$myday+1;$i<=31 || $i<=30 || $i<=28;$i++) {
$output[] = $i;
}
But print_r won't do it, I need to return as each value to use in different if conditions
This is easily done using DateTime(), DateInterval(), DatePeriod(), and relative date formats.
$start = (new DateTime())->setDate(date('Y'), date('m'), $myday + 1);
$end = new DateTime('first day of next month');
$interval = new DateInterval('P1D');
$period = new DatePeriod($start, $interval, $end);
$days = array();
foreach($period as $date) {
$days[] = $date->format('d');
}
Results
Array
(
[0] => 20
[1] => 21
[2] => 22
[3] => 23
[4] => 24
[5] => 25
[6] => 26
[7] => 27
[8] => 28
[9] => 29
[10] => 30
[11] => 31
)
Demo

PHP, multidimensional arrays: to intersected events with days of the month

I want to build a movie timetable. I have $array1 containing the movie titles and airing dates and times:
array =
0: array =
Title: string = American Beauty
Date: string = 25/09/2012
Time: string = 15:00 - 16:20
1: array =
Title: string = The Godfather
Date: string = 25/09/2012
Time: string = 16:20 - 18:20
2: array =
Title: string = Pulp Fiction
Date: string = 26/09/2012
Time: string = 15:00 - 16:20
And I have $array2 containing the days of the month grouped by Mondays, Tuesday s, Wednesday s, Thursday s and Fridays (no movies during the weekend)
Array
(
[1] => Array
(
[0] => 3
[1] => 10
[2] => 17
[3] => 24
[4] =>
)
[2] => Array
(
[0] => 4
[1] => 11
[2] => 18
[3] => 25
[4] =>
)
[3] => Array
(
[0] => 5
[1] => 12
[2] => 19
[3] => 26
[4] =>
)
[4] => Array
(
[0] => 6
[1] => 13
[2] => 20
[3] => 27
[4] =>
)
[5] => Array
(
[0] => 7
[1] => 14
[2] => 21
[3] => 28
[4] =>
)
)
I need to intersect these two arrays so I can print under day 25 the movie “American Beauty” also under day 25 “The Godfather” and under day 26 “Pulp Fiction”.
Meaning I need to print:
SEPTEMBER 2012
Monday Tuesday Wednesday ....
3 4 5
10 11 12
17 18 19
24 25 26
15:00-16:20 American Beauty 15:00-16:20 Pulp Fiction
16:20-18:20 The Godfather
My tries so far:
foreach( $array1 as $key => $value )
{
$theTime = $value['Time'];
$theTime = explode("/", $theTime );
$days[] = $theTime [0];
$months[] = $theTime [1];
}
So I have all the airing days in array $days but from here I don’t know how to follow or even if this approach is the correct one.
Here's how I get $array2:
$month = 9;
$year = 2012;
for ($i = 1; $i <= 31; $i++)
{
$timestamp = mktime(0, 0, 0, $month , $i, $year);
if (date("n", $timestamp) == $month )
{
$day = date("N", $timestamp);
// Monday 1 to Friday 5
if ($day == 1 OR $day <= 5) {
$array2[$day][] = date("j", $timestamp);
}
}
}
Please help, I’m stuck.
Thanks very much
Ok you will iterate over $array1 and parse the date of the movie.
Then, you will look inside array2 if your day is there
foreach($array1 as $movie){
$movieDate = new DateTime($movie);
//as you indexed $array2 with monday = 1 -> friday = 5 you can use the "w" format
if(isset($array2[$movieDate->format("w"))){
$array[$movieDate->format("j")][] = $movie;
}
}
I made some mutation in your output array, it becomes :
SEPTEMBER 2012
Monday Tuesday Wednesday ....
3=>[] 4 =>[] 5=>[]
10=>[] 11 =>[] 12=>[]
17=>[] 18 =>[] 19=>[]
24 =>[] 25=>[ 26 =>[
15:00-16:20 American Beauty, 15:00-16:20 Pulp Fiction]
16:20-18:20 The Godfather]

Compare todays dayname and time through array?

I have an array like this:
Array
(
[0] => stdClass Object
(
[Start] => 08:00
[dayName] => Tuesday
[dayID] => 2
[courseName] => Math
)
[1] => stdClass Object
(
[Start] => 10:00
[dayName] => Tuesday
[dayID] => 2
[courseName] => Geography
)
[2] => stdClass Object
(
[Start] => 14:00
[dayName] => Tuesday
[dayID] => 2
[courseName] => Science
)
[3] => stdClass Object
(
[Start] => 10:00
[dayName] => Thursday
[dayID] => 4
[courseName] => Math
)
[4] => stdClass Object
(
[Start] => 18:00
[dayName] => Friday
[dayID] => 5
[courseName] => History
)
)
What I want to do is , I want to compare the daya nd time now to the values in the array. For example lets assume that it is 7:00 am and it is Tuesday. Then I want to get the Object[0]. But if it is 11:00 o'clock then i need to get the Object[2] which starts at 14:00 on Tuesday.
It it is Tuesday and 16:00 o'clock then i need Object[3] .
If it is a weekend then i need the beginning of the week which is Tuesday at 08:00 with the Math Course.
I tried to get that using key => value but I mixed up.
How can I compare the Day and then time and in case there is a Course on that combination just pick it up if not just continue checking.
regards
littleblue
function getObject($array){
$timeNow = date('U'); // time now
$oneHour = $timeNow+3600; // time now + 1 hour
foreach($array as $num => $one){ // loop in each $array
$date = strtotime($one->Start); // convert start time to timestamp
if($date >= $timeNow && $date < $oneHour && date('l', $date) == $one->dayName){ // if all criteria met
return $array[$num]; // return that object
}
}
return array('no data'); // if no criteria is met return no data.
}
$course = getObject($yourArray);
echo $course->courseName;
You can mix the use of DateTime and a simple min search :
$myCourse = null;//initialisation
$myCourseDate =null;
$now = new DateTime;
foreach($array as $course){
//get the date from the datas
$date = DateTime::createFromFormat('l h:i',$course->dayName.' '.course->start);
if($now < $date && ($myCourseDate === null || $myCourseDate > $date)){
$myCourse = $course;
$myCourseDate = $date;
}
}
//at the end of the loop, you've got the expected course

Categories