Trying to get total time in transition without weekends

Bryan_Karsh January 25, 2017

Hi gang,

I know Jaimie has a great example of calculating total time an issue's been in a particular status:

https://scriptrunner.adaptavist.com/latest/jira/scripted-fields.html#_total_time_this_issue_has_been_in_progress

I've been trying to modify it to only count duration during weekdays (no weekends). I've seen some examples, but I can't get my version to work. I feel like I am close, but missing something. Can someone take a look at my script, and suggest what I need to change? Thanks!!

 

PS – if someone has a way to use jiraDurationUtils to parse the duration to keep out weekends. that would be good to know. Wasn't successful via that approach either. 

 

import com.atlassian.jira.component.ComponentAccessor
import static java.util.GregorianCalendar.*
import com.atlassian.jira.issue.history.ChangeItemBean

enableCache = { -> false }

def changeHistoryManager = ComponentAccessor.getChangeHistoryManager()

def myStatus = "In Progress"

List<Long> rt = [0L]
def changeItems = changeHistoryManager.getChangeItemsForField(issue, "status")
changeItems.reverse().each { ChangeItemBean item ->
    item.toString == myStatus

    def timeStart = System.currentTimeMillis()

    def timeEnd = item.created.getTime()

    def c1 = new GregorianCalendar()

    c1.setTimeInMillis(timeStart)

    int w1 = c1.get(DAY_OF_WEEK);
    c1.add(DAY_OF_WEEK, -w1);

    def c2 = new GregorianCalendar()
    c2.setTimeInMillis(timeEnd)
    int w2 = c2.get(DAY_OF_WEEK);
    c2.add(DAY_OF_WEEK, -w2);

    //end Saturday to start Saturday
    def days = (c2.getTimeInMillis() - c1.getTimeInMillis()) / (1000 * 60 * 60 * 24) as long
    def daysWithoutWeekendDays = days - (days * 2 / 7) as long

    // Adjust days to add on (w2) and days to subtract (w1) so that Saturday
    // and Sunday are not included
    if (w1 == SUNDAY && w2 != SATURDAY) {
        w1 = MONDAY;
    } else if (w1 == SATURDAY && w2 != SUNDAY) {
        w1 = FRIDAY;
    }

    if (w2 == SUNDAY) {
        w2 = MONDAY;
    } else if (w2 == SATURDAY) {
        w2 = FRIDAY;
    }

    //convert to seconds for Duration
    def timeDiff = (daysWithoutWeekendDays - w1 + w2) * (60 * 60 * 24)

    // def timeDiff = timeStart - timeEnd
    if (item.fromString == myStatus) {
        rt << -timeDiff
    }
    if (item.toString == myStatus) {
        rt << timeDiff
    }
}

def total = rt.sum() as Long
return total ?: 0L

2 answers

2 votes
Sanjay Dhandare January 16, 2020

//After working and troubleshooting I came up with the solution which gives actual time excluding weekend (Saturday and Sunday)

 

 

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.history.ChangeItemBean
import java.util.concurrent.TimeUnit
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.bc.issue.IssueService.UpdateValidationResult
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.bc.issue.IssueService.IssueResult
import com.atlassian.jira.issue.IssueInputParameters
import com.atlassian.jira.issue.changehistory.ChangeHistoryManager
import com.atlassian.core.util.DateUtils
import com.atlassian.jira.issue.history.ChangeItemBean

def statusCode = ['Done','In Progress','In testing','In Implementation','To Do'];

IssueManager im = ComponentAccessor.getIssueManager()

//MutableIssue issue = im.getIssueObject('TES-24')  // Uncomment for troubleshoot in console 

ChangeHistoryManager changeHistoryManager = ComponentAccessor.getChangeHistoryManager()

String myStatus = "In Progress"   // can be taken dynamically ->  issue.getStatus.name

List<Long> rt = [0L]

long curTime = System.currentTimeMillis();

changeHistoryManager.getChangeItemsForField(issue, "status").reverse().each { ChangeItemBean item ->

item.toString == myStatus

Calendar c1 = new GregorianCalendar()

c1.setTimeInMillis(item.created.getTime())

int iHolydayCnt = 0;

while(c1.getTimeInMillis() < curTime)
{
c1.add(Calendar.DAY_OF_YEAR, 1)

if((c1.get(Calendar.DAY_OF_WEEK).equals(Calendar.SATURDAY)) || c1.get(Calendar.DAY_OF_WEEK).equals(Calendar.SUNDAY) )
++iHolydayCnt;
//log.warn(iHolydayCnt)
}
//convert to seconds for Duration
long timeDiff = curTime - item.created.getTime() - iHolydayCnt*(60*60*24*1000)

// def timeDiff = timeStart - timeEnd
if (item.fromString == myStatus) {
rt << -timeDiff
}
if (item.toString == myStatus) {
rt << timeDiff
}
}

def total = rt.sum()/1000 as Long
def mytotal =DateUtils.getDurationString(total)
log.warn(total)
log.warn(mytotal)
return mytotal ?: 0L

// Happy Coding // Sanjay_D_D_Programmer

Madhusudan Bhosale January 16, 2020

Thanks buddy..
It helped me a lot !

Like Sanjay Dhandare likes this
Kunal Saraf January 16, 2020

Well done buddy..

works really great to get the actual time excluding weekends.

Like Sanjay Dhandare likes this
Sanjay Dhandare January 16, 2020

Thanks Kunal for acknowledging ! 

Zaldy Parian
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 17, 2020

@Madhusudan Bhosale 

Can you please give me the steps to get this implemented in our Jira Cloud?

Appreciate it very much.

Regards,

Zaldy

1 vote
Vasiliy Zverev
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 25, 2017

Try this one to find holydays count:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.changehistory.ChangeHistoryManager

import com.atlassian.jira.issue.history.ChangeItemBean

ChangeHistoryManager changeHistoryManager = ComponentAccessor.getChangeHistoryManager()

String myStatus = "In Progress"

List&lt;Long&gt; rt = [0L]

long curTime = System.currentTimeMillis();

changeHistoryManager.getChangeItemsForField(issue, "status").reverse().each { ChangeItemBean item -&gt;
    item.toString == myStatus   
    
    Calendar c1 = new GregorianCalendar()
    c1.setTimeInMillis(item.created.getTime())
    int iHolydayCnt = 0;
    while(c1.getTimeInMillis() &lt; curTime){
        c1.add(Calendar.DAY_OF_YEAR, 1)
        if((c1.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) || (c1.get(Calendar.SUNDAY)) )
            ++iHolydayCnt;            
    }          
    //convert to seconds for Duration
    long timeDiff = curTime - item.created.getTime() - iHolydayCnt*(60*60*24*1000)

    // def timeDiff = timeStart - timeEnd
    if (item.fromString == myStatus) {
        rt &lt;&lt; -timeDiff
    }
    if (item.toString == myStatus) {
        rt &lt;&lt; timeDiff
    }
}

def total = rt.sum() as Long
return total ?: 0L
Sanjay Dhandare January 16, 2020

Thanks buddy Your scripts helped me a lot but need some minor correction which i did you can refer above.

Chhaya Gadade January 22, 2020

Hi @Vasiliy Zverev ,

   Is this script working for initial statuses,e.g Open Or To Do like that?,in my case it is working for remaining statuses rather than initial status i.e.Open or To Do,can you please help me.

Suggest an answer

Log in or Sign up to answer