Okay, how do I explain this. Let say I have an array of numbers/days.
$days = array(31,24,08,14,17);
Now I have 4 cycles with particular day range.
Cycle 1: 23-01
Cycle 2: 02-08
Cycle 3: 09-15
Cycle 4: 16-22
So now I want to count how many of the value from the days array fall on each cycle.
Cycle 1 will count as 2 since 31 and 24 falls within 23-01
Cycle 2 will count 1 (08)
Cycle 3 will count 1 (14)
Cycle 4 will count 1 (17)
The numbers are from days of a given date and I just have to count the days that fall in. I already can count from cycle 2-4 but having problem with cycle 1.
$cycle1 = 0;
$cycle2 = 0;
$cycle3 = 0;
$cycle4 = 0;
$days = array(31,24,08,14,17);
foreach ($days as $day)
{
if ($day >= 23 && $day <= 01)
{
$cycle1++;
}
if ($day >= 02 && $day <= 08)
{
$cycle2++;
}
if ($day >= 09 && $day <= 15)
{
$cycle3++;
}
if ($day >= 16 && $day <= 22)
{
$cycle4++;
}
}
Thanks, hope someone can shed some light on how to do it via only date('d',strtotime(datestring)); range.
<?php
$days = array(31,24,14,17,1,16);
/*
Cycle 2: 02-08 =>() = 0
Cycle 3: 09-15 =>(14) = 1
Cycle 4: 16-22 =>(17,16) = 2
Cycle 1: 23-01 =>(31,24,1) = 3
*/
$cycle1 = $cycle2 = $cycle3 = $cycle4 = 0;
foreach ($days as $day)
{
if($day >= 23)
$cycle1++;
elseif($day >= 16)
$cycle4++;
elseif($day >= 9)
$cycle3++;
elseif($day >= 2)
$cycle2++;
else
$cycle1++;
}
echo "cycle1=$cycle1<br>cycle2=$cycle2<br>cycle3=$cycle3<br>cycle4=$cycle4<br>";
Related
I made this switch, but I dont know this last step (the ?? and the comments).
If someone can help me, thanks a lot!
<?
$nuDatumTijd = date("Y-m-d H:i:s");
$nuUur = date("H");
switch(true)
{
case $nuUur > 8 && $nuUur < 13:
$aantSecErbij = ??; // number of seconds untill the first next 13:00
$weerOp = date($nuDatumTijd,$aantSecErbij);
echo $weerOp;
break;
case $nuUur > 12 && $nuUur < 18:
$aantSecErbij = ??; // number of seconds untill the first next 19:00
$weerOp = date($nuDatumTijd,$aantSecErbij);
echo $weerOp;
break;
case $nuUur > 17 && $nuUur < 22:
$aantSecErbij = ??; // number of seconds untill the first next 9:00 (so that is the next day)
$weerOp = date($nuDatumTijd,$aantSecErbij);
echo $weerOp;
break;
}
?>
I now have fixed it this way, thanks for your input:
$nuUur = date("H");
if ($nuUur > 8 && $nuUur < 13)
{
$weerOp = strtotime('today 13:00');
$weerOpNetjes = date('Y-m-d H:i:s', $weerOp);
echo $weerOpNetjes;
}
elseif ($nuUur > 12 && $nuUur < 18)
{
$weerOp = strtotime('today 19:00');
$weerOpNetjes = date('H:i', $weerOp);
echo $weerOpNetjes;
}
elseif ($nuUur > 17 && $nuUur < 22)
{
$weerOp = strtotime('tomorrow 9:00');
$weerOpNetjes = date('H:i', $weerOp);
echo $weerOpNetjes;
}
switch-case can be used this way too, no problem about that.
$aantSecErbij = ??; // number of seconds untill the first next 13:00
If this means the number of seconds until today's 1pm then the following will get you the timestamp of today's 1pm.
$now = getdate();
$time1pm = mktime(13, 0, 0, $now['mon'], $now['mday'], $now['year']);
If it means the number of seconds between now and today's 1pm then you need to subtract with current timestamp.
$now = getdate();
$diff1pm = mktime(13, 0, 0, $now['mon'], $now['mday'], $now['year']) - time();
.
$aantSecErbij = ??; // number of seconds untill the first next 9:00 (so that is the next day)
For the next day you can add 1 to the day part and don't have to worry about the end of month. PHP will figure out the right date for you.
$now = getdate();
$tomorrow9am = mktime(9, 0, 0, $now['mon'], $now['mday'] + 1, $now['year']);
Ok.. so I've created myself a messy problem.
So I have a jquery slider that shows 5 slides of content
1) -2 hours ago
2) -1 hour ago
3) (0) present
4) +1 hours
5) +2 hours
The content for each slide is decided by what time of day it is. However when it comes to trying to go back/forwards 1 to 2 hours during the run up to midnight and after midnight the whole script breaks, and kills the site.
<?php
$h = date('G', strtotime ("-2 hour")); //set variable $h to the hour of the day.
$m = date('i', strtotime ("-2 hour")); //set variable $m to the min of the hour.
$d = date('w', strtotime ("-2 hour")); //set variable $d to the day of the week.
// SATURDAY SCHEDULE
if ($d == 6 && $h >= 0 && $h < 07) $file ='earlyhours.php';
else if ($d == 6 && $h >= 07 && $h < 09) $file ='breakfast.php';
else if ($d == 6 && $h >= 09 && $h < 12) $file ='throughthemorning.php';
else if ($d == 6 && $h >= 12 && $h < 13) $file ='rewind.php';
else if ($d == 6 && $h >= 13 && $h < 17 && $m <= 30) $file ='nonstop.php';
else if ($d == 6 && $h >= 17 && $m >= 30 && $h <21) $file ='livetrend.php';
else if ($d == 6 && $h >= 17 && $m >= 35 && $h < 21) $file ='nonstop.php';
else if ($d == 6 && $h >= 21 && $h < 18) $file ='gennation.php';
else if ($d == 6 && $h >= 23) $file ='earlyhours.php';
else if ($d == 7 && $h >= 0) $file ='earlyhours.php';
require $_SERVER['DOCUMENT_ROOT'] . '/collection/profiles/' . $file . '';
?>
As you can see it figures the time and then drops the correct file in - there's five of these for everyday of the week (-2.php, -1.php, 0.php, 1.php, 2.php).
Does anybody have a solution? Ideally I need to stop the break, but I don't want my visitors to be scrolling +1 / 2 or -1 / 2 hours on for the same days rotation when it nears, and steps over midnight.
For example, right now the code is broken on -2.php until at least 2am (my timezone) so that it back track.
I've totally burnt myself out trying to figure this one out.
The problems arising from the change of day can become intractable. I'd tackle this a different way. Start by calculating the day and hour for the five periods your interested in and use DateTime to do the heavy lifting. Then, use a function to provide the schedule item for a particular day/time combination.
Here's a skeleton
<?php
date_default_timezone_set('Pacific/Auckland');
$now = new DateTime();
$oneHour = new DateInterval('PT1H');
$minusOne = (clone $now);
$minusOne->sub($oneHour);
$minusTwo = (clone $minusOne);
$minusTwo->sub($oneHour);
$plusOne = (clone $now);
$plusOne->add($oneHour);
$plusTwo = (clone $plusOne);
$plusTwo->add($oneHour);
echo returnFile($minusTwo);
echo returnFile($minusOne);
echo returnFile($now);
echo returnFile($plusOne);
echo returnFile($plusTwo);
function returnFile(DateTime $t) {
$day = $t->format('D');
$hour = $t->format('G');
// echo "Day:$day, Hour: $hour;<br>";
switch ($day) {
case 'Mon':
if ($hour<7) {
// Small hours Monday...
$filename = "smallMonday.html";
break;
}
if ($hour<12) {
// Monday morning
$filename = "morningMonday.html";
break;
}
break;
case 'Tue':
if ($hour >=23) {
// Late Tuesday
$filename = "lateTuesday.html";
}
default:
$filename = "Some other time";
}
return $filename;
}
?>
I haven't put in a complete schedule - you can work that out.
If you're using PHP 5.5 or later you can use DateTimeImmutable instead of DateTime which does away with all the cloning.
There's a fiddle here
Get rid of the leading zeros in your comparisons. Those are octal numbers and not decimals. You won't get the results you expect.
// 09 is not a valid octal number. It gets converted to zero in decimal.
else if ($d == 6 && $h >= 07 && $h < 09)
..
else if ($d == 6 && $h >= 09 && $h < 12) $file ='throughthemorning.php';
I have given up on trying to do this in MySQL and instead I'm going to inject the result into my array of results (which is used later in a JS app).
I have a loop to go through each result:
$data = $result->fetchAll();
foreach($data as $i => $row) {
// Something
$data[$i]['Age'] = $row['Age'];
}
I want it to add up the seconds between $data[$i]['Age'] which is a datetime and the current datetime.
Normally this would be easy but how do I exclude weekends AND time between 16:30 and 07:30?
I don't think this is too specific or uninteresting, so here is the answer thanks to one of my colleagues:
public static function calculateTime($startDate, $endDate) {//Returns Seconds Passed
date_default_timezone_set('Europe/London');
//Opening Hours - Can pull from database depending on users working hours
$workingHoursOpen = new DateTime('07:30:00');
$workingHoursClose = new DateTime('16:30:00');
//Time worked from and to
$timeStarted = strtotime(date('H:i:s', strtotime($endDate)));
$timeFinished = strtotime(date('H:i:s', strtotime($startDate)));
$workingSeconds = $workingHoursClose->getTimestamp() - $workingHoursOpen->getTimestamp();
$workingSecondsv2 = $timeFinished - $timeStarted;
//Option to send array of holidays (3rd param)
$workingDays = Util::getWorkingDays(date('Y-m-d', strtotime($startDate)), date('Y-m-d', strtotime($endDate)), array());
$totalWorkingSeconds = $workingDays * $workingSeconds; //Working days * 9 hours
$secondsClosed = 0;
$i = 0;
while ($i < $workingDays) {
$secondsClosed = $secondsClosed - (15 * 3600);
$i++;
}
$secondsPassed = ($workingSecondsv2 - $totalWorkingSeconds) + (9 * 3600);
$secondsPassed = -1 * ($secondsPassed); // Invert number (was giving -XX)
return $secondsPassed;
}
public static function getWorkingDays($startDate, $endDate, $holidays) {
// do strtotime calculations just once
$endDate = strtotime($endDate);
$startDate = strtotime($startDate);
$days = ($endDate - $startDate) / 86400 + 1;
$no_full_weeks = floor($days / 7);
$no_remaining_days = fmod($days, 7);
//It will return 1 if it's Monday,.. ,7 for Sunday
$the_first_day_of_week = date("N", $startDate);
$the_last_day_of_week = date("N", $endDate);
//---->The two can be equal in leap years when february has 29 days, the equal sign is added here
//In the first case the whole interval is within a week, in the second case the interval falls in two weeks.
if ($the_first_day_of_week <= $the_last_day_of_week) {
if ($the_first_day_of_week <= 6 && 6 <= $the_last_day_of_week)
$no_remaining_days--;
if ($the_first_day_of_week <= 7 && 7 <= $the_last_day_of_week)
$no_remaining_days--;
}
else {
// (edit by Tokes to fix an edge case where the start day was a Sunday
// and the end day was NOT a Saturday)
// the day of the week for start is later than the day of the week for end
if ($the_first_day_of_week == 7) {
// if the start date is a Sunday, then we definitely subtract 1 day
$no_remaining_days--;
if ($the_last_day_of_week == 6) {
// if the end date is a Saturday, then we subtract another day
$no_remaining_days--;
}
} else {
// the start date was a Saturday (or earlier), and the end date was (Mon..Fri)
// so we skip an entire weekend and subtract 2 days
$no_remaining_days -= 2;
}
}
//The no. of business days is: (number of weeks between the two dates) * (5 working days) + the remainder
//---->february in none leap years gave a remainder of 0 but still calculated weekends between first and last day, this is one way to fix it
$workingDays = $no_full_weeks * 5;
if ($no_remaining_days > 0) {
$workingDays += $no_remaining_days;
}
//We subtract the holidays
foreach ($holidays as $holiday) {
$time_stamp = strtotime($holiday);
//If the holiday doesn't fall in weekend
if ($startDate <= $time_stamp && $time_stamp <= $endDate && date("N", $time_stamp) != 6 && date("N", $time_stamp) != 7)
$workingDays--;
}
return $workingDays;
}
Works 100% and can be expanded to bring in work hours from a database.
I have calculate the employee experience(months) in joining date to current date. I want every **last four months in a year** (eg 9-12 and 21-24 and 33-36 etc....) employeeexperience have shown as different color.(php code)
First year calculation has no problem after the years the conditions is not satisfy the `above criteria.`
This is my code but i need satisfy above criteria.
if($months % 9 == 0 || $months % 10 == 0 || $months % 11 == 0 || $months % 12 == 0)
{
<span style="color:green;"><?php echo $u_tot_exp;?><span>
}
else
{
<span style="color:black;"><?php echo $u_tot_exp;?><span>
}
The problem is your misunderstanding of the modulus operator %. You're using $months % 11 == 0 to mean "if the month is the eleventh in a year", but that isn't what it means. It actually means "if the month is a multiple of eleven after the first month". So this means November one year (the eleventh month), then October the next (the 22nd) then September (the 33rd).
The effect multiplies with % 10 or % 9. If we assume that the first year is 2014, it will select the following months:
2014: September, October, November, December
2015: June, August, October, December
2016: March, June, September, December
The % operator works by calculating the remainder when the number on the left is divided by the number on the right. Since we're working in years, we always need to divide by 12. You then want to check if the number left over is between 3 (i.e. September) and 0 (i.e. December).
$monthsToGo = $months % 12; // months remaining in the year
if ($monthsToGo >= 3) { // i.e. after September
echo "<span style=\"color:green;\">$u_tot_exp<span>";
} else {
echo "<span style=\"color:black;\">$u_tot_exp<span>";
}
Note that I have also fixed the code that outputs your HTML.
**Finally i have get the result using this code.**
<?php
$currentDate = date("d-m-Y");
// joining_date is name of field in DB.
$date1 = date_create("".$u_joining_date.""); //
$date2 = date_create("".$currentDate."");
$diff12 = date_diff($date2, $date1);
$hub_days = $diff12->days;
$months = $diff12->m;
$years = $diff12->y;
$tot_months = (($years * 12) + $months);
//$monthsToGo = $months % 12;
// months remaining in the year
//$monthsmod = $monthsToGo % 10;
if ($tot_months != 0)
{
if($months % 9 == 0 || $months % 10 == 0 || $months % 11 == 0 || $months % 12 == 0)
{
?>
<span style="color:green;"><?php echo $tot_months;?>month(s)<span>
<?php
}
else
{
?>
<span style="color:black;"><?php echo $tot_months;?>month(s)<span>
<?php
}
}
?>
I have asked this question before and accepted the answer but now I found that the php version on our server is 5.2 and DateTime::diff() is not working on that.
I want to calculate person's age in months plus days using date of birth and a given date.
Date Format Input: Y-m-d (example: 1986-08-23)
Output:
5 months and 20 days old.
150 months and 4 days old.
285 months and 30 days old.
Thanks
Here's a solution that'll accurately determine the number of months and number of days, including leap years. It assumes that things like July 21 to August 21 is 1 month 0 days, not 1 month 1 day, and that March 21 to April 20 is 0 months 30 days, not 1 month 0 days. The latter in both cases is what occurs when you just do a straight divide by 30 to calculate months.
I'm sure there's a better way to optimize the function, but it gets the job done:
function diff_date($start_date, $end_date) {
list($start_year, $start_month, $start_day) = explode('-', $start_date);
list($end_year, $end_month, $end_day) = explode('-', $end_date);
$month_diff = $end_month - $start_month;
$day_diff = $end_day - $start_day;
$months = $month_diff + ($end_year - $start_year) * 12;
$days = 0;
if ($day_diff > 0) {
$days = $day_diff;
}
else if ($day_diff < 0) {
$days = $end_day;
$months--;
if ($month_diff > 0) {
$days += 30 - $start_day;
if (in_array($start_month, array(1, 3, 5, 7, 8, 10, 12))) {
$days++;
}
else if ($start_month == 2) {
if (($start_year % 4 == 0 && $start_year % 100 != 0) || $start_year % 400 == 0) {
$days--;
}
else {
$days -= 2;
}
}
if (in_array($end_month - 1, array(1, 3, 5, 7, 8, 10, 12))) {
$days++;
}
else if ($end_month - 1 == 2) {
if (($end_year % 4 == 0 && $end_year % 100 != 0) || $end_year % 400 == 0) {
$days--;
}
else {
$days -= 2;
}
}
}
}
return array($months, $days);
}
list($months, $days) = diff_date('1984-05-26', '2010-04-29');
print $months . ' months and ' . $days . ' days old.';
Output:
314 months and 3 days old.
Edit: I tried to get rid of redundancy in the code, and forgot to rename a variable. This function will now work correctly for diff_date('2010-06-29', '2011-07-01').
Edit: Now correctly works for end months occurring after months with 31 or 28/29 days.
Use your favorite date parsing function (strtotime, strptime, mktime) to get an UNIX timestamp out of the date, then the interval ($now - $then)... and then work out how many seconds there are in a month and use that to calculate how many months the person has lived (division and remainder are your friends).
This'll give you a mathematically precise value that should be close enough to real life too.