What I can do if would like start my January month since 2016-01-01 not 2016-01-02.
https://3v4l.org/uRRfU
function countDaysForChoosenYears(int $year):int
{
$att = [];
for ($i = 1; $i <= 12; $i++) {
$att[] = cal_days_in_month(CAL_GREGORIAN, $i, $year);
}
$att = array_sum($att);
return $att;
}
$YearMonthDayStructure = [];
$Date = new DateTime('2016-01-01');
for ($i = 1; $i <= countDaysForChoosenYears(2016); $i++) {
$monthName = $Date->format('F');
$yearNumber = $Date->format('Y');
$YearMonthDayStructure[$yearNumber][$monthName][$Date->format('d')] = $Date->add(new DateInterval('P1D'))->format('Y-m-d');
}
print_r($YearMonthDayStructure);
The very first time you enter the loop you are adding P1D to the date. So your first date ends up being 2 Jan because you added P1D to 1 Jan on that line with the $Date->add. It's not like $x++ where the '++' happens after you use the variable. It performs the add and then gives the result, with the added P1D, to the $YearMonthDayStructure value.
Related
Hello i have this code:
$anno = 2020;
$settimana = 53;
$anno2 = 2021;
$settimana2 = 1;
for($i = 1; $i <= 7; $i++){
$giorno = date('d/m/Y', strtotime($anno."W".$settimana.$i));
echo $giorno."<br>";
}
echo "<br><hr><br>";
for($i = 1; $i <= 7; $i++){
$giorno2 = date('d/m/Y', strtotime($anno2."W".$settimana2.$i));
echo $giorno2."<br>";
}
This is the output of first loop:
28/12/2020
29/12/2020
30/12/2020
31/12/2020
01/01/2021
02/01/2021
03/01/2021
This is the output of the second loop
15/03/2021
22/03/2021
29/03/2021
05/04/2021
12/04/2021
19/04/2021
26/04/2021
But i wait this output
04/01/2021
05/01/2021
06/01/2021
07/01/2021
08/01/2021
09/01/2021
How can i resolve the problem?
You can try this function
Modify this function as your requirements.
Create array of whole week by running a loop from 1 to 6 days.
you will get your required result.
function getStartAndEndDate($week, $year) {
$dto = new DateTime();
$dto->setISODate($year, $week);
$ret['week_start'] = $dto->format('Y-m-d');
$dto->modify('+6 days');
$ret['week_end'] = $dto->format('Y-m-d');
return $ret;
}
$week_array = getStartAndEndDate(1,2021);
print_r($week_array);
//output
Array
(
[week_start] => 2021-01-04
[week_end] => 2021-01-10
)
EDIT:
I checked your code and i think problem is with $settimana2 = 1; change this variable to $settimana2 = 01;
I have project built using laravel and a I have to build a function that counts all the complete quarters that are in the selected date range - the dates used are inserted via input.
Here are the quarters(i used numerical representations for the months)
01 - 03 first quarter
04 - 06 second quarter
07 - 09 third quarter
10 - 12 forth quarter
I would really appreciate your help,because I've been at it for an entire day now and basically have nothing to show for it,i thing I've been trying so hard i'm actually at the point where i'm so tired, i can t think straight.
I do have some code but it;s worthless, because it doesn't work, and any kind of idea or snippet of code is welcomed.
Thanks for your help in advance.
I managed to do this using multiple functions; basically, if this is needed for chart statistics, then a more specific approach might be the case.
I have done this in Laravel with timestamp dates as input (this code can be adapted for getting semesters also :) , it works and is already tested):
public static function getQuartersBetween($start_ts, $end_ts)
{
$quarters = [];
$months_per_year = [];
$years = self::getYearsBetween($start_ts, $end_ts);
$months = self::getMonthsBetween($start_ts, $end_ts);
foreach ($years as $year) {
foreach ($months as $month) {
if ($year->format('Y') == $month->format('Y')) {
$months_per_year[$year->format('Y')][] = $month;
}
}
}
foreach ($months_per_year as $year => $months) {
$january = new Date('01-01-' . $year);
$march = new Date('01-03-' . $year);
$april = new Date('01-04-' . $year);
$june = new Date('01-06-' . $year);
$july = new Date('01-07-' . $year);
$september = new Date('01-09-' . $year);
$october = new Date('01-10-' . $year);
$december = new Date('01-12-' . $year);
if (in_array($january, $months) && in_array($march, $months)) {
$quarter_per_year['label'] = 'T1 / ' . $year;
$quarter_per_year['start_day'] = $january->startOfMonth();
$quarter_per_year['end_day'] = $march->endOfMonth()->endOfDay();
array_push($quarters, $quarter_per_year);
}
if (in_array($april, $months) && in_array($june, $months)) {
$quarter_per_year['label'] = 'T2 / ' . $year;
$quarter_per_year['start_day'] = $april->startOfMonth();
$quarter_per_year['end_day'] = $june->endOfMonth()->endOfDay();
array_push($quarters, $quarter_per_year);
}
if (in_array($july, $months) && in_array($september, $months)) {
$quarter_per_year['label'] = 'T3 / ' . $year;
$quarter_per_year['start_day'] = $july->startOfMonth();
$quarter_per_year['end_day'] = $september->endOfMonth()->endOfDay();
array_push($quarters, $quarter_per_year);
}
if (in_array($october, $months) && in_array($december, $months)) {
$quarter_per_year['label'] = 'T4 / ' . $year;
$quarter_per_year['start_day'] = $october->startOfMonth();
$quarter_per_year['end_day'] = $december->endOfMonth()->endOfDay();
array_push($quarters, $quarter_per_year);
}
}
return $quarters;
}
and getting the years between:
public static function getYearsBetween($start_ts, $end_ts, $full_period = false)
{
$return_data = [];
$current = mktime(0, 0, 0, date('m', $start_ts), date('d', $start_ts), date('Y', $start_ts));
while ($current < $end_ts) {
$temp_date = $current;
$year = new Date($temp_date);
$return_data[] = $year;
$current = strtotime("+1 year", $current); // add a year
}
if ($full_period) {
$return_data[] = $end_ts;
}
return $return_data;
}
, also getting the months needed
public static function getMonthsBetween($start_ts, $end_ts, $full_period = false)
{
$return_data = $month_list = [];
$current = mktime(0, 0, 0, date('m', $start_ts), date('d', $start_ts), date('Y', $start_ts));
while ($current <= $end_ts) {
$temp_date = $current;
$date = new Date($temp_date);
$month_list[] = $date;
$current = strtotime("+1 month", $current); // add a month
}
$start_date_last_month = new Date(array_first($month_list));
$start_date_last_month = $start_date_last_month->startOfMonth()->format('m-d');
$temp_end_date = new Date($start_ts);
$temp_end_date = $temp_end_date->format('m-d');
if ($start_date_last_month < $temp_end_date) {
array_shift($month_list);
}
$end_date_last_month = new Date(end($month_list));
$current_day_month = $end_date_last_month->endOfMonth()->format('m-d');
$temp_end_date = new Date($end_ts);
$end_day_of_month = $temp_end_date->format('m-d');
if ($end_day_of_month < $current_day_month) {
array_pop($month_list);
}
if (count($month_list) == 0) {
$month_list[] = $end_date_last_month->subMonth();
}
$return_data = $month_list;
if ($full_period) {
$return_data[] = $end_ts;
}
return $return_data;
}
You can do something like in this example:
$February = 2;
$October = 10;
$completedQuarters = ceil($October/3) - ceil($February/3); // = 3
What about the quarter in which the date range starts, should it also count? If it should only count if it begins in the first month of a quarter you can check for it like this:
$completedQuarters = ceil($October/3) - ceil($February/3) -1; // = 2
if($February-1%3 == 0) $completedQuarters += 1;
You´re description is not very clear, let me know if that´s what you had in mind.
Not sure if the following is what you are meaning but might be useful
$date_start='2015/03/12';
$date_end='2017/11/14';
$timezone=new DateTimeZone('Europe/London');
$start=new DateTime( $date_start, $timezone );
$end=new DateTime( $date_end, $timezone );
$difference = $end->diff( $start );
$months = ( ( $difference->format('%y') * 12 ) + $difference->format('%m') );
$quarters = intval( $months / 3 );
printf( 'Quarters between %s and %s is %d covering %d months', $start->format('l, jS F Y'), $end->format('l, jS F Y'), $quarters, $months );
/*
This will output
----------------
Quarters between Thursday, 12th March 2015 and Tuesday, 14th November 2017 is 10 covering 32 months
*/
Something like this in the function and you should be set.
use Carbon\Carbon;
$first = Carbon::parse('2012-1-1'); //first param
$second = Carbon::parse('2014-9-15'); //second param
$fY = $first->year; //2012
$fQ = $first->quarter; //1
$sY = $second->year; //2014
$sQ = $second->quarter; //3
$n = 0; //the number of quarters we have counted
$i = 0; //an iterator we will use to determine if we are in the first year
for ($y=$fY; $y < $sY; $y++, $i++) { //for each year less than the second year (if any)
$s = ($i > 0) ? 1 : $fQ; //determine the starting quarter
for ($q=$s; $q <= 4; $q++) { //for each quarter
$n++; //count it
}
}
if ($sY > $fY) { //if both dates are not in the same year
$n = $n + $sQ; //total is the number of quarters we've counted plus the second quarter value
} else {
for ($q=$fQ; $q <= $sQ; $q++) { //for each quarter between the first quarter and second
$n++; //count it
}
}
print $n; //the value to return (11)
I would like to ask why December is skipping when you try to run the code below? Can somebody help me or explain to me why december is not included in looping? thanks
$date = "2013-03-31";
$d1 = explode("-",$date);
$i = 0;
while ($i < 12)
{
$j = $d1[2];
if(cal_days_in_month(CAL_GREGORIAN, $d1[1], $d1[0]) < $d1[2])
$j = cal_days_in_month(CAL_GREGORIAN, $d1[1], $d1[0]) ;
echo $d1[0]."-".$d1[1]."-".$j."<br>";
$d1[1]++;
if($d1[1] == 12)
{
$d1[0]++;
$d1[1] = 1;
}
$i++;
if($d1[1] < 10)
$d1[1]="0".$d1[1];
}
Result:
2013-03-31
2013-04-30
2013-05-31
2013-06-30
2013-07-31
2013-08-31
2013-09-30
2013-10-31
2013-11-30
2014-01-31
2014-02-28
2014-03-31
Missing :
2013-12-31
here is my fixed version:
<?php
$date = "2013-03-31";
$d1 = explode("-",$date);
$i = 0;
while ( $i<=12 ){
$j = $d1[2];
if(cal_days_in_month(CAL_GREGORIAN,$d1[1],$d1[0])<$d1[2])
$j = cal_days_in_month(CAL_GREGORIAN,$d1[1],$d1[0]);
echo $d1[0]."-".$d1[1]."-".$j."<br>";
if($d1[1]==12){
$d1[0]++;
$d1[1] = 1;
}else{
$d1[1]++;
}
$i++;
if($d1[1]<10)
$d1[1] = "0".$d1[1];
}
basically you were dealing with the role over from 12 to 1 incorrectly.
I want a PHP for loop that goes to certain number say "23" and again starts from "0".
Actually I want for the listing of time in 24 hours format and suppose a case is: I have to show time from 9 AM to 2 AM (i.e 9,10,11,12,13,14,...........23,0,1,2)
$i= range(0,23);//it doest work as it creates an array containing a range of elements
$start_time = 9;
$end_time = 2;
for ($i = $start_time ; $i<= $end_time ; $i++)
{
echo $i;
}
Please suggest a way.
Since your use-case mentions time-sensitive information you might be best off learning to use the date and strtotime functions (or the DateTime classes):
$time = strtotime('2013-09-14 02:00');
$endTime = strtotime('2013-09-15 09:00');
while ($time <= $endTime) {
echo date('Y-m-d H:i:s', $time)."\n";
$time = strtotime('+1 hour', $time);
}
// 2013-09-14 02:00:00
// 2013-09-14 03:00:00
// 2013-09-14 04:00:00
// 2013-09-14 05:00:00
// etc.
$start_time = 9;
$end_time = 2;
$end_time += ($end_time < $start_time) ? 24 : 0;
for ($i = $start_time; $i<= $end_time; $i++) {
echo ($i % 24);
}
Reason, the line $end_time += ($end_time < $start_time) ? 24 : 0; checks to see if the end time is less than the start time (which we assume means the next day), and if it is, it adds 24 hours to it. The line $i %24 is the modulus operator which will divide the number and give the remainder, so if it's 25, it will give you 1 back. Note that all hours being worked with will need to be in 24 hour format to use this method.
You can use the modulo to deduct 24 from numbers when they're greater than 23.
$start_time = 9;
$end_time = 2;
for( $i = $start_time; $i % 24 != $end_time; $i++ )
{
echo $i % 24;
}
Note that you need to be careful with this; if $end_time is greater than 23 it will be stuck in an infinite loop.
Try this its working
<?php
$i= range(0,23);//it doest work as it creates an array containing a range of elements
$start_time = 9;
$end_time = 2;
$max_value=23;
if($start_time>=$end_time)
{
for ($i = $start_time ; $i<= $max_value; $i++)
{
echo $i;
}
for($i=0; $i<=$end_time; $i++)
{
echo $i;
}
}
else
{
for ($i = $start_time ; $i<= $max_value; $i++)
{
echo $i;
}
}
?>
Again late to Answer , Try this
<?php
$start_time = 20;
$end_time = 10;
$maxTime=23;
$minTime=0;
for ($i = $minTime ; $i<=$maxTime - abs($start_time-$end_time) ; $i++)
{
$validTime= $start_time + ($i % $maxTime);
$validTime= $validTime>$maxTime?$validTime-$maxTime:$validTime;
echo $validTime;
}
?>
Check this out. Hope this helps
$start_time = 9;
$end_time = 2;
$flag = 1;
while($flag) [
echo $start_time . "<br>";
$start_time++;
if ($start_time == 23) { $start_time = 0; }
if ($start_time == $end_time) {
$flag = 0;
}
}
Does it have to be a for loop?
You can try this
function hours($range, $recurse = true, $end = array())
{
foreach($range as $time)
{
echo $time . "\n";
}
if($recurse && sizeof($end) > 0)
{
$range = range($end['start'], $end['end']);
hours($range, false);
}
}
$range = range(9,23);
$end = array('start' => 0, 'end' => 2);
hours($range, true, $end);
Maybe better to use date:
$hours = 8;
for ($i=1; $i<=8; $i++){
echo 'TIME1 = '.date("Y-m-d H:i:s",mktime (20+$i,15,18,06,05,2013)).'<br>';
}
or better DateTime class:
$date = DateTime::createFromFormat('Y-m-d H:i:s', '2013-06-05 20:15:18');
$hours = 8;
for ($i=0; $i<8; $i++){
$date->add(new DateInterval('PT1H'));
echo 'TIME2 = '.$date->format('Y-m-d H:i:s').'<br>';
}
Thanks everybody for your help, using your ideas I got my work done.
Here is the code that actually worked.
$start_time = some_dynamic_value;
$end_time = some_dynamic_value;
$i= $start_time;
$flag = false;
if($start_time > $end_time)
$flag = true;
while ($i <= $end_time || $flag)
{
echo $i;
if($i == 24)
{
$i= 0;
$flag = false;
}
$i++;
}
I have array of week numbers from 1 to 52. how i can convert it to
[week 1 jan],[week 2 jan] .......
using PHP
OK ... I fix it and here is my code
function getWeeks($date, $rollover)
{
$cut = substr($date, 0, 8);
$daylen = 86400;
$timestamp = strtotime($date);
$first = strtotime($cut . "00");
$elapsed = ($timestamp - $first) / $daylen;
$i = 1;
$weeks = 1;
for($i; $i<=$elapsed; $i++)
{
$dayfind = $cut . (strlen($i) < 2 ? '0' . $i : $i);
$daytimestamp = strtotime($dayfind);
$day = strtolower(date("l", $daytimestamp));
if($day == strtolower($rollover)) $weeks ++;
}
return $weeks;
}
and in the foreach I added
$x="1/1/2013 + ".$record->tms." weeks";
$m=date("Y-m-d", strtotime($x));
$first_week_start=getWeeks($m, "sunday");
if($first_week_start == 1){$typo="st";}
if($first_week_start == 2){$typo="nd";}
if($first_week_start == 3){$typo="rd";}
if($first_week_start == 4){$typo="th";}
if($first_week_start == 5){$typo="th";}
$month=date("M", strtotime($m));
$final_format .= "'".$first_week_start.$typo ." week in ".$month."'";
Try a loop, start with 1/jan, use DateInterval::createFromDateString('1 week'); and DateTime::add each time in the loop to add the next week, use DateTime::format to get the month also checking the current year in each iteration to make sure the loop hasn't moved to the next year.
Code:
date_default_timezone_set("UTC");
$weeks = array();
$dt = new DateTime("2013-01-01");
$interval = DateInterval::createFromDateString("1 week");
for($i=1; $i <= 52; $i++)
{
$weeks[$i] = "week " . $i . " " . $dt->format("M");
$dt = $dt->add($interval);
}
print_r($weeks);
If you want a function that will return a month abbreviation from a week:
function weekMonth($week)
{
date_default_timezone_set("UTC");
return (new DateTime("2013-01-01"))->add(DateInterval::createFromDateString($week." week"))->format("M");
}
echo weekMonth(6);