confusing date manipulations - php

tying to go through all sundays like this:
/*self::WEEK = 604800*/
/* 3600 * 24 * 7 looks like 7 days for me*/
$start = 1286053200;
for ($i=0; $i < 10; $i++) {
echo date('d.m.Y H:i:s.u, D (z)', $start) . ' (' . $start . ')<br/>';
$start += self::WEEK;
}
but in some case i see this:
03.10.2010 00:00:00.000000, Sun (275) (1286053200)
10.10.2010 00:00:00.000000, Sun (282) (1286658000)
17.10.2010 00:00:00.000000, Sun (289) (1287262800)
24.10.2010 00:00:00.000000, Sun (296) (1287867600)
31.10.2010 00:00:00.000000, Sun (303) (1288472400)
06.11.2010 23:00:00.000000, Sat (309) (1289077200) <--
13.11.2010 23:00:00.000000, Sat (316) (1289682000)
20.11.2010 23:00:00.000000, Sat (323) (1290286800)
27.11.2010 23:00:00.000000, Sat (330) (1290891600)
04.12.2010 23:00:00.000000, Sat (337) (1291496400)
in other words lost an hour!? where?!

Try strtotime()
$start = 1286053200;
for ($i=0; $i < 10; $i++) {
echo date('d.m.Y H:i:s.u, D (z)', strtotime(' +' . ($i * 7) . ' DAYS',$start)) . ' (' . $start . ')<br/>';
}

Daylight saving?
Try gmdate() instead.

I created a function for a similar problem. Maybe you'll find it useful.
function getDays($year, $dayofweek, $format, $timezone='UTC')
{
$fridays = array();
$startDate = new DateTime("{$year}-01-01 {$dayofweek}", new DateTimezone($timezone));
$year++;
$endDate = new DateTime("{$year}-01-01", new DateTimezone($timezone));
$int = new DateInterval('P7D');
foreach(new DatePeriod($startDate, $int, $endDate) as $d) {
$fridays[] = $d->format($format);
}
return $fridays;
}
$sundays = getDays('2010', 'Sunday', 'd.m.Y H:i:s.u, D (z)', 'America/New_York');
var_dump($sundays);

Related

How to get month name of custom range

In my laravel application,
The input is like this:
$from_year = 2019;
$from_month = 10;
$to_year = 2020;
$to_month = 4;
The expected output:
months = [
'October 2019', 'November 2019', 'December 2019', 'January 2020', 'February 2020', 'March 2020', 'April 2020'
]
Thanks in advance.
You could use couple methods that uses DateTime. First of all, you could create current and end date (with 1st day of the month) objects, and then calculate month difference using date_diff. Then it's just simple for with adding month interval.
Vanilla PHP solution would look like this:
$from_year = 2019;
$from_month = 10;
$to_year = 2020;
$to_month = 4;
$date = new DateTime("$from_year-$from_month-01");
$diff = date_diff($date, new DateTime("$to_year-$to_month-01"));
$monthsDiff = $diff->y * 12 + $diff->m;
$interval = new DateInterval('P1M');
$monthsArray = [];
for($i = 0; $i <= $monthsDiff; $i++){
$monthsArray[] = $date->format('F Y');
$date->add($interval);
}
Also, as you can see, I'm using the format method on DateTime object. More about the method you can read here.
$startDate = date($from_year.'-'.$from_month.'-01');
$diff = (($to_year - $from_year) * 12) + ($to_month - $from_month);
$months = [];
for($i=0;$i<=$diff;$i++) {
$months[] = date('F Y', strtotime('+'.$i.' month', strtotime($startDate)));
}
simple code with date() function
try following code
<?php
$from_year = 2019;
$from_month = 10;
$to_year = 2020;
$to_month = 4;
$arr = [];
for($i=$from_year;$i<$to_year;$i++) {
if($i==$from_year){
$fmonth = $from_month;
}else{
$fmonth = 1;
}
for($j=$fmonth;$j<=12;$j++){
array_push($arr,DateTime::createFromFormat('!m', $j)->format('F'). " ".$i);
}
}
for($i=1;$i<=$to_month;$i++){
array_push($arr,DateTime::createFromFormat('!m', $i)->format('F'). " ".$to_year);
}
print_r($arr);
?>
This can be done using Carbon and CarbonPeriod libraries.
Here is how it goes:
use Carbon\Carbon;
use Carbon\CarbonPeriod;
$from_year = 2019;
$from_month = 10;
$to_year = 2020;
$to_month = 4;
$fromDate = new Carbon('1-' . $from_month . '-' . $from_year);
$toDate = new Carbon('1-' . $to_month . '-' . $to_year);
$differnces = CarbonPeriod::create($fromDate, '1 month', $toDate);
$differenceInDates = [];
foreach ($differnces as $differnce) {
$differenceInDates[] = $differnce->format("M F");
}
This will give you the result you want.
$from_year = 2019;
$from_month = 10;
$to_year = 2020;
$to_month = 4;
$start = strtotime($from_year . "-" . $from_month . "-01");
$end = strtotime($to_year . "-" . $to_month . "-01");
$months = [date("F Y",$start)];
while(strtotime(end($months)) < $end){
$months[] = date("F Y",strtotime(end($months) . " +1 month"));
}

How to convert Date & Time into specific range in PHP

I have following php dates for example:
2018-07-16 02:07:30
2018-07-16 02:17:30
2018-07-16 02:37:30
2018-07-16 02:47:30
I have to convert above dates in to below dates grammatically:
2018-07-16 02:15:00
2018-07-16 02:30:00
2018-07-16 02:45:00
2018-07-16 03:00:00
e.g If minute is 1-15 It should be 15, If minutes is 16-30 It should be 30, If minutes is 31-45 It should be 45, and If minutes is 46-60 It should be 00.
First, you should get the timestring from the date, then set fraction 900 (seconds) which is equal to 15 minutes. You can Convert 900 Seconds to Minutes, then get the timestring_fraction by $timestring_fraction = $timestring % $fraction; and calculate minutes and create a new date by doing this date('Y-m-d H:i:s', $minutes).
Code
$date = '2018-07-16 02:37:30';
$timestring = strtotime($date);
// 900 seconds which is equal to 15 minutes
$fraction = 900;
$timestring_fraction = $timestring % $fraction;
$minutes = $timestring + ($fraction - $timestring_fraction);
$updated_date = date('Y-m-d H:i:s', $minutes);
echo $updated_date;
Output
// 2018-07-16 02:07:30
2018-07-16 02:15:00
// 2018-07-16 02:17:30
2018-07-16 02:30:00
// 2018-07-16 02:37:30
2018-07-16 02:45:00
// 2018-07-16 02:47:30
2018-07-16 03:00:00
Updated Answer
What if the time is something like this 2018-07-16 02:30:00 then the solution will be
$timestring_fraction = $timestring % $fraction;
if ($timestring_fraction === 0) {
echo $date;
}
else {
$minutes = $timestring + ($fraction - $timestring_fraction);
$updated_date = date('Y-m-d H:i:s', $minutes);
echo $updated_date;
}
because in this scenario if minutes is exactly same i.e. 15, 30, 45 or 00 then time fraction would be zero as well, so you need to check time fraction before making a new date
Please try with
$date = "2018-07-16 02:48:30";
$cons = date('Y-m-d H:',strtotime($date));
$min = date('i',strtotime($date));
$min = $min + 15 - ($min % 15) ;
if ($min == 60){
$min = '00';
$final = date('Y-m-d H:i:s',strtotime($cons.$min));
$final = date('Y-m-d H:i:s', strtotime($final.'1 hour'));
}else{
$final = date('Y-m-d H:i:s',strtotime($cons.$min));
}
echo $final;
create one function and pass date into that function . function will return pass date with your desire output .
You can use the format() method. --> http://php.net/manual/de/function.date.php
There you can find parameters with which you can access the values of the date you are looking for. Then make a if-clause to check and set the date right.
Maybe make an array for better structure!
For example:
$day = date_create("2018-07-16 02:15:00");
$dates = array($day); // And so on...
echo $dates[1]->format("H");
// You get the hour in 24h format with like --> 02
// with i you get the minute like --> 15
Than you make a switch-Statement or a if-statement and edit the values, not that complicated!
I hope I could help you!
Another example with arrays, which need to be optimized:
<?php
$array = [
'2018-07-16 02:07:30',
'2018-07-16 02:17:30',
'2018-07-16 02:37:30',
'2018-07-16 02:47:30'
];
$newArray = [];
foreach ($array as $elem) {
$time = explode(' ', $elem)[1];
$date = explode(' ', $elem)[0];
$timePart = explode(':', $time);
$minutes = $timePart[1];
if ($minutes > 1 && $minutes < 15) {
$newTime = $date . ' ' . $timePart[0] . ':15:' . $timePart[2];
} else if ($minutes > 15 && $minutes < 30) {
$newTime = $date . ' ' . $timePart[0] . ':30:' . $timePart[2];
} else if ($minutes > 30 && $minutes < 45) {
$newTime = $date . ' ' . $timePart[0] . ':45:' . $timePart[2];
} else if ($minutes > 45) {
$newTime = $date . ' ' . $timePart[0] . ':00:' . $timePart[2];
}
$newArray[] = $newTime;
}
echo "<pre>"; var_dump($newArray); exit;
?>
U can easy convert it to datetime object.
Try this code:
$dateString = '2018-07-16 02:47:30';
$date = new DateTime($dateString);
$minute = $date->format('i');
switch(true) {
case $minute <= 15:
$minute = 15;
break;
case $minute <= 30:
$minute = 30;
break;
case $minute <= 45:
$minute = 45;
break;
case $minute <= 60:
$minute = 60;
break;
}
$date->setTime($date->format("H"), $minute);
echo $date->format("Y-m-d H:i:s");
You can change date by following :
$date = '2018-07-16 02:07:30';
$justdate = date('Y-m-d', strtotime($date));
$justdate = new DateTime($justdate);
$sdate = date('s', strtotime($date));
$idate = date('i', strtotime($date));
$hdate = date('h', strtotime($date));
$idate = number_format($idate);
if ($idate >= 0 && $idate <= 15) {
$idate = '15';
$justdate->setTime($hdate, $idate, $sdate);
$justdate = $justdate->format('Y-m-d H:i:s');
} else if ($idate >= 16 && $idate <= 30) {
$idate = '30';
$justdate->setTime($hdate, $idate, $sdate);
$justdate = $justdate->format('Y-m-d H:i:s');
} else {
$hdate = $hdate + 1;
$idate = '00';
$sdate = '00';
$justdate->setTime($hdate, $idate, $sdate);
$justdate = $justdate->format('Y-m-d H:i:s');
}
echo $justdate;exit;

Skip weekends in php date

I have this code :
for ($i = 2; $i > -3; $i--)
{
$class="";
if(date('D d-m')==date('D d-m', strtotime($i . ' days ago')))
{
$class=' class="distinct"';
}
echo '<li'.$class.'>'.date('D d-m', strtotime($i . ' days ago')) . '</li>'.'<br />';
}
And it outputs this:
Wed 17-05
Thu 18-05
Fri 19-05
Sat 20-05
Sun 21-05
I was wondering how i can skip the weekends, so it only shows the 5 days monday-friday. Any ideas how to exclude this?
You can start by creating a timestamp for monday and adding enough seconds to advance a day five times.
Like so:
$monday = strtotime('last monday');
for ($i = 0; $i < 5; $i++)
{
echo date('D d-m', $monday) . '<br />';
$monday = $monday + (60 * 60 * 24); // Add a day
}
I thing getDate() is just what you need. Where you can use 'wday' to check which day of the week it is (from 0 - Sunday, to 6 - Saturday). Example:
for ($i = 2; $i > -3; $i--)
{
$date = getDate(strtotime($i . ' days ago'));
if($date['wday'] == 6 || $date['wday'] == 0) {
echo "Weekend!\n";
}
else {
echo "Regular day...\n";
}
}
And it outputs:
Regular day...
Regular day...
Regular day...
Weekend!
Weekend!
Update:
for($i = -2; $i <= 2; $i++)
{
echo date ( 'D d-m' , strtotime ( "$i weekdays" ) ) . '<br>';
}
Will output:
Wed 17-05
Thu 18-05
Fri 19-05
Mon 22-05
Tue 23-05
===================================
Old answer:
$thisMonday = date("d-M-Y", strtotime('monday this week'));
for ($i = 0; $i <= 4; $i++)
{
$class="";
$date = date('d-M-Y', strtotime("+$i days", strtotime($thisMonday)));
if(date('D d-m') == date('D d-m', strtotime($i . ' days ago')))
{
$class=' class="distinct"';
}
echo '<li'.$class.'>'. date('D d-m', strtotime($date)) . '</li>'.'<br />';
}

Split date ranges into corresponding weeks

I have date ranges called from and to.I want to convert it to weeks.
Suppose from date is 1-10-2014 and to date is 31-10-2014
Then result is:
1st week : 01-10-2014 to 04-10-2014
2nd : 05-102014 to 11-10-2014
3rd : 12-10-2014 to 18-10-2014
4th : 19-10-2014 to 25-10-2014
5th : 26-10-2014 to 31-10-2014
In php.I try several code but that didn't given the absolute result only give 01 to 7 , 8 to 14 etc.
Pls help.
I already try answers from
Get the date of one week from today with PHP in stack overflow
date("Y-m-d",strtotime("+1 week"));
This snippet uses Sunday as the first day of the week:
$start = new DateTime('2014-10-01');
$end = new DateTime('2014-10-31 23:59');
$interval = new DateInterval('P1D');
$dateRange = new DatePeriod($start, $interval, $end);
$weekNumber = 1;
$weeks = array();
foreach ($dateRange as $date) {
$weeks[$weekNumber][] = $date->format('Y-m-d');
if ($date->format('w') == 6) {
$weekNumber++;
}
}
Each week will have all the days in it.
If you just want the first and last days of each week then you can just use array_shift and array_pop to get them. For example, for the first week you can use:
$wk1Start = array_shift($weeks[1]); //gives you first day of week 1
$wk1End = array_pop($weeks[1]); // give you the last day of week 1
If you want the start and end dates for each week, here is a way of doing it:
$ranges = array_map(function($week) {
return 'start: ' . array_shift($week)
. ', end: ' . array_pop($week); },
$weeks);
This is the output of $ranges for me:
Array
(
[1] => start: 2014-10-01, end: 2014-10-04
[2] => start: 2014-10-05, end: 2014-10-11
[3] => start: 2014-10-12, end: 2014-10-18
[4] => start: 2014-10-19, end: 2014-10-25
[5] => start: 2014-10-26, end: 2014-10-31
)
You can easily change the week starting day (set to Monday at the moment):
$fromDate = '2018-05-03';
$toDate = '2018-08-11';
$result = getWeekRanges($fromDate, $toDate);
array_walk_recursive($result, 'applyFormat');
echo '<pre>';
print_r($result);
echo '</pre>';
function getWeekRanges($start, $end) {
$timeStart = strtotime($start);
$timeEnd = strtotime($end);
$out = [];
$milestones[] = $timeStart;
$timeEndWeek = strtotime('next Monday', $timeStart);
while ($timeEndWeek < $timeEnd) {
$milestones[] = $timeEndWeek;
$timeEndWeek = strtotime('+1 week', $timeEndWeek);
}
$milestones[] = $timeEnd;
$count = count($milestones);
for ($i = 1; $i < $count; $i++) {
if( $i == $count - 1) {
$out[] = [
'start' => $milestones[$i - 1],
'end' => $milestones[$i]
];
}else{
$out[] = [
'start' => $milestones[$i - 1],
'end' => $milestones[$i] - 1
];
}
}
return $out;
}
function applyFormat(&$item) {
$item = date('Y-m-d', $item);
}
Try
$start_date = date('Y-m-d', strtotime('2014-10-01'));
$end_date = date('Y-m-d', strtotime('2014-10-31'));
$i=1;
for($date = $start_date; $date <= $end_date; $date = date('Y-m-d', strtotime($date. ' + 7 days'))) {
echo getWeekDates($date, $start_date, $end_date, $i);
echo "\n";
$i++;
}
function getWeekDates($date, $start_date, $end_date, $i) {
$week = date('W', strtotime($date));
$year = date('Y', strtotime($date));
$from = date("Y-m-d", strtotime("{$year}-W{$week}+1")); //Returns the date of monday in week
if($from < $start_date) $from = $start_date;
$to = date("Y-m-d", strtotime("{$year}-W{$week}-7")); //Returns the date of sunday in week
if($to > $end_date) $to = $end_date;
echo "$i th ".$from." to ".$to.'<br>';
}
output :-
1 th 2014-10-01 to 2014-10-05
2 th 2014-10-06 to 2014-10-12
3 th 2014-10-13 to 2014-10-19
4 th 2014-10-20 to 2014-10-26
5 th 2014-10-27 to 2014-10-31

Get mondays tuesdays etc

How can I echo all dates for mondays/ wednesday / friday between these two dates?
This is what I have been working with:
function get_days ( $s, $e )
{
$r = array ();
$s = strtotime ( $s . ' GMT' );
$e = strtotime ( $e . ' GMT' );
$day = gmdate ( 'l', $s );
do
{
$r[] = $day . ', ' . gmdate ( 'Y-m-d', $s );
$s += 86400 * 7;
} while ( $s <= $e );
return $r;
}
print_r ( get_days ( $start, $end ) );
Try this:
function getDates($start_date, $end_date, $days){
// parse the $start_date and $end_date string values
$stime=new DateTime($start_date);
$etime=new DateTime($end_date);
// make a copy so we can increment by day
$ctime = clone $stime;
$results = array();
while( $ctime <= $etime ){
$dow=$ctime->format("w");
// assumes $days is array containing integers for Sun (0) - Sat (6)
if( in_array($dow, $days) ){
// make a copy to return in results
$results[]=clone $ctime;
}
// incrememnt by 1 day
//$ctime=date_add($ctime, date_interval_create_from_date_string('1 days'));
$ctime->modify("+1 days");
}
return $results;
}
// get every Tues, Wed, Fri from now to End of June
getDates('2011-06-15','2011-06-30',array(2,3,5));
You should be able to get the days using strtotime(). It accepts arguments like next Tuesday and also parses 2011-06-15 into a correct timestamp. And yes, you need one (or more) loop(s).
This should be sufficient to point you in the right direction.
Ok, you updated your question while I was writing my answer. You can't assume that a day always has 86400 seconds. When DST starts or ends your assumption will be incorrect.
<?php
$start = "1 Jan 2011";
$end = "20 Jan 2011";
$dates = getDays($start, $end);
print_r($dates);
function getDays($start,$end)
{
$t = new DateTime("$start 12:00");
$e = new DateTime($end ." 12:00");
$out = array();
for (; $t<=$e; $t->modify("+1 day")) {
$day = $t->format("D");
if (in_array($day, array('Mon','Wed','Fri'))) {
$out[] = $t->format('d M Y');
}
}
return $out;
}

Categories