How to get date of the month 15 and 30 - php

I trying get something like this
16 Jul 2014, 12:00 am - 31 Jul 2014, 11:59 pm
How do I achieve it, I know I can use the strtotime feature with $date, but how do I get the half of a month such as 1-15 , 16-31 or maybe 16-30 (depend on some months)
$newDate = strtotime('+15 days',$date)
Thanks for helping!!

Could be done like so:
<?php
$a_date = "2014-7-24"; // calculate from given date (month does count for total days)
$last_day = date("t", strtotime($a_date)); // 31
$median = floor($last_day * .5); // 15
echo "1-" . $median; // 1-15
echo $median + 1 . "-" . $last_day; // 16-31
?>
Edit
Added function:
function split_date($date) {
$last_day = date("t", strtotime($date));
$median = floor($last_day * .5);
return array("last_day" => $last_day, "median" => $median);
}
Return an array: Array ( [last_day] => 31 [median] => 15 )

Related

Prorate days in months across multiple months

I have an example of a start date and end date below which is 1st Of December 2020 - 15th of February 2021
$startDate = '2020-12-01'
$endDate = '2021-02-15'
Ideal result that i'm trying to achieve:
December = 31 days 31 days = 1.0
January = 31 days / 31 days = 1.0
February = 15 days / 28 days = 0.53
Total Quantity = 2.53
My current formula:
$endDate->diffInDays($startDate)
77/90 days * 3 months = 2.57
$monthPeriod = CarbonPeriod::create($startDate, $endDate)->month();
$yearPeriod = CarbonPeriod::create($startDate, $endDate)->year();
$months = collect($monthPeriod)->map(function (Carbon $date) {
return [
'month' => $date->month,
'name' => $date->format('F'),
'days' => $date->daysInMonth,
];
});
foreach ($months as $month) {
$quantity = $endDate->diffInDays($startDate)
}
$startDate = Carbon::parse('2020-12-01');
$endDate = Carbon::parse('2021-02-15');
$startDate->floatDiffInMonths($endDate);
If the 15th is included, then you actually need to add 1 day so you get 16th midnignth as the end of the range:
$startDate->floatDiffInMonths($endDate->addDay());
From the Carbon documentation:
echo Carbon::parse('2000-01-15')->floatDiffInMonths('2000-02-24'); // 1.3103448275862
// floatDiffInMonths count as many full months as possible from the start date
// (for instance 31 days if the start is in January), then consider the number
// of days in the months for ending chunks to reach the end date.

PHP How to extract first days of the weeks from a Month from Unix timestamp

There is this Unix timestamp and it needs to generate the first days of the week as an array.
$time = '1456034400';
// This present Month February 2016
// in calendar the February has the start of the week
// Sunday 7
// Sunday 14
// Sunday 21
// Sunday 28
How do you get an array like this from the Unix Timestamp:
$weekdays = array(
0 => 7,
1 => 14,
2 => 21,
3 => 28
);
And this method needs to work and be accurate for any given month in years not just Feb 2016.
function getSundays($y, $m)
{
return new DatePeriod(
new DateTime("first Sunday of $y-$m"),
DateInterval::createFromDateString('next sunday'),
new DateTime("last day of $y-$m")
);
}
$days="";
foreach (getSundays(2016, 04) as $Sunday) {
$days[] = $Sunday->format("d");
}
var_dump($days);
https://3v4l.org/DVYM5
A bit faster way (since it uses a simple calculation to iterate weeks):
$time = 1456034400;
$firstDay = strtotime('first Sunday of '.date('M',$time).' '.date('Y',$time));
$lastDay = mktime(0,0,0,date('m',$time)+1,1,date('Y', $time));
$weekdays = array();
for ($i = $firstDay; $i < $lastDay; $i += 7*24*3600){
$weekdays[] = date('d',$i);
}
https://3v4l.org/lQkB2/perf#tabs

PHP - Fetch week's first-last date if start-end date falls midweek

$month_year = 'JUL-2015';
$cal = $Calendar->getweek(date("m", strtotime($month_year)), date("Y", strtotime($month_year)));
$call_arr = array();
foreach ($cal['start_day'] as $cal_key => $cal_no) {
$call_arr[] = $cal_no . " - " . $cal['end_day'][$cal_key];
}
The above outputs week range for the month of JUL-2015 like below
Array
(
[0] => 1 - 5
[1] => 6 - 12
[2] => 13 - 19
[3] => 20 - 26
[4] => 27 - 31
)
The first week of JUL-2015 starts from Wednesday. How could I achieve following when user selects Start-End date from Calendar
Check if start-date(1-Jul) and end-date(5-Jul) for first week of
July falls mid-week and does not start from Monday
If start/end date for any week starts from mid-week i.e. not from
Monday, how to fetch the starting date of that week ? In our case it
would be (29-JUN)
For last week of JUL-2015(27 - 31), the starting date would be
27-JUL and end date would be 2-AUG for that specific week
$day = '2015-05-04';
$weekDay = date('w', strtotime($day));
$weekStart = date('Y-m-d',strtotime($day . ' -'.$weekDay. ' days'));
$weekEnd = date('Y-m-d',strtotime($day .' +'.(6-$weekDay). ' days'));
echo $weekStart . ' + ' . $weekEnd;

Find weekly periods (starting on a Monday) for a month

I'm trying to find the weekly periods for a given month and year. Dates should start on a Monday and end on a Sunday. If the 1st of the month is a Sunday (Ex May 2011), it should be the first element.
May 2011
May 1 (Sunday)
May 2 - May 8 (Monday - Sunday)
May 9 - May 15 (Monday - Sunday)
May 17 - Ma6y 22 (Monday - Sunday)
May 23 - May 29 (Monday - Sunday)
May 30 - May 31 (Monday - Tuesday)
September 2012
September 1 - September 2
September 3 - September 9
September 10 - September 16
September 17 - September 23
September 24 - September 30
I am using this function to calculate the week numbers for two dates - I.e. the 1st day of the month and last day of the month.
public function getWeekNumbers($startDate, $endDate)
{
$p = new DatePeriod(
new DateTime($startDate),
new DateInterval('P1W'),
new DateTime($endDate)
);
$weekNumberList = array();
foreach ($p as $w)
{
$weekNumber = $w->format('W');
$weekNumberList[] = ltrim($weekNumber, '0');
}
return $weekNumberList;
}
Strangely, for the month of January, it returns week numbers of [52, 1, 2, 3, 4] when I'm expecting [1, 2, 3, 4, 5].
Once I have the week numbers, I'm using them like so:
//The following loop will populate the dataset with the entire month's durations - regardless if hours were worked or not.
$firstDayOfMonth = date('Y-m-d', strtotime("first day of {$this->year}-{$monthName}"));
$lastDayOfMonth = date('Y-m-d', strtotime("last day of {$this->year}-{$monthName}"));
foreach ($this->getWeekNumbers($firstDayOfMonth, $lastDayOfMonth) as $key => $weekId)
{
// find first mоnday of the year
$firstMon = strtotime("mon jan {$this->year}");
// calculate how many weeks to add
$weeksOffset = $weekId - date('W', $firstMon);
$beginDays = $weeksOffset * 7;
$endDays = ($weeksOffset * 7) + 6;
$searchedMon = strtotime(date('Y-m-d', $firstMon) . " +{$beginDays} days");
$searchedSun = strtotime(date('Y-m-d', $firstMon) . " +{$endDays} days");
echo date("M d", $searchedMon) . " - " . date("M d", $searchedSun);
}
Since, the getWeekNumbers function isn't returning the week numbers I'm expecting, it's not surprising that the output of the above function is
Dec 24 - Dec 30 (2012)
Jan 02 - Jan 08 (2012)
Jan 09 - Jan 15 (2012)
Jan 16 - Jan 22 (2012)
Jan 23 - Jan 29 (2012)
Note that the 1st line (Dec 24 - Dec 30) is the end of the current year (2012) and not the end of last year (2011).
Ideally, I want it to look like
Any ideas? Thanks!!
If you need all weeks for selected month, and all dates for selected week, then this is all you need:
function getWeekDays($month, $year)
{
$p = new DatePeriod(
DateTime::createFromFormat('!Y-n-d', "$year-$month-01"),
new DateInterval('P1D'),
DateTime::createFromFormat('!Y-n-d', "$year-$month-01")->add(new DateInterval('P1M'))
);
$datesByWeek = array();
foreach ($p as $d) {
$dateByWeek[ $d->format('W') ][] = $d;
}
return $dateByWeek;
}
getWeekDays() function returns multi dimension array. first key is week number. 2 level is array, that has dates saved as DateTime object.
Fetch example:
print_r( getWeekDays(5, 2011) ); # May 2011
print_r( getWeekDays(9, 2012) ); # Sep 2012
I had a little time extra, so I written an example ;-)
$datesByWeek = getWeekDays(8, 2012);
$o = '<table border="1">';
$o.= '<tr><th>Week</th><th>Monday</th><th>Tuesday</th><th>Wednesday</th><th>Thursday</th><th>Friday</th><th>Saturday</th><th>Sunday</th></tr>';
foreach ($datesByWeek as $week => $dates) {
$firstD = $dates[0];
$lastD = $dates[count($dates)-1];
$o.= "<tr>";
$o.= "<td>" . $firstD->format('M d') . ' - ' . $lastD->format('M d') . "</td>";
$N = $firstD->format('N');
for ($i = 1; $i < $N; $i++) {
$o.= "<td>-</td>";
}
foreach ($dates as $d) {
$o.= "<td>" . $d->format('d.') . " / 0.00</td>";
# for selected date do you magic
}
$N = $lastD->format('N');
for ($i = $N; $i < 7; $i++) {
$o.= "<td>-</td>";
}
$o.= "</tr>";
}
$o.= '</table>';
echo $o;
Output looks like:
The following assumes that the user can pick the month and year for which they wan to run the report (the value posted being 1-12 for month and YYYY for year). There may be a more elegant way to do it, but this seems to work for me. Also, at the top of your post, you say that you want the weeks to be Monday - Sunday. However, your example/screenshot at the bottom shows weeks being Sunday to Saturday. The below is for the originally-stated goal of Monday - Sunday.
$month = $_POST["month"];
$year = $_POST["year"];
$endDate = date("t", strtotime($year."-".$month."-01"));
$dayOfWeekOfFirstOfMonth = date("w", strtotime($year."-".$month."-01"));
$lastDayOfFirstWeek = 8 - $dayOfWeekOfFirstOfMonth;
$weeksArray = array(array("firstDay"=>1, "lastDay"=>$lastDayOfFirstWeek));
$loopDate = $lastDayOfFirstWeek + 1;
while($loopDate < $endDate)
{
$weeksArray[] = array("firstDay"=>$loopDate, "lastDay"=>($loopDate+6 > $endDate ? $endDate : $loopDate+6));
$loopDate+=7;
}
foreach($weeksArray as $week)
{
echo date("M d", strtotime($year."-".$month."-".$week["firstDay"])) . " - " . date("M d", strtotime($year."-".$month."-".$week["lastDay"])) . "\n";
}
this works perfect!!! phpfiddle here
<?php
// start and end must be timestamps !!!!
$start = 1346976000; // Thu 2012-09-06
$end = 1348704000; // Tue 2012-09-26
// generate the weeks
$weeks = generateweeks($start, $end);
// diaplay the weeks
echo 'From: '.fDate($start).'<br>';
foreach ($weeks as $week){
echo fDate($week['start']).' '.fDate($week['end']).'<br>';
}
echo 'To: '.fDate($end).'<br>';
/* outputs this:
From: Thu 2012-09-06
Thu 2012-09-06 Sun 2012-09-09
Mon 2012-09-10 Sun 2012-09-16
Mon 2012-09-17 Sun 2012-09-23
Mon 2012-09-24 Wed 2012-09-26
To: Wed 2012-09-26
*/
// $start and $end must be unix timestamps (any range)
// returns an array of arrays with 'start' and 'end' elements set
// for each week (or part of week) for the given interval
// return values are also in timestamps
function generateweeks($start,$end){
$ret = array();
$start = E2D($start);
$end = E2D($end);
$ns = nextSunday($start);
while(true){
if($ns>=$end) {insert($ret,$start,$end);return $ret;}
insert($ret,$start,$ns);
$start = $ns +1;
$ns+=7;
}
}
// helper function to append the array and convert back to unix timestamp
function insert(&$arr, $start, $end){$arr[] = array('start'=>D2E($start), 'end'=>D2E($end));}
// recives any date on CD format returns next Sunday on CD format
function nextSunday($Cdate){return $Cdate + 6 - $Cdate % 7;}
// recives any date on CD format returns previous Monday on CD format // finaly not used here
function prevMonday($Cdate){return $Cdate - $Cdate % 7;}
// recives timestamp returns CD
function E2D($what){return floor($what/86400)+2;} // floor may be optional in some circunstances
// recives CD returns timestamp
function D2E($what){return ($what-2)*86400;} // 24*60*60
// just format the timestamp for output, you can adapt it to your needs
function fDate($what){return date('D Y-m-d',$what);}

Return dates of current calendar week as array in PHP5

How would I put together a PHP5 function that would find the current calendar week and return the dates of each day in the week as an array, starting on Monday? For example, if the function were run today (Thu Feb 25 2010), the function would return an array like:
[0] => Mon Feb 22 2010<br />
[1] => Tue Feb 23 2010<br />
[2] => Wed Feb 24 2010<br />
[3] => Thu Feb 25 2010<br />
[4] => Fri Feb 26 2010<br />
[5] => Sat Feb 27 2010<br />
[6] => Sun Feb 28 2010<br />
It doesn't matter what format the dates are stored as in the array, as I assume that'd be very easy to change. Also, it'd be nice to optionally be able to supply a date as a parameter and get the calendar week of that date instead of the current one.
Thanks!
I suppose a solution would be to start by getting the timestamp that correspond to last monday, using strtotime :
$timestampFirstDay = strtotime('last monday');
But if you try with today (thursday), with something like this :
$timestampFirstDay = strtotime('last thursday');
var_dump(date('Y-m-d', $timestampFirstDay));
you'll get :
string '2010-02-18' (length=10)
i.e. last week... For strtotime, "last" means "the one before today".
Which mean you'll have to test if today is "last monday" as returned by strtotime plus one week -- and, if so, add one week...
Here's a possible (there are probably smarter ideas) solution :
$timestampFirstDay = strtotime('last monday');
if (date('Y-m-d', $timestampFirstDay) == date('Y-m-d', time() - 7*24*3600)) {
// we are that day... => add one week
$timestampFirstDay += 7 * 24 * 3600;
}
And now that we have the timestamp of "last monday", we can write a simple for loop that loops 7 times, adding 1 day each time, like this :
$currentDay = $timestampFirstDay;
for ($i = 0 ; $i < 7 ; $i++) {
echo date('Y-m-d', $currentDay) . '<br />';
$currentDay += 24 * 3600;
}
Which will give us this kind of output :
2010-02-22
2010-02-23
2010-02-24
2010-02-25
2010-02-26
2010-02-27
2010-02-28
Now, up to you to :
Modify that for loop so it stores the dates in an array
Decide which format you want to use for the date function
Have fun ;-)
Lessee. . First, to avoid any timezone issues I'd peg to noon on the day you want to compare against, so an hour either way won't cause any problems.
$dateCompare = time(); // replace with a parameter
$dateCompare = mktime(12, 0, 0, date('n', $dateCompare),
date('j', $dateCompare), date('Y', $dateCompare));
Then find the day of week of your date.
$dow = date('N', $dateCompare);
1 is Monday, so figure out how many days from Monday we are.
$days = $dow - 1;
Now subtract days worth of seconds until you get back to Monday.
$dateCompare -= (3600 * 24 * $days);
Now assemble your array of days.
$output = array();
for ($x = 0; $x < 7; $x++) {
$output[$x] = $dateCompare + ($x * 24 * 3600);
}
This is an array of timestamps, but you could store the dates as strings if you prefer.

Categories