Sum times from Array using Carbon - php

How can i sum times into array using Carbon?
<?php
namespace App\Models;
use Carbon\Carbon;
class Appointment extends BaseModel
{
public static function total_time()
{
$appointments = Appointment::get();
$sumtimes = [];
foreach($appointments as $a){
$dti = Carbon::parse($a->dateinitial);
$dtf = Carbon::parse($a->datefinal);
$time = $dti->diff($dtf)->format('%H:%I:%S');
$sumtimes[] = $time;
}
$sumtimes= sum($sumtimes);
return $sumtimes;
}
inside sum_times, there is a list of times that need to be summed like:
$sum_times[0] = "00:01:18"
$sum_times[1] = "00:03:11"
$sum_times[2] = "01:01:18"
$sum_times[3] = "00:01:28"
I need it to return "01:07:15"

<?php
public static function total_time(): string
{
$seconds = 0;
foreach(Appointment::get() as $appointment){
$dateinitial = Carbon::parse($appointment->dateinitial);
$datefinal = Carbon::parse($appointment->datefinal);
$seconds += $datefinal->diffInSeconds($dateinitial);
}
return gmdate('H:i:s', $seconds);
}
Also you must set for your fields (dateinitial, datefinal) cast datetime for automated parsing to Carbon type. Docs for date casts.

Each result of diff can be continuously added to a datum. At the end of the loop we get the sum as the difference from the base date to the date. Carbon is an extension of DateTime. I show the sample code with the base class so that it is reproducible for everyone.
$data = [
['from' => '2022-03-01 16:00', 'to' => '2022-03-02 12:00'], //20:00:00
['from' => '2022-03-02 12:30', 'to' => '2022-03-02 22:02'], //09:32:00
]; //total 29:32:00
$basis = '2000-01-01';
$dateBase = date_create('2000-01-01');
$date = clone $dateBase;
foreach($data as $dates){
$dateFrom = date_create($dates['from']);
$dateTo = date_create($dates['to']);
$diff = $dateFrom->diff($dateTo);
$date->add($diff);
}
$totalDiff = $dateBase->diff($date);
$hours = $totalDiff->d *24 + $totalDiff->h; //days * 24 + hours
echo 'Sum: '.$hours.$totalDiff->format(':%I:%S');
//Sum: 29:32:00
Try self on 3v4l.org

Related

Display last working day if not Saturday or Sunday for 12 months

I am having trouble getting the last working day of the month to dispaly for 12 months and display the last working day of the month (not a weekend), if I just display one month using:
echo date('l', strtotime($lastworkingday))." ".$lastworkingday;
it works, but I can only get the 12 months to display for 12 month using I can't workout how to get it working. It only works for 12 month using the below.
echo $lastworkingday->format('t-m-Y') . " | ";
The problem is it shows the last working day of the month even if it is a weekend. Where am I going wrong please.
<?php
namespace App\Console\Commands;
use DateTime;
use DatePeriod;
use DateInterval;
use Illuminate\Console\Command;
class ExportCalendarPayments extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'calendar:payments';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Exports Payment Calendar Spreadsheet';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
//Create an instance of now
$now = new \DateTime( '01-01-2021', new \DateTimeZone( 'Europe/London' ) );
//sets the absolute last day of the month based off $now
$lastdateofthemonth = new \DateTime( $now->format("t-m-Y"), new \DateTimeZone( 'Europe/London' ) );
$lastdateofthemonth->add(new \DateInterval('P11M'));
$lastdateofthemonth = date("31-07-2021");
$lastworkingday = date('l', strtotime($lastdateofthemonth));
if($lastworkingday == "Saturday") {
$newdate = strtotime ('-1 day', strtotime($lastdateofthemonth));
$lastworkingday = date ('j-m-Y', $newdate);
}
elseif($lastworkingday == "Sunday") {
$newdate = strtotime ('-2 day', strtotime($lastdateofthemonth));
$lastworkingday = date ( 'j-m-Y' , $newdate );
}
/*This output correct date, but I can't get it to show for each of the 12 months*/ echo date('l', strtotime($lastworkingday))." ".$lastworkingday;
//Define our interval (12months)
$interval = new \DateInterval('P1M');
//testing date interval setup
//echo $interval->format('%d days');
//Setup a DatePeriod instance to iterate between the start and end date by the interval
$period = new \DatePeriod( $now, $interval, $lastworkingday );
//Iterate over the DatePeriod instance
foreach( $period as $lastworkingday ){
//Make sure the day displayed is greater than or equal to todayy.
//if( ){
/*echo $lastworkingday->format( 't-m-Y' ) . " | "; */
echo $lastworkingday->format('t-m-Y') . " | ";
/* echo date('l', strtotime($lastworkingday))." ".$lastworkingday;*/
//}
}
//
$data_array = array (
array ('1','2','2'),
array ('2','2','2'),
array ('3','6','2'),
array ('4','2','2'),
array ('6','5','2')
);
$csv = "Period,Basic Payment,Bonus Payment \n";//Column headers
foreach ($data_array as $record){
$csv.= $record[0].','.$record[1].','.$record[2]."\n"; //Append data to csv
}
$csv_handler = fopen ('csvfile.csv','w');
fwrite ($csv_handler,$csv);
fclose ($csv_handler);
echo 'Data saved to csvfile.csv';
}
}

Recursive object instantiation (in PHP)?

So in my PHP program I'm creating a calendar feature and one of the classes is "CalendarDay". What I want to do is be able to instantiate a new day for each day count, so for example new CalendarDay (22) means a new 22nd of the month date. There is also a show() function used for displaying each day. The class itself functions normally but when I try instantiating new days using recursion it no longer seems to work as everything related to the instantiated object disappears from the webpage.
class CalendarDay{
private $current_month;
private $current_year;
private $current_date;
public $reminderSet;
public $reminders;
public function __construct($current_day_of_month){
$current_year = date("Y");
$current_month = date("m");
$this->days_in_month = cal_days_in_month(CAL_GREGORIAN, $current_month, $current_year);
$this->current_date = date("d");
$this->current_day_of_month = $current_day_of_month;
}
public function show(){
$output = '<div class = "generator>"';
//$output .= $this->current_date;
//$output .= '<h1>' . $this->current_date . '</h1>';
$output .= '</div>';
$output .= $this->current_day_of_month;
echo $output;
}
}
My failed attempt at recursion:
for ($countTo31 == 0; $countTo31 == 31; $countTo31++){
$holder = $countTo31;
$date = new CalendarDay ($holder);
$date->show();
}
For the reference, this original block of code without the recursion works normally:
$holder = $countTo31;
$date = new CalendarDay ($holder);
$date->show();
I'm very confused with what you're trying to accomplish...
You have a "day" class which takes input to initialise a specific day but instead actually works out the current day based on date("Y-m-d");?.. And then outputs the input day anyway?
Honestly, it looks more like you want a "month" object
Initial problems
You use == to define your starting point
== is not an assignment operator, it's a comparison.
It effectively adds an additional iteration of the loop at the start of the loop
for($i == 1; $i < 5; $i++){
echo $i;
}
// Loop 1:
// --> Notice on $i == 1
// --> Notice on $i < 5
// --> Notice on echo $i
// --> Notice on $i++
// Loop 2:
--> $i = 1 BECAUSE of the previous $i++
so the intended loop starts...
Additionaly the loop, in this case, should start with 1 not 0(!)
You use == to define your condition
for loops like yours work effectively as:
for ( A ; B ; C ){
// Do something...
}
// Loop works as:
// Check A against B
// If TRUE then "Do something..."
// and then do C
// IF FALSE then break
However, even if your assignment (A) was correct (i.e. $countTo31 = 1), it still wouldn't work because 1 !== 31 and therfore the loop breaks from the start
It should be $countTo31 <= 31
Looping over object, rewriting the variable
Your code currently rewrites the variable which holds the date object with every loop
Effectively you create an object to output the day, output that data, and instantly remove the object so that it can't be used for anyting else...
Your HTML output has a " in the wrong place:
$output = '<div class = "generator>"';
//Should be...
$output = '<div class = "generator">';
Some of the variables in your class are not assigned or declared properly
$current_month is declared but never assigned
$current_year is declared but never assigned
$current_day_of_month is assigned but not declared
$days_in_month is assigned but not declared
Interim solution
Without further information on what you are intending to do it isn't possible to give good/accurate guidance, so I will leave a working example which should show you what to do:
$days_in_month = cal_days_in_month(
CAL_GREGORIAN,
date("m"),
date("Y")
);
for ($day = 1; $day <= $days_in_month; $day++){
echo "Day {$day}<br>";
}
Proposed changes
It doesn't look as though you really even want a "day" class for the functions you're trying to implement. So, in my mind, it would be better to first create a "month" object with all of the days of the month and then have that generate a "day" object for each day of the month which then can gather the information for each day e.g. reminders.
Doing it this way you can then update each day as you go with, for example, user input or database data.
class Month
{
private $month;
private $year;
private $days = [];
public function __construct($month, $year)
{
$this->month = $month;
$this->year = $year;
$number_of_days = cal_days_in_month(
CAL_GREGORIAN,
$month,
$year
);
for ($i = 1; $i <= $number_of_days; $i++){
$date = "{$this->year}-{$this->month}-{$i}";
// $days[] = new Day($date);
$this->days[$i] = new Day($date);
}
}
public function getDay($day)
{
return $this->days[$day];
}
public function getNumberOfDays()
{
return count($this->days);
}
}
class Day
{
private $date;
private $reminders = [];
public function __construct($date)
{
$this->date = $date;
// Initialise day...
# Get reminders
# Get meetings
# Get bills to pay
}
public function getReminders()
{
return $this->reminders;
}
public function setReminder($content, $time)
{
// Set reminders
$this->reminders[] = [
"content" => $content,
"time" => $time
];
}
public function show()
{
return date("d / m / Y", strtotime($this->date));
}
}
$month = new Month(12, 2020);
for ($i = 1; $i <= $month->getNumberOfDays(); $i++){
echo $month->getDay($i)->show()."<br>";
}

Telegram-Bot problem with a command (php)

i'm making a Telegram bot using php language, i want to add a cooldown to a command, i already tried with sleep(), but the result still the same, it doesn't work, someone can help me?
At least this is possible? or i need to re code the bot in another language?
here the code:
<?php
namespace Longman\TelegramBot\Commands\UserCommands;
use Longman\TelegramBot\Commands\UserCommand;
use Longman\TelegramBot\Request;
class DiscordCommand extends UserCommand{
protected $name = 'discord';
protected $description = 'Linka server discord';
protected $usage = '/discord';
protected $version = '1.0.0';
public function execute()
{
$message = $this->getMessage();
$chat_id = $message->getChat()->getId();
$message_id = $message->getMessageId();
$text = 'Ciaoo';
$data = [
'chat_id' => $chat_id,
'text' => $text];
$started_at = time();
if($current_time==$started_at)
return Request::sendMessage($data);
$cooldown = 60*60*1; //1 minutes
$current_time = time();
$timeLeft = $current_time - $started_at;
if($timeLeft >= $cooldown)
return Request::sendMessage($data);
I will comment your code, I see some possible errors here:
$started_at = time();
if($current_time==$started_at) // You're using $current_time, but is not set
return Request::sendMessage($data);
$cooldown = 60*60*1; //This is not 1 minutes, 60*60*1 is 1 hour
$current_time = time();
$timeLeft = $current_time - $started_at;
if($timeLeft >= $cooldown)
return Request::sendMessage($data);

How to avoid ThrottleRequestsException in Laravel unit test?

I am working on an application that has date logic within i.e something will be returned from the database based on the date, and only the relevant data for that date should be returned. How would I go about unit testing this? There are 24 dates that return 24 different pieces of data, I thought maybe doing something like this,
public function testGetActiveData()
{
$this->withoutExceptionHandling();
//Create the data
$dates = CarbonPeriod::create('2019-12-01', '2019-12-12');
$start_date = new Carbon("2019-12-01 00:00:00");
$dates->forEach(function($date){
$data = factory(Data::class)->create([
'date_playable' => $date->toDateTimeString()
]);
factory(LinkedData::class, 15)->create([
'data_id' => $data->id
]);
});
for($day = 1; $day <= 24; $day++) {
if($day = 1) {
Cache::put('data_date', $start_date->toDateTimeString(), now()->addMinutes(30));
} else {
Cache::put('data_date', $start_date->toDateTimeString()->addDays($day), now()->addMinutes(30));
}
$response = $this->json('GET', '/api/data');
$response->assertJson(['date_playable' => Cache::get('data_date')]);
}
}
However this errors due to too many attempts, is there a better way to test this? An obvioulsy I am testing dates in the future so I am pushing a "future date" into cache and then using that is there a better of doing that also?
As described in this comment of a similar problem, you may disable the default Laravel rate limit in your test by applying withoutMiddleware before the TestCase get or json calls.
public function testGetActiveData()
{
$this->withoutExceptionHandling();
//Create the data
$dates = CarbonPeriod::create('2019-12-01', '2019-12-12');
$start_date = new Carbon("2019-12-01 00:00:00");
$dates->forEach(function($date){
$data = factory(Data::class)->create([
'date_playable' => $date->toDateTimeString()
]);
factory(LinkedData::class, 15)->create([
'data_id' => $data->id
]);
});
for($day = 1; $day <= 24; $day++) {
if($day = 1) {
Cache::put('data_date', $start_date->toDateTimeString(), now()->addMinutes(30));
} else {
Cache::put('data_date', $start_date->toDateTimeString()->addDays($day), now()->addMinutes(30));
}
// circumvent the throttle rate limit middleware
// with the "withoutMiddleware" method
$response = $this->withoutMiddleware()->json('GET', '/api/data');
$response->assertJson(['date_playable' => Cache::get('data_date')]);
}
}

Laravel 5 ORM update request, like date_add

I beg to excuse me for my poor english.
So, I have Laravel 5 ORM, and i need to make request that should add date to some rows, like MySQL DATE_ADD. Input is single date interval and array of id's, output is rows of database, that was changed by adding date interval. Ideally, it should be one ORM request. I know that it is possible to use "bad" way and get all rows, update it in a code, and insert to database, but imho it's not good.
I hope answer will be link to some help site or some code if it's does not complicate you. Thanks for your attention!
public function update($id)
{
$user_id = Auth::user()->id;
$rep_task = RepTask::find($id);
$cl_task = \Request::has('json') ? json_decode(\Request::input('json'),true) : \Request::all();
$ids = [];
$task_id = $rep_task->task_id;
$rep_tasks = RepTask::where('task_id', '=', $task_id)
->select('id')
->get();
$new_date = date_create_from_format(self::DATE_FULLCALENDAR_FORMAT, $cl_task['new_date']);
$selected_task_date = date_create_from_format(self::DATE_MYSQL_FORMAT, $rep_task->start_date);
$diff = date_diff($selected_task_date, $new_date);
if(\Request::has('json'))
{
$ids = [1,2,3]; //this for easy understanding
DB::table('rep_task')
->whereIn('id', $ids)
->update(['start_date' => DB::raw('DATE_ADD(start_date, INTERVAL ' . $diff->d . ' DAY)')]);
$out_json = ['updated' => $ids];
return json_encode($out_json, JSON_UNESCAPED_UNICODE);
}
else
{
$start_date = 0;
$end_date = 0;
if (!isset($cl_task['name']) || !isset($cl_task['text']))
return "{'error':'columns are not defined'}";
if (isset($cl_task['start_date']) && isset($cl_task['end_date']))
{
$dt = date_create_from_format(self::DATE_FULLCALENDAR_FORMAT, $cl_task['start_date']);
$start_date = $dt->format(self::DATE_MYSQL_FORMAT);
$dt = date_create_from_format(self::DATE_FULLCALENDAR_FORMAT,$cl_task['end_date']);
$end_date = $dt->format(self::DATE_MYSQL_FORMAT);
}
$rep_task->name = $cl_task['name'];
$rep_task->text = $cl_task['text'];
$rep_task->start_date = $start_date;
$rep_task->end_date = $end_date;
$rep_task->users_id = $user_id;
$rep_task->save();
}
$user_id = Auth::user()->id;
$tasks = Task::getAllTasksByUserFullcalendar($user_id);
return view(
'task.index',
[
'tasks' => $tasks
]
);
}

Categories