Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in
Celebration

Earn badges and make progress

You're on your way to the next level! Join the Kudos program to earn points and save your progress.

Deleted user Avatar
Deleted user

Level 1: Seed

25 / 150 points

Next: Root

Avatar

1 badge earned

Collect

Participate in fun challenges

Challenges come and go, but your rewards stay with you. Do more to earn more!

Challenges
Coins

Gift kudos to your peers

What goes around comes around! Share the love by gifting kudos to your peers.

Recognition
Ribbon

Rise up in the ranks

Keep earning points to reach the top of the leaderboard. It resets every quarter so you always have a chance!

Leaderboard

Come for the products,
stay for the community

The Atlassian Community can help you and your team get more value out of Atlassian products and practices.

Atlassian Community about banner
4,461,945
Community Members
 
Community Events
176
Community Groups

scripted field - time spent in status - translation from DC to Cloud

Hello, I've tried to translate the script that shows how much time a ticket stayed in a specific status.

It does the Job, but I'd like a second opinion from someone who really is an expert to let me know if I've done it right.

Reference: https://library.adaptavist.com/entity/count-the-time-an-issue-was-in-a-particular-status


Script is as follows: 
----------------------------------------Begin script----------------------------------------

import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.text.SimpleDateFormat;
import java.util.Date;
// Status to be counted
def statusName = "In Progress"
// Jira datetime field format
def formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")

def changeHistoryManager = get("/rest/api/3/issue/${issue.key}/changelog")
.asObject(Map).body.values.findAll{it.items.field.contains("status")}
def totalStatusTime = [0L]
// Every status change is checked
def changeItems = changeHistoryManager as List<String,String>
logger.info("Change Items list is ${changeItems}")
changeItems.reverse().each { item ->
def createdtime = ZonedDateTime.parse((item.created),formatter).toDate()
logger.info("Created Time is ${createdtime}")
def timeDiff = System.currentTimeMillis() - createdtime.time
logger.info("Time Difference is ${timeDiff}")
String fromString = "${item.items.fromString}"
logger.info ("${fromString}")
// Subtract time if the "from" status is equal to the status to be checked and from and to statuses are different.
// This allows to count the time the issue is in the state for the first time
if (item.items.fromString.contains(statusName) && item.items.fromString != item.items.toString) {
totalStatusTime << -timeDiff
}
// Add time if the "to" status is equal to the status to be checked
if (item.items.toString.contains(statusName)) {
totalStatusTime << timeDiff
}
}

def total = totalStatusTime.sum() as Long
// Every time (added or subtracted) is summed and divided by 1000 to get seconds
(total / 1000) as long ?: 0L

----------------------------------------END script----------------------------------------

 

2 answers

1 accepted

0 votes
Answer accepted

Small upgrade, fixed the issue where the 1st status time was showing negative values.

-------------------------------begins scripts-------------------------------

import java.time.ZonedDateTime
import java.text.SimpleDateFormat
import java.util.Date
// Status to be counted
def statusName = "In Progress"
def statusNameCheck = "[${statusName}]"
// Jira date timestamp field format
def timePattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
//make current time to long number in miliseconds
long currentTime = System.currentTimeMillis()
//get issuedata thrugh API
def issuedata = get("/rest/api/3/issue/${issue.key}?expand=changelog")
.asObject(Map).body
//filter changelogs into list
def statusChanges = issuedata.changelog.histories.findAll{it.items.field.contains("status")}
//get current time and format
def issueCreatedDate = new SimpleDateFormat(timePattern).parse(issuedata.fields.created)
//create a list of long numbers and add 0 as 1st item
List<Long> totalStatusTime = [0]
//calculate time difference between current time and issue created time
def createdDateDiff = System.currentTimeMillis() - issueCreatedDate.getTime()
//add time difference to totalStatusTime list with shift left for 1st status in workflow
if (statusName == "New"){totalStatusTime << createdDateDiff}
//convert statusChanges to a list of strings
def changeItems = statusChanges as List<String,String>
// Every status change is checked
changeItems.reverse().each { item ->
def createdDate = new SimpleDateFormat(timePattern).parse(item.created).getTime()
long timeDiff = currentTime - createdDate
logger.info("Time Difference is ${timeDiff}")
//extract from Status
def fromString = "${item.items.fromString}"
//extract to Status
def toString = "${item.items.toString}"
// Subtract time if the "from" status is equal to the status to be checked and from and to statuses are different.
// This allows to count the time the issue is in the state for the first time
if (fromString == statusNameCheck && fromString != toString) {
totalStatusTime << -timeDiff
}
// Add time if the "to" status is equal to the status to be checked
if (toString == statusNameCheck) {
totalStatusTime << timeDiff
}
}

def total = totalStatusTime.sum() as Long
// Every time (added or subtracted) is summed and divided by 1000 to get seconds
total / 1000 as Long ?: 0

-------------------------------ends scripts-------------------------------

Hello everyone, this is being very helpful to me at the moment!

I have one question though... this return a value in seconds. Is there a way to get a 'pretty' time format out of this? Like 4d 2h 5m for example?

Thank you!

Hi @Bianca Fialho ,

 

Add these lines to your code:

import java.util.concurrent.TimeUnit ->  add it after line 3 to import the Time Unit Java class

and replace "total / 1000 as Long ?: 0" with following lines.

 

long DD = TimeUnit.MILLISECONDS.toDays(total)
long HH = TimeUnit.MILLISECONDS.toHours(total) %24
long MM = TimeUnit.MILLISECONDS.toMinutes(total) % 60
long SS = TimeUnit.MILLISECONDS.toSeconds(total) % 60
String prettyDuration = String.format("%02dd %02dh %02dm %02ds",DD, HH, MM, SS)

 

This will do it.

Wow that works amazing, thank you so much for the complete and speedy answer!!

You, sir, are awesome!

Like Teodor Hoza likes this

Glad I could help!

Sorry, I have one more question as I'm having the same issue you fixed in yours of negative numbers showing for some statuses.

//add time difference to totalStatusTime list with shift left for 1st status in workflow
if (statusName == "New"){totalStatusTime << createdDateDiff}

What does "New" stand for in this line? Should I replace it with the name of the first status in my workflow? 

Thanks again for the awesome code!

In order for this to work, you need to replace New with the 1st status from your workflow.

 

if (statusName == "First status"){totalStatusTime << createdDateDiff}

or you can define a new variable that fetches your 1st status in your workflow by using the transition rest endpoint under the issues class.

Suggest an answer

Log in or Sign up to answer
TAGS

Atlassian Community Events