Related
I want to implement Birthday countdown time. Normally, birthday normally takes place once in a year eg within 365 days. I downloaded this code from stackoverflow to check the next birthday day of someone who was born on august 22 1982. the days count down should be less than 365 days but the code below is giving a higher value with negative sign.
$rem = strtotime('1982-22-08') - time();
$day = floor($rem / 86400);
$hr = floor(($rem % 86400) / 3600);
$min = floor(($rem % 3600) / 60);
$sec = ($rem % 60);
if($day) echo "$day Days ";
if($hr) echo "$hr Hours ";
if($min) echo "$min Minutes ";
if($sec) echo "$sec Seconds ";
echo "Remaining...";
the next birthday countdown should be less than 365 days
Thanks
Its because you have wrong date format in strtotime and return nothing.
Documentation says
strtotime — Parse about any English textual datetime description into
a Unix timestamp
So if you use
strtotime('08/22/18')
it will work.
Also you should take actual year if you want say "hey your birthday in this is will be..."
What about trying this method:
$birth_month = 8;
$birth_day = 22;
$year = date('Y');
$month = date('n');
$day = date('j');
if ($birth_month < $month || ($birth_month == $month && $birth_day < $day))
$year++;
$target = mktime(0,0,0,$birth_month,$birth_day,$year);
$today = time();
$rem = abs($target - $today);
$days = (int)($rem/86400);
echo "Remaining days till next birthday: $days days!";
This question already has answers here:
Finding the number of days between two dates
(34 answers)
Closed 3 months ago.
I want to do is to count the days between two dates excluding the weekends and i;m done doing that using the function below. But whenever the $startDate is greater than the $endDate i can't get the proper result. I try to use if ($startDate>$endDate) and i'm stock with that condition and honestly don't know what is the next step.
function getWorkingDays($startDate,$endDate){
// do strtotime calculations just once
$startDate = strtotime($startDate);
$endDate = strtotime($endDate);
//The total number of days between the two dates. We compute the no. of seconds and divide it to 60*60*24
//We add one to inlude both dates in the interval.
$days = ($endDate - $startDate) / 86400 + 0;
$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);
// If one of the value is empty it will return "0"
if ($startDate == '' || $endDate == '')
return "0"; // Default value
//---->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;
}
return $workingDays;
}
$startTimeStamp = strtotime("2011/07/01");
$endTimeStamp = strtotime("2011/07/17");
$timeDiff = abs($endTimeStamp - $startTimeStamp);
$numberDays = $timeDiff/86400; // 86400 seconds in one day
// and you might want to convert to integer
$numberDays = intval($numberDays);
OR
function dateDiff($start, $end) {
$start_ts = strtotime($start);
$end_ts = strtotime($end);
$diff = $end_ts - $start_ts;
return round($diff / 86400);
}
echo dateDiff("2011-02-15", "2012-01-16").'days';
//Get number of days deference between current date and given date.
echo dateDiff("2011-02-15", date('Y-m-d')).'days';
For Count days excluding use below code
$start = new DateTime('7/17/2017');
$end = new DateTime('7/24/2017');
$oneday = new DateInterval("P1D");
$daysName = array('Mon', 'Tue', 'Wed', 'Thu', 'Fri');
$days = array();
foreach(new DatePeriod($start, $oneday, $end->add($oneday)) as $day) {
$day_num = $day->format("N"); /* 'N' number days 1 (mon) to 7 (sun) */
if($day_num < 6) { /* weekday */
$days[$day->format("Y-m-d")] = date('D', strtotime($day->format("Y-m-d")));;
}
}
echo "<pre>";
print_r($days);
echo count($days);
This will check whether start date is less than end date. If yes, then it will display the days.
<?php
if($days = getWorkingDays("2017-05-01","2018-01-01")){
echo $days;
}
function getWorkingDays($startDate,$endDate){
$startDate = strtotime($startDate);
$endDate = strtotime($endDate);
if($startDate <= $endDate){
$datediff = $endDate - $startDate;
return floor($datediff / (60 * 60 * 24));
}
return false;
}
?>
Output: 245
Functions Used:
strtotime(): The strtotime() function parses an English textual datetime into a Unix timestamp
floor(): The floor() function rounds a number DOWN to the nearest integer
Edit-1: Getting Days After Excluding Weekends (saturdays & sundays)
//getWorkingDays(start_date, end_date)
if($days = getWorkingDays("2017-05-01","2018-01-01")){
echo $days;
}
function getWorkingDays($startDate,$endDate){
$days = false;
$startDate = strtotime($startDate);
$endDate = strtotime($endDate);
if($startDate <= $endDate){
$datediff = $endDate - $startDate;
$days = floor($datediff / (60 * 60 * 24)); // Total Nos Of Days
$sundays = intval($days / 7) + (date('N', $startDate) + $days % 7 >= 7); // Total Nos Of Sundays Between Start Date & End Date
$saturdays = intval($days / 7) + (date('N', $startDate) + $days % 6 >= 6); // Total Nos Of Saturdays Between Start Date & End Date
$days = $days - ($sundays + $saturdays); // Total Nos Of Days Excluding Weekends
}
return $days;
}
?>
Sources:
calculate sundays between two dates
The intval() function is used to get the integer value of a variable.
See Description date('N', $date) : N - The ISO-8601 numeric representation of a day (1 for Monday, 7 for Sunday)
There is the script of code for do this.
<?php
$now = time(); // or your date as well
$your_date = strtotime("2010-01-01");
$datediff = $now - $your_date;
echo floor($datediff / (60 * 60 * 24));
?>
or
$datetime1 = new DateTime("2010-06-20");
$datetime2 = new DateTime("2011-06-22");
$difference = $datetime1->diff($datetime2);
echo 'Difference: '.$difference->y.' years, '
.$difference->m.' months, '
.$difference->d.' days';
print_r($difference);
try this
public function datediff($sdate,$edate){
$diffformat='%a';
$date1 = date_create($sdate);
$date2 = date_create($edate);
$diff12 = date_diff($date2, $date1);
$days = $diff12->format($diffformat) + 1;}
EDIT: I noticed in the comment you want to exclude the weekend day/days (however you didn't mention that in your post !)
you can add the number of days you want to exclude from the week
you can use DateTime::diff and use the option for absolute result (positive difference always)
<?php
function daysBetween2Dates($date1, $date2, $execludedDaysFromWeek = 0)
{
try{
$datetime1 = new \DateTime($date1);
$datetime2 = new \DateTime($date2);
}catch (\Exception $e){
return false;
}
$interval = $datetime1->diff($datetime2,true);
$days = $interval->format('%a');
if($execludedDaysFromWeek < 0 || $execludedDaysFromWeek > 7){
$execludedDaysFromWeek = 0 ;
}
return ceil($days * (7-$execludedDaysFromWeek) / 7);
}
Usage Example
// example 1 : without weekend days, start date is the first one
$days = daysBetween2Dates('2016-12-31','2017-12-31');
echo $days;
// example 2 : without weekend days, start date is the second one
$days = daysBetween2Dates('2017-12-31', '2016-12-31');
echo "<br>\n" .$days;
// example 3 : with weekend days, it returns 6 days for the week
$days = daysBetween2Dates('2017-12-31', '2017-12-24',-1);
echo "<br>\n" .$days;
exit;
this outputs
365
365
6
live demo (https://eval.in/835862)
use date_diff() which returns the difference between two DateTime objects.
$diff=date_diff($startDate,$endDate);
I need to extract the total hours in a any month, given just the MONTH and the YEAR, taking into account leap years.
Here is my code so far...
$MonthName = "January";
$Year = "2013";
$TimestampofMonth = strtotime("$MonthName $Year");
$TotalMinutesinMonth = $TimestampofMonth / 60 // to convert to minutes
$TotalHoursinMonth = $TotalMinutesinMonth / 60 // to convert to hours
Just work out the number of days in the month and then multiply by 24, like so:
// Set the date in any format
$date = '01/01/2013';
// another possible format etc...
$date = 'January 1st, 2013';
// Get the number of days in the month
$days = date('t', strtotime($date));
// Write out the days
echo $days;
You can do this:
<?php
$MonthName = "January";
$Year = "2013";
$days = date("t", strtotime("$MonthName 1st, $Year"));
echo $days * 24;
You can use DateTime::createFromFormat since you don't have day
$date = DateTime::createFromFormat("F Y", "January 2013");
printf("%s hr(s)",$date->format("t") * 24);
Well if you are looking at working day its a different approach
$date = "January 2013"; // You only know Month and year
$workHours = 10; // 10hurs a day
$start = DateTime::createFromFormat("F Y d", "$date 1"); // added first
printf("%s hr(s)", $start->format("t") * 24);
// if you are only looking at working days
$end = clone $start;
$end->modify(sprintf("+%d day", $start->format("t") - 1));
$interval = new DateInterval("P1D"); // Interval
var_dump($start, $end);
$hr = 0;
foreach(new DatePeriod($start, $interval, $end) as $day) {
// Exclude sarturday & Sunday
if ($day->format('N') < 6) {
$hr += $workHours; // add working hours
}
}
printf("%s hr(s)", $hr);
<?php
function get_days_in_month($month, $year)
{
return $month == 2 ? ($year % 4 ? 28 : ($year % 100 ? 29 : ($year %400 ? 28 : 29))) : (($month - 1) % 7 % 2 ? 30 : 31);
}
$month = 4;
$year = 2013;
$total_hours = 24 * get_days_in_month($month, $year);
?>
you can use above function to retrieve total days in a month taking into account leap year and then multiply the value to 24
plus, you can also use a cal_days_in_month function but it only supports PHP builds of PHP 4.0.7 and higher.
and if you are using the above "get_day_in_month" then you need to parse the string into integer which can be done like this
FOR MONTH
<?php
$date = date_parse('July');
$month_int = $date['month'];
?>
FOR YEAR
<?php
$year_string = "2013"
$year_int = (int) $year_string
?>
Here's what I've got so far:
/**
* Parse a duration between 2 date/times in seconds
* and to convert that duration into a formatted string
*
* #param integer $time_start start time in seconds
* #param integer $time_end end time in seconds
* #param string $format like the php strftime formatting uses %y %m %w %d %h or %i.
* #param boolean $chop chop off sections that have 0 values
*/
public static function FormatDateDiff($time_start = 0, $time_end = 0, $format = "%s", $chop = false) {
if($time_start > $time_end) list($time_start, $time_end) = array($time_end, $time_start);
list($year_start,$month_start,$day_start) = explode('-',date('Y-m-d',$time_start));
list($year_end,$month_end,$day_end) = explode('-',date('Y-m-d',$time_end));
$years = $year_end - $year_start;
$months = $month_end - $month_start;
$days = $day_start - $day_end;
$weeks = 0;
$hours = 0;
$mins = 0;
$secs = 0;
if(mktime(0,0,0,$month_end,$day_end) < mktime(0,0,0,$month_start,$day_start)) {
$years -= 1;
}
if($days < 0) {
$months -= 1;
$days += 30; // this is an approximation...not sure how to figure this out
}
if($months < 0) $months += 12;
if(strpos($format, '%y')===false) {
$months += $years * 12;
}
if(strpos($format, '%w')!==false) {
$weeks = floor($days/7);
$days %= 7;
}
echo date('Y-m-d',$time_start).' to '.date('Y-m-d',$time_end).": {$years}y {$months}m {$weeks}w {$days}d<br/>";
}
(It's incomplete and inaccurate)
I can't seem to get the math right. Naively dividing it out won't work because of leap years and differing lengths of months.
The logic also needs to change depending on the format string. For example, passing 04-Feb-2010 to 28-Jun-2011 (as unix timestamps) with format string %y year %m month %d day should output 1 year 4 month 24 day but if %y year is omitted then it needs to add 12 months to the month, i.e., output should be 16 month 24 day.
Should handle times too...but I haven't got to that yet.
None of these date_diff solutions handle weeks. And I don't know how I could hack it into date_diff, so that's not really a solution for me.
Furthermore, $diff->format doesn't do what I asked...to give the total months and days if "bigger units" are omitted. Example:
>>> $start = new DateTime('04-Feb-2010')
>>> $end = new DateTime('28-Jun-2011')
>>> $diff = $start->diff($end)
>>> $diff->format('%m months, %d days')
'4 months, 24 days'
Should be 16 months, 24 days, as I stated earlier. Please stop being so quick to close my question as a dupe before you understand it fully. If the solutions to other questions can be tweaked to solve this, fine, but please explain how, because I don't get it.
To be clear,
if %y is omitted, years should be rolled in the months
if %m is omitted, months should be rolled into the days
if %w is omitted, weeks should be rolled into the days
if %h is omitted, hours should be rolled into minutes
if %m is omitted, minutes should be rolled into seconds
If "smaller units" are omitted, the next biggest unit can be rounded or floored where it makes sense.
I don't expect an accepted answer, but here is how to get date_diff to do weeks.
<?php
$january = new DateTime('2010-01-01');
$february = new DateTime('2011-02-20 3:35:28');
$interval = $february->diff($january);
$parts = $interval->format('%y %m %d %h %i %s %a');
$weeks = 0;
list($years, $months, $days, $hours, $minutes, $seconds, $total_days) = explode(' ', $parts);
if ($days >= 7) {
$weeks = (int)($days / 7);
$days %= 7;
}
echo "$years years, $months months, $weeks weeks, $days days, $hours hours, $minutes minutes $seconds seconds";
// 1 years, 1 months, 2 weeks, 5 days, 3 hours, 35 minutes 28 seconds
Maybe with that you can integrate it into your function to do the rolling over and handling the user given format.
If the bigger units aren't given, you can start from the largest unit and apply them back to the next smaller unit. (i.e. 1 year 1 month with no years should add 12 back to months). If "month" isn't included in the format, then you can use the total days to handle the fact that months have different numbers of days.
I would use DateTime::diff() for this:
$start = new DateTime('2012-01-01 12:00:00');
$end = new DateTime('2012-01-20 06:59:59');
$diff = $start->diff($end);
echo $diff->format('%d days, %h hours, %m minutes, %s seconds');
See DateInterval::format() for more info about the formats.
$absolute = false; //default, returns years, months, days, etc. True would return seconds
$difference = date_diff($dateTimeStart, $dateTimeEnd, $absolute);
echo $difference->format("%y Year(s) %m Month(s) ...");
I would try this first, if it does not work for your purposes then you could try to use the Calendar functions to fetch the correct number of days in each month.
I think you would need to decide upon your own logic for calculating weeks. Personally, I would say $weeks = $difference->d / 7; but there is no strictly correct way to count elapsed weeks in a portion of a month. Think of a calendar, we often speak of first, second, third week, but unless the month started on a Sunday (or Monday, or Saturday, depending on company, religion, etc.) then really we are not being absolute in these descriptions. You can say absolutely that there have been 3 Sundays (for instance) since the beginning of the month, but not three weeks. On the 28th, have four weeks passed? What if the month started on Wed, then is it five?
Also, if you want a custom format (35 Months) you can always access the members directly and concatenate a format string.
Here's my attempt at an interesting problem. It's not quite working 100%, but it's very close.
The function begins by calculating the total number of seconds and months that the date difference requires. Then, using the $tokens array that is sorted in ascending order, it loops through those tokens and tries to match it with the input $format. If the $format is found, the appropriate value is subtracted from the total number of months or seconds.
However, there is a possibility of having a value greater than zero for months or years, but the $format string didn't specify either of those parameters. If so, the function rolls over the appropriate number of days in order to come up with the correct calculations.
I've briefly tested it, and it works for all of the examples in this thread. You can test it out on codepad to see if you can break it! :) I'd be interested in improvements upon this.
<?php
function calc( $start, $end, $format = '%s', $chop = false)
{
$tokens = array( '%y', '%m', '%w', '%d', '%h', '%i', '%s');
if( !is_a( $start, 'DateTime') || !is_a( $end, 'DateTime'))
{
return;
}
$diff = $start->diff( $end);
$months = ($diff->y * 12) + $diff->m;
$secs = ($diff->d * 24 * 3600) +
($diff->h * 3600) +
($diff->i * 60) +
($diff->s);
$output = array();
while( $token = array_shift( $tokens))
{
$token_present = !(strpos( $format, $token) === false);
switch( $token)
{
case '%y':
if( ($months / 12) > 0 && $token_present)
{
$output[$token] = floor( $months / 12);
$months -= $output[$token] * 12;
}
break;
case '%m':
if( $months > 0 && $token_present)
{
$output[$token] = $months;
$months = 0;
}
break;
case '%w':
// Rollover between (months or years) and seconds
if( (!isset( $output['%y']) || !isset( $output['%m'])) && $months > 0)
{
$days = $diff->format( '%a');
// Need a fix for leap year probably.
$days -= (isset( $output['%y'])) ? ($output['%y'] * 365) : 0;
$days -= $diff->d;
$secs += ($days * 24 * 60 * 60);
}
$val = (7 * 24 * 60 * 60);
if( ($secs / $val) > 0 && $token_present)
{
$output[$token] = floor( $secs / $val);
$secs -= $output[$token] * $val;
}
break;
case '%d':
$val = (24 * 60 * 60);
if( ($secs / $val) > 0 && $token_present)
{
$output[$token] = floor( $secs / $val);
$secs -= $output[$token] * $val;
}
break;
case '%h':
$val = (60 * 60);
if( ($secs / $val) > 0 && $token_present)
{
$output[$token] = floor( $secs / $val);
$secs -= $output[$token] * $val;
}
break;
case '%i':
$val = (60);
if( ($secs / $val) > 0 && $token_present)
{
$output[$token] = floor( $secs / $val);
$secs -= $output[$token] * $val;
}
break;
case '%s':
if( $secs > 0 && $token_present)
{
$output[$token] = $secs;
}
break;
}
}
// Filter out blank keys and replace their tokens in the $format string
$filtered = $chop ? array_filter( $output) : $output;
$format = str_replace( array_diff( array_keys($output), array_keys($filtered)), '', $format);
return str_replace( array_keys( $filtered), array_values( $filtered), $format);
}
$start = new DateTime('04-Feb-2010');
$end = new DateTime('28-Jun-2011');
echo calc( $start, $end, "%m months %d days\n"); // 16 months 24 days
$january = new DateTime('2010-01-01');
$february = new DateTime('2011-02-20 3:35:28');
echo calc( $january, $february, '%y years %m months %w weeks %d days %h hours %i minutes %s seconds'); // 1 years 1 months 2 weeks 5 days 3 hours 35 minutes 28 seconds
I think I've got it:
if($time_start > $time_end) list($time_start, $time_end) = array($time_end, $time_start);
$start_dt = new DateTime();
$end_dt = new DateTime();
$start_dt->setTimestamp($time_start);
$end_dt->setTimestamp($time_end);
$has_time = preg_match('`%[his]`',$format) > 0;
if(!$has_time) {
$start_dt->setTime(0,0,0);
$end_dt->setTime(0,0,0);
}
$interval = $end_dt->diff($start_dt);
$parts = $interval->format('%y %m %d %h %i %s %a');
$weeks = 0;
list($years, $months, $days, $hours, $mins, $secs, $total_days) = explode(' ',$parts);
if(strpos($format,'%y')===false) {
$months += $years * 12;
}
if(strpos($format,'%m')===false) {
$days = $total_days;
if(strpos($format,'%y')!==false) {
$start_dt->add(new DateInterval('P'.$years.'Y'));
$interval = $end_dt->diff($start_dt);
$days = $interval->days;
}
}
if(strpos($format,'%w')!==false) {
$weeks = (int)($days/7);
$days %= 7;
}
if(strpos($format,'%d')===false) {
$hours += $days * 24;
}
if(strpos($format,'%h')===false) {
$mins += $hours * 60;
}
if(strpos($format,'%i')===false) {
$secs += $mins * 60;
}
(FYI, I just do some basic str_replacing at the end to throw it into my custom format string)
Edit: There's still 1 more scenario I don't know how to handle... when years and days are requested but not months, the output will be wrong. I'm wondering if I should just mod the total days with 365.... it's kind of a rare scenario.
Edit2: Solved it! We'll just add that many years to the start date and then recalculate the total days.
I have a table with a datetime field, and I want to pull that time stamp and use PHP to convert it to the nearest largest unit of time. For example, if the entry was made 2 minutes and 36 seconds ago, I want to echo 2 minutes in PHP. If it was 3 hours and 5 minutes ago, I want it to say 3 hours. If it was 6 days and 4 hours and 40 minutes ago, it should say 6 days. You get my drift. And if it's under a minute, just the number of seconds.
I am not familiar at all about any of PHP's date or time functions, so please don't assume I already know anything. Thanks.
Here's another function for you:
function relativeTime($timestamp, $format = "Y-m-d")
{
$difference = time() - $timestamp;
if ($difference >= 604800) { // 7 days
return date($format, $timestamp);
}
$periods = array("Second", "Minute", "Hour", "Day");
$lengths = array("60","60","24","7","4.35","12","10");
$ending = "Ago";
for($j = 0; $difference >= $lengths[$j]; $j++)
$difference /= $lengths[$j];
$difference = round($difference);
if($difference != 1) $periods[$j].= "s";
$text = "$difference $periods[$j] $ending";
return $text;
}
It returns values like "5 Minutes Ago", "3 Days Ago", and "34 Seconds Ago". However if the date is over 7 days old, it just returns the full date, i.e. "2010-04-19".
If your field is date or datetime use
SELECT UNIX_TIMESTAMP(field) FROM...
if your field is stored as an int (seconds since 1970) just use
SELECT field FROM...
Get that integer value from the database into a PHP variable $secs, this is the number of seconds since 1970. We assume the date is in the past, then
$diff = time() - $secs;
if ($diff < 60) echo $diff . ' seconds';
else {
$diff = intval($diff / 60);
if ($diff < 60) echo $diff . ' minutes';
else {
$diff = intval($diff / 60);
if ($diff < 24) echo $diff . ' hours';
else {
$diff = intval($diff / 24);
echo $diff . ' days';
}
}
}