UseCase: Admin assigns tasks to People. Before we assign them we can see their tasks in a gantt chart. According to the task assign date and deadline, conflict days (overlap days) are generated between tasks.
I wrote this function to get overlapping dates between two dates. But now I need to get non overlapping days between two dates, below is the function I wrote.
$tasks = Assign_review_tasks::where('assigned_to', $employee)
->where('is_active', \Constants::$REVIEW_ACTIVE)
->whereNotNull('permit_id')->get();
$obj['task'] = count($tasks);
// count($tasks));
if (count($tasks) > 0) {
if (count($tasks) > 1) {
$start_one = $tasks[count($tasks) - 1]->start_date;
$end_one = $tasks[count($tasks) - 1]->end_date;
$end_two = $tasks[count($tasks) - 2]->end_date;
$start_two = $tasks[count($tasks) - 2]->start_date;
if ($start_one <= $end_two && $end_one >= $start_two) { //If the dates overlap
$obj['day'] = Carbon::parse(min($end_one, $end_two))->diff(Carbon::parse(max($start_two, $start_one)))->days + 1; //return how many days overlap
} else {
$obj['day'] = 0;
}
// $arr[] = $obj;
} else {
$obj['day'] = 0;
}
} else {
$obj['day'] = 0;
}
$arr[] = $obj;
start_date and end_date are taken from database,
I tried modifying it to,
(Carbon::parse((min($end_one, $end_two))->add(Carbon::parse(max($start_two, $start_one))))->days)->diff(Carbon::parse(min($end_one, $end_two))->diff(Carbon::parse(max($start_two, $start_one)))->days + 1);
But it didn't work, in simple terms this is what I want,
Non conflicting days = (end1-start1 + end2-start2)- Current overlapping days
I'm having trouble translate this expression . Could you help me? Thanks in advance
before trying to reimplement complex stuff I recommend you take a look at enhanced-period for Carbon
composer require cmixin/enhanced-period
CarbonPeriod::diff macro method is what I think you're looking for:
use Carbon\CarbonPeriod;
use Cmixin\EnhancedPeriod;
CarbonPeriod::mixin(EnhancedPeriod::class);
$a = CarbonPeriod::create('2018-01-01', '2018-01-31');
$b = CarbonPeriod::create('2018-02-10', '2018-02-20');
$c = CarbonPeriod::create('2018-02-11', '2018-03-31');
$current = CarbonPeriod::create('2018-01-20', '2018-03-15');
foreach ($current->diff($a, $b, $c) as $period) {
foreach ($period as $day) {
echo $day . "\n";
}
}
This will output all the days that are in $current but not in any of the other periods. (E.g. non-conflicting days)
I have a list of version numbers like,
Versions = [0.0.10, 0.0.11, 0.0.13, 0.0.14, 0.0.15, 0.0.16, 0.0.17, 0.0.18, 0.0.19, 0.0.20, 0.0.21, 0.0.22, 0.0.23, 0.0.24, 0.0.25, 0.0.26, 0.0.27, 0.0.28, 0.0.29, 0.0.3, 0.0.30, 0.0.33, 0.0.34, 0.0.35, 0.0.36, 0.0.37, 0.0.38, 0.0.39, 0.0.4, 0.0.41, 0.0.42, 0.0.43, 0.0.44, 0.0.45, 0.0.46, 0.0.47, 0.0.48, 0.0.49, 0.0.5, 0.0.5-delivery.5, 0.0.50, 0.0.51, 0.0.52, 0.0.53, 0.0.54, 0.0.55, 0.0.56, 0.0.57, 0.0.58, 0.0.59, 0.0.6, 0.0.60, 0.0.61, 0.0.62, 0.0.63, 0.0.64, 0.0.7, 0.0.8, 0.0.9]'
And i need to get the last version (0.0.64), Versions.sort() && Collections.max(Versions) doesn't work for me.
So I developed this function blow
def mostRecentVersion(def versions) {
def lastversion = "0.0.0"
for (def items : versions) {
def version = items.tokenize('-')[0]
def ver = version.tokenize('.')
def lastver = lastversion.tokenize('.')
if (lastver[0].toInteger() < ver[0].toInteger() ){
lastversion = version
}else if(lastver[0].toInteger() == ver[0].toInteger()) {
if (lastver[1].toInteger() < ver[1].toInteger() ){
lastversion = version
}else if(lastver[1].toInteger() == ver[1].toInteger()){
if (lastver[2].toInteger() < ver[2].toInteger() ){
lastversion = version
}
}
}
}
return lastversion }
i'm asking if there is something better,
Thank you for help :)
the idea:
build map with sortable key and original version value, then sort map by keys, then get only values
to create sortable key for each value
split version to digits & not-digit strings array
prepend to each part 0 to have minimum length 3 (assume each number not longer then 3 digits)
join array to string
so, for 0.11.222-dev ->
1. [ '0', '.', '11', '222', '-dev' ]
2. [ '000', '00.', '011', '222', '-dev' ]
3. '00000.011222-dev'
the code
def mostRecentVersion(versions){
return versions.collectEntries{
[(it=~/\d+|\D+/).findAll().collect{it.padLeft(3,'0')}.join(),it]
}.sort().values()[-1]
}
//test cases:
def fullVersions = ['0.0.10', '0.0.11', '0.0.13', '0.0.14', '0.0.15', '0.0.16',
'0.0.17', '0.0.18', '0.0.19', '0.0.20', '0.0.21', '0.0.22', '0.0.23', '0.0.24',
'0.0.25', '0.0.26', '0.0.27', '0.0.28', '0.0.29', '0.0.3', '0.0.30', '0.0.33',
'0.0.34', '0.0.35', '0.0.36', '0.0.37', '0.0.38', '0.0.39', '0.0.4', '0.0.41',
'0.0.42', '0.0.43', '0.0.44', '0.0.45', '0.0.46', '0.0.47', '0.0.48', '0.0.49',
'0.0.5', '0.0.5-delivery.5', '0.0.50', '0.0.51', '0.0.52', '0.0.53', '0.0.54',
'0.0.55', '0.0.56', '0.0.57', '0.0.58', '0.0.59', '0.0.6', '0.0.60', '0.0.61',
'0.0.62', '0.0.63', '0.0.64', '0.0.7', '0.0.8', '0.0.9']
assert mostRecentVersion(fullVersions) == '0.0.64'
assert mostRecentVersion(['0.0.5-delivery.5', '0.0.3', '0.0.5']) == '0.0.5-delivery.5'
assert mostRecentVersion(['0.0.5.5', '0.0.5-delivery.5', '0.0.5']) == '0.0.5.5'
I believe this will work... it also keeps the original version strings around, incase 0.5.5-devel.5 is the latest... It relies on the fact that Groovy will use a LinkedHashMap for the sorted map, so the order will be preserved :-)
def mostRecentVersion(def versions) {
versions.collectEntries {
[it, it.split(/\./).collect { (it =~ /([0-9]+).*/)[0][1] }*.toInteger()]
}.sort { a, b ->
[a.value, b.value].transpose().findResult { x, y -> x <=> y ?: null } ?:
a.value.size() <=> b.value.size() ?:
a.key <=> b.key
}.keySet()[-1]
}
def fullVersions = ['0.0.10', '0.0.11', '0.0.13', '0.0.14', '0.0.15', '0.0.16', '0.0.17', '0.0.18', '0.0.19', '0.0.20', '0.0.21', '0.0.22', '0.0.23', '0.0.24', '0.0.25', '0.0.26', '0.0.27', '0.0.28', '0.0.29', '0.0.3', '0.0.30', '0.0.33', '0.0.34', '0.0.35', '0.0.36', '0.0.37', '0.0.38', '0.0.39', '0.0.4', '0.0.41', '0.0.42', '0.0.43', '0.0.44', '0.0.45', '0.0.46', '0.0.47', '0.0.48', '0.0.49', '0.0.5', '0.0.5-delivery.5', '0.0.50', '0.0.51', '0.0.52', '0.0.53', '0.0.54', '0.0.55', '0.0.56', '0.0.57', '0.0.58', '0.0.59', '0.0.6', '0.0.60', '0.0.61', '0.0.62', '0.0.63', '0.0.64', '0.0.7', '0.0.8', '0.0.9']
assert mostRecentVersion(fullVersions) == '0.0.64'
assert mostRecentVersion(['0.0.5-delivery.5', '0.0.3', '0.0.5']) == '0.0.5-delivery.5'
assert mostRecentVersion(['0.0.5.5', '0.0.5-delivery.5', '0.0.5']) == '0.0.5.5'
Edit:
Made a change so that 0.5.5.5 > 0.5.5-devel.5
I need help , I have an arrayList of objects . This object contains multiple fields I'm interested in this question by two date fields (date_panne date_mise and running) and two other time fields (heure_panne and time start),
And I would like to obtain the sum of the difference between (date_panne, heure_panne) and (date_mise_en_marche; heure_mise_en_marche) to give the total time of failure.
if someone can help me please I will be gratful this is my function :
public String disponibile() throws Exception {
int nbreArrets = 0;
List<Intervention> allInterventions = interventionDAO.fetchAllIntervention();
List<Intervention> listInterventions = new ArrayList<Intervention>();
for (Intervention currentIntervention : allInterventions) {
if (currentIntervention.getId_machine() == this.intervention.getId_machine()
&& currentIntervention.getDate_panne().compareTo(getProductionStartDate()) >= 0
&& currentIntervention.getDate_panne().compareTo(getProductionEndDate()) <= 0) {
listInterventions.add(currentIntervention);
}
}
savedInterventionList = listInterventions;
return "successView" ;
}
Assuming the the dates are truncated to the day and are of type java.util.Date, and that the times only contain hours, minutes, seconds and milliseconds and are also of type Date, start by creating a method like
private Date combine(Date dateOnly, Date timeOnly) {
Calendar dateCalendar = Calendar.getInstance();
dateCalendar.setTime(dateOnly);
Calendar timeCalendar = Calendar.getInstance();
timeCalendar.setTime(timeOnly);
dateCalendar.add(Calendar.HOUR_OF_DAY, timeCalendar.get(Calendar.HOUR_OF_DAY));
dateCalendar.add(Calendar.MINUTE, timeCalendar.get(Calendar.MINUTE));
dateCalendar.add(Calendar.SECOND, timeCalendar.get(Calendar.SECOND));
dateCalendar.add(Calendar.MILLISECOND, timeCalendar.get(Calendar.MILLISECOND));
return dateCalendar.getTime();
}
Now, it's simply a matter of looping through the interventions you want to sum, computing the difference between the dates as milliseconds, and add them:
long totalMillis = 0L;
for (Intervention intervention : interventions) {
Date marche = combine(intervention.getDateMiseEnMarche(), intervention.getTimeMiseEnMarche());
Date panne = combine(intervention.getDatePanne(), intervention.getTimePanne());
long differenceInMillis = marche.getTime() - panne.getTime();
totalMillis += differenceInMillis;
}
Please post any smarty syntax to Get number of days between two dates from my database. i was to able to display all the other fields,but this date field with number of days not working as the way i was expected.Please let me know is there any way to get this solution without any smarty additional plugins.
Smarty does not include any specific functions for doing date math operations. They have the date_format for timestamps, but otherwise you'd either have to write your own days_diff plugin, find one online, or do the date math in PHP and assign to a new variable in Smarty.
Here is my function for this problem:
/*
* Smarty plugin
* -------------------------------------------------------------
* Type: function
* Name: date_diff
* Author: RafaĆ Pawlukiewicz
* Purpose: factor difference between two dates in days, weeks, or years
* Input: d1 = "mm/dd/yyyy" or "yyyy/mm/dd" or "yyyy-mm-dd"
* d2 = "mm/dd/yyyy" or "yyyy/mm/dd" or "yyyy-mm-dd" or $smarty.now
* assign = name of variable to assign difference to
* interval = "days" (default), "weeks", "years"
* Examples: {date_diff d1="2020-01-20"}
* Examples: {date_diff d1="2020-01-20" d2=2020-02-10 interval="weeks"}
* Examples: {date_diff d1="2020-01-20" d2=2020-02-10 assign="variable_diff"} result: {$variable_diff}
* -------------------------------------------------------------
*/
function smarty_function_date_diff($params, &$smarty)
{
$d1 = isset($params['d1']) ? $params['d1'] : date('Y-m-d');
$d2 = isset($params['d2']) ? $params['d2'] : date('Y-m-d');
$assign_name = isset($params['assign']) ? $params['assign'] : '';
$date1 = strtotime($d1);
$date2 = strtotime($d2);
// use current for empty string
if (! $date1) {
$date1 = date('Y-m-d');
}
if (! $date2) {
$date2 = date('Y-m-d');
}
$interval = isset($params['interval']) ? $params['interval'] : 'days';
// diff in days
$diff = ($date2 - $date1) / 60 / 60 / 24;
if ($interval === "weeks") {
$diff /= 7;
}
elseif ($interval === "years") {
$diff /= 365.25;
}
$diff = floor($diff);
if ($assign_name) {
$smarty->assign($assign_name, $diff);
}
else {
return $diff;
}
}