Php - weeks/days from days - php

I have a number of days to a date in the future but would like to know how many weeks and days it is. Also, noting that if its less than a week, then it simply returns the same number.
Is this possible?
e.g. 17 days would be 2 weeks and 3 days
e.g. 4 days would be 4 days

I would try something like this:
$days = 17;
$weeks = floor($days / 7);
$dayRemainder = $days % 7;
echo $days.'<br/>'.$weeks.'<br/>'.$dayRemainder;//add whatever logic you need here to get the display the way you want it.

$weeks = intval($days / 7);
$days = $days % 7;
if($weeks)
{
printf("%d weeks", $weeks);
}
if($days)
{
if($weeks)
{
printf(" and ");
}
printf("%d days", $days);
}

Something along the lines of this should work
function getnumweeks(d) {
totalDays = d;
numWeeks = floor(d/7);
if numWeeks != 0 {
extraDays = totalDays % 7;
return array(extraDays, numWeeks);
} else {
return array(totalDays, 0)
}
}
Then you can call and use it as such:
ans = getnumweeks(17)
ans[0] <- Contains number of days
ans[1] <- Contains Number of Weeks

As the Piskvor mentioned, you should use the modulo operator:
$weeks = $days/7;
$daysleft = $days%7;

Let's say x is number of days, W is output value of weeks and D is output value of days remaining.
First do integer division
W = x / 7;
Then you take remainder:
D = x % 7;

$num_days = $databack30[days_to_next_event];
$weeks = floor($num_days/7);
$days = $num_days % 7;
if($weeks>'0'){ $whenitis = ' in '.$weeks.' weeks and '.$days.' days'; }
else { $whenitis = ' in '.$days.' days'; }

I would suggest you to re-use this powerful function datediff:
http://www.addedbytes.com/lab/php-datediff-function/
as suggested in php weeks between 2 dates
or taking inspiration from that code.

Related

How to convert 'X hours Y minutes' time string into z minutes in php

I have been stuck with php date time conversion. I have to convert a dynamic time string like 'd days X hours Y minutes' into the total minutes. This time string is dynamic and returned by some third party API. This could be like 'X hours Y minutes', 'Y minutes' etc..
Please help me if someone is having any clue for this.
Thanks in advance.
As Joe replied, here a little push on your way. Note the + in front, as we are adding. We could turn them both into date objects and do a diff() to get the mentioned DateInterval of course.
$apiTimeStamp = strtotime("+1 weeks 2 days 4 hours 2 seconds");
echo abs($apiTimeStamp - time()) / 60;
you can try this:
<?php
$min=0;
$arr = '1 hours 20 minutes';
$a=explode(' ',$arr);
if($a[1] == 'hours')
{
$min = $min+ $a[0]*60;
}
if($a[3] == 'minutes')
{
$min =$min+ $a[2];
}
if($a[1] == 'minutes')
{
$min = $min+ $a[0];
}
echo "'".$min." minutes"."'";
?>
<?php
$apistring = "10 Hours 15 Minutes";
preg_match("#([\d]+)[/\s]+(?i)(?=hours)#", $apistring, $hours);
preg_match("#([\d]+)[/\s]+(?i)(?=minutes)#", $apistring, $minutes);
if (is_numeric($hours[1])==true) {
$intHourMinutes = $hours[1]*60;
}
else {
$intHourMinutes = 0;
}
if (is_numeric($minutes[1])==true) {
$intMinutes = $minutes[1];
}
else {
$intMinutes = 0;
}
$totalminutes=$intHourMinutes+$intMinutes;
print_r($totalminutes);
?>

How do I find date prior to another date in php

I need to find date x such that it is n working days prior to date y.
I could use something like date("Y-m-d",$def_date." -5 days");, but in that case it wont take into consideration the weekend or off-date. Let's assume my working days would be Monday to Saturday, any idea how I can accomplish this?
Try this
<?php
function businessdays($begin, $end) {
$rbegin = is_string($begin) ? strtotime(strval($begin)) : $begin;
$rend = is_string($end) ? strtotime(strval($end)) : $end;
if ($rbegin < 0 || $rend < 0)
return 0;
$begin = workday($rbegin, TRUE);
$end = workday($rend, FALSE);
if ($end < $begin) {
$end = $begin;
$begin = $end;
}
$difftime = $end - $begin;
$diffdays = floor($difftime / (24 * 60 * 60)) + 1;
if ($diffdays < 7) {
$abegin = getdate($rbegin);
$aend = getdate($rend);
if ($diffdays == 1 && ($astart['wday'] == 0 || $astart['wday'] == 6) && ($aend['wday'] == 0 || $aend['wday'] == 6))
return 0;
$abegin = getdate($begin);
$aend = getdate($end);
$weekends = ($aend['wday'] < $abegin['wday']) ? 1 : 0;
} else
$weekends = floor($diffdays / 7);
return $diffdays - ($weekends * 2);
}
function workday($date, $begindate = TRUE) {
$adate = getdate($date);
$day = 24 * 60 * 60;
if ($adate['wday'] == 0) // Sunday
$date += $begindate ? $day : -($day * 2);
return $date;
}
$def_date="";//define your date here
$preDay='5 days';//no of previous days
date_sub($date, date_interval_create_from_date_string($preDay));
echo businessdays($date, $def_date); //date prior to another date
?>
Modified from PHP.net
Thanks for the help guys, but to solve this particular problem I wrote a simple code:
$sh_padding = 5; //No of working days to count backwards
$temp_sh_padding = 1; //A temporary holder
$end_stamp = strtotime(date("Y-m-d", strtotime($date_format)) . " -1 day"); //The date(timestamp) from which to count backwards
$start_stamp = $end_stamp; //start from same as end day
while($temp_sh_padding<$sh_padding)
{
$sh_day = date('w',$start_stamp);
if($sh_day==0){ //Skip if sunday
}
else
{
$temp_sh_padding++;
}
$start_stamp = strtotime(date("Y-m-d",$start_stamp)." -1 day");
}
$sh_st_dte = date("Y-m-d",$start_stamp); //The required start day
A quick bit of googling got me to this page, which includes a function for calculating the number of working days between two dates.
It should be fairly trivial to adjust that concept to suit your needs.
Your problem, however, is that the concept of "working days" being monday to friday is not universal. If your software is only ever being used in-house, then it's okay to make some assumptions, but if it's intended for use by third parties, then you can't assume that they'll have the same working week as you.
In addition, public holidays will throw a big spanner in the works, by removing arbitrary dates from various working weeks throughout the year.
If you want to cater for these, then the only sensible way of doing it is to store the dates of the year in a calendar (ie a big array), and mark them individually as working or non-working days. And if you're going to do that, then you may as well use the same mechanism for weekends too.
The down-side, of course, is that this would need to be kept up-to-date. But for weekends, at least, that would be trivial (loop through the calendar in advance and mark weekend days where date('w')==0 or date('w')==6).

Get Dates of the Last 7 Days in Array In Custom Format

How do I get the exact dates of the last 7 days including today in a custom format (dd/mm)?
In the resulting array I would like to get something like (dates are examples only):
1=>11/2 (today minus 7 days)
2=>12/2 (today minus 6 days)
...
7=>17/2 (today)
function getLastNDays($days, $format = 'd/m'){
$m = date("m"); $de= date("d"); $y= date("Y");
$dateArray = array();
for($i=0; $i<=$days-1; $i++){
$dateArray[] = '"' . date($format, mktime(0,0,0,$m,($de-$i),$y)) . '"';
}
return array_reverse($dateArray);
}
Usage:
$arr = getLastNDays(7);
or
$arr = getLastNDays(7, 'd/m/Y');
You can combine the 2 functions date() and strtotime(). for example:
echo date("Y-m-d", strtotime("7 days ago"));
Try:
for ($i=0; $i<7; $i++)
{
echo date("d/m", strtotime($i." days ago")).'<br />';
}
You should be able to work out how to get them in the correct order and into an array :)
Hope that helps
time() gives you the current timestamp.
86400 seconds are one day (60 * 60 * 24).
date() gives you a custom date string.
for ($iDay = 6; $iDay >= 0; $iDay--) {
$aDays[7 - $iDay] = date('d/m', time() - $iDay * 86400);
}
Also see this example.
If you don't want the leading zeros, use 'j/n' as custom date format parameter:
for ($iDay = 6; $iDay >= 0; $iDay--) {
$aDays[7 - $iDay] = date('j/n', time() - $iDay * 86400);
}
Also see this updated example.
=== UPDATE ===
#Dagon's idea to use strtotime() to get the timestamp is great. Here the better solution:
for ($iDay = 6; $iDay >= 0; $iDay--) {
$aDays[7 - $iDay] = date('j/n', strtotime("-" . $iDay . " day"));
}
And an example.

PHP calculating number of days between 2 dates

I am developing a web application which revolves around dates.
I need to calculate numbers based around days elasped, for example - pseudo code
$count_only = array('monday', 'wednesday', 'friday'); //count only these days
$start_date = 1298572294; // a day in the past
$finish_date = 1314210695; //another day
$var = number_of_days_between($start_date, $finish_date, $count_only);
Is there a way determine how many full days have elapsed, while only counting certain days?
You can simplify this considerably by calculating how many complete weeks fall between the two specified dates, then do some math for the beginning/end partial weeks to account for dangling dates.
e.g.
$start_date = 1298572294; // Tuesday
$finish_date = 1314210695; // Wednesday
$diff = 1314210695-1298572294 = 15638401 -> ~181 days -> 25.8 weeks -> 25 full weeks.
Then it's just a simple matter of checking for the dangling dates:
Tuesday -> add 2 days for Wednesday+Friday to get to the end of the week
Wednesday -> add 1 day for Monday to get to the beginning on the week
Total countable days = (25 * 3) + 2 + 1 = 75 + 3 = 78 countable days
You could create a loop which goes to the next day in the $count_only array, from the $start_date and stopping (returning from the function) upon reaching the $end_date.
function number_of_days_between($start_date, $finish_date, $count_only) {
$count = 0;
$start = new DateTime("#$start_date");
$end = new DateTime("#$finish_date");
$days = new InfiniteIterator(new ArrayIterator($count_only));
foreach ($days as $day) {
$count++;
$start->modify("next $day");
if ($start > $end) {
return $count;
}
}
}
Of course there is a way :-)
The days that have been elapsed is simply
$elapsed_days = floor(($finish_date-$start_date) / 86400);
This will not get the result you need. What you could do is the following (pesudo)code:
$elapsed_days = floor(($finish_date-$start_date) / 86400);
for(int $i=0;$i<$elapsed_days;$i++){
$act_day_name = strtolower(date('l',$start_date+$i*86400));
if(in_array($act_day_name,$count_only){
// found matching day
}
}
What I do:
I iterate over every day which is between the both dates, get the day-name with date('l'); and check if it's within the array.
There may be some fine tuning need to be done, but this should get you going.
Just a bit faster approach than "iterating through all days":
$count_only = array(1, 3, 5); // days numbers from getdate() function
$start_date = 1298572294;
$finish_date = 1314210695;
function days($start_date, $finish_date, $count_only)
{
$cnt = 0;
// iterate over 7 days
for ($deltaDays = 0; $deltaDays < 7; $deltaDays++)
{
$rangeStart = $start_date + $deltaDays * 86400;
// check the weekday of rangeStart
$d = getDate($rangeStart);
if (in_array($d['wday'], $count_only))
{
$cnt += ceil(($finish_date - $rangeStart) / 604800);
}
}
return $cnt;
}
The idea is to count number of weeks using some additional offsets for mondays, tuesdays, wednesdays etc.

how to find the last monday of the month

I'm not sure how to go about this one. I'm building a calendar in PHP and need users to be able to add a repeating event that follows the following rule:
Last [DOW] of the month (so Last [Mon/Tues/Wed/etc] of the week)
I've got the rule itself stored, I'm just not sure how best to extrapolate the last Mon/Tue/Wed of the month in PHP? I fell like i'm making this more complicated than it needs to be.
Assuming you have variables for $month=4, $dow=3 and $year=2011 how would I best do this?
For everything date-related that you can express in proper English but have a hard time expressing using numbers, strtotime is your best friend.
echo strtotime("last Monday of June 2011");
This returns a timestamp that you can use as the second parameter to date and the likes to get a proper, human-readable date. Since it's a built-in function written in C, this solution is also much faster than almost anything else you could come up with written in PHP (though I'm quite sure it wouldn't matter much in a real-world scenario).
So assuming you have $month=4, $dow=3 and $year=2011, you'll need an array mapping $month values to their English textual representations and another array mapping $dow values to their textual representations.
Here's an alternative:
<?
function lastDayOfMonth($month, $year) {
switch ($month) {
case 2:
# if year is divisible by 4 and not divisible by 100
if (($year % 4 == 0) && ($year % 100) > 0)
return 29;
# or if year is divisible by 400
if ($year % 400 == 0)
return 29;
return 28;
case 4:
case 6:
case 9:
case 11:
return 30;
default:
return 31;
}
}
function lastDayOfWeek($month, $year, $dow) {
$d = new DateTime();
#Finding the last day of month
$d = $d->setDate($year, $month, lastDayOfMonth($month, $year));
#Getting the day of week of last day of month
$date_parts = getdate($d->getTimestamp());
$diff = 0;
#if we can't find the $dow in this week... (cause it would lie on next month)
if ($dow > $date_parts['wday']) {
# ...we go back a week.
$diff -= 7;
}
return $date_parts['mday'] + $diff + ($dow - $date_parts['wday']);
}
# checking the algorithm for this month...
for ($i=0; $i < 7; $i++) {
echo lastDayOfWeek(6,2011,$i) . "<br>";
}
?>
I have a generic function for you to calculate the nth day of a month. Hope this could help you to resolve your issue.
function get_Nth_dow($dow, $occurence, $m, $y)
{
$numdays = date('t', mktime(0, 0, 0, $m, 1, $y));
$add = 7 * ($occurence - 1);
$firstdow = date('w', mktime(0, 0, 0, $m, 1, $y));
$diff = $firstdow - $dow;
$day_of_month = 1;
if ($diff > 0)
{
$day_of_month += ($add - $diff);
}
elseif ($diff < $numdays)
{
$day_of_month -= ($diff - $add);
}
return $day_of_month;
}
$DOW = day of the week (0 = Sunday, 6 = Saturday).
$X = occurence (1 = first, 2 = third, etc..). If the given month does
not have the occurrence, then it will return the last. For example, if
you ask for the 7th occurrence of Friday, it will return the last
Friday of the month.
$M = month
$Y = year
Example, get_Nth_DOW(2,3,7,2009) will return the third Tuesday of 7th 2009.

Categories