Hi community,
I need help to do the last step on the definition of a scripted field that returns the time the issue has spent into the current status.
Below is the scripted field code:
import com.atlassian.core.util.DateUtils import com.atlassian.jira.ComponentManager import com.atlassian.jira.issue.history.ChangeItemBean import com.atlassian.jira.issue.Issue def componentManager = ComponentManager.getInstance() def changeHistoryManager = componentManager.getChangeHistoryManager() /*def inProgressName = "In Progress"
Get the current status name */ def inProgressName = issue.getStatusObject().getName() def rt = [0] changeHistoryManager.getChangeItemsForField (issue, "status").reverse().each {ChangeItemBean item -> def timeDiff = System.currentTimeMillis() - item.created.getTime() if (item.fromString == inProgressName) { rt << -timeDiff } if (item.toString == inProgressName){ rt << timeDiff } } DateUtils.getDurationString(Math.round(rt.sum() / 1000))
That's a slightly modified version of the Groovy Scripted Fiels example (link).
The code works properly to return a string well formatted ( e.g. 1h 11m) by setting the Free Text Field template.
What I need now is to convert the string into a Data Format so that I can query it to know issues that are in the same status since one week for istance.
If I set the Date Time Template and I put this linecodes instead of the very last one:
def strDuration = DateUtils.getDurationString(Math.round(rt.sum() / 1000)) DateUtils.getDuration(strDuration)
I got the error below:
$datePickerFormatter.format($value)
Any idea how I can convert the duration string into a data-time friendly value?
Regards
Marco
Community moderators have prevented the ability to post new answers.
If you use the Date Time Template you have to return a Timestamp object not a long. So maybe what you want is a Number Template and than return the days or hours the issue was in the current status as Double object.
So using the Number template and returning
return (Math.round(rt.sum() / 3600000)) as Double
should give you the number of hours the issue was in the current status.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Henning,
Thanks for your reply. It returns the number of hours, but it still does not work properly. I had '4h 11m', now I've got '4' nut the JQL filter does not see it as a number.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Did you configure the searcher as a number searcher? Both template and searcher have to be "number".
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.
What was ultimately the full working script for this? It's exactly what I'm looking to do in my system as well. Thanks.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Did you ever get the full working script? I am trying the same thing.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
For Jira 7+ this would be
import com.atlassian.jira.component.ComponentAccessor
def changeHistoryManager = ComponentAccessor.changeHistoryManager
def currentStatusName = issue?.status?.name
def rt = [0]
changeHistoryManager.getChangeItemsForField (issue, "status").reverse().each {item ->
def timeDiff = System.currentTimeMillis() - item.created.getTime()
if (item.fromString == currentStatusName) {
rt << -timeDiff
}
if (item.toString == currentStatusName){
rt << timeDiff
}
}
return (Math.round(rt.sum() / 3600000)) as Double
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks for the reply!
I am getting the following error on line 11 (rt << -timeDiff>
[static type checking] - cannot call <T> java.util.list <java.lang.Integer>#leftShift(T) with arguments [long] @ line 11, column 9.
Any help?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Try to initialize the list with a long:
def rt = [0L]
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi
I'm getting an error.
Cannot find matching method java.lang.Object#div(int). Please check if the right and if the method exists
Cannot find matching method
java.lang.Math#round(java.lang.Object) Please check if the declared type is right and if the method exists.
This I get on the last line (return statement)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Mmh, maybe there is a NULL creation date (this shouldn't be the case). Try to add
rt -= null
before the return statement and see if this helps.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hello @Henning Tietgens,
We're trying to create a custom field which can show the "time in current status" in days for the issues in JIRA. The field has to reset and show the new value(new age) whenever the issue is transitioned. I created a custom script field and added the code which was suggested in your earlier comments. Look like its giving me the reslut in Hours. How should I change it to get the result Days? Thanks in Advance.
FYI, we're on 7.12.1
This is code that I applied
import com.atlassian.jira.component.ComponentAccessor
def changeHistoryManager = ComponentAccessor.changeHistoryManager
def currentStatusName = issue?.status?.name
def rt = [0L]
changeHistoryManager.getChangeItemsForField (issue, "status").reverse().each {item ->
def timeDiff = System.currentTimeMillis() - item.created.getTime()
if (item.fromString == currentStatusName) {
rt << -timeDiff
}
if (item.toString == currentStatusName){
rt << timeDiff
}
}
return (Math.round(rt.sum() / 3600000)) as Double
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You have to calculate the number of days instead the number of hours. How, depends on your meaning of "day". 24h = 1 day or 8h (working hours) = 1d?
If 8h = 1 day the last line would be
return (Math.round(rt.sum() / 3600000 / 8)) as Double
Btw, this number is calculated every time the issue is displayed, not every time the issue is transitioned.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks for the quick response. I've modified the code and its working perfectly now. As you mentioned, it's only working when the ticket is displayed. But I think we can live with it. We just need to know the status age when looking at the displayed ticket.
Final Code
import com.atlassian.jira.component.ComponentAccessor
def changeHistoryManager = ComponentAccessor.changeHistoryManager
def currentStatusName = issue?.status?.name
def rt = [0L]
changeHistoryManager.getChangeItemsForField (issue, "status").reverse().each {item ->
def timeDiff = System.currentTimeMillis() - item.created.getTime()
if (item.fromString == currentStatusName) {
rt << -timeDiff
}
if (item.toString == currentStatusName){
rt << timeDiff
}
}
return (Math.round(rt.sum() / 3600000 / 24)) as Double
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi All,
I have tried with the above code to get time in current status and i am getting error as below. Can you please help me on this error.
Code i have used is:
import com.atlassian.jira.component.ComponentAccessor
def changeHistoryManager = ComponentAccessor.changeHistoryManager
def currentStatusName = issue?.status?.name
def rt = [0L]
changeHistoryManager.getChangeItemsForField (issue, "status").reverse().each {item ->
def timeDiff = System.currentTimeMillis() - item.created.getTime()
if (item.fromString == currentStatusName) {
rt << -timeDiff
}
if (item.toString == currentStatusName){
rt << timeDiff
}
}
return (Math.round(rt.sum() / 3600000 / 24)) as Double
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi,
try
return (Math.round((rt.sum() as Long) / 3600000 / 24)) as Double
as last line.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Many thanks for you response.
New error occurs with the above code
Error message in the custom field:
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi,
the Static Type checking error is only in the editor, at runtime the type should be clear. But If you don't want to see the error icon use this as the last line.
return (Math.round(((rt.sum() as Long) / 3600000 / 24) as Long)) as Double
Make sure to select "Number field" as Template for the scripted field.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thank you, it works.
What is the fucntion i should use to display the result in below format?
Eg: 2w 2d
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
If you want a duration the result has to be a long containing the durations in seconds, currently the script results in days as Double. Change the last line to
def total = rt.sum() as Long
return (total / 1000) as long ?: 0L
and use the "Duration" or "Duration (time-tracking)" template.
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.