You're on your way to the next level! Join the Kudos program to earn points and save your progress.
Level 1: Seed
25 / 150 points
Next: Root
1 badge earned
Challenges come and go, but your rewards stay with you. Do more to earn more!
What goes around comes around! Share the love by gifting kudos to your peers.
Keep earning points to reach the top of the leaderboard. It resets every quarter so you always have a chance!
Join now to unlock these features and more
The Atlassian Community can help you and your team get more value out of Atlassian products and practices.
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----------------------------------------
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!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Wow that works amazing, thank you so much for the complete and speedy answer!!
You, sir, are awesome!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.