Laravel Carbon plus or minute one minute for comparing time - php

I am working on a notification then checks every minute for a scheduled notification. It never calls it because my now variable is in a minute format (2021-01-28 10:27) where as the database send_date is stored (2021-01-28 10:15:11)
$now = date("Y-m-d H:i", strtotime(Carbon::now()));
$notifications = Notification::get();
if($notifications !== null)
{
Log::info('Notifications are not null ' .$now); // shows in log (2021-01-28 10:27)
$notifications->where('send_date', $now)->each(function($message) {
Log::info('looking at send_date'); // never shows in log
}
}
Or is there another way of doing this, that I am not seeing?

$notifications = Notification::get();
if($notifications !== null)
{
Log::info('Notifications are not null ' .$now); // shows in log (2021-01-28 10:27)
$notifications->whereBetween('send_date', [Carbon::now()->subMinute()->format('Y-m-d H:i'), Carbon::now()->addMinute()->format('Y-m-d H:i')])->each(function($message) {
Log::info('looking at send_date'); // never shows in log
}
}
Reference :
whereBetween, Carbon

Then you could use the following way
$notifications->whereBetween('send_date', [Carbon::now()->startOfMinute(), Carbon::now()->endOfMinute()])->each(function($message) {
If you need to format the time yourself then:
$notifications->whereBetween('send_date', [Carbon::now()->startOfMinute()->format('Y-m-d H:I:s'), Carbon::now()->endOfMinute('Y-m-d H:I:s')])->each(function($message) {

Related

Wrong timestamp inserted when I call the update method on controller from another laravel app

I'm calling an update method from a laravel app unfortunately a wrong updated_at is inserted with one hour delta despite the timezone is the same on each sides
You can see the difference here between the result of a dump of the source datetime and the query on the other side, there is a difference of one hour :
Here is the code I use in order to call the remote controller:
$updatedIntranet = new DateTime($stagesIntranet[$key]->updated_at);
$stageSiteValueIndex = array_keys($stagesSiteIds,$id);
echo('id : '. $id);
$updatedsite = new DateTime($stagesSite[$stageSiteValueIndex[0]]->updated_at);
$diffTimestamps = $updatedIntranet->getTimestamp() - $updatedsite->getTimestamp();
echo '------- updated intranet ---------<br />';
dump($stageIntranet->updated_at);
echo '-------- updated site --------<br />';
dump($stagesSite[$stageSiteValueIndex[0]]->updated_at);
echo '--------diff--------<br />';
// site must be updated
if( $diffTimestamps != 0)
{
dump('delta : '.$diffTimestamps);
$countUpdated++;
$stageIntranet->id = $stageIntranet->id_stages;
unset($stageIntranet->id_stages);
$stageIntranetCleanUTF8 = $this->utf8ize($stageIntranet->toArray());
$stageIntranetJson = json_encode($stageIntranetCleanUTF8,JSON_UNESCAPED_UNICODE);
$updateResponse = $client->put(
$this->updateTarget.'/'.$stageIntranet->id,
[
'json'=>[$stageIntranetJson],
]
);
dd($updateResponse->getBody()->getContents());
}
So next time I launch the code delta should be 0 and unfortunately there is always 3600 seconds as you can see
I got the answer, it's a breaking change since Laravel 7 you must override the default Datetime serialization in your model, see : https://laravel.com/docs/7.x/upgrade#date-serialization

PHP variable assignment in foreach loop - unknown behavior

This has me completely stumped. I am using a Cakephp 3.9.6 application and tplaner/When library on PHP 7.4 to generate recurring events. Somewhere, the start and end dates are being set as the same date. Here is the section from my EventsController::add method:
$data = $this->request->getData();
$copies = new When();
$copies->freq($data['frequency'])
->interval($data['interval'])
->wkst('MO');
if ($data['frequency'] == 'WEEKLY') {
$copies->byday(implode(',', $data['days']));
}
if (!empty($data['count'])) {
$copies->count($data['count']);
} else {
$copies->until(new DateTime($data['last_date'] . " 23:59:59"));
}
$copies->startDate(new DateTime($event->start->toDateTimeString()))->generateOccurrences();
$newCopies = $copies->occurrences;
$interval = $event->start->diff($event->end);
foreach ($newCopies as $copy) {
Log::debug($copy); //Shows the next date in the series calculated from start date
if ($copy == $event->start) {
continue; //First event already saved in rest of action, do not create another copy
}
$temp = $event->toArray(); //copy entity details to array
$temp['start'] = $copy; //assign new start time
$start = $copy; //thought maybe due to race condition? Copying to new object to modify end time
$temp['end'] = $start->add($interval); //$interval calculated from original event data, added to new start time
Log::debug($temp);
$result = $this->Events->newEntity($temp); //return to new entity
Log::debug($result);
$events[] = $result; //add to array of entities for saveMany()
}
The problem I have is that the new start date in the array/entity are the same as the end date:
Log::debug($copy) outputs the correct new start date
Log::debug($temp) shows the array, but the start and end properties are the same...
you can not do $start=$copy as they will be the same "object" with different references, you actually want to CLONE $copy so it is a separate object. So when you alter one you do not touch the other

PHP - Handling dates before and after christ

Im making Biogram on my site which lists known historical figures.
Right now, Im just getting values from database, and on many IF statements, determine what to display.
/* #var $bio \Models\Library\Biography */
$birth = [];
$death = [];
$date = null;
if($bio->getBirthMonth() != null) {
if ($bio->getBirthDay() != null) {
$birth = [
$bio->getBirthDay(),
$bio->getBirthMonth(),
$bio->getBirthYear(),
];
} else {
$birth = [
$bio->getBirthMonth(),
$bio->getBirthYear(),
];
}
} else {
$birth = [
$bio->getBirthYear(),
];
}
if($bio->getDeathMonth() != null) {
if ($bio->getDeathDay() != null) {
$death = [
$bio->getDeathDay(),
$bio->getDeathMonth(),
$bio->getDeathYear(),
];
} else {
$death = [
$bio->getDeathMonth(),
$bio->getDeathYear(),
];
}
} else {
$death = [
$bio->getDeathYear(),
];
}
if (!array_filter($birth) && array_filter($death)) {
$date = 'zm. ' . implode('.', $death);
}
if (array_filter($birth) && !array_filter($death)) {
$date = 'ur. ' . implode('.', $birth);
}
if (!array_filter($birth) && !array_filter($death)) {
$date = null;
}
if (array_filter($birth) && array_filter($death)) {
$date = implode('.', $birth) . ' - ' . implode('.', $death);
}
But first of all, Im not happy with this kind of code (don't know if I can write it better).
Secondly when im using Carbon (for example), and want to display year from medival ages, it looks like 0552 instead of 552.
The last thing is that there is no "year 0" in history. There were year 1 After Christ and 1 Before Christ. So when I want to have year -200 it gives me -199.
I know this may be handled by adding -1 to date if it's BC, but I think this is not the right way.
Is there any php library for DateTime that handles all the Dates well?
Also can I, and if so; how to rewrite this code above to look better?
Cheers :)
This is a very interesting problem.
Firstly your if statements - I would write a helper function within $bio that contains the logic regarding what to display as your date, making reference to the other properties that exist within $bio. You could call it getPrettyDate() or something like that. That's potentially where your logic for getting the year to display correctly would go too.
After some considerable googling and not much luck, this answer seems to be the most helpful on this subject, certainly some food for thought.
It's also worth noting that using DATE when persisting this information to your database (assuming you're using MySQL, which you may well not be) is probably not the way forward in your case - as noted in that answer, the MySQL definition of DATE is the following
DATE
A date. The supported range is '1000-01-01' to '9999-12-31'.
I have also after writing this just stumbled across this answer which might be the best approach. Good luck!
More reading on ISO-8601 in the context of 'Year 0' here.

time greater than another time

I am preparing a small php attendance script which will record the time and date of given user.
I am trying to display a message that if person is LATE after given time php to display a message you are late
$CURRENTTIME = new DateTime($data['current_time']);
$CURRENTTIME = $CURRENTTIME->format('H:i:s');
$OFFICETIME = new DateTime('10:20:00');
$OFFICETIME = $OFFICETIME->format('H:i:s');
var_dump($CURRENTTIME);
var_dump($OFFICETIME);
if ($CURRENTTIM > $OFFICETIME) {
echo 'you are late tody';
} else {
echo 'Thank you for being on time';
}
also i wanted to learn the code if i need a result in between time? let say i need to display result if employee is in between 10:00:00 - 10:30:00
DateTime objects are comparable so no need to compare their formatted strings. Just compare the objects themselves.
$CURRENTTIME = new DateTime($data['current_time']);
$OFFICETIME = new DateTime('10:20:00');
if ($CURRENTTIME > $OFFICETIME) {
echo 'you are late tody';
} else {
echo 'Thank you for being on time';
}
See this answer for how to see if a time is between two times. It's pretty much the same concept.
Sidenote: There was a typo in your code. $CURRENTTIM which should read as $CURRENTTIME.

php RRD graph separation

I am trying to create RRD graphs with the help of PHP in order to keep track of the inoctets,outoctets and counter of a server.
So far the script is operating as expected but my problems comes when I am trying to produce 2 or more separate graphs. I am trying to produce (hourly, weekly , etc) graphs. I thought by creating a loop would solve my problem, since I have split the RRA in hours and days. Unfortunately I end up having 2 graphs that updating simultaneously as expected but plotting the same thing. Has any one encounter similar problem? I have applied the same program in perl with RRD::Simple,where is extremely easy and everything is adjusted almost automatically.
I have supplied under a working example of my code with the minimum possible data because the code is a bit long:
<?php
$file = "snmp-2";
$rrdFile = dirname(__FILE__) . "/snmp-2.rrd";
$in = "ifInOctets";
$out = "ifOutOctets";
$count = "sysUpTime";
$step = 5;
$rounds = 1;
$output = array("Hourly","Daily");
while (1) {
sleep (6);
$options = array(
"--start","now -15s", // Now -10 seconds (default)
"--step", "".$step."",
"DS:".$in.":GAUGE:10:U:U",
"DS:".$out.":GAUGE:10:U:U",
"DS:".$count.":ABSOLUTE:10:0:4294967295",
"RRA:MIN:0.5:12:60",
"RRA:MAX:0.5:12:60",
"RRA:LAST:0.5:12:60",
"RRA:AVERAGE:0.5:12:60",
"RRA:MIN:0.5:300:60",
"RRA:MAX:0.5:300:60",
"RRA:LAST:0.5:300:60",
"RRA:AVERAGE:0.5:300:60",
);
if ( !isset( $create ) ) {
$create = rrd_create(
"".$rrdFile."",
$options
);
if ( $create === FALSE ) {
echo "Creation error: ".rrd_error()."\n";
}
}
$t = time();
$ifInOctets = rand(0, 4294967295);
$ifOutOctets = rand(0, 4294967295);
$sysUpTime = rand(0, 4294967295);
$update = rrd_update(
"".$rrdFile."",
array(
"".$t.":".$ifInOctets.":".$ifOutOctets.":".$sysUpTime.""
)
);
if ($update === FALSE) {
echo "Update error: ".rrd_error()."\n";
}
$start = $t - ($step * $rounds);
foreach ($output as $test) {
$final = array(
"--start","".$start." -15s",
"--end", "".$t."",
"--step","".$step."",
"--title=".$file." RRD::Graph",
"--vertical-label=Byte(s)/sec",
"--right-axis-label=latency(min.)",
"--alt-y-grid", "--rigid",
"--width", "800", "--height", "500",
"--lower-limit=0",
"--alt-autoscale-max",
"--no-gridfit",
"--slope-mode",
"DEF:".$in."_def=".$file.".rrd:".$in.":AVERAGE",
"DEF:".$out."_def=".$file.".rrd:".$out.":AVERAGE",
"DEF:".$count."_def=".$file.".rrd:".$count.":AVERAGE",
"CDEF:inbytes=".$in."_def,8,/",
"CDEF:outbytes=".$out."_def,8,/",
"CDEF:counter=".$count."_def,8,/",
"COMMENT:\\n",
"LINE2:".$in."_def#FF0000:".$in."",
"COMMENT:\\n",
"LINE2:".$out."_def#0000FF:".$out."",
"COMMENT:\\n",
"LINE2:".$count."_def#FFFF00:".$count."",
);
$outputPngFile = rrd_graph(
"".$test.".png",
$final
);
if ($outputPngFile === FALSE) {
echo "<b>Graph error: </b>".rrd_error()."\n";
}
} /* End of foreach function */
$debug = rrd_lastupdate (
"".$rrdFile.""
);
if ($debug === FALSE) {
echo "<b>Graph result error: </b>".rrd_error()."\n";
}
var_dump ($debug);
$rounds++;
} /* End of while loop */
?>
A couple of issues.
Firstly, your definition of the RRD has a step of 5seconds and RRAs with steps of 12x5s=1min and 300x5s=25min. They also have a length of only 60 rows, so 1hr and 25hr respectively. You'll never get a weekly graph this way! You need to add more rows; also the step seems rather short, and you might need a smaller-step RRA for hourly graphs and a larger-step one for weekly graphs.
Secondly, it is not clear how you're calling the graph function. You seem to be specifying:
"--start","".$start." -15s",
"--end", "".$t."",
"--step","".$step."",
... which would force it to use the 5s interval (unavailable, so the 1min one would always get used) and for the graph to be only for the time window from the start to the last update, not a 'hourly' or 'daily' as you were asking.
Note that the RRA you have defined do not define the time window of the graph you are asking for. Also, just because you have more than one RRA defined, it doesnt mean you'll get more than one graph unless oyu call the graph function twice with different arguments.
If you want a daily graph, use
"--start","end - 1 hour",
"--end",$t,
Do not specify a step as the most appropriate available will be used anyway. For a daily graph, use
"--start","end - 1 day"
"--end",$t,
Similarly, no need to specify a step.
Hopefully this will make it a little clearer. Most of the RRD graph options have sensible defaults, and RRDTool is pretty good at picking the correct RRA to use based on the graph size, time window, and DEF statements.

Categories