DateTime period issues - php

I've got strange behaviour with datetime's in php.
For some reason this code produces wrong result:
$period = new DatePeriod(
new DateTime('2017-03-20'),
DateInterval::createFromDateString('1 day'),
new DateTime('2017-03-31')
);
foreach($period as $dt){
$a[] = $dt->format('Y-m-d');
}
So expected result is period from 20 to 31, but it's not. Here is actual result:
Array
(
[0] => 2017-03-20
[1] => 2017-03-21
[2] => 2017-03-22
[3] => 2017-03-23
[4] => 2017-03-24
[5] => 2017-03-25
[6] => 2017-03-26
[7] => 2017-03-27
[8] => 2017-03-28
[9] => 2017-03-29
[10] => 2017-03-30
)
So what i'm missing here, or that's a php bug?

Following this user statement on official PhP documentation about DatePeriod::
[...] an example to include the end date using the DateTime method 'modify'
This class seems to ignore the end date. You will need to modify the end date to include this gap (of +1 unit, in your case +1 day).

Related

Carbon\Carbon giving me issues

hello i'm trying to build an application that plots a graph for the last 7 days beginning with today, and i'm using Laravel 5 - Carbon\Carbon date package..
so if today is wednesday it would end on tuesday
if today is friday it would end on thurdsay nxt week
$now = Carbon::now();
$ar = [];
for($i=1; $i<7; $i++){
array_push($ar, $now->subDays($i));
}
pr($ar, true);
where pr() is a helper function similar to dd() i wrote that just die-dumps in a simple way, but i get this output, with the first problem being that, keeping in mind that today is - Friday, 30th November, 2018, 2018-11-30
Array(
[0] => Carbon\Carbon Object
(
[date] => 2018-11-09 12:23:53.793501
[timezone_type] => 3
[timezone] => UTC
)
[1] => Carbon\Carbon Object
(
[date] => 2018-11-09 12:23:53.793501
[timezone_type] => 3
[timezone] => UTC
)
[2] => Carbon\Carbon Object
(
[date] => 2018-11-09 12:23:53.793501
[timezone_type] => 3
[timezone] => UTC
)
[3] => Carbon\Carbon Object
(
[date] => 2018-11-09 12:23:53.793501
[timezone_type] => 3
[timezone] => UTC
)
[4] => Carbon\Carbon Object
(
[date] => 2018-11-09 12:23:53.793501
[timezone_type] => 3
[timezone] => UTC
)
[5] => Carbon\Carbon Object
(
[date] => 2018-11-09 12:23:53.793501
[timezone_type] => 3
[timezone] => UTC
)
it should continue as 29th, 28th, 27th, but its going far back as 09th of november, and its not even sequencial, like 09, 08, 07, 06, just 09 of november and i dont know what i'm getting wrong, please i need assistance, thanks.
When you use a function on a carbon object, the object will update itself and return a reference to the object. So, your $ar array contains several references to the same object. Every time you use subDays you are actually updating every object in your array.
If you want to fill your array with different carbon objects, you have to create a new instance every time. For example, like this:
$ar = [];
for($i=1; $i<7; $i++){
array_push($ar, now()->subDays($i));
}
now() is a helper function in Laravel that returns a new instance of Carbon::now().
$day = Carbon::today();
$ar = [];
for($i=1; $i<=7; $i++){
array_push($ar, $day);
$day->subDay(1);
}
Here $day->subDay(1); method is modifying the object value itself subtracting by 1 instead of returning the modified value.
$ar = [];
for($i=1; $i<7; $i++){
$now = Carbon::now();
$ar[] = $now->subDays($i);
}
Carbon will update it's instance everytime you call subdays, so you need to reninitilize.

CalendarView get only today's events

I am working with the graph in PHP, and building a calendar widget for a site that should pull only today's events, including all day events.
Everything works, however it also pulls all day events for yesterday and I cannot figure out what I am doing wrong.
$today = new DateTime( 'now', new DateTimeZone( 'America/New_York' ) );
$tomorrow = new DateTime( 'tomorrow', new DateTimeZone( 'America/New_York' ) );
$start_date = $today->format('Y-m-d');
$end_date = $tomorrow->format('Y-m-d');
$events = ms_get_data_as_json( 'calendarview?startdatetime=' . $start_date . '&enddatetime=' . $end_date . '&$orderby=start/DateTime' );
the formatted request string outputs as calendarview?startdatetime=2018-05-18&enddatetime=2018-05-19&$orderby=start/DateTime which would appear to work correctly, however sending this request, the first object returned is an all day event for the previous day. See sample output:
[0] => stdClass Object
(
[createdDateTime] => 2018-05-18T13:30:37.8672462Z
[lastModifiedDateTime] => 2018-05-18T13:34:25.2248155Z
[categories] => Array
(
)
[originalStartTimeZone] => UTC
[originalEndTimeZone] => UTC
[reminderMinutesBeforeStart] => 1080
[isReminderOn] =>
[hasAttachments] =>
[subject] => Test yesterday
[bodyPreview] =>
[importance] => normal
[sensitivity] => normal
[isAllDay] => 1
[isCancelled] =>
[isOrganizer] => 1
[responseRequested] => 1
[seriesMasterId] =>
[showAs] => free
[type] => singleInstance
[onlineMeetingUrl] =>
[recurrence] =>
[responseStatus] => stdClass Object
(
[response] => organizer
[time] => 0001-01-01T00:00:00Z
)
[body] => stdClass Object
(
[contentType] => html
[content] =>
)
[start] => stdClass Object
(
[dateTime] => 2018-05-17T00:00:00.0000000
[timeZone] => UTC
)
[end] => stdClass Object
(
[dateTime] => 2018-05-18T00:00:00.0000000
[timeZone] => UTC
)
)
The start property is clearly for the prior date.
I've tried to change my query to include timestamps startdatetime=2018-05-18T00:00:01Z&enddatetime=2018-05-18T23:59:59Z yet I still get the same results. I've tried to change my $today and $tomorrow variables to use UTC, as the returned result says OriginalStartTimeZone is UTC, but I still get the same results.
Any help is appreciated.
I think there's a bit of an inequality problem in the way the apply the start/end dates filters, and it ends up including events that end on the start time (or start on the end time).
At the moment, it seems the solution is to add 1 second to the filter's start time, and subtract 1 second from the filter's end time. You'll still get all-day events for the requested date, but not all-day events for the previous or next day.
Let us know if you find situations which don't work with this method!

PHP: print all days between a given day and end of month

I don't want to return DATE (Y-m-d).
I need to print all days until end of month from a given day independently of the month or year.
I tried both [$array as $i] - [$array as $key] and didn't work.
$myday (for example = 19)
return $days
would result:
Array
[0] => 20
[1] => 21
[2] => 22
[3] => 23
...
[31] => 31 || [30] => 30 || [28] => 28
I would need each value for $days to compare each to another field.
Didn't try to use $myday as regular number instead of treating as date. And not use strtotime, mktime....
EDITING
Need something very simple like this one:
$output = array();
for ($i=$myday+1;$i<=31 || $i<=30 || $i<=28;$i++) {
$output[] = $i;
}
But print_r won't do it, I need to return as each value to use in different if conditions
This is easily done using DateTime(), DateInterval(), DatePeriod(), and relative date formats.
$start = (new DateTime())->setDate(date('Y'), date('m'), $myday + 1);
$end = new DateTime('first day of next month');
$interval = new DateInterval('P1D');
$period = new DatePeriod($start, $interval, $end);
$days = array();
foreach($period as $date) {
$days[] = $date->format('d');
}
Results
Array
(
[0] => 20
[1] => 21
[2] => 22
[3] => 23
[4] => 24
[5] => 25
[6] => 26
[7] => 27
[8] => 28
[9] => 29
[10] => 30
[11] => 31
)
Demo

How to get current date/time as a date object in PHP

How do you get today's date, as a date object?
I'm trying to compute the difference between some start date and today. The following will not work, because getdate() returns an array and not a date object:
$today = getdate();
$start = date_create('06/20/2012');
$diff = date_diff($start, $today);
echo($today . '<br/>' . $start . '<br/>' . $diff);
Output:
Array ( [seconds] => 8 [minutes] => 1 [hours] => 16 [mday] => 11 [wday] => 1 [mon] => 6 [year] => 2012 [yday] => 162 [weekday] => Monday [month] => June [0] => 1339455668 )
DateTime Object ( [date] => 2012-06-20 00:00:00 [timezone_type] => 3 [timezone] => America/Los_Angeles )
new DateTime('now');
http://www.php.net/manual/en/datetime.construct.php
Comparing is easy:
$today = new DateTime('now');
$newYear = new DateTime('2012-01-01');
if ($today > $newYear) {
}
Op's edit
I just needed to call date_default_timezone_set, and then this code worked for me.
To get difference in days use this:
$today = new DateTime('today');
the time in this object eill be 00:00:00
If you want difference with hours minutes and seconds use this:
$now = new DateTime('now');
I ended up using the date_create constructor (no parameter) to get the current date.
$diff = date_diff(date_create('06/20/2012'), date_create());
print_r($diff);
Output:
DateInterval Object ( [y] => 0 [m] => 0 [d] => 8 [h] => 6 [i] => 30 [s] => 40 [invert] => 1 [days] => 8 )
I have no idea why, but Mike B's answer (and any constructor I tried for DateTime) threw an error for me in PHP5 / IIS.

Weird issue with PHP's DateTime::add not adding time

I've managed to reduce this to a small script which reproduces the issue (Tried on two different PC's, but both with 5.3.6):
<?php
$item = array('monthly_on_the' => 4);
$date = new DateTime();
$date->modify('first day of this month');
print_r($date);
$interval = new DateInterval('P'.$item['monthly_on_the'].'D');
print_r($interval);
$return = $date->add($interval);
if (!$return) die('Bad stuff happened!');
print_r($date);
DateTime Object
(
[date] => 2012-02-01 17:15:23
[timezone_type] => 3
[timezone] => Australia/Sydney
)
DateInterval Object
(
[y] => 0
[m] => 0
[d] => 4
[h] => 0
[i] => 0
[s] => 0
[invert] => 0
[days] =>
)
DateTime Object
(
[date] => 2012-02-01 17:15:23
[timezone_type] => 3
[timezone] => Australia/Sydney
)
Is this a bug and if so, has it been fixed in more recent versions of PHP? Or is there something weird in the time stuff that I'm overlooking?
Yes it's a bug. I'm experiencing the same thing with PHP 5.3.6. Apparently it's fixed in 5.3.7. See the changelog:
http://www.php.net/ChangeLog-5.php#5.3.7
Bug Report:
https://bugs.php.net/bug.php?id=54340
Workaround (if you can't upgrade):
$date->setTimestamp(strtotime('first day of this month', $date->getTimestamp()));

Categories