Here's the case.
I store vacation information of employees in mysql in unix timestamp.
What I want to do is to
- show the vacation days in a calendar;
- show how much time passed since last vacation;
The result I'm trying to get is like in this picture:
http://postimg.org/image/7tdw4hmwf/
The problem is my calendar is starting from 31-12-1969 and showing too many days.
Here's the code:
$vac_begin = '1412100000';
$vac_end = '1412877600';
// $vac_end = '1414087200';
$ve = new DateTime(date("d-m-Y", $vac_end));
$today = new DateTime(date('d-m-Y'));
$time_passed = $today->diff($ve)->format('%y years %m months');
echo 'Vacation start:'.date("d-m-Y", $vac_begin).'<br/>';
echo 'Vacation end:'.date("d-m-Y", $vac_end).'<br/>';
echo 'Time passed since last vacation: '.$time_passed.'<br/>';
//---------------------------------------
echo 'Days to show in calendar<br/>';
//Get monday of the week
$before = date("N", $vac_begin) - 1;
//Get sunday of the week
$after = 7 - date("N", $vac_end);
//Vacation days
$datediff = $vac_end - $vac_begin;
//Get number of remaining days to show in calendar
$remaining = 42 - (floor($datediff/(60*60*24)) + 1 + $before + $after);
//Allocate remaining days before and after vacation period
$floor = floor($remaining/7/2);
$round = round($remaining/7/2);
if($before > $after){
$after += $round*7;
$before += $floor*7;
} else{
$after += $floor*7;
$before += $round*7;
}
$format_sdate = date("d-m-Y", $vac_begin);
$format_edate = date("d-m-Y", $vac_end);
//Get first day to show in calendar
$cal_start_date = date("d-m-Y", strtotime($format_sdate.' -'.$before.' days'));
//Get last day to show in calendar
$cal_end_date = date("d-m-Y", strtotime($format_edate.' +'.$after.' days'));
$begin = new DateTime($cal_start_date);
$end = new DateTime($cal_end_date);
$end = $end->modify('+1 day');
$interval = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($begin, $interval, $end);
foreach ($period as $dt){
echo $dt->format("d").', ';
}
echo $cal_start_date;
Related
I need to get the total number of days every 6 months from the given total number of days.
So far this is what I achieved.
$begin = new DateTime( '2019-08-31' );
$end = new DateTime( '2020-08-31' );
// get interval in months
$interval1 = DateInterval::createFromDateString('6 month');
$period = new DatePeriod($begin,$interval1,$end);
$counter = 0;
foreach($period as $date){
$counter++;
}
echo "counter:".$counter."<br>";
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin, $interval ,$end);
$count = 0;
foreach($daterange as $date){
//echo $date->format("Ymd") . "<br>";
$count++;
}
echo "<br>count:".$count;
for($i=1;$i<=$counter;$i++){
}
Actual result:
counter:2
count:366
What I want to achieve:
counter:2
count:366
result:182 // for the first 6 months
result:184 // for the next 6 months
For add month, a start date with day = 31 is a problem. Datetime adds 6 month like this:
echo date_create("2019-08-31")
->modify("+6 Month")
->format("Y-m-d")
; //2020-03-02
If the start is at the beginning of a month, the solution is simple.
With DateTime::diff the difference can be calculated in full days.
$begin = new DateTime( '2019-08-01' );
$end = new DateTime( '2020-08-01' );
$interval = "6 Month";
$counter = 0;
while($begin < $end){
$curStart = clone $begin;
$begin->modify($interval);
$diffDays = $curStart->diff($begin)->days;
echo $curStart->format("Y-m-d")." - ".$begin->format("Y-m-d");
echo ": ".$diffDays." Days<br>";
}
Outputs
2019-08-01 - 2020-02-01: 184 Days
2020-02-01 - 2020-08-01: 182 Days
How to enlist all the days between for instance 2018-06-04 and 2018-06-10 that between 2018-06-04 - 2018-06-10 those days will be 2018-06-05, 2018-06-06, 2018-06-07, 2018-06-08, 2018-06-09, the same goes for 2018-06-11 - 2018-06-17 and so on...
So far I'ive managed to divide month into week chunks (below), I want to further divide weeks into days...
2018-06-04 - 2018-06-10
2018-06-11 - 2018-06-17
2018-06-18 - 2018-06-24
2018-06-25 - 2018-07-01
http://zakodowac.pl/
This is my PHP code which produces week chunks above 2018-06-04 - 2018-06-10 and so on...:
function getMondays($y, $m) {
return new DatePeriod(
new DateTime("first monday of $y-$m"),
DateInterval::createFromDateString('next monday'),
new DateTime("last day of $y-$m")
);
}
function list_week_days($year, $month) {
foreach (getMondays($year, $month) as $monday) {
echo $monday->format(" Y-m-d\n");
echo '-';
$sunday = $monday->modify('next Sunday');
echo $sunday->format(" Y-m-d\n");
echo '<br>';
}
}
list_week_days(2018, 06);
could you try this:
$begin = strtotime('2018-06-04');
$end = strtotime('2018-06-10');
while($begin < $end){
$begin = $begin +84600;
echo date('Y-m-d', $begin) . ' ';
}
if correctly understood, then the following should yield the results you expect:
// set current date
$date = '04/30/2009';
// parse about any English textual datetime description into a Unix timestamp
$ts = strtotime($date);
// calculate the number of days since Monday
$dow = date('w', $ts);
$offset = $dow - 1;
if ($offset < 0) {
$offset = 6;
}
// calculate timestamp for the Monday
$ts = $ts - $offset*86400;
// loop from Monday till Sunday
for ($i = 0; $i < 7; $i++, $ts += 86400){
print date("m/d/Y l", $ts) . "\n";
}
if you want to be even more clever, you can use:
// set current date
$date = '04/30/2009';
// parse about any English textual datetime description into a Unix timestamp
$ts = strtotime($date);
// find the year (ISO-8601 year number) and the current week
$year = date('o', $ts);
$week = date('W', $ts);
// print week for the current date
for($i = 1; $i <= 7; $i++) {
// timestamp from ISO week date format
$ts = strtotime($year.'W'.$week.$i);
print date("m/d/Y l", $ts) . "\n";
}
All of which, alongside more information, can be found on this website and credit goes to the author of that post.
this code get count hours between tow times
ineed out put like this
6:00:00AM
6:30:00AM
7:00:00AM
7:30:00AM
8:00:00AM
8:30:00AM
......
10:30:00PM
how i can do this
$start = date_create('6:00:00AM');
$end = date_create('11:00:00PM');
$diff = date_diff($end, $start);
print_r($diff->h);
Alternatively you could use DatePeriod to build the list of dates on the desired specification, as opposed to iterating over comparisons of the date and adding the increment.
$start = date_create('6:00:00AM');
$end = date_create('11:00:00PM');
$interval = \DateInterval::createFromDateString('30 minutes');
$periods = new \DatePeriod($start, $interval, $end);
foreach ($periods as $date) {
echo $date->format('h:i:sA') . \PHP_EOL;
}
Result: https://3v4l.org/FnEae
06:00:00AM
06:30:00AM
07:00:00AM
07:30:00AM
08:00:00AM
08:30:00AM
//..
10:30:00PM
Since \DateTime::diff() won't always show the total hours between dates with different days, you can count the hours between the two dates by using iterator_count on the DatePeriod of the desired interval:
$start = date_create('6:00:00AM');
$end = date_create('11:00:00PM');
$interval = \DateInterval::createFromDateString('1 hour');
$periods = new \DatePeriod($start, $interval, $end);
echo iterator_count($periods) . ' hours';
Result: https://3v4l.org/P75K7
17 hours
<?php
$start = date_create('6:00:00AM');
$end = date_create('11:00:00PM');
$halfHour = new DateInterval('PT1800S');
while ($start < $end) {
print ($start->format('h:i:sA').PHP_EOL);
$start->add($halfHour);
}
?>
Create 2 Datetime objects and a date interval object and iterate while less than the end Datetime add the interval each time.
$start = date_create('6:00:00AM');
$end = date_create('11:00:00PM');
$interval = new DateInterval('PT30M');
while ($start <= $end) {
echo $start->format('H:i:s');
$start->add($interval);
}
for example I have two dates 2015-10-28 and 2015-12-31. from these I want to know how many saturday and sunday in that given date range. I can find the diff between that dates but I can't find how many weekends.
anyone ever made this?
here is my current code:
function createDateRange($maxDate, $cell, $lead, $offArray = array()){
$dates = [];
--$cell;
--$lead;
$edate = date('Y-m-d', strtotime($maxDate." -$lead day"));
$sdate = date('Y-m-d', strtotime($edate." -$cell day"));
$start = new DateTime($sdate);
$end = new DateTime($edate);
$end = $end->modify('+1 day');
$interval = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($start, $interval, $end);
foreach($period as $d){
$dt = $d->format('Y-m-d');
if(!in_array($dt, $dates)){
$dates[] = $dt;
}
}
return $dates;
}
basically I want to add sat+sun count to the date range.
The trick is to use an O(1)-type algorithm to solve this.
Given your starting date, move to the first Saturday. Call that from
Given your ending date, move back to the previous Friday. Call that to
Unless you have an edge case (where to is less than from), compute (to - from) * 2 / 7 as the number of weekend days, and add that to any weekend days passed over in steps (1) and (2).
This is how I do it in production, although generalised for arbitrary weekend days.
Use this function:
function getDateForSpecificDayBetweenDates($startDate, $endDate, $weekdayNumber)
{
$startDate = strtotime($startDate);
$endDate = strtotime($endDate);
$dateArr = array();
do
{
if(date("w", $startDate) != $weekdayNumber)
{
$startDate += (24 * 3600); // add 1 day
}
} while(date("w", $startDate) != $weekdayNumber);
while($startDate <= $endDate)
{
$dateArr[] = date('Y-m-d', $startDate);
$startDate += (7 * 24 * 3600); // add 7 days
}
return($dateArr);
}
The function call to get dates for all Sunday's in year 2015:
$dateArr = getDateForSpecificDayBetweenDates('2015-01-01', '2015-12-31', 0);
print "<pre>";
print_r($dateArr);
//周日0 周一1 .....
$data = 4;//周四
$t1 ='2015-10-28';
$t2 = '2015-12-31';
$datetime1 = date_create($t1);
$datetime2 = date_create($t2);
$interval = date_diff($datetime1, $datetime2);
$day = $interval->format('%a');
$result = ($day)/7;
$start = getdate(strtotime($t1))['wday'];
$end = getdate(strtotime($t2))['wday'];
if($data>=$start && $data<=$end){
echo floor($result)+1;
}else{
echo floor($result);
}
Let's assume I have two dates in variables, like
$date1 = "2009-09-01";
$date2 = "2010-05-01";
I need to get the count of months between $date2 and $date1($date2 >= $date1). I.e. i need to get 8.
Is there a way to get it by using date function, or I have to explode my strings and do required calculations?
Thanks.
For PHP >= 5.3
$d1 = new DateTime("2009-09-01");
$d2 = new DateTime("2010-05-01");
var_dump($d1->diff($d2)->m); // int(4)
var_dump($d1->diff($d2)->m + ($d1->diff($d2)->y*12)); // int(8)
DateTime::diff returns a DateInterval object
If you don't run with PHP 5.3 or higher, I guess you'll have to use unix timestamps :
$d1 = "2009-09-01";
$d2 = "2010-05-01";
echo (int)abs((strtotime($d1) - strtotime($d2))/(60*60*24*30)); // 8
But it's not very precise (there isn't always 30 days per month).
Last thing : if those dates come from your database, then use your DBMS to do this job, not PHP.
Edit: This code should be more precise if you can't use DateTime::diff or your RDBMS :
$d1 = strtotime("2009-09-01");
$d2 = strtotime("2010-05-01");
$min_date = min($d1, $d2);
$max_date = max($d1, $d2);
$i = 0;
while (($min_date = strtotime("+1 MONTH", $min_date)) <= $max_date) {
$i++;
}
echo $i; // 8
Or, if you want the procedural style:
$date1 = new DateTime("2009-09-01");
$date2 = new DateTime("2010-05-01");
$interval = date_diff($date1, $date2);
echo $interval->m + ($interval->y * 12) . ' months';
UPDATE: Added the bit of code to account for the years.
Or a simple calculation would give :
$numberOfMonths = abs((date('Y', $endDate) - date('Y', $startDate))*12 + (date('m', $endDate) - date('m', $startDate)))+1;
Accurate and works in all cases.
This is another way to get the number of months between two dates:
// Set dates
$dateIni = '2014-07-01';
$dateFin = '2016-07-01';
// Get year and month of initial date (From)
$yearIni = date("Y", strtotime($dateIni));
$monthIni = date("m", strtotime($dateIni));
// Get year an month of finish date (To)
$yearFin = date("Y", strtotime($dateFin));
$monthFin = date("m", strtotime($dateFin));
// Checking if both dates are some year
if ($yearIni == $yearFin) {
$numberOfMonths = ($monthFin-$monthIni) + 1;
} else {
$numberOfMonths = ((($yearFin - $yearIni) * 12) - $monthIni) + 1 + $monthFin;
}
I use this:
$d1 = new DateTime("2009-09-01");
$d2 = new DateTime("2010-09-01");
$months = 0;
$d1->add(new \DateInterval('P1M'));
while ($d1 <= $d2){
$months ++;
$d1->add(new \DateInterval('P1M'));
}
print_r($months);
Using DateTime, this will give you a more accurate solution for any amount of months:
$d1 = new DateTime("2011-05-14");
$d2 = new DateTime();
$d3 = $d1->diff($d2);
$d4 = ($d3->y*12)+$d3->m;
echo $d4;
You would still need to handle the leftover days $d3->d if your real world problem is not as simple and cut and dry as the original question where both dates are on the first of the month.
This is a simple method I wrote in my class to count the number of months involved into two given dates :
public function nb_mois($date1, $date2)
{
$begin = new DateTime( $date1 );
$end = new DateTime( $date2 );
$end = $end->modify( '+1 month' );
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($begin, $interval, $end);
$counter = 0;
foreach($period as $dt) {
$counter++;
}
return $counter;
}
In case the dates are part of a resultset from a mySQL query, it is much easier to use the TIMESTAMPDIFF function for your date calculations and you can specify return units eg. Select TIMESTAMPDIFF(MONTH, start_date, end_date)months_diff from table_name
strtotime is not very precise, it makes an approximate count, it does not take into account the actual days of the month.
it's better to bring the dates to a day that is always present in every month.
$date1 = "2009-09-01";
$date2 = "2010-05-01";
$d1 = mktime(0, 0, 1, date('m', strtotime($date1)), 1, date('Y', strtotime($date1)));
$d2 = mktime(0, 0, 1, date('m', strtotime($date2)), 1, date('Y', strtotime($date2)));
$total_month = 0;
while (($d1 = strtotime("+1 MONTH", $d1)) <= $d2) {
$total_month++;
}
echo $total_month;
I have used this and works in all conditions
$fiscal_year = mysql_fetch_row(mysql_query("SELECT begin,end,closed FROM fiscal_year WHERE id = '2'"));
$date1 = $fiscal_year['begin'];
$date2 = $fiscal_year['end'];
$ts1 = strtotime($date1);
$ts2 = strtotime($date2);
$te=date('m',$ts2-$ts1);
echo $te;