How to retrieve an array of each date within two epochs - php

I have two epochs. I want to figure out all the dates that are valid within the two epochs.
For example, if I have the epochs 946684800 (Sat, 01 Jan 2000 00:00:00 GMT) and 947203200 (Fri, 07 Jan 2000 00:00:00 GMT), I want to be able to get: 01/01/2000, 02/01/2000, 03/01/2000, 04/01/2000, etc.

If you have PHP 5.3 or newer, you could do this:
$date1 = new DateTime;
$date1->setTimestamp(946684800);
$date2 = new DateTime;
$date2->setTimestamp(947203200);
$interval = new DateInterval('P1D');
while ( $date1 <= $date2 )
{
$dates_in_between[] = $date1->getTimestamp();
$date1->add($interval);
}
Alternatively, you could use this:
// 1 day = 60 seconds * 60 minutes * 24 hours = 86400
for ($date = 946684800; $date <= 947203200; $date += 86400)
$dates_in_beteween[] = $date;
$dates_in_between will contain a list of "dates" in between.

PHP time values are just Unix timestamps - seconds since Jan 1/1970. Going off PHP 5's datetime object:
$start = strtotime('01 Jan 2000');
$end = strtotime('07 Jan 2000');
for ($d = $start; $d <= $end; $d += 86400) { // increment by 86,400 seconds, aka 1 day
echo date('d/m/Y', $d);
}
There's better ways of going about it, using the DateTime / DateInterval objects, but this is just to show the basics.

Given that your epoch is in seconds you could always add the number of seconds found in a day to the first epoch:
946684800 + 86400 = 946771200 -> Sun, 02 Jan 2000 00:00:00 GMT
And go on like this, I explain better:
947203200 - 946684800 = 518400 / 86400 = 6 (exactly 6 days)
so (PSEUDOCODE):
for(int i = 946684800; i<946684800 ;i+=86400){
day = getDate(i);
}

$epoch1 = '946684800';
$epoch2 = '947203200';
$i = 0;
while($time < $epoch2) {
$time = mktime(0, 0, 0, date("m", $epoch1) , date("d", $epoch1)+$i, date("Y",$epoch1));
echo date('d/m/Y', $time)."<br>";
$i++;
}

If understanding the question right, you want every DAY within the 2 epochs (2000-01-01 and 2000-01-07)..
Can be done like so:
<?php
$epoch1 = 946684800;
$epoch2 = 947203200;
$difference = $epoch1 - $epoch2;
..
//count days
$amountOfDays = round(($epoch2-$epoch1)/86400);
//looping all days
for($i=1; $i<=$amountOfDays; $i++) {
echo date('d/m/Y', $epoch1+($i*86400);
}
?>

$start = strtotime('2011-06-01');
$end = strtotime('2011-06-15');
$date = $start;
$anArray = array();
while ($date <= $end) {
$date = strtotime("+1 DAY", $date);
$anArray[] = $date;
}

Related

PHP: DatePeriod with last day of month

I'd like to work with PHP DateInterval to iterate through months:
$from = new DateTime();
$from->setDate(2014, 1, 31);
$period = new DatePeriod($from, new DateInterval('P1M'), 12);
I'd expect it to returns 31 January, 28 February (as the DateInterval is 1 month), but it actually returns 31 January, 3 March, 3 of April... hence skipping February.
Is there any way to do this simply?
Thanks!
EDIT : as a refernece, here is a solution that seems to cover most use cases:
$date = new DateTime('2014-01-31');
$start = $date->format('n');
for ($i = 0; $i < 28; $i++) {
$current = clone $date;
$current->modify('+'.$i.' month');
if ($current->format('n') > ($start % 12) && $start !== 12) {
$current->modify('last day of last month');
}
$start++;
echo $current->format('Y-m-d').PHP_EOL;
}
You can use DateTime::modify():
$date = new DateTime('last day of january');
echo $date->format('Y-m-d').PHP_EOL;
for ($i = 1; $i < 12; $i++) {
$date->modify('last day of next month');
echo $date->format('Y-m-d').PHP_EOL;
}
EDIT: I think I didn't understand your question clearly. Here is a new version:
$date = new DateTime('2014-01-31');
for ($i = 0; $i < 12; $i++) {
$current = clone $date;
$current->modify('+'.$i.' month');
if ($current->format('n') > $i + 1) {
$current->modify('last day of last month');
}
echo $current->format('Y-m-d').PHP_EOL;
}
The issue is cause by the variance between the last day in each of the months within the range. ie. February ending on 28 instead of 31 and the addition of 1 month from the last day 2014-01-31 + 1 month = 2014-03-03 https://3v4l.org/Y42QJ
To resolve the issue with DatePeriod and simplify it a bit, adjust the initial date by resetting the specified date to the first day of the specified month, by using first day of this month.
Then during iteration, you can modify the date period date by using last day of this month to retrieve the bounds of the currently iterated month.
Example: https://3v4l.org/889mB
$from = new DateTime('2014-01-31');
$from->modify('first day of this month'); //2014-01-01
$period = new DatePeriod($from, new DateInterval('P1M'), 12);
foreach ($period as $date) {
echo $date->modify('last day of this month')->format('Y-m-d');
}
Result:
2014-01-31
2014-02-28
2014-03-31
2014-04-30
2014-05-31
2014-06-30
2014-07-31
2014-08-31
2014-09-30
2014-10-31
2014-11-30
2014-12-31
2015-01-31
Then to expand on this approach, in order to retrieve the desired day from the specified date, such as the 29th. You can extract the specified day and adjust the currently iterated month as needed when the day is out of bounds for that month.
Example: https://3v4l.org/SlEJc
$from = new DateTime('2014-01-29');
$day = $from->format('j');
$from->modify('first day of this month'); //2014-01-01
$period = new DatePeriod($from, new DateInterval('P1M'), 12);
foreach ($period as $date) {
$lastDay = clone $date;
$lastDay->modify('last day of this month');
$date->setDate($date->format('Y'), $date->format('n'), $day);
if ($date > $lastDay) {
$date = $lastDay;
}
echo $date->format('Y-m-d');
}
Result:
2014-01-29
2014-02-28 #notice the last day of february is used
2014-03-29
2014-04-29
2014-05-29
2014-06-29
2014-07-29
2014-08-29
2014-09-29
2014-10-29
2014-11-29
2014-12-29
2015-01-29
You may try like this:
$date = new DateTime();
$lastDayOfMonth = $date->modify(
sprintf('+%d days', $date->format('t') - $date->format('j'))
);
I would do it probably like this
$max = array (
31,28,31,30,31,30,31,31,30,31,30,31
); //days in month
$month = 1;
$year = 2014;
$day = 31;
$iterate = 12;
$dates = array();
for ($i = 0;$i < $iterate;$i++) {
$tmp_month = ($month + $i) % 12;
$tmp_year = $year + floor($month+$i)/12;
$tmp_day = min($day, $max[$tmp_month]);
$tmp = new DateTime();
$tmp->setDate($tmp_year, $tmp_month + 1, $tmp_day);
$dates[] = $tmp;
}
var_dump($dates);
This keeps to the same day each month if possible

php DateTime calculations, how to calculate time between DateTime's depending on working hours

I would like to calculate some times. I need to know how many worktime hours are between a call entry and now regarding on the worktimes.
for example:
call stored yesterday 15:00
worktime ends: 18:00
worktime begins: 08:00
now: 10:00
So i need to know the age my call has during the working hours:
call stored >> worktime end: 3h
worktimebegin >> now: 2h
age: 5h
I would like to use php DateTime.
How would you proceed?
I think this can help you out:
//workdays till 18:00 and start 08:00
function calculateWorkHours(DateTime $Start, DateTime $End) {
//validate given parameters
if ($Start > $End) throw new Exception('$Start date cannot be later than $End date');
$hours = 0;
do {
//get the current hour
$currentHour = $Start->format('H');
//while the $currenthour is lower then 18 and higher than 7
if($currentHour < 18 && $currentHour >= 8) {
$hours++;
}
$Start->modify('+1 hour');
} while($End > $Start);
return $hours;
}
$Start = new DateTime('yesterday 150000');
$End = new DateTime('100000');
echo calculateWorkHours($Start, $End); //returns 5
$Start = new DateTime('yesterday 060000');
$End = new DateTime('120000');
echo calculateWorkHours($Start, $End); //returns 14
$Start = new DateTime('-2 days 150000');
$End = new DateTime('100000');
echo calculateWorkHours($Start, $End); //return 15

PHP - Calculating working hours between two dates but exclude the time when request is on hold

Can some one help me write a function that calculates the number of working hours between two dates but want to exclude the time when the request had a status of "On Hold".
So lets say the request came in at 3PM friday and was closed at 3PM Wednesday, and working hours are from 8AM to 5PM pacific (Mon thru Friday)...Total working hours will be 27 hours...but if the request remained on hold from Monday 3PM till Tuesday 3PM...Actual work time on the request really becomes 18 hours instead of 27 hours.
I have recently started working on PHP and have been assigned this task which is very confusing to me. Please help
All you have to do is get the total time elapsed, then substract the non-working hours.
You can use dateTime and datePeriod php objects for that (requires php 5.3)
Here a small script to do what you want (but you will have probably to adapt for your needs)
<?php
ini_set('display_errors', 'on');
define('DAY_WORK', 32400); // 9 * 60 * 60
define('HOUR_START_DAY', '08:00:00');
define('HOUR_END_DAY', '17:00:00');
// get begin and end dates of the full period
$date_begin = '2013-11-29 15:00:00';
$date_end = '2013-12-03 15:00:00';
// keep the initial dates for later use
$d1 = new DateTime($date_begin);
$d2 = new DateTime($date_end);
// and get the datePeriod from the 1st to the last day
$period_start = new DateTime($d1->format('Y-m-d 00:00:00'));
$period_end = new DateTime($d2->format('Y-m-d 23:59:59'));
$interval = new DateInterval('P1D');
//$interval = new DateInterval('weekdays'); // 1 day interval to get all days between the period
$period = new DatePeriod($period_start, $interval, $period_end);
$worked_time = 0;
$nb = 0;
// for every worked day, add the hours you want
foreach($period as $date){
$week_day = $date->format('w'); // 0 (for Sunday) through 6 (for Saturday)
if (!in_array($week_day,array(0, 6)))
{
// if this is the first day or the last dy, you have to count only the worked hours
if ($date->format('Y-m-d') == $d1->format('Y-m-d'))
{
$end_of_day_format = $date->format('Y-m-d '.HOUR_END_DAY);
$d1_format = $d1->format('Y-m-d H:i:s');
$end_of_day = new DateTime($end_of_day_format);
$diff = $end_of_day->diff($d1)->format("%H:%I:%S");
$diff = split(':', $diff);
$diff = $diff[0]*3600 + $diff[1]*60 + $diff[0];
$worked_time += $diff;
}
else if ($date->format('Y-m-d') == $d2->format('Y-m-d'))
{
$start_of_day = new DateTime($date->format('Y-m-d '.HOUR_START_DAY));
$d2_format = $d2->format('Y-m-d H:i:s');
$end_of_day = new DateTime($end_of_day_format);
$diff = $start_of_day->diff($d2)->format('%H:%I:%S');
$diff = split(':', $diff);
$diff = $diff[0]*3600 + $diff[1]*60 + $diff[0];
$worked_time += $diff;
}
else
{
// otherwise, just count the full day of work
$worked_time += DAY_WORK;
}
}
if ($nb> 10)
die("die ".$nb);
}
echo sprintf('Works from %s to %s, You worked %d hour(s)', $date_begin, $date_end, $worked_time/60/60);
Calculate work time with an accuracy of 1 minute.
WARNING: This function can take many seconds to load as it does a loop for every minute between the time span.
<?php
$request = array(
'start' => '3PM Nov 29 2013',
'end' => '3PM Dec 4 2013'
);
echo calculate_work($request);
/**
* Calculate work time by looping through every minute
* #param array $request start to end time
* #return int work time in minutes
*/
function calculate_work($request)
{
$start = strtotime($request['start']);
$end = strtotime($request['end']);
$work_time = 0;
/* Add 1 minute to the start so that we don't count 0 as a minute */
for ($time = $start + 60; $time <= $end; $time += 60)
{
// Weekends
if (date('D', $time) == 'Sat' OR date('D', $time) == 'Sun')
continue;
// Non Working Hours
if (date('Hi', $time) <= '0800' OR date('Hi', $time) > '1700')
continue;
// On Hold
if ($time > strtotime('3PM Dec 2 2013') AND $time <= strtotime('3PM Dec 3 2013'))
continue;
$work_time++;
}
// Divide by 60 to turn minutes into hours
return $work_time / 60;
}
/**
* Get the total working hours in seconds between 2 dates..
* #param DateTime $start Start Date and Time
* #param DateTime $end Finish Date and Time
* #param array $working_hours office hours for each weekday (0 Monday, 6 Sunday), Each day must be an array containing a start/finish time in seconds since midnight.
* #return integer
* #link https://github.com/RCrowt/working-hours-calculator
*/
function getWorkingHoursInSeconds(DateTime $start, DateTime $end, array $working_hours)
{
$seconds = 0; // Total working seconds
// Calculate the Start Date (Midnight) and Time (Seconds into day) as Integers.
$start_date = clone $start;
$start_date = $start_date->setTime(0, 0, 0)->getTimestamp();
$start_time = $start->getTimestamp() - $start_date;
// Calculate the Finish Date (Midnight) and Time (Seconds into day) as Integers.
$end_date = clone $end;
$end_date = $end_date->setTime(0, 0, 0)->getTimestamp();
$end_time = $end->getTimestamp() - $end_date;
// For each Day
for ($today = $start_date; $today <= $end_date; $today += 86400) {
// Get the current Weekday.
$today_weekday = date('w', $today);
// Skip to next day if no hours set for weekday.
if (!isset($working_hours[$today_weekday][0]) || !isset($working_hours[$today_weekday][1])) continue;
// Set the office hours start/finish.
$today_start = $working_hours[$today_weekday][0];
$today_end = $working_hours[$today_weekday][1];
// Adjust Start/Finish times on Start/Finish Day.
if ($today === $start_date) $today_start = min($today_end, max($today_start, $start_time));
if ($today === $end_date) $today_end = max($today_start, min($today_end, $end_time));
// Add to total seconds.
$seconds += $today_end - $today_start;
}
return gmdate("H:i:s", $seconds);
}

PHP: strtotime() gives wrong output

In my script, I have a given end date. To get the start date, I subtract 23 months to the end date. Basically, what my script should do is to output 24 months (w/ year) - the last month/year to be printed should always be the specified end date.
For some reason, my script isn't returning my desired results. Given the $end = '2013-07-05', the script returns the result correctly. It prints out Aug 11 to Jul 13 which is correct.
But for some dates (e.g. $end = '2013-07-31'), the output is wrong. The result should be Sep 11 to Aug 13. But in this case, it outputs Aug 11 to Aug 13 which is absolutely wrong.
Here's my code:
<?php
$end = strtotime('2013-07-31 +1 month');
$date = strtotime('2013-07-31 -23 month');
$start = $month = $date;
$months = "";
while($month < $end)
{
$months .= date('M y', intval($month))." ";
$month = strtotime("+1 month", intval($month));
}
echo $months;
?>
I think there's something wrong with strtotime(). Thanks in advance.
You can't really use month calculations like that, especially when dealing with end-of-month values:
e.g. if it's July 31, what's -1 month to strtotime?
php > echo date('r', strtotime('2013-07-31 -1 month'));
Mon, 01 Jul 2013 00:00:00 -0600
A human would probably pick out June 30th, but strtotime isn't human. This DOES work for February 28th and generally any date where the day value is <= 28. Once you get into the 29,30,31 area, then you get these unexepected results
php > echo date('r', strtotime('2013-04-28 -1 month'));
Thu, 28 Mar 2013 00:00:00 -0600
How about
$endMonth = '8';
$year = '2013';
$i = 24;
while( $i > 0 ){
$month = ($endMonth - $i)%12;
if( $month == 0 ){
$year = $year - 1;
$month = 12;
}
$months .= date('M y', strtotime($year.'-'.$month.'-02'));
$i--;
}
Based on Marc B's answer I modified the script to deal with the 29,30,31 of each month. What I did was, if the date is 29, 30, or 31, it will be subtracted with 3 days so that the date will be either 28 or below and would work just fine with the current code that I have. It worked for me so I guess I'll just stick with this for now. Here's the updated code:
<?php
$dt = "2013-07-31";
$dy = strtotime($dt);
$day = date("d", $dy);
if (($day == 29) || ($day == 30) || ($day == 31)){
$dt = strtotime("$dt -3 days");
$dt = date('Y-m-d', $dt);
}
$end = strtotime("$dt +1 month");
$date = strtotime("$dt -23 month");
$start = $month = $date;
$months = "";
while($month < $end)
{
$months .= date('M y', intval($month))." ";
$month = strtotime("+1 month", intval($month));
}
echo $months;
?>
Thanks for your help and insights. :)

extract total hours in a particular MONTH and YEAR, taking into account leap years, using PHP

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
?>

Categories