I am practicing with dates in php. I a bit of a newbie so bear my ignorance
I am trying to see when a time is before noon.
So I have a variable coming in with this format 2014-03-07 13:28:00.000
I get the time like this
$submissonTime = date('H:i:s', strtotime($value['job_submission_date']));
then I want to set another variable as $noon and i am doing this:
$noon = date('H:i:s', '12:00:00.000');
However the value of noon is 12:00:12
what i want to do is basically:
if($submissionTime <= $noon){
//do my stuff
}
NB I want to enter the if statement when even when it is 12:00:00 and stop entering when it is 12:00:01
Any help please?
Try
$noon = date('Y-m-d 12:00:00'); // today noon with date
$submissonTime = date('Y-m-d H:i:s', strtotime($value['job_submission_date']));
if(strtotime($submissonTime) <= strtotime($noon)){
//do my stuff
}
if you want to compare only time use both format
$noon = date('12:00:00');
$submissonTime = date('H:i:s', strtotime($value['job_submission_date']));
if (date("A") == "AM")
{
// AM-Code
} else {
// PM-Code
}
Why don't you go with only one string of code getting the hour?
$Hour = date("G"); //24-hour format of an hour without leading zeros
if($Hour < 12) {
// do the code
}
Or in your case
$Hour = date("G", strtotime($value['job_submission_date']));
update
If you need 12:00:00 and not 12:00:01 and later on, you will need to define minutes and seconds:
$Hour = date("G"); //24-hour format of an hour without leading zeros
$Minute = intval(date("i")); // will give minutes without leading zeroes
$Second = intval(date("s"));
if(($Hour < 12) || ($Hour == 12 && $Minute == 0 && Second == 0)) {
// do the code
}
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).
I know about the unwanted behaviour of PHP's function
strtotime
For example, when adding a month (+1 month) to dates like: 31.01.2011 -> 03.03.2011
I know it's not officially a PHP bug, and that this solution has some arguments behind it, but at least for me, this behavior has caused a lot waste of time (in the past and present) and I personally hate it.
What I found even stranger is that for example in:
MySQL: DATE_ADD('2011-01-31', INTERVAL 1 MONTH) returns 2011-02-28
or
C# where new DateTime(2011, 01, 31).AddMonths(1); will return 28.02.2011
wolframalpha.com giving 31.01.2013 + 1 month as input; will return Thursday, February 28, 2013
It sees to me that others have found a more decent solution to the stupid question that I saw alot in PHP bug reports "what day will it be, if I say we meet in a month from now" or something like that. The answer is: if 31 does not exists in next month, get me the last day of that month, but please stick to next month.
So MY QUESTION IS: is there a PHP function (written by somebody) that resolves this not officially recognized bug? As I don't think I am the only one who wants another behavior when adding / subtracting months.
I am particulary interested in solutions what also work not just for the end of the month, but a complete replacement of strtotime. Also the case strotime +n months should be also dealt with.
Happy coding!
what you need is to tell PHP to be smarter
$the_date = strtotime('31.01.2011');
echo date('r', strtotime('last day of next month', $the_date));
$the_date = strtotime('31.03.2011');
echo date('r', strtotime('last day of next month', $the_date));
assuming you are only interesting on the last day of next month
reference - http://www.php.net/manual/en/datetime.formats.relative.php
PHP devs surely don't consider this as bug. But in strtotime's docs there are few comments with solutions for your problem (look for 28th Feb examples ;)), i.e. this one extending DateTime class:
<?php
// this will give us 2010-02-28 ()
echo PHPDateTime::DateNextMonth(strftime('%F', strtotime("2010-01-31 00:00:00")), 31);
?>
Class PHPDateTime:
<?php
/**
* IA FrameWork
* #package: Classes & Object Oriented Programming
* #subpackage: Date & Time Manipulation
* #author: ItsAsh <ash at itsash dot co dot uk>
*/
final class PHPDateTime extends DateTime {
// Public Methods
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Calculate time difference between two dates
* ...
*/
public static function TimeDifference($date1, $date2)
$date1 = is_int($date1) ? $date1 : strtotime($date1);
$date2 = is_int($date2) ? $date2 : strtotime($date2);
if (($date1 !== false) && ($date2 !== false)) {
if ($date2 >= $date1) {
$diff = ($date2 - $date1);
if ($days = intval((floor($diff / 86400))))
$diff %= 86400;
if ($hours = intval((floor($diff / 3600))))
$diff %= 3600;
if ($minutes = intval((floor($diff / 60))))
$diff %= 60;
return array($days, $hours, $minutes, intval($diff));
}
}
return false;
}
/**
* Formatted time difference between two dates
*
* ...
*/
public static function StringTimeDifference($date1, $date2) {
$i = array();
list($d, $h, $m, $s) = (array) self::TimeDifference($date1, $date2);
if ($d > 0)
$i[] = sprintf('%d Days', $d);
if ($h > 0)
$i[] = sprintf('%d Hours', $h);
if (($d == 0) && ($m > 0))
$i[] = sprintf('%d Minutes', $m);
if (($h == 0) && ($s > 0))
$i[] = sprintf('%d Seconds', $s);
return count($i) ? implode(' ', $i) : 'Just Now';
}
/**
* Calculate the date next month
*
* ...
*/
public static function DateNextMonth($now, $date = 0) {
$mdate = array(0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
list($y, $m, $d) = explode('-', (is_int($now) ? strftime('%F', $now) : $now));
if ($date)
$d = $date;
if (++$m == 2)
$d = (($y % 4) === 0) ? (($d <= 29) ? $d : 29) : (($d <= 28) ? $d : 28);
else
$d = ($d <= $mdate[$m]) ? $d : $mdate[$m];
return strftime('%F', mktime(0, 0, 0, $m, $d, $y));
}
}
?>
Here's the algorithm you can use. It should be simple enough to implement yourself.
Have the original date and the +1 month date in variables
Extract the month part of both variables
If the difference is greater than 1 month (or if the original is December and the other is not January) change the latter variable to the last day of the next month. You can use for example t in date() to get the last day: date( 't.m.Y' )
Had the same issue recently and ended up writing a class that handles adding/subtracting various time intervals to DateTime objects.
Here's the code:
https://gist.github.com/pavlepredic/6220041#file-gistfile1-php
I've been using this class for a while and it seems to work fine, but I'm really interested in some peer review. What you do is create a TimeInterval object (in your case, you would specify 1 month as the interval) and then call addToDate() method, making sure you set $preventMonthOverflow argument to true. The code will make sure that the resulting date does not overflow into next month.
Sample usage:
$int = new TimeInterval(1, TimeInterval::MONTH);
$date = date_create('2013-01-31');
$future = $int->addToDate($date, true);
echo $future->format('Y-m-d');
Resulting date is:
2013-02-28
Here is an implementation of an improved version of Juhana's answer above:
<?php
function sameDateNextMonth(DateTime $createdDate, DateTime $currentDate) {
$addMon = clone $currentDate;
$addMon->add(new DateInterval("P1M"));
$nextMon = clone $currentDate;
$nextMon->modify("last day of next month");
if ($addMon->format("n") == $nextMon->format("n")) {
$recurDay = $createdDate->format("j");
$daysInMon = $addMon->format("t");
$currentDay = $currentDate->format("j");
if ($recurDay > $currentDay && $recurDay <= $daysInMon) {
$addMon->setDate($addMon->format("Y"), $addMon->format("n"), $recurDay);
}
return $addMon;
} else {
return $nextMon;
}
}
This version takes $createdDate under the presumption that you are dealing with a recurring monthly period, such as a subscription, that started on a specific date, such as the 31st. It always takes $createdDate so late "recurs on" dates won't shift to lower values as they are pushed forward thru lesser-valued months (e.g., so all 29th, 30th or 31st recur dates won't eventually get stuck on the 28th after passing thru a non-leap-year February).
Here is some driver code to test the algorithm:
$createdDate = new DateTime("2015-03-31");
echo "created date = " . $createdDate->format("Y-m-d") . PHP_EOL;
$next = sameDateNextMonth($createdDate, $createdDate);
echo " next date = " . $next->format("Y-m-d") . PHP_EOL;
foreach(range(1, 12) as $i) {
$next = sameDateNextMonth($createdDate, $next);
echo " next date = " . $next->format("Y-m-d") . PHP_EOL;
}
Which outputs:
created date = 2015-03-31
next date = 2015-04-30
next date = 2015-05-31
next date = 2015-06-30
next date = 2015-07-31
next date = 2015-08-31
next date = 2015-09-30
next date = 2015-10-31
next date = 2015-11-30
next date = 2015-12-31
next date = 2016-01-31
next date = 2016-02-29
next date = 2016-03-31
next date = 2016-04-30
I have solved it by this way:
$startDate = date("Y-m-d");
$month = date("m",strtotime($startDate));
$nextmonth = date("m",strtotime("$startDate +1 month"));
if((($nextmonth-$month) > 1) || ($month == 12 && $nextmonth != 1))
{
$nextDate = date( 't.m.Y',strtotime("$initialDate +1 week"));
}else
{
$nextDate = date("Y-m-d",strtotime("$initialDate +1 month"));
}
echo $nextDate;
Somewhat similar to the Juhana's answer but more intuitive and less complications expected. Idea is like this:
Store original date and the +n month(s) date in variables
Extract the day part of both variables
If days do not match, subtract number of days from the future date
Plus side of this solution is that works for any date (not just the border dates) and it also works for subtracting months (by putting - instead of +).
Here is an example implementation:
$start = mktime(0,0,0,1,31,2015);
for ($contract = 0; $contract < 12; $contract++) {
$end = strtotime('+ ' . $contract . ' months', $start);
if (date('d', $start) != date('d', $end)) {
$end = strtotime('- ' . date('d', $end) . ' days', $end);
}
echo date('d-m-Y', $end) . '|';
}
And the output is following:
31-01-2015|28-02-2015|31-03-2015|30-04-2015|31-05-2015|30-06-2015|31-07-2015|31-08-2015|30-09-2015|31-10-2015|30-11-2015|31-12-2015|
function ldom($m,$y){
//return tha last date of a given month based on the month and the year
//(factors in leap years)
$first_day= strtotime (date($m.'/1/'.$y));
$next_month = date('m',strtotime ( '+32 day' , $first_day)) ;
$last_day= strtotime ( '-1 day' , strtotime (date($next_month.'/1/'.$y)) ) ;
return $last_day;
}
I have to try and work out if a unix timestamp is between 21 days and 49 days from the current date. Can anyone help me to work this out? Thanks!
Welcome to SO!
This should do it:
if (($timestamp > time() + 1814400) && ($timestamp < time() + 4233600)) {
// date is between 21 and 49 days in the FUTURE
}
This can be simplified, but I thought you wanted to see a more verbose example :)
I get 1814400 from 21*24*60*60 and 4233600 from 41*24*60*60.
Edit: I assumed future dates. Also note time() returns seconds (as opposed to milliseconds) since the Epoch in PHP.
This is how you do it in the past (since you edited your question):
if (($timestamp > time() - 4233600) && ($timestamp < time() - 1814400)) {
// date is between 21 and 49 days in the PAST
}
The PHP5 DateTime class is very suited to these sort of tasks.
$current = new DateTime();
$comparator = new DateTime($unixTimestamp);
$boundary1 = new DateTime();
$boundary2 = new DateTime();
$boundary1->modify('-49 day'); // 49 days in the past
$boundary2->modify('-21 day'); // 21 days in the past
if ($comparator > $boundary1 && $comparator < $boundary2) {
// given timestamp is between 49 and 21 days from now
}
strtotime is very useful in these situations, since you can almost speak natural english to it.
$ts; // timestamp to check
$d21 = strtotime('-21 days');
$d49 = strtotime('-49 days');
if ($d21 > $ts && $ts > $d49) {
echo "Your timestamp ", $ts, " is between 21 and 49 days from now.";
}
i am develop a webpage in that i need to calculate x days from a specified date , The problem is we exclude the saturday and sunday . For example $Shipdate = '06/30/2009' and the x is 5 means , i want the answer '7' [ie 30 is tuesday so after 5 days it will be sunday , so there is two holiday(saturday and sunday) so we add 5+2(for saturday and sunday)]=7. Please help me to find out , Thanks in advance.
Generally you will need to be able to specify a calendar with significant days excluded. Consider Christmas Day or public holidays. This appears to be code that will consider public holidays, you need to modify it or parameterise it with your set of holidays.
<?php
// ** Set Beginning and Ending Dates, in YYYY-mm-dd format **
$begin = '2008-01-01';
$end = '2008-03-31';
$begin_mk = strtotime("$begin");
$end_mk = strtotime("$end");
// ** Calculate number of Calendar Days between the two dates
$datediff = ( $end_mk > $begin_mk ? ( $end_mk - $begin_mk ) : ( $begin_mk - $end_mk ) );
$days = ( ( $datediff / 3600 ) / 24 );
$days = $days + 1; // to be inclusive of last date;
// ** Count days excluding Sundays **
$iteration = 0;
$numDaysExSunday = 0;
for ($i=1; $i<=$days; $i++) {
$weekday = date("w", strtotime("$begin + $iteration day"));
echo "$weekday<br>";
**// i change only this line to add saturday**
if ($weekday !== '0' && $weekday !== '6') {
$numDaysExSunday++;
}
$iteration++;
}
// ** Output number of days excluding Sundays **
echo $numDaysExSunday;
?>
i take it from
http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_23499410.html
the solution Excluding Sundays but need to change only one line to exclude saturday i write it in the code
function Weekdays($start,$end){
$days=0;
if ( $end <= $start ) {
// This is invalid data.
// You may consider zero to be valid, up to you.
return; // Or throw an error, whatever.
}
while($start<$end){
$dayofweek = date('w',$start);
if( 6!= $dayofweek && 0 != $dayofweek){
$days++;
}
$start = strtotime('+1 day',$start);
}
return $days;
}
You may want to tweak it a bit depending on whether you want to count it as one day or zero if the start is the same day as the end.