List Weeks of Year in a Month in PHP - php

The scenario I have here is that, I need to select a Year and Month. And I need to show the Weeks in that currently selected Month. Let me explain it here ...
2017 -> Oct -> Week N
( this should be the Week of year . E.x this week is #40 for 2017.) So I need to list number of weeks that lies in Oct for this year.
Thank you.

Considered Michel's solution How to get year-sensitive calendar week ? to avoid excess week from previous december to current january.
function getWeekNo( $date ) {
$t = strtotime($date) ;
$w=(int)date('W', $t);
$m=(int)date('n', $t);
$w=($w==1?($m==12?53:1):($w>=51?($m==1?0:$w):$w));
return $w ;
}
$month = '10-2017' ;
$firstDay = '01-' . $month ;
$lastDay = Date('t-m-Y', strtotime($firstDay)) ;
$firstWeek = getWeekNo($firstDay) ;
$lastWeek = getWeekNo($lastDay) ;
for( $i = $firstWeek; $i <= $lastWeek; $i++ ) {
//echo "Week $i <br/>";
echo "Week " . ($i + 1) . "<br/>"; //if you want to start january 1st as Week 1
}

Based on Desai's answer, I tried this on Carbon PHP ( on Laravel 5.5 ). I'm posting my answer in case anyone is looking for this.
$month = 10;
$year = 2017;
$date = \Carbon\Carbon::create($year,$month);
$startOfMonth = $date->startOfMonth();
$endOfMonth = $date->copy()->endOfMonth();
$startWeek = $startOfMonth->format('W');
$endWeek = $endOfMonth->copy()->format('W');
for( $i = $startWeek; $i <= $endWeek; $i++ )
{
echo "Week #" . $i;
}
Thank you all for your answers. Have a great day.

Try this code: Get first day and last day of month, count week numbers and loop over it
$year = "2017";
$month = "10";
$day = "01";
$first_date = $year."-".$month."-".$day;
$last_date = date("Y-m-t",strtotime($first_date));
$first_week = date("W",strtotime($first_date));
$last_week = date("W",strtotime($last_date));
for($i=$first_week;$i<=$last_week;$i++)
{
echo "Week #".$i.", ";
}
Note that October has total 6 weeks. 1st date on Sunday last on Tuesday
DEMO

According to carbon documentation at CarbonDocs
$dt = Carbon::parse('2012-9-5 23:26:11.123789');
var_dump($dt->weekOfYear);

Sorry, I can't reply yet to the first comment, but the above solution is not working correctly if the last day of month have in first week of new year (test case: 2019-12-01).
I made a quick fix (based on original code):
// Input date format: YYYY-mm-dd
function getMonthWeekNumbers( $first_date )
{
$last_date = date( "Y-m-t",strtotime( $first_date ) );
$first_week = date( "W",strtotime( $first_date ) );
$last_week = date( "W",strtotime( $last_date ) );
// If last day of month have on first week on next year, subtract a week from the date
if( $last_week == '01' )
{
$last_week = date( "W",( strtotime( $last_date )-604800 ) );
}
for( $i=$first_week; $i <= $last_week; $i++ )
{
echo "Week #".$i.", ";
}
}
It working fine with any input dates.
DEMO

Related

Increment one month to date 2020-01-30 cancels the next month

Given date is 2019-12-30, and I want to add 1 month for every iteration in the loop (so 5 times).
I wrote this code:
$begin_date = '2019-12-30';
for ($i = 1; $i <= 5; $i++) {
echo '<p>' . $begin_date . '</p>';
$time = strtotime($begin_date);
$begin_date = date("Y-m-d", strtotime("+1 month", $time));
}
And I got the following result
2019-12-30
2019-01-30
2019-03-01 invalid -- I would expect 2019-02-28, at least last day
2019-04-01 invalid
2019-05-01 invalid
You can use DateTime objects, then modify the object to the last day of the next month. If the day of the month is greater than 30, subtract one (as it can never be higher than 31 anyways).
$begin_date = '2019-12-30';
$date = new DateTime($begin_date);
for ($i = 1; $i <= 5; $i++) {
echo '<p>'.$date->format("Y-m-d")."</p>\n";
$date->modify("last day of next month");
if ($date->format("d") > 30) {
$date->modify("-1 day");
}
}
Live demo at https://3v4l.org/jhX95
If you're looking for a more dynamic way (in case the date is not always the 30th), you can duplicate the original object, and subtract the current day of month from the original day of the month.
$begin_date = '2019-12-30';
$date = new DateTime($begin_date);
$original_date = clone $date;
for ($i = 1; $i <= 5; $i++) {
echo '<p>'.$date->format("Y-m-d")."</p>\n";
$date->modify("last day of next month");
if ($date->format("d") > $original_date->format("d")) {
$date->modify("-".($date->format("d") - $original_date->format("d"))." day");
}
}
Live demo at https://3v4l.org/kkOkM

PHP script date modify issue when using in loop

EDITED directly to the problem :
The code :
<?php
$date = new DateTime('2000-01-31'); // or whatever
for ($i = 0; $i < 100; $i++) {
$currentDay = $date->format('d');
if ($currentDay < $date->format('t')) {
$date->modify('+1 month');
if ($date->format('d') < $currentDay) {
$date->modify('last day of previous month');
}
} else {
$date->modify('last day of next month');
}
echo $date->format('Y-m-d') . "<br>";
}
So, if starting date is 2000-01-31, it works fine. That's just because 31 is the last day of january, so, any other month it will put the last date of the month.
But, if u change starting date to 2000-01-30, it's broken. That's because 30 january is not the last day in january. But anyway, 30 january is greater than days in february, so it transform date to 28/29 february. Since 28/29 february is the last day in february, it proceed the code like when this date == number of days in the month, and on the next iteration instead of putting 30 march, it puts 'last day of next month' (31 of march).
And that's not the unique case. Same thing if u put starting date for example 30-08-2000. 30 is not the last day of august, so it change the date to 30 of september, 30 september is the last day of the september, so it change the date to 31 of octomber, but it's not what I expect.
If I've understood your question correctly then this should be what you're after:
$date = new DateTime('2000-01-31'); // or whatever
$day = $date->format('d');
$date->setDate($date->format('Y'), $date->format('m'), 1);
for ($i = 0; $i < 100; $i++) {
$date->modify('+1 month');
echo echo $date->format('t') < $day ? $date->format('Y-m-t') : $date->format('Y-m-' . $day);
echo '<br />';
}
Hope this helps!
Do I understand correctly that
you want to print the same day for all following months
in case it's higher than the maximum days in the month, last day of that month should be used instead
If yes, this could work:
<?php
$date = new DateTime('2000-01-28'); // or whatever
#echo $date->format('d')." ".$date->format('t');
$expectedDay = $date->format('d');
$month = $date->format('m');
$year = $date->format('Y');
for ($i = 0; $i < 100; $i++) {
echo $date->format('Y-m-d') . "<br>";
if ($month++ == 12) {
$year++;
$month = 1;
}
$date->modify("${year}-${month}-1");
if ($expectedDay > $date->format('t')) {
$day = $date->format('t');
} else {
$day = $expectedDay;
}
$date->modify("${year}-${month}-${day}");
}

how to get each month last date in php, year will change according to cuurent date

i want to get each month last date for every year. year will change and it should take from currdate.
i tried below one
$day = date( 't-m-Y' );
But am writing different if condition for each month. So in this code i want to give constant month. year will change. Is it possible to do like that?
can anyone help me to do this.
Check demo here.
<?php
$year = date("Y");
echo $year . "\n";
for ($i = 1; $i <= 12; $i++)
{
$month = strtotime("$year-$i");
echo date("t", $month) . "\n";
}
output:
2017
31
28
31
30
31
30
31
31
30
31
30
31
// get Current Date
$date = date('j-m-Y');
echo date("j-m-y", strtotime($date));//Current Month date with Current year
echo "Current Year =".date("Y", strtotime($date))." , Current Month Days =".date("t", strtotime($date))." , Current Month Last Day Date =".date("t-m-Y", strtotime($date));
t returns the number of days in the month of a given date
so you can pass the dynamic year and constant month like this to know the last day of month
<?php
$year ="2017";
echo date("Y-m-t", strtotime(date("$year-04-d")));
?>
OUTPUT:
2017-04-30
update 1:
$date = new DateTime('last day of 2017-04');
echo $date->format('Y-m-d');
you can check this code
$a_date = "2017-04-17";
echo date("Y-m-t", strtotime($a_date));
or use
$current_date = "2017-04-17";
$date = new DateTime($current_date);
$date->modify('last day of this month');
echo $date->format('Y-m-d');
echo $first_date = date('Y-m-d',strtotime('first day of this month'));
echo $last_date = date('Y-m-d',strtotime('last day of this month'));
this is your code
echo $last_date = date('t-03-Y');
and this is output
30-03-2017
The last date of the month stays the same year in and year out, i.e. December will have 31 days whether referencing this year or the next. The only thing that changes is on what day of the week the last day of a month falls. So, the following indicates how to obtain all this data for the current month and the remaining months of the year as well as for next year.
<?php
// preliminaries
try {
$date = new DateTime("#".time());
} catch (Exception $e) {
echo $e->getMessage();
exit(1);
}
$strDate = $date->format("Y-n-t");
list($Y,$m,$t) = explode("-",$strDate);
$offset = 12 - $m;
$max = $offset + 1; // include current month
//this year starting with current month:
for ( $i=0; $i < $max; $i++ ){
$mo_day_one_yr = "$Y-" . ( $m + $i ) . "-1";
$date->modify( $mo_day_one_yr );
echo $date->format("D, t-M-Y"),"\n";
if( $i == ( $max -1 )) echo "\n";
}
// next year:
for ( $i=1, $Y+=1, $max=12; $i <= $max; $i++ ){
$mo_day_one_yr = "$Y-$i-1";
$date->modify( $mo_day_one_yr );
echo $date->format("D, t-M-Y"),"\n";
}
Live code
Note, the DateTime object gets initialized with a Unix timestamp string but one could also just simply provide a parameter of "now". Also, the try-catch is a good idea just in case an issue should arise in terms of instantiating the DateTime object.

PHP Dates getting a start date and end date for each period

Okay I'm trying to generate the end of the billing period from one date; my question is if I have a variable $billing_period = 02/28/2016 and the billing periods are on every 14th and 28th of each month. from this one variable how can I generate the end date of the period when they have different days appart depending on the start date?
What's confusing to me is that if the date is the 28th it has either 15 or 16days apart from the 14th which is the start of the next billing period. And if the date is the 14th then it has 14 days apart from the 28th. Thanks for any help
EDIT
- The image here shows the date which is selected which is the 02/14/2016 how can I echo the next billing date which would be 02/28/2016 from just the start date
This is my code for the array and getting the start date.
<?
$date = array('16-01-14','16-01-28','16-02-14','16-02-28','16-03-14','16-03-28','16-04-14','16-04-28',
'16-05-14','16-05-28','16-06-14','16-06-28','16-07-14','16-07-28','16-08-14','16-08-28','16-09-14','16-09-28','16-10-14','16-10-28',
'16-11-14','16-11-28','16-12-14','16-12-28');
$currentdate = date('y-m-d');
foreach ($date as $i => $d) {
if ($currentdate >= $d && ($i == count($date)-1 || $currentdate < $date[$i+1])) {
$selected = "selected";
$selected_int = $i;
} else {
$selected = "";
}
list($year, $month, $day) = explode('-', $d);
echo "<option $selected>" . date("m/d/Y", strtotime($d)) . "</option>";
}
?>
Hope I understood well.
What you are trying to do is determine which is your billing period depending on the date you previously selected.
So, you select a date ($date).
Then you need to know the selected day
$timestamp = strtotime($date);
$day = date('D', $timestamp);
Now that you have your day you can make the comparations.
$datetime = new DateTime($date);
if ($day == 14 ){ // if you select 14th then your billing is on the 28th
$billing = $datetime->modify($date->format('Y-m-28'));
}else{ // if you didn't select 14th, then you select 28, and you add one month and set the day in 14th.
$next_month = $datetime->modify('+1 month');
$billing = $next_month->modify($date->format('Y-m-14'));
}
Build an array with the billing dates, get the current key and increment it to get the next value. Simple example with strings:
$dates = ['02/28/2016', '03/14/2016', '03/28/2016', ...];
$key = array_search( '03/14/2016', $dates );
$nextDate = $dates[$key + 1]; // 03/28/2016
Is this what you want to get?
Here the code to get you the next date, just in case you want to do it as a one off.
$date = new DateTime();
$next = $date->format('14/m/Y');
if ($date->format('d') >= 14 && $date->format('d') < 28) {
$next = $date->format('28/m/Y');
}
if ($date->format('d') >= 28) {
$date->modify('+1 month');
$next = $date->format('14/m/Y');
}
echo $next;
Here's the code turned into the function which you can call whenever you need it, it'll return a DateTime() object so you can output the date in whatever format you need at the time, or perform further comparisons/modifications should you need to down the line.
function nextBillingDate($date, $format = 'd/m/Y') {
$date = DateTime::createFromFormat($format, $date);
$next = $date->format('14/m/Y');
if ($date->format('d') >= 14 && $date->format('d') <= 28) {
$next = $date->format('28/m/Y');
}
if ($date->format('d') >= 28) {
$date->modify('+1 month');
$next = $date->format('14/m/Y');
}
return DateTime::createFromFormat('d/m/Y', $next);
}
Example use:
$date = nextBillingDate('28/02/2016');
echo $date->format('d/m/Y');
Outputs:
14/03/2016
Hope it helps.

php - for loop for each month of year

I want a loop that checks the current month, 12 months in the future and 4 months in the past.
For example: Today is 1st August 08. My loop should go through April, May, June, July, August, September, October, November, December, January, February, March, April, May, June, July, and August.
I have tried strotime but I don't know how I can loop 4 months back and 12 months in the future.
Here is my code
$i = 1;
$month = strtotime('2013-08-01');
while($i <= 12) {
$month_name = date('F', $month);
echo $month_name;
echo "<br>";
$month = strtotime('+1 month', $month);
$i++;
I think Yoshi was almost there with his answer, but using DatePeriod with DateTime is more consistent and makes for more readable code IMHO:-
$oneMonth = new \DateInterval('P1M');
$startDate = \DateTime::createFromFormat('d H:i:s', '1 00:00:00')->sub(new \DateInterval('P4M'));
$period = new \DatePeriod($startDate, $oneMonth, 16);
foreach($period as $date){
//$date is an instance of \DateTime. I'm just var_dumping it for illustration
var_dump($date);
}
See it working
This can be quite tricky, here's how I would do it:
$month = date("n", "2013-08-01") - 1; // -1 to get 0-11 so we can do modulo
// since you want to go back 4 you can't just do $month - 4, use module trick:
$start_month = $month + 8 % 12;
// +8 % 12 is the same is -4 but without negative value issues
// 2 gives you: 2+8%12 = 10 and not -2
for ($i = 0; $i < 16; $i += 1) {
$cur_month = ($start_month + $i) % 12 + 1; // +1 to get 1-12 range back
$month_name = date('F Y', strtotime($cur_month . " months"));
var_dump(month_name);
}
something like this?:
$start = -4;
$end = 12;
for($i=$start; $i<=$end;$i++) {
$month_name = date('F Y', strtotime("$i months"));
echo $month_name;
echo "<br>";
}
Your code, just slightly modified.
date_default_timezone_set('UTC');
$i = 1;
$month = strtotime('-4 month');
while($i <= 16) {
$month_name = date('F', $month);
echo $month_name;
echo "<br>";
$month = strtotime('+1 month', $month);
$i++;
}
Simplest solution:
for($i=-4; $i<=12; $i++) {
echo date("F",strtotime( ($i > 0) ? "+$i months" : "$i months") )."\n";
}
Explanation:
The loop starts at -4 and goes all the way upto 12 (total 17, including 0). The ternary statement inside strtotime() simply checks if $i is positive, and if it is, a + is inserted so that we'll get the results for strtotime("+1 months") and similar.
Ta-da!
Using DateTime is the easiest and more readable way.
I would do it like this:
$from = new DateTime('-4 month');
$to = new DateTime('+12 month');
while($from < $to){
echo $from->modify('+1 month')->format('F');
}

Categories